testProcess.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
  5. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  8. PURPOSE. See the above copyright notices for more information.
  9. =========================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(Process.h)
  12. /* Work-around CMake dependency scanning limitation. This must
  13. duplicate the above list of headers. */
  14. #if 0
  15. # include "Process.h.in"
  16. #endif
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #if defined(_WIN32)
  21. # include <windows.h>
  22. #else
  23. # include <unistd.h>
  24. #endif
  25. int runChild(const char* cmd[], int state, int exception, int value,
  26. int share, int output, int delay, double timeout);
  27. int test1(int argc, const char* argv[])
  28. {
  29. (void)argc; (void)argv;
  30. fprintf(stdout, "Output on stdout from test returning 0.\n");
  31. fprintf(stderr, "Output on stderr from test returning 0.\n");
  32. return 0;
  33. }
  34. int test2(int argc, const char* argv[])
  35. {
  36. (void)argc; (void)argv;
  37. fprintf(stdout, "Output on stdout from test returning 123.\n");
  38. fprintf(stderr, "Output on stderr from test returning 123.\n");
  39. return 123;
  40. }
  41. int test3(int argc, const char* argv[])
  42. {
  43. (void)argc; (void)argv;
  44. fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
  45. fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
  46. fflush(stdout);
  47. fflush(stderr);
  48. #if defined(_WIN32)
  49. Sleep(15000);
  50. #else
  51. sleep(15);
  52. #endif
  53. fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
  54. fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
  55. return 0;
  56. }
  57. int test4(int argc, const char* argv[])
  58. {
  59. #if defined(_WIN32)
  60. /* Avoid error diagnostic popups since we are crashing on purpose. */
  61. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
  62. #endif
  63. (void)argc; (void)argv;
  64. fprintf(stdout, "Output before crash on stdout from crash test.\n");
  65. fprintf(stderr, "Output before crash on stderr from crash test.\n");
  66. fflush(stdout);
  67. fflush(stderr);
  68. *(int*)0 = 0;
  69. fprintf(stdout, "Output after crash on stdout from crash test.\n");
  70. fprintf(stderr, "Output after crash on stderr from crash test.\n");
  71. return 0;
  72. }
  73. int test5(int argc, const char* argv[])
  74. {
  75. int r;
  76. const char* cmd[4];
  77. (void)argc;
  78. cmd[0] = argv[0];
  79. cmd[1] = "run";
  80. cmd[2] = "4";
  81. cmd[3] = 0;
  82. fprintf(stdout, "Output on stdout before recursive test.\n");
  83. fprintf(stderr, "Output on stderr before recursive test.\n");
  84. fflush(stdout);
  85. fflush(stderr);
  86. r = runChild(cmd, kwsysProcess_State_Exception,
  87. kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15);
  88. fprintf(stdout, "Output on stdout after recursive test.\n");
  89. fprintf(stderr, "Output on stderr after recursive test.\n");
  90. fflush(stdout);
  91. fflush(stderr);
  92. return r;
  93. }
  94. #define TEST6_SIZE (4096*2)
  95. void test6(int argc, const char* argv[])
  96. {
  97. int i;
  98. char runaway[TEST6_SIZE+1];
  99. (void)argc; (void)argv;
  100. for(i=0;i < TEST6_SIZE;++i)
  101. {
  102. runaway[i] = '.';
  103. }
  104. runaway[TEST6_SIZE] = '\n';
  105. /* Generate huge amounts of output to test killing. */
  106. for(;;)
  107. {
  108. fwrite(runaway, 1, TEST6_SIZE+1, stdout);
  109. fflush(stdout);
  110. }
  111. }
  112. int runChild(const char* cmd[], int state, int exception, int value,
  113. int share, int output, int delay, double timeout)
  114. {
  115. int result = 0;
  116. char* data = 0;
  117. int length = 0;
  118. kwsysProcess* kp = kwsysProcess_New();
  119. if(!kp)
  120. {
  121. fprintf(stderr, "kwsysProcess_New returned NULL!\n");
  122. return 1;
  123. }
  124. kwsysProcess_SetCommand(kp, cmd);
  125. kwsysProcess_SetTimeout(kp, timeout);
  126. if(share)
  127. {
  128. kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
  129. kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1);
  130. }
  131. kwsysProcess_Execute(kp);
  132. if(!share)
  133. {
  134. while(kwsysProcess_WaitForData(kp, &data, &length, 0))
  135. {
  136. if(output)
  137. {
  138. fwrite(data, 1, length, stdout);
  139. fflush(stdout);
  140. }
  141. if(delay)
  142. {
  143. /* Purposely sleeping only on Win32 to let pipe fill up. */
  144. #if defined(_WIN32)
  145. Sleep(100);
  146. #endif
  147. }
  148. }
  149. }
  150. kwsysProcess_WaitForExit(kp, 0);
  151. switch (kwsysProcess_GetState(kp))
  152. {
  153. case kwsysProcess_State_Starting:
  154. printf("No process has been executed.\n"); break;
  155. case kwsysProcess_State_Executing:
  156. printf("The process is still executing.\n"); break;
  157. case kwsysProcess_State_Expired:
  158. printf("Child was killed when timeout expired.\n"); break;
  159. case kwsysProcess_State_Exited:
  160. printf("Child exited with value = %d\n",
  161. kwsysProcess_GetExitValue(kp));
  162. result = ((exception != kwsysProcess_GetExitException(kp)) ||
  163. (value != kwsysProcess_GetExitValue(kp))); break;
  164. case kwsysProcess_State_Killed:
  165. printf("Child was killed by parent.\n"); break;
  166. case kwsysProcess_State_Exception:
  167. printf("Child terminated abnormally: %s\n",
  168. kwsysProcess_GetExceptionString(kp));
  169. result = ((exception != kwsysProcess_GetExitException(kp)) ||
  170. (value != kwsysProcess_GetExitValue(kp))); break;
  171. case kwsysProcess_State_Error:
  172. printf("Error in administrating child process: [%s]\n",
  173. kwsysProcess_GetErrorString(kp)); break;
  174. };
  175. if(result)
  176. {
  177. if(exception != kwsysProcess_GetExitException(kp))
  178. {
  179. fprintf(stderr, "Mismatch in exit exception. "
  180. "Should have been %d, was %d.\n",
  181. exception, kwsysProcess_GetExitException(kp));
  182. }
  183. if(value != kwsysProcess_GetExitValue(kp))
  184. {
  185. fprintf(stderr, "Mismatch in exit value. "
  186. "Should have been %d, was %d.\n",
  187. value, kwsysProcess_GetExitValue(kp));
  188. }
  189. }
  190. if(kwsysProcess_GetState(kp) != state)
  191. {
  192. fprintf(stderr, "Mismatch in state. "
  193. "Should have been %d, was %d.\n",
  194. state, kwsysProcess_GetState(kp));
  195. result = 1;
  196. }
  197. kwsysProcess_Delete(kp);
  198. return result;
  199. }
  200. int main(int argc, const char* argv[])
  201. {
  202. int n = 0;
  203. #if 0
  204. {
  205. HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  206. DuplicateHandle(GetCurrentProcess(), out,
  207. GetCurrentProcess(), &out, 0, FALSE,
  208. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
  209. SetStdHandle(STD_OUTPUT_HANDLE, out);
  210. }
  211. {
  212. HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
  213. DuplicateHandle(GetCurrentProcess(), out,
  214. GetCurrentProcess(), &out, 0, FALSE,
  215. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
  216. SetStdHandle(STD_ERROR_HANDLE, out);
  217. }
  218. #endif
  219. if(argc == 2)
  220. {
  221. n = atoi(argv[1]);
  222. }
  223. else if(argc == 3)
  224. {
  225. n = atoi(argv[2]);
  226. }
  227. /* Check arguments. */
  228. if(n < 1 || n > 6 || (argc == 3 && strcmp(argv[1], "run") != 0))
  229. {
  230. fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
  231. return 1;
  232. }
  233. if(argc == 3)
  234. {
  235. switch (n)
  236. {
  237. case 1: return test1(argc, argv);
  238. case 2: return test2(argc, argv);
  239. case 3: return test3(argc, argv);
  240. case 4: return test4(argc, argv);
  241. case 5: return test5(argc, argv);
  242. case 6: test6(argc, argv); return 0;
  243. }
  244. fprintf(stderr, "Invalid test number %d.\n", n);
  245. return 1;
  246. }
  247. if(n >= 0 && n <= 6)
  248. {
  249. int states[6] =
  250. {
  251. kwsysProcess_State_Exited,
  252. kwsysProcess_State_Exited,
  253. kwsysProcess_State_Expired,
  254. kwsysProcess_State_Exception,
  255. kwsysProcess_State_Exited,
  256. kwsysProcess_State_Expired
  257. };
  258. int exceptions[6] =
  259. {
  260. kwsysProcess_Exception_None,
  261. kwsysProcess_Exception_None,
  262. kwsysProcess_Exception_None,
  263. kwsysProcess_Exception_Fault,
  264. kwsysProcess_Exception_None,
  265. kwsysProcess_Exception_None
  266. };
  267. int values[6] = {0, 123, 1, 1, 0, 0};
  268. int outputs[6] = {1, 1, 1, 1, 1, 0};
  269. int delays[6] = {0, 0, 0, 0, 0, 1};
  270. double timeouts[6] = {10, 10, 10, 10, 30, 10};
  271. int r;
  272. const char* cmd[4];
  273. #ifdef _WIN32
  274. char* argv0 = 0;
  275. if(n == 0 && (argv0 = strdup(argv[0])))
  276. {
  277. /* Try converting to forward slashes to see if it works. */
  278. char* c;
  279. for(c=argv0; *c; ++c)
  280. {
  281. if(*c == '\\')
  282. {
  283. *c = '/';
  284. }
  285. }
  286. cmd[0] = argv0;
  287. }
  288. else
  289. {
  290. cmd[0] = argv[0];
  291. }
  292. #else
  293. cmd[0] = argv[0];
  294. #endif
  295. cmd[1] = "run";
  296. cmd[2] = argv[1];
  297. cmd[3] = 0;
  298. fprintf(stdout, "Output on stdout before test %d.\n", n);
  299. fprintf(stderr, "Output on stderr before test %d.\n", n);
  300. fflush(stdout);
  301. fflush(stderr);
  302. #if defined(__FreeBSD__)
  303. if(n == 4)
  304. {
  305. putenv("TEST_PROCESS_4=1");
  306. }
  307. #endif
  308. r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
  309. outputs[n-1], delays[n-1], timeouts[n-1]);
  310. fprintf(stdout, "Output on stdout after test %d.\n", n);
  311. fprintf(stderr, "Output on stderr after test %d.\n", n);
  312. fflush(stdout);
  313. fflush(stderr);
  314. #if _WIN32
  315. if(argv0) { free(argv0); }
  316. #endif
  317. return r;
  318. }
  319. else
  320. {
  321. fprintf(stderr, "Test number out of range\n");
  322. return 1;
  323. }
  324. }