testProcess.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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 <kwsys/Process.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #if defined(_WIN32)
  15. # include <windows.h>
  16. #else
  17. # include <unistd.h>
  18. #endif
  19. int runChild(const char* cmd[], int state, int exception, int value,
  20. int share, int output, int delay, double timeout);
  21. int test1(int argc, const char* argv[])
  22. {
  23. (void)argc; (void)argv;
  24. fprintf(stdout, "Output on stdout from test returning 0.\n");
  25. fprintf(stderr, "Output on stderr from test returning 0.\n");
  26. return 0;
  27. }
  28. int test2(int argc, const char* argv[])
  29. {
  30. (void)argc; (void)argv;
  31. fprintf(stdout, "Output on stdout from test returning 123.\n");
  32. fprintf(stderr, "Output on stderr from test returning 123.\n");
  33. return 123;
  34. }
  35. int test3(int argc, const char* argv[])
  36. {
  37. (void)argc; (void)argv;
  38. fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
  39. fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
  40. fflush(stdout);
  41. fflush(stderr);
  42. #if defined(_WIN32)
  43. Sleep(5000);
  44. #else
  45. sleep(5);
  46. #endif
  47. fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
  48. fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
  49. return 0;
  50. }
  51. int test4(int argc, const char* argv[])
  52. {
  53. (void)argc; (void)argv;
  54. fprintf(stdout, "Output before crash on stdout from crash test.\n");
  55. fprintf(stderr, "Output before crash on stderr from crash test.\n");
  56. fflush(stdout);
  57. fflush(stderr);
  58. *(int*)0 = 0;
  59. fprintf(stdout, "Output after crash on stdout from crash test.\n");
  60. fprintf(stderr, "Output after crash on stderr from crash test.\n");
  61. return 0;
  62. }
  63. int test5(int argc, const char* argv[])
  64. {
  65. int r;
  66. const char* cmd[4];
  67. (void)argc;
  68. cmd[0] = argv[0];
  69. cmd[1] = "run";
  70. cmd[2] = "4";
  71. cmd[3] = 0;
  72. fprintf(stdout, "Output on stdout before recursive test.\n");
  73. fprintf(stderr, "Output on stderr before recursive test.\n");
  74. fflush(stdout);
  75. fflush(stderr);
  76. r = runChild(cmd, kwsysProcess_State_Exception,
  77. kwsysProcess_Exception_Fault, 1, 1, 1, 0, 2);
  78. fprintf(stdout, "Output on stdout after recursive test.\n");
  79. fprintf(stderr, "Output on stderr after recursive test.\n");
  80. fflush(stdout);
  81. fflush(stderr);
  82. return r;
  83. }
  84. #define TEST6_SIZE (4096*2)
  85. int test6(int argc, const char* argv[])
  86. {
  87. int i;
  88. char runaway[TEST6_SIZE+1];
  89. (void)argc; (void)argv;
  90. for(i=0;i < TEST6_SIZE;++i)
  91. {
  92. runaway[i] = '.';
  93. }
  94. runaway[TEST6_SIZE] = '\n';
  95. /* Generate huge amounts of output to test killing. */
  96. for(;;)
  97. {
  98. fwrite(runaway, 1, TEST6_SIZE+1, stdout);
  99. fflush(stdout);
  100. }
  101. return 0;
  102. }
  103. int runChild(const char* cmd[], int state, int exception, int value,
  104. int share, int output, int delay, double timeout)
  105. {
  106. int result = 0;
  107. char* data = 0;
  108. int length = 0;
  109. kwsysProcess* kp = kwsysProcess_New();
  110. if(!kp)
  111. {
  112. fprintf(stderr, "kwsysProcess_New returned NULL!\n");
  113. return 1;
  114. }
  115. kwsysProcess_SetCommand(kp, cmd);
  116. kwsysProcess_SetTimeout(kp, timeout);
  117. if(share)
  118. {
  119. kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
  120. kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1);
  121. }
  122. kwsysProcess_Execute(kp);
  123. if(!share)
  124. {
  125. while(kwsysProcess_WaitForData(kp, &data, &length, 0))
  126. {
  127. if(output)
  128. {
  129. fwrite(data, 1, length, stdout);
  130. fflush(stdout);
  131. }
  132. if(delay)
  133. {
  134. /* Purposely sleeping only on Win32 to let pipe fill up. */
  135. #if defined(_WIN32)
  136. Sleep(100);
  137. #endif
  138. }
  139. }
  140. }
  141. kwsysProcess_WaitForExit(kp, 0);
  142. switch (kwsysProcess_GetState(kp))
  143. {
  144. case kwsysProcess_State_Starting:
  145. printf("No process has been executed.\n"); break;
  146. case kwsysProcess_State_Executing:
  147. printf("The process is still executing.\n"); break;
  148. case kwsysProcess_State_Expired:
  149. printf("Child was killed when timeout expired.\n"); break;
  150. case kwsysProcess_State_Exited:
  151. printf("Child exited with value = %d\n",
  152. kwsysProcess_GetExitValue(kp));
  153. result = ((exception != kwsysProcess_GetExitException(kp)) ||
  154. (value != kwsysProcess_GetExitValue(kp))); break;
  155. case kwsysProcess_State_Killed:
  156. printf("Child was killed by parent.\n"); break;
  157. case kwsysProcess_State_Exception:
  158. printf("Child terminated abnormally: %s\n",
  159. kwsysProcess_GetExceptionString(kp));
  160. result = ((exception != kwsysProcess_GetExitException(kp)) ||
  161. (value != kwsysProcess_GetExitValue(kp))); break;
  162. case kwsysProcess_State_Error:
  163. printf("Error in administrating child process: [%s]\n",
  164. kwsysProcess_GetErrorString(kp)); break;
  165. };
  166. if(result)
  167. {
  168. if(exception != kwsysProcess_GetExitException(kp))
  169. {
  170. fprintf(stderr, "Mismatch in exit exception. Should have been %d.\n",
  171. exception);
  172. }
  173. if(value != kwsysProcess_GetExitValue(kp))
  174. {
  175. fprintf(stderr, "Mismatch in exit value. Should have been %d.\n",
  176. value);
  177. }
  178. }
  179. if(kwsysProcess_GetState(kp) != state)
  180. {
  181. fprintf(stderr, "Mismatch in state. Should have been %d.\n", state);
  182. result = 1;
  183. }
  184. kwsysProcess_Delete(kp);
  185. return result;
  186. }
  187. int main(int argc, const char* argv[])
  188. {
  189. int n = 0;
  190. #if 0
  191. {
  192. HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  193. DuplicateHandle(GetCurrentProcess(), out,
  194. GetCurrentProcess(), &out, 0, FALSE,
  195. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
  196. SetStdHandle(STD_OUTPUT_HANDLE, out);
  197. }
  198. {
  199. HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
  200. DuplicateHandle(GetCurrentProcess(), out,
  201. GetCurrentProcess(), &out, 0, FALSE,
  202. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
  203. SetStdHandle(STD_ERROR_HANDLE, out);
  204. }
  205. #endif
  206. if(argc == 2)
  207. {
  208. n = atoi(argv[1]);
  209. }
  210. else if(argc == 3)
  211. {
  212. n = atoi(argv[2]);
  213. }
  214. /* Check arguments. */
  215. if(n < 1 || n > 6 || (argc == 3 && strcmp(argv[1], "run") != 0))
  216. {
  217. fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
  218. return 1;
  219. }
  220. if(argc == 3)
  221. {
  222. switch (n)
  223. {
  224. case 1: return test1(argc, argv);
  225. case 2: return test2(argc, argv);
  226. case 3: return test3(argc, argv);
  227. case 4: return test4(argc, argv);
  228. case 5: return test5(argc, argv);
  229. case 6: return test6(argc, argv);
  230. }
  231. fprintf(stderr, "Invalid test number %d.\n", n);
  232. return 1;
  233. }
  234. if(n >= 0 && n <= 6)
  235. {
  236. int states[6] =
  237. {
  238. kwsysProcess_State_Exited,
  239. kwsysProcess_State_Exited,
  240. kwsysProcess_State_Expired,
  241. kwsysProcess_State_Exception,
  242. kwsysProcess_State_Exited,
  243. kwsysProcess_State_Expired
  244. };
  245. int exceptions[6] =
  246. {
  247. kwsysProcess_Exception_None,
  248. kwsysProcess_Exception_None,
  249. kwsysProcess_Exception_None,
  250. kwsysProcess_Exception_Fault,
  251. kwsysProcess_Exception_None,
  252. kwsysProcess_Exception_None
  253. };
  254. int values[6] = {0, 123, 1, 1, 0, 0};
  255. int outputs[6] = {1, 1, 1, 1, 1, 0};
  256. int delays[6] = {0, 0, 0, 0, 0, 1};
  257. double timeouts[6] = {3, 3, 3, 3, 3, 0.1};
  258. int r;
  259. const char* cmd[4];
  260. cmd[0] = argv[0];
  261. cmd[1] = "run";
  262. cmd[2] = argv[1];
  263. cmd[3] = 0;
  264. fprintf(stdout, "Output on stdout before test %d.\n", n);
  265. fprintf(stderr, "Output on stderr before test %d.\n", n);
  266. fflush(stdout);
  267. fflush(stderr);
  268. r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
  269. outputs[n-1], delays[n-1], timeouts[n-1]);
  270. fprintf(stdout, "Output on stdout after test %d.\n", n);
  271. fprintf(stderr, "Output on stderr after test %d.\n", n);
  272. fflush(stdout);
  273. fflush(stderr);
  274. return r;
  275. }
  276. else
  277. {
  278. fprintf(stderr, "Test number out of range\n");
  279. return 1;
  280. }
  281. }