Skip to content

Commit 97802bd

Browse files
cuiziweizwxiaoxiang781216
authored andcommitted
testing/libc/popen: add popen/dpopen test for shell and no-shell modes
Add tests for popen()/pclose() and dpopen()/dpclose() that work in both shell (NSH) and no-shell (direct posix_spawnp) modes. The test binary doubles as its own target via the --echo sub-command. Tests: 1-4: popen - basic read, multi-arg, pclose, invalid mode 5-7: dpopen - basic read, multi-arg, dpclose Signed-off-by: cuiziwei <cuiziwei@xiaomi.com>
1 parent 740fda9 commit 97802bd

5 files changed

Lines changed: 356 additions & 0 deletions

File tree

testing/libc/popen/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# ##############################################################################
2+
# apps/testing/libc/popen/CMakeLists.txt
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
7+
# license agreements. See the NOTICE file distributed with this work for
8+
# additional information regarding copyright ownership. The ASF licenses this
9+
# file to you under the Apache License, Version 2.0 (the "License"); you may not
10+
# use this file except in compliance with the License. You may obtain a copy of
11+
# the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations under
19+
# the License.
20+
#
21+
# ##############################################################################
22+
23+
if(CONFIG_TESTING_POPEN)
24+
nuttx_add_application(
25+
NAME
26+
popen_test
27+
STACKSIZE
28+
${CONFIG_DEFAULT_TASK_STACKSIZE}
29+
MODULE
30+
${CONFIG_TESTING_POPEN}
31+
SRCS
32+
popen_test.c)
33+
endif()

testing/libc/popen/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see the file kconfig-language.txt in the NuttX tools repository.
4+
#
5+
6+
config TESTING_POPEN
7+
tristate "popen()/dpopen() test"
8+
default n
9+
depends on SYSTEM_POPEN
10+
---help---
11+
Test popen()/pclose() and dpopen()/dpclose() in both shell
12+
and no-shell modes. The test binary doubles as its own
13+
popen/dpopen target via --echo.
14+
15+
if TESTING_POPEN
16+
endif

testing/libc/popen/Make.defs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
############################################################################
2+
# apps/testing/libc/popen/Make.defs
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
ifneq ($(CONFIG_TESTING_POPEN),)
24+
CONFIGURED_APPS += $(APPDIR)/testing/libc/popen
25+
endif

testing/libc/popen/Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
############################################################################
2+
# apps/testing/libc/popen/Makefile
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
include $(APPDIR)/Make.defs
24+
25+
PROGNAME = popen_test
26+
PRIORITY = SCHED_PRIORITY_DEFAULT
27+
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
28+
MODULE = $(CONFIG_TESTING_POPEN)
29+
30+
MAINSRC = popen_test.c
31+
32+
include $(APPDIR)/Application.mk

testing/libc/popen/popen_test.c

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/****************************************************************************
2+
* apps/testing/libc/popen/popen_test.c
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one or more
7+
* contributor license agreements. See the NOTICE file distributed with
8+
* this work for additional information regarding copyright ownership. The
9+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
* "License"); you may not use this file except in compliance with the
11+
* License. You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
* License for the specific language governing permissions and limitations
19+
* under the License.
20+
*
21+
****************************************************************************/
22+
23+
/****************************************************************************
24+
* Included Files
25+
****************************************************************************/
26+
27+
#include <nuttx/config.h>
28+
#include <stdio.h>
29+
#include <string.h>
30+
#include <unistd.h>
31+
#include <fcntl.h>
32+
33+
/****************************************************************************
34+
* Private Functions
35+
****************************************************************************/
36+
37+
static int test_popen_read(void)
38+
{
39+
FILE *fp;
40+
char buf[256];
41+
int found = 0;
42+
43+
printf("[TEST 1] popen read...\n");
44+
fp = popen("popen_test --echo hello_popen", "r");
45+
if (fp == NULL)
46+
{
47+
printf("[FAIL] popen returned NULL\n");
48+
return 1;
49+
}
50+
51+
while (fgets(buf, sizeof(buf), fp) != NULL)
52+
{
53+
printf(" > %s", buf);
54+
if (strstr(buf, "hello_popen"))
55+
{
56+
found = 1;
57+
}
58+
}
59+
60+
pclose(fp);
61+
printf("%s\n", found ? "[PASS]" : "[FAIL] missing output");
62+
return !found;
63+
}
64+
65+
static int test_popen_multiarg(void)
66+
{
67+
FILE *fp;
68+
char buf[256];
69+
int found = 0;
70+
71+
printf("[TEST 2] popen multi-arg...\n");
72+
fp = popen("popen_test --echo aaa bbb ccc", "r");
73+
if (fp == NULL)
74+
{
75+
printf("[FAIL] popen returned NULL\n");
76+
return 1;
77+
}
78+
79+
while (fgets(buf, sizeof(buf), fp) != NULL)
80+
{
81+
printf(" > %s", buf);
82+
if (strstr(buf, "aaa bbb ccc"))
83+
{
84+
found = 1;
85+
}
86+
}
87+
88+
pclose(fp);
89+
printf("%s\n", found ? "[PASS]" : "[FAIL] wrong output");
90+
return !found;
91+
}
92+
93+
static int test_pclose_complete(void)
94+
{
95+
FILE *fp;
96+
char buf[256];
97+
98+
printf("[TEST 3] pclose completes...\n");
99+
fp = popen("popen_test --echo ok", "r");
100+
if (fp == NULL)
101+
{
102+
printf("[FAIL] popen returned NULL\n");
103+
return 1;
104+
}
105+
106+
while (fgets(buf, sizeof(buf), fp) != NULL);
107+
pclose(fp);
108+
printf("[PASS]\n");
109+
return 0;
110+
}
111+
112+
static int test_popen_invalid_mode(void)
113+
{
114+
FILE *fp;
115+
116+
printf("[TEST 4] popen invalid mode...\n");
117+
fp = popen("popen_test", "x");
118+
if (fp == NULL)
119+
{
120+
printf("[PASS]\n");
121+
return 0;
122+
}
123+
124+
pclose(fp);
125+
printf("[FAIL] should return NULL\n");
126+
return 1;
127+
}
128+
129+
static int test_dpopen_read(void)
130+
{
131+
char buf[256];
132+
ssize_t n;
133+
pid_t pid;
134+
int found = 0;
135+
int fd;
136+
137+
printf("[TEST 5] dpopen read...\n");
138+
fd = dpopen("popen_test --echo hello_dpopen", O_RDONLY, &pid);
139+
if (fd < 0)
140+
{
141+
printf("[FAIL] dpopen returned %d\n", fd);
142+
return 1;
143+
}
144+
145+
while ((n = read(fd, buf, sizeof(buf) - 1)) > 0)
146+
{
147+
buf[n] = '\0';
148+
printf(" > %s", buf);
149+
if (strstr(buf, "hello_dpopen"))
150+
{
151+
found = 1;
152+
}
153+
}
154+
155+
dpclose(fd, pid);
156+
printf("%s\n", found ? "[PASS]" : "[FAIL] missing output");
157+
return !found;
158+
}
159+
160+
static int test_dpopen_multiarg(void)
161+
{
162+
char buf[256];
163+
ssize_t n;
164+
pid_t pid;
165+
int found = 0;
166+
int fd;
167+
168+
printf("[TEST 6] dpopen multi-arg...\n");
169+
fd = dpopen("popen_test --echo xxx yyy zzz", O_RDONLY, &pid);
170+
if (fd < 0)
171+
{
172+
printf("[FAIL] dpopen returned %d\n", fd);
173+
return 1;
174+
}
175+
176+
while ((n = read(fd, buf, sizeof(buf) - 1)) > 0)
177+
{
178+
buf[n] = '\0';
179+
printf(" > %s", buf);
180+
if (strstr(buf, "xxx yyy zzz"))
181+
{
182+
found = 1;
183+
}
184+
}
185+
186+
dpclose(fd, pid);
187+
printf("%s\n", found ? "[PASS]" : "[FAIL] wrong output");
188+
return !found;
189+
}
190+
191+
static int test_dpclose_complete(void)
192+
{
193+
char buf[256];
194+
pid_t pid;
195+
int fd;
196+
197+
printf("[TEST 7] dpclose completes...\n");
198+
fd = dpopen("popen_test --echo ok", O_RDONLY, &pid);
199+
if (fd < 0)
200+
{
201+
printf("[FAIL] dpopen returned %d\n", fd);
202+
return 1;
203+
}
204+
205+
while (read(fd, buf, sizeof(buf)) > 0);
206+
dpclose(fd, pid);
207+
printf("[PASS]\n");
208+
return 0;
209+
}
210+
211+
/****************************************************************************
212+
* Public Functions
213+
****************************************************************************/
214+
215+
int main(int argc, FAR char *argv[])
216+
{
217+
int fail = 0;
218+
219+
/* Sub-command: echo args back, used as popen/dpopen target */
220+
221+
if (argc > 1 && strcmp(argv[1], "--echo") == 0)
222+
{
223+
int i;
224+
for (i = 2; i < argc; i++)
225+
{
226+
printf("%s%s", i > 2 ? " " : "", argv[i]);
227+
}
228+
229+
printf("\n");
230+
return 0;
231+
}
232+
233+
printf("=== popen/dpopen test ===\n\n");
234+
235+
/* popen tests */
236+
237+
fail += test_popen_read();
238+
fail += test_popen_multiarg();
239+
fail += test_pclose_complete();
240+
fail += test_popen_invalid_mode();
241+
242+
/* dpopen tests */
243+
244+
fail += test_dpopen_read();
245+
fail += test_dpopen_multiarg();
246+
fail += test_dpclose_complete();
247+
248+
printf("\n=== Results: %d failed ===\n", fail);
249+
return fail;
250+
}

0 commit comments

Comments
 (0)