Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
0.process.cpp
Go to the documentation of this file.
1
28// tell Compaq C++ we need POSIX errno constants that are otherwise
29// guarded (not defined) in the compiler's pure C++ libc headers
30#undef __PURE_CNAME
31#include <errno.h> // for ENOENT, ECHILD, ESRCH, errno
32#include <string.h> // for strcmp()
33
34#include <rw_process.h> // for rw_process_create(), rw_waitpid()
35#include <rw_driver.h> // for rw_test()
36
37static int _rw_child = 0;
38static int _rw_timeout = 5;
39
40static char arg1[] = "--child=1";
41static char arg2[] = "--no-stdout";
42
43static char* args [] = { 0, arg1, arg2, 0 };
44static const int nargs = sizeof (args) / sizeof (*args) - 1;
45
46static rw_pid_t _rw_pid = -1;
47
48static int join_test (rw_pid_t pid, bool should_hang)
49{
50 int result = 0;
51 const rw_pid_t ret = rw_waitpid (pid, &result, _rw_timeout);
52
53 rw_assert (-1 != ret, __FILE__, __LINE__,
54 "rw_waitpid() failed, errno = %{#m}");
55
56 if (-1 == ret)
57 return 1;
58
59 if (0 == ret) {
60 // set to ignore rw_error diagnostic
61 rw_enable (rw_error, false);
62
63 // time_out elapsed, kill the process
64 if (1 == rw_process_kill (pid)) {
65 // the process not yet terminated
66 // wait for process termination and remove the zombie process
67 rw_waitpid (pid, 0);
68 }
69
70 // enable rw_error diagnostic
72
73 rw_assert (should_hang, __FILE__, __LINE__,
74 "The child process unexpectedly deadlocked");
75
76 return should_hang ? 0 : 1;
77 }
78
79 rw_assert (!should_hang, __FILE__, __LINE__,
80 "Expected the deadlocked process, but process exited "
81 "with code: %d",
82 result);
83
84 if (!should_hang)
85 rw_assert (0 == result, __FILE__, __LINE__,
86 "Process exit code: expected 0, got %d", result);
87
88 return result;
89}
90
91static int test_process_create1 ()
92{
93 rw_info (0, 0, 0,
94 "Exercising the rw_process_create "
95 "(const char*, char* const []) overload");
96
97 const rw_pid_t pid = rw_process_create (args [0], args);
98
99 rw_assert (-1 != pid, __FILE__, __LINE__,
100 "rw_process_create() failed, errno = %{#m}");
101
102 if (-1 == pid)
103 return 1;
104
105 // save the pid for test exercising rw_waitpid() fail
106 if (-1 == _rw_pid)
107 _rw_pid = pid;
108
109 return join_test (pid, false);
110}
111
112static int test_process_create2 ()
113{
114 rw_info (0, 0, 0,
115 "Exercising the rw_process_create (const char*, ...) overload");
116
117 const rw_pid_t pid = rw_process_create ("\"%s\" %s %s",
118 args[0], args[1], args[2]);
119
120 rw_assert (-1 != pid, __FILE__, __LINE__,
121 "rw_process_create() failed, errno = %{#m}");
122
123 if (-1 == pid)
124 return 1;
125
126 // save the pid for test exercising rw_waitpid() fail
127 if (-1 == _rw_pid)
128 _rw_pid = pid;
129
130 return join_test (pid, false);
131}
132
133static int test_process_deadlocked ()
134{
135 rw_info (0, 0, 0,
136 "Exercising the rw_waitpid() with timeout and deadlocked process");
137
138 const rw_pid_t pid = rw_process_create ("\"%s\" --child=2 %s",
139 args[0], args[2]);
140
141 rw_assert (-1 != pid, __FILE__, __LINE__,
142 "rw_process_create() failed, errno = %{#m}");
143
144 return -1 == pid ? 1 : join_test (pid, true);
145}
146
147static int test_process_create_fail ()
148{
149 rw_info (0, 0, 0,
150 "Exercising the rw_process_create() behavior "
151 "when invalid path specified");
152
153 // set to ignore rw_error diagnostic
154 rw_enable (rw_error, false);
155
156 const rw_pid_t pid = rw_process_create ("/\\/\\/\\", args);
157
158 // enable rw_error diagnostic
160
161 rw_assert (-1 == pid, __FILE__, __LINE__,
162 "rw_process_create returns %ld, expected -1",
163 long (pid));
164
165 if (-1 != pid) {
166 rw_waitpid (pid, 0);
167 return 1;
168 }
169
170 rw_assert (ENOENT == errno, __FILE__, __LINE__,
171 "errno: expected ENOENT, got %{#m}");
172
173 return ENOENT == errno ? 0 : 1;
174}
175
176static int test_waitpid_fail ()
177{
178 if (-1 == _rw_pid) {
179 rw_info (0, 0, 0,
180 "The test, exercising the rw_waitpid() behavior "
181 "when invalid pid specified is disabled");
182
183 return 0;
184 }
185
186 rw_info (0, 0, 0,
187 "Exercising the rw_waitpid() behavior "
188 "when invalid pid specified");
189
190 // set to ignore rw_error diagnostic
191 rw_enable (rw_error, false);
192
193 const rw_pid_t pid = rw_waitpid (_rw_pid, 0);
194
195 // enable rw_error diagnostic
197
198 rw_assert (-1 == pid, __FILE__, __LINE__,
199 "rw_waitpid returns %ld, expected -1",
200 long (pid));
201
202 if (-1 != pid)
203 return 1;
204
205 rw_assert (ECHILD == errno, __FILE__, __LINE__,
206 "errno: expected ECHILD, got %{#m}");
207
208 return ECHILD == errno ? 0 : 1;
209}
210
211static int test_process_kill_fail ()
212{
213 if (-1 == _rw_pid) {
214 rw_info (0, 0, 0,
215 "The test, exercising the rw_process_kill() behavior "
216 "when invalid pid specified is disabled");
217
218 return 0;
219 }
220
221 rw_info (0, 0, 0,
222 "Exercising the rw_process_kill() behavior "
223 "when invalid pid specified");
224
225 // set to ignore rw_error diagnostic
226 rw_enable (rw_error, false);
227
228 const int res = rw_process_kill (_rw_pid);
229
230 // enable rw_error diagnostic
232
233 rw_assert (-1 == res, __FILE__, __LINE__,
234 "rw_process_kill returns %ld, expected -1",
235 long (res));
236
237 if (-1 != res)
238 return 1;
239
240 rw_assert (ESRCH == errno, __FILE__, __LINE__,
241 "errno: expected ESRCH, got %{#m}");
242
243 return ESRCH == errno ? 0 : 1;
244}
245
246static int
247run_test (int argc, char** argv)
248{
249 if (_rw_child) {
250
251 rw_info (0, 0, 0,
252 "The child process: _rw_child = %i", _rw_child);
253
254 if (2 == _rw_child) {
255 // simulate the deadlock
256 while (true) ;
257 }
258
259 // compare number of parameters with expected
260 if (nargs != argc)
261 return nargs;
262
263 // compare the parameters with expected
264 for (int i = 1; i < argc; ++i) {
265 if (0 != strcmp (argv [i], args [i]))
266 return i;
267 }
268
269 return 0;
270 }
271
272 args [0] = argv [0];
273
274 int fails = 0;
275
276 if (test_process_create1 ())
277 ++fails;
278
279 if (test_process_create2 ())
280 ++fails;
281
282 if (test_process_deadlocked ())
283 ++fails;
284
285 if (test_process_create_fail ())
286 ++fails;
287
288 if (test_waitpid_fail ())
289 ++fails;
290
291 if (test_process_kill_fail ())
292 ++fails;
293
294 return fails;
295}
296
297int main (int argc, char *argv[])
298{
299 return rw_test (argc, argv, __FILE__,
300 "0.process",
301 "", run_test,
302 "|-child#0 "
303 "|-timeout#",
304 &_rw_child,
305 &_rw_timeout,
306 0 /*sentinel*/);
307}
#define i
Definition 17.names.cpp:126
#define res
Definition 17.names.cpp:531
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
#define ENOENT
Definition exec.cpp:93
#define ESRCH
Definition exec.cpp:96
#define ECHILD
Definition exec.cpp:102
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT bool rw_enable(int(*fun)(int, const char *, int, const char *,...), bool enable=true)
Definition driver.cpp:1698
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_RWSTD_SSIZE_T rw_pid_t
Definition rw_process.h:33
_TEST_EXPORT rw_pid_t rw_process_create(const char *,...)
Definition process.cpp:395
_TEST_EXPORT rw_pid_t rw_waitpid(rw_pid_t, int *, int=-1)
Definition process.cpp:533
_TEST_EXPORT int rw_process_kill(rw_pid_t, int=-1)
Definition process.cpp:663