Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / testProcess.c
blobdf69ded4a56a189f19ede4c7b2e766a37acbe95d
1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: testProcess.c,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(Process.h)
17 /* Work-around CMake dependency scanning limitation. This must
18 duplicate the above list of headers. */
19 #if 0
20 # include "Process.h.in"
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #if defined(_WIN32)
28 # include <windows.h>
29 #else
30 # include <unistd.h>
31 #endif
33 #if defined(__BORLANDC__)
34 # pragma warn -8060 /* possibly incorrect assignment */
35 #endif
37 #if defined(__BEOS__) && !defined(__ZETA__)
38 /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
39 # include <be/kernel/OS.h>
40 static inline void testProcess_usleep(unsigned int msec)
42 snooze(msec);
44 #else
45 # define testProcess_usleep usleep
46 #endif
48 int runChild(const char* cmd[], int state, int exception, int value,
49 int share, int output, int delay, double timeout, int poll,
50 int repeat, int disown);
52 int test1(int argc, const char* argv[])
54 (void)argc; (void)argv;
55 fprintf(stdout, "Output on stdout from test returning 0.\n");
56 fprintf(stderr, "Output on stderr from test returning 0.\n");
57 return 0;
60 int test2(int argc, const char* argv[])
62 (void)argc; (void)argv;
63 fprintf(stdout, "Output on stdout from test returning 123.\n");
64 fprintf(stderr, "Output on stderr from test returning 123.\n");
65 return 123;
68 int test3(int argc, const char* argv[])
70 (void)argc; (void)argv;
71 fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
72 fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
73 fflush(stdout);
74 fflush(stderr);
75 #if defined(_WIN32)
76 Sleep(15000);
77 #else
78 sleep(15);
79 #endif
80 fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
81 fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
82 return 0;
85 int test4(int argc, const char* argv[])
87 #if defined(_WIN32)
88 /* Avoid error diagnostic popups since we are crashing on purpose. */
89 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
90 #elif defined(__BEOS__)
91 /* Avoid error diagnostic popups since we are crashing on purpose. */
92 disable_debugger(1);
93 #endif
94 (void)argc; (void)argv;
95 fprintf(stdout, "Output before crash on stdout from crash test.\n");
96 fprintf(stderr, "Output before crash on stderr from crash test.\n");
97 fflush(stdout);
98 fflush(stderr);
99 *(int*)0 = 0;
100 fprintf(stdout, "Output after crash on stdout from crash test.\n");
101 fprintf(stderr, "Output after crash on stderr from crash test.\n");
102 return 0;
105 int test5(int argc, const char* argv[])
107 int r;
108 const char* cmd[4];
109 (void)argc;
110 cmd[0] = argv[0];
111 cmd[1] = "run";
112 cmd[2] = "4";
113 cmd[3] = 0;
114 fprintf(stdout, "Output on stdout before recursive test.\n");
115 fprintf(stderr, "Output on stderr before recursive test.\n");
116 fflush(stdout);
117 fflush(stderr);
118 r = runChild(cmd, kwsysProcess_State_Exception,
119 kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1, 0);
120 fprintf(stdout, "Output on stdout after recursive test.\n");
121 fprintf(stderr, "Output on stderr after recursive test.\n");
122 fflush(stdout);
123 fflush(stderr);
124 return r;
127 #define TEST6_SIZE (4096*2)
128 void test6(int argc, const char* argv[])
130 int i;
131 char runaway[TEST6_SIZE+1];
132 (void)argc; (void)argv;
133 for(i=0;i < TEST6_SIZE;++i)
135 runaway[i] = '.';
137 runaway[TEST6_SIZE] = '\n';
139 /* Generate huge amounts of output to test killing. */
140 for(;;)
142 fwrite(runaway, 1, TEST6_SIZE+1, stdout);
143 fflush(stdout);
147 /* Define MINPOLL to be one more than the number of times output is
148 written. Define MAXPOLL to be the largest number of times a loop
149 delaying 1/10th of a second should ever have to poll. */
150 #define MINPOLL 5
151 #define MAXPOLL 20
152 int test7(int argc, const char* argv[])
154 (void)argc; (void)argv;
155 fprintf(stdout, "Output on stdout before sleep.\n");
156 fprintf(stderr, "Output on stderr before sleep.\n");
157 fflush(stdout);
158 fflush(stderr);
159 /* Sleep for 1 second. */
160 #if defined(_WIN32)
161 Sleep(1000);
162 #else
163 sleep(1);
164 #endif
165 fprintf(stdout, "Output on stdout after sleep.\n");
166 fprintf(stderr, "Output on stderr after sleep.\n");
167 fflush(stdout);
168 fflush(stderr);
169 return 0;
172 int test8(int argc, const char* argv[])
174 /* Create a disowned grandchild to test handling of processes
175 that exit before their children. */
176 int r;
177 const char* cmd[4];
178 (void)argc;
179 cmd[0] = argv[0];
180 cmd[1] = "run";
181 cmd[2] = "108";
182 cmd[3] = 0;
183 fprintf(stdout, "Output on stdout before grandchild test.\n");
184 fprintf(stderr, "Output on stderr before grandchild test.\n");
185 fflush(stdout);
186 fflush(stderr);
187 r = runChild(cmd, kwsysProcess_State_Disowned, kwsysProcess_Exception_None,
188 1, 1, 1, 0, 10, 0, 1, 1);
189 fprintf(stdout, "Output on stdout after grandchild test.\n");
190 fprintf(stderr, "Output on stderr after grandchild test.\n");
191 fflush(stdout);
192 fflush(stderr);
193 return r;
196 int test8_grandchild(int argc, const char* argv[])
198 (void)argc; (void)argv;
199 fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
200 fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
201 fflush(stdout);
202 fflush(stderr);
203 /* TODO: Instead of closing pipes here leave them open to make sure
204 the grandparent can stop listening when the parent exits. This
205 part of the test cannot be enabled until the feature is
206 implemented. */
207 fclose(stdout);
208 fclose(stderr);
209 #if defined(_WIN32)
210 Sleep(15000);
211 #else
212 sleep(15);
213 #endif
214 return 0;
217 int runChild2(kwsysProcess* kp,
218 const char* cmd[], int state, int exception, int value,
219 int share, int output, int delay, double timeout,
220 int poll, int disown)
222 int result = 0;
223 char* data = 0;
224 int length = 0;
225 double userTimeout = 0;
226 double* pUserTimeout = 0;
227 kwsysProcess_SetCommand(kp, cmd);
228 if(timeout >= 0)
230 kwsysProcess_SetTimeout(kp, timeout);
232 if(share)
234 kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
235 kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1);
237 if(disown)
239 kwsysProcess_SetOption(kp, kwsysProcess_Option_Detach, 1);
241 kwsysProcess_Execute(kp);
243 if(poll)
245 pUserTimeout = &userTimeout;
248 if(!share && !disown)
250 int p;
251 while((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout)))
253 if(output)
255 if(poll && p == kwsysProcess_Pipe_Timeout)
257 fprintf(stdout, "WaitForData timeout reached.\n");
258 fflush(stdout);
260 /* Count the number of times we polled without getting data.
261 If it is excessive then kill the child and fail. */
262 if(++poll >= MAXPOLL)
264 fprintf(stdout, "Poll count reached limit %d.\n",
265 MAXPOLL);
266 kwsysProcess_Kill(kp);
269 else
271 fwrite(data, 1, length, stdout);
272 fflush(stdout);
275 if(poll)
277 /* Delay to avoid busy loop during polling. */
278 #if defined(_WIN32)
279 Sleep(100);
280 #else
281 testProcess_usleep(100000);
282 #endif
284 if(delay)
286 /* Purposely sleeping only on Win32 to let pipe fill up. */
287 #if defined(_WIN32)
288 Sleep(100);
289 #endif
294 if(disown)
296 kwsysProcess_Disown(kp);
298 else
300 kwsysProcess_WaitForExit(kp, 0);
303 switch (kwsysProcess_GetState(kp))
305 case kwsysProcess_State_Starting:
306 printf("No process has been executed.\n"); break;
307 case kwsysProcess_State_Executing:
308 printf("The process is still executing.\n"); break;
309 case kwsysProcess_State_Expired:
310 printf("Child was killed when timeout expired.\n"); break;
311 case kwsysProcess_State_Exited:
312 printf("Child exited with value = %d\n",
313 kwsysProcess_GetExitValue(kp));
314 result = ((exception != kwsysProcess_GetExitException(kp)) ||
315 (value != kwsysProcess_GetExitValue(kp))); break;
316 case kwsysProcess_State_Killed:
317 printf("Child was killed by parent.\n"); break;
318 case kwsysProcess_State_Exception:
319 printf("Child terminated abnormally: %s\n",
320 kwsysProcess_GetExceptionString(kp));
321 result = ((exception != kwsysProcess_GetExitException(kp)) ||
322 (value != kwsysProcess_GetExitValue(kp))); break;
323 case kwsysProcess_State_Disowned:
324 printf("Child was disowned.\n"); break;
325 case kwsysProcess_State_Error:
326 printf("Error in administrating child process: [%s]\n",
327 kwsysProcess_GetErrorString(kp)); break;
330 if(result)
332 if(exception != kwsysProcess_GetExitException(kp))
334 fprintf(stderr, "Mismatch in exit exception. "
335 "Should have been %d, was %d.\n",
336 exception, kwsysProcess_GetExitException(kp));
338 if(value != kwsysProcess_GetExitValue(kp))
340 fprintf(stderr, "Mismatch in exit value. "
341 "Should have been %d, was %d.\n",
342 value, kwsysProcess_GetExitValue(kp));
346 if(kwsysProcess_GetState(kp) != state)
348 fprintf(stderr, "Mismatch in state. "
349 "Should have been %d, was %d.\n",
350 state, kwsysProcess_GetState(kp));
351 result = 1;
354 /* We should have polled more times than there were data if polling
355 was enabled. */
356 if(poll && poll < MINPOLL)
358 fprintf(stderr, "Poll count is %d, which is less than %d.\n",
359 poll, MINPOLL);
360 result = 1;
363 return result;
366 int runChild(const char* cmd[], int state, int exception, int value,
367 int share, int output, int delay, double timeout,
368 int poll, int repeat, int disown)
370 int result = 1;
371 kwsysProcess* kp = kwsysProcess_New();
372 if(!kp)
374 fprintf(stderr, "kwsysProcess_New returned NULL!\n");
375 return 1;
377 while(repeat-- > 0)
379 result = runChild2(kp, cmd, state, exception, value, share,
380 output, delay, timeout, poll, disown);
382 kwsysProcess_Delete(kp);
383 return result;
386 int main(int argc, const char* argv[])
388 int n = 0;
389 #if 0
391 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
392 DuplicateHandle(GetCurrentProcess(), out,
393 GetCurrentProcess(), &out, 0, FALSE,
394 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
395 SetStdHandle(STD_OUTPUT_HANDLE, out);
398 HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
399 DuplicateHandle(GetCurrentProcess(), out,
400 GetCurrentProcess(), &out, 0, FALSE,
401 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
402 SetStdHandle(STD_ERROR_HANDLE, out);
404 #endif
405 if(argc == 2)
407 n = atoi(argv[1]);
409 else if(argc == 3 && strcmp(argv[1], "run") == 0)
411 n = atoi(argv[2]);
413 /* Check arguments. */
414 if(((n >= 1 && n <= 8) || n == 108) && argc == 3)
416 /* This is the child process for a requested test number. */
417 switch (n)
419 case 1: return test1(argc, argv);
420 case 2: return test2(argc, argv);
421 case 3: return test3(argc, argv);
422 case 4: return test4(argc, argv);
423 case 5: return test5(argc, argv);
424 case 6: test6(argc, argv); return 0;
425 case 7: return test7(argc, argv);
426 case 8: return test8(argc, argv);
427 case 108: return test8_grandchild(argc, argv);
429 fprintf(stderr, "Invalid test number %d.\n", n);
430 return 1;
432 else if(n >= 1 && n <= 8)
434 /* This is the parent process for a requested test number. */
435 int states[8] =
437 kwsysProcess_State_Exited,
438 kwsysProcess_State_Exited,
439 kwsysProcess_State_Expired,
440 kwsysProcess_State_Exception,
441 kwsysProcess_State_Exited,
442 kwsysProcess_State_Expired,
443 kwsysProcess_State_Exited,
444 kwsysProcess_State_Exited
446 int exceptions[8] =
448 kwsysProcess_Exception_None,
449 kwsysProcess_Exception_None,
450 kwsysProcess_Exception_None,
451 kwsysProcess_Exception_Fault,
452 kwsysProcess_Exception_None,
453 kwsysProcess_Exception_None,
454 kwsysProcess_Exception_None,
455 kwsysProcess_Exception_None
457 int values[8] = {0, 123, 1, 1, 0, 0, 0, 0};
458 int outputs[8] = {1, 1, 1, 1, 1, 0, 1, 1};
459 int delays[8] = {0, 0, 0, 0, 0, 1, 0, 0};
460 double timeouts[8] = {10, 10, 10, 10, 30, 10, -1, 10};
461 int polls[8] = {0, 0, 0, 0, 0, 0, 1, 0};
462 int repeat[8] = {2, 1, 1, 1, 1, 1, 1, 1};
463 int r;
464 const char* cmd[4];
465 #ifdef _WIN32
466 char* argv0 = 0;
467 if(n == 0 && (argv0 = strdup(argv[0])))
469 /* Try converting to forward slashes to see if it works. */
470 char* c;
471 for(c=argv0; *c; ++c)
473 if(*c == '\\')
475 *c = '/';
478 cmd[0] = argv0;
480 else
482 cmd[0] = argv[0];
484 #else
485 cmd[0] = argv[0];
486 #endif
487 cmd[1] = "run";
488 cmd[2] = argv[1];
489 cmd[3] = 0;
490 fprintf(stdout, "Output on stdout before test %d.\n", n);
491 fprintf(stderr, "Output on stderr before test %d.\n", n);
492 fflush(stdout);
493 fflush(stderr);
494 r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
495 outputs[n-1], delays[n-1], timeouts[n-1],
496 polls[n-1], repeat[n-1], 0);
497 fprintf(stdout, "Output on stdout after test %d.\n", n);
498 fprintf(stderr, "Output on stderr after test %d.\n", n);
499 fflush(stdout);
500 fflush(stderr);
501 #if _WIN32
502 if(argv0) { free(argv0); }
503 #endif
504 return r;
506 else if(argc > 2 && strcmp(argv[1], "0") == 0)
508 /* This is the special debugging test to run a given command
509 line. */
510 const char** cmd = argv+2;
511 int state = kwsysProcess_State_Exited;
512 int exception = kwsysProcess_Exception_None;
513 int value = 0;
514 double timeout = 0;
515 int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0);
516 return r;
518 else
520 /* Improper usage. */
521 fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
522 return 1;