1
0

testprocess.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. #include <SDL3/SDL.h>
  2. #include <SDL3/SDL_main.h>
  3. #include <SDL3/SDL_test.h>
  4. #ifdef SDL_PLATFORM_WINDOWS
  5. #define EXE ".exe"
  6. #else
  7. #define EXE ""
  8. #endif
  9. /*
  10. * FIXME: Additional tests:
  11. * - stdin to stdout
  12. * - stdin to stderr
  13. * - read env, using env set by parent process
  14. * - exit codes
  15. * - kill process
  16. * - waiting twice on process
  17. * - executing a non-existing program
  18. * - executing a process linking to a shared library not in the search paths
  19. * - piping processes
  20. * - forwarding SDL_IOFromFile stream to process
  21. * - forwarding process to SDL_IOFromFile stream
  22. */
  23. typedef struct {
  24. const char *childprocess_path;
  25. } TestProcessData;
  26. static TestProcessData parsed_args;
  27. static void SDLCALL setUpProcess(void **arg) {
  28. *arg = &parsed_args;
  29. }
  30. static const char *options[] = { "/path/to/childprocess" EXE, NULL };
  31. static SDL_Environment *DuplicateEnvironment(const char *key0, ...)
  32. {
  33. va_list ap;
  34. const char *keyN;
  35. SDL_Environment *env = SDL_GetEnvironment();
  36. SDL_Environment *new_env = SDL_CreateEnvironment(SDL_FALSE);
  37. if (key0) {
  38. char *sep = SDL_strchr(key0, '=');
  39. if (sep) {
  40. *sep = '\0';
  41. SDL_SetEnvironmentVariable(new_env, key0, sep + 1, SDL_TRUE);
  42. *sep = '=';
  43. SDL_SetEnvironmentVariable(new_env, key0, sep, SDL_TRUE);
  44. } else {
  45. SDL_SetEnvironmentVariable(new_env, key0, SDL_GetEnvironmentVariable(env, key0), SDL_TRUE);
  46. }
  47. va_start(ap, key0);
  48. for (;;) {
  49. keyN = va_arg(ap, const char *);
  50. if (keyN) {
  51. sep = SDL_strchr(keyN, '=');
  52. if (sep) {
  53. *sep = '\0';
  54. SDL_SetEnvironmentVariable(new_env, keyN, sep + 1, SDL_TRUE);
  55. *sep = '=';
  56. } else {
  57. SDL_SetEnvironmentVariable(new_env, keyN, SDL_GetEnvironmentVariable(env, keyN), SDL_TRUE);
  58. }
  59. } else {
  60. break;
  61. }
  62. }
  63. va_end(ap);
  64. }
  65. return new_env;
  66. }
  67. static int SDLCALL process_testArguments(void *arg)
  68. {
  69. TestProcessData *data = (TestProcessData *)arg;
  70. const char *process_args[] = {
  71. data->childprocess_path,
  72. "--print-arguments",
  73. "--",
  74. "",
  75. " ",
  76. "a b c",
  77. "a\tb\tc\t",
  78. "\"a b\" c",
  79. "'a' 'b' 'c'",
  80. "%d%%%s",
  81. "\\t\\c",
  82. "evil\\",
  83. "a\\b\"c\\",
  84. "\"\\^&|<>%", /* characters with a special meaning */
  85. NULL
  86. };
  87. SDL_Process *process = NULL;
  88. char *buffer;
  89. int exit_code;
  90. int i;
  91. process = SDL_CreateProcess(process_args, SDL_TRUE);
  92. SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
  93. if (!process) {
  94. goto failed;
  95. }
  96. exit_code = 0xdeadbeef;
  97. buffer = (char *)SDL_ReadProcess(process, NULL, &exit_code);
  98. SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
  99. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  100. if (!buffer) {
  101. goto failed;
  102. }
  103. for (i = 3; process_args[i]; i++) {
  104. char line[64];
  105. SDL_snprintf(line, sizeof(line), "|%d=%s|", i - 3, process_args[i]);
  106. SDLTest_AssertCheck(!!SDL_strstr(buffer, line), "Check %s is in output", line);
  107. }
  108. SDL_free(buffer);
  109. SDLTest_AssertPass("About to destroy process");
  110. SDL_DestroyProcess(process);
  111. return TEST_COMPLETED;
  112. failed:
  113. SDL_DestroyProcess(process);
  114. return TEST_ABORTED;
  115. }
  116. static int SDLCALL process_testInheritedEnv(void *arg)
  117. {
  118. TestProcessData *data = (TestProcessData *)arg;
  119. const char *process_args[] = {
  120. data->childprocess_path,
  121. "--print-environment",
  122. "--expect-env", NULL,
  123. NULL,
  124. };
  125. SDL_PropertiesID props;
  126. SDL_Process *process = NULL;
  127. Sint64 pid;
  128. SDL_IOStream *process_stdout = NULL;
  129. char buffer[256];
  130. SDL_bool wait_result;
  131. int exit_code;
  132. static const char *const TEST_ENV_KEY = "testprocess_environment";
  133. char *test_env_val = NULL;
  134. test_env_val = SDLTest_RandomAsciiStringOfSize(32);
  135. SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY, test_env_val);
  136. SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY, test_env_val, SDL_TRUE);
  137. SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val);
  138. process_args[3] = buffer;
  139. props = SDL_CreateProperties();
  140. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
  141. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
  142. process = SDL_CreateProcessWithProperties(props);
  143. SDL_DestroyProperties(props);
  144. SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
  145. if (!process) {
  146. goto failed;
  147. }
  148. props = SDL_GetProcessProperties(process);
  149. SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
  150. pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
  151. SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
  152. process_stdout = SDL_GetProcessOutput(process);
  153. SDLTest_AssertCheck(process_stdout != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDOUT_POINTER) returns a valid IO stream");
  154. if (!process_stdout) {
  155. goto failed;
  156. }
  157. for (;;) {
  158. size_t amount_read;
  159. amount_read = SDL_ReadIO(process_stdout, buffer, sizeof(buffer) - 1);
  160. if (amount_read > 0) {
  161. buffer[amount_read] = '\0';
  162. SDLTest_Log("READ: %s", buffer);
  163. } else if (SDL_GetIOStatus(process_stdout) != SDL_IO_STATUS_NOT_READY) {
  164. break;
  165. }
  166. SDL_Delay(10);
  167. }
  168. SDLTest_AssertPass("About to wait on process");
  169. exit_code = 0xdeadbeef;
  170. wait_result = SDL_WaitProcess(process, SDL_TRUE, &exit_code);
  171. SDLTest_AssertCheck(wait_result == SDL_TRUE, "Process should have closed when closing stdin");
  172. SDLTest_AssertPass("exit_code will be != 0 when environment variable was not set");
  173. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  174. SDLTest_AssertPass("About to destroy process");
  175. SDL_DestroyProcess(process);
  176. SDL_free(test_env_val);
  177. return TEST_COMPLETED;
  178. failed:
  179. SDL_free(test_env_val);
  180. SDL_DestroyProcess(process);
  181. return TEST_ABORTED;
  182. }
  183. static int SDLCALL process_testNewEnv(void *arg)
  184. {
  185. TestProcessData *data = (TestProcessData *)arg;
  186. const char *process_args[] = {
  187. data->childprocess_path,
  188. "--print-environment",
  189. "--expect-env", NULL,
  190. NULL,
  191. };
  192. SDL_Environment *process_env;
  193. SDL_PropertiesID props;
  194. SDL_Process *process = NULL;
  195. Sint64 pid;
  196. SDL_IOStream *process_stdout = NULL;
  197. char buffer[256];
  198. SDL_bool wait_result;
  199. int exit_code;
  200. static const char *const TEST_ENV_KEY = "testprocess_environment";
  201. char *test_env_val = NULL;
  202. test_env_val = SDLTest_RandomAsciiStringOfSize(32);
  203. SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val);
  204. process_args[3] = buffer;
  205. process_env = DuplicateEnvironment("PATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", buffer, NULL);
  206. props = SDL_CreateProperties();
  207. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
  208. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, process_env);
  209. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
  210. process = SDL_CreateProcessWithProperties(props);
  211. SDL_DestroyProperties(props);
  212. SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
  213. if (!process) {
  214. goto failed;
  215. }
  216. props = SDL_GetProcessProperties(process);
  217. SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
  218. pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
  219. SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
  220. process_stdout = SDL_GetProcessOutput(process);
  221. SDLTest_AssertCheck(process_stdout != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDOUT_POINTER) returns a valid IO stream");
  222. if (!process_stdout) {
  223. goto failed;
  224. }
  225. for (;;) {
  226. size_t amount_read;
  227. amount_read = SDL_ReadIO(process_stdout, buffer, sizeof(buffer) - 1);
  228. if (amount_read > 0) {
  229. buffer[amount_read] = '\0';
  230. SDLTest_Log("READ: %s", buffer);
  231. } else if (SDL_GetIOStatus(process_stdout) != SDL_IO_STATUS_NOT_READY) {
  232. break;
  233. }
  234. SDL_Delay(10);
  235. }
  236. SDLTest_AssertPass("About to wait on process");
  237. exit_code = 0xdeadbeef;
  238. wait_result = SDL_WaitProcess(process, SDL_TRUE, &exit_code);
  239. SDLTest_AssertCheck(wait_result == SDL_TRUE, "Process should have closed when closing stdin");
  240. SDLTest_AssertPass("exit_code will be != 0 when environment variable was not set");
  241. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  242. SDLTest_AssertPass("About to destroy process");
  243. SDL_free(test_env_val);
  244. SDL_DestroyProcess(process);
  245. SDL_DestroyEnvironment(process_env);
  246. return TEST_COMPLETED;
  247. failed:
  248. SDL_free(test_env_val);
  249. SDL_DestroyProcess(process);
  250. SDL_DestroyEnvironment(process_env);
  251. return TEST_ABORTED;
  252. }
  253. static int process_testStdinToStdout(void *arg)
  254. {
  255. TestProcessData *data = (TestProcessData *)arg;
  256. const char *process_args[] = {
  257. data->childprocess_path,
  258. "--stdin-to-stdout",
  259. NULL,
  260. };
  261. SDL_PropertiesID props;
  262. SDL_Process *process = NULL;
  263. Sint64 pid;
  264. SDL_IOStream *process_stdin = NULL;
  265. SDL_IOStream *process_stdout = NULL;
  266. const char *text_in = "Tests whether we can write to stdin and read from stdout\r\n{'succes': true, 'message': 'Success!'}\r\nYippie ka yee\r\nEOF";
  267. size_t amount_written;
  268. size_t amount_to_write;
  269. char buffer[128];
  270. size_t total_read;
  271. SDL_bool wait_result;
  272. int exit_code;
  273. props = SDL_CreateProperties();
  274. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
  275. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP);
  276. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
  277. process = SDL_CreateProcessWithProperties(props);
  278. SDL_DestroyProperties(props);
  279. SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
  280. if (!process) {
  281. goto failed;
  282. }
  283. props = SDL_GetProcessProperties(process);
  284. SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
  285. pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
  286. SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
  287. process_stdin = SDL_GetProcessInput(process);
  288. SDLTest_AssertCheck(process_stdin != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDIN_POINTER) returns a valid IO stream");
  289. process_stdout = SDL_GetProcessOutput(process);
  290. SDLTest_AssertCheck(process_stdout != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDOUT_POINTER) returns a valid IO stream");
  291. if (!process_stdin || !process_stdout) {
  292. goto failed;
  293. }
  294. SDLTest_AssertPass("About to write to process");
  295. amount_to_write = SDL_strlen(text_in);
  296. amount_written = SDL_WriteIO(process_stdin, text_in, amount_to_write);
  297. SDLTest_AssertCheck(amount_written == amount_to_write, "SDL_WriteIO(subprocess.stdin) wrote %" SDL_PRIu64 " bytes, expected %" SDL_PRIu64, (Uint64)amount_written, (Uint64)amount_to_write);
  298. if (amount_to_write != amount_written) {
  299. goto failed;
  300. }
  301. SDL_FlushIO(process_stdin);
  302. total_read = 0;
  303. buffer[0] = '\0';
  304. for (;;) {
  305. size_t amount_read;
  306. if (total_read >= sizeof(buffer) - 1) {
  307. SDLTest_AssertCheck(0, "Buffer is too small for input data.");
  308. goto failed;
  309. }
  310. SDLTest_AssertPass("About to read from process");
  311. amount_read = SDL_ReadIO(process_stdout, buffer + total_read, sizeof(buffer) - total_read - 1);
  312. if (amount_read == 0 && SDL_GetIOStatus(process_stdout) != SDL_IO_STATUS_NOT_READY) {
  313. break;
  314. }
  315. total_read += amount_read;
  316. buffer[total_read] = '\0';
  317. if (total_read >= sizeof(buffer) - 1 || SDL_strstr(buffer, "EOF")) {
  318. break;
  319. }
  320. SDL_Delay(10);
  321. }
  322. SDLTest_Log("Text read from subprocess: %s", buffer);
  323. SDLTest_AssertCheck(SDL_strcmp(buffer, text_in) == 0, "Subprocess stdout should match text written to stdin");
  324. SDLTest_AssertPass("About to close stdin");
  325. /* Closing stdin of `subprocessstdin --stdin-to-stdout` should close the process */
  326. SDL_CloseIO(process_stdin);
  327. process_stdin = SDL_GetProcessInput(process);
  328. SDLTest_AssertCheck(process_stdin == NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDIN_POINTER) is cleared after close");
  329. SDLTest_AssertPass("About to wait on process");
  330. exit_code = 0xdeadbeef;
  331. wait_result = SDL_WaitProcess(process, SDL_TRUE, &exit_code);
  332. SDLTest_AssertCheck(wait_result == SDL_TRUE, "Process should have closed when closing stdin");
  333. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  334. if (!wait_result) {
  335. SDL_bool killed;
  336. SDL_Log("About to kill process");
  337. killed = SDL_KillProcess(process, SDL_TRUE);
  338. SDLTest_AssertCheck(killed, "SDL_KillProcess succeeded");
  339. }
  340. SDLTest_AssertPass("About to destroy process");
  341. SDL_DestroyProcess(process);
  342. return TEST_COMPLETED;
  343. failed:
  344. SDL_DestroyProcess(process);
  345. return TEST_ABORTED;
  346. }
  347. static int process_testSimpleStdinToStdout(void *arg)
  348. {
  349. TestProcessData *data = (TestProcessData *)arg;
  350. const char *process_args[] = {
  351. data->childprocess_path,
  352. "--stdin-to-stdout",
  353. NULL,
  354. };
  355. SDL_Process *process = NULL;
  356. SDL_IOStream *input = NULL;
  357. const char *text_in = "Tests whether we can write to stdin and read from stdout\r\n{'succes': true, 'message': 'Success!'}\r\nYippie ka yee\r\nEOF";
  358. char *buffer;
  359. size_t result;
  360. int exit_code;
  361. process = SDL_CreateProcess(process_args, SDL_TRUE);
  362. SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
  363. if (!process) {
  364. goto failed;
  365. }
  366. SDLTest_AssertPass("About to write to process");
  367. input = SDL_GetProcessInput(process);
  368. SDLTest_AssertCheck(input != NULL, "SDL_GetProcessInput()");
  369. result = SDL_WriteIO(input, text_in, SDL_strlen(text_in));
  370. SDLTest_AssertCheck(result == SDL_strlen(text_in), "SDL_WriteIO() wrote %d, expected %d", (int)result, (int)SDL_strlen(text_in));
  371. SDL_CloseIO(input);
  372. input = SDL_GetProcessInput(process);
  373. SDLTest_AssertCheck(input == NULL, "SDL_GetProcessInput() after close");
  374. exit_code = 0xdeadbeef;
  375. buffer = (char *)SDL_ReadProcess(process, NULL, &exit_code);
  376. SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
  377. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  378. if (!buffer) {
  379. goto failed;
  380. }
  381. SDLTest_Log("Text read from subprocess: %s", buffer);
  382. SDLTest_AssertCheck(SDL_strcmp(buffer, text_in) == 0, "Subprocess stdout should match text written to stdin");
  383. SDL_free(buffer);
  384. SDLTest_AssertPass("About to destroy process");
  385. SDL_DestroyProcess(process);
  386. return TEST_COMPLETED;
  387. failed:
  388. SDL_DestroyProcess(process);
  389. return TEST_ABORTED;
  390. }
  391. static int process_testMultiprocessStdinToStdout(void *arg)
  392. {
  393. TestProcessData *data = (TestProcessData *)arg;
  394. const char *process_args[] = {
  395. data->childprocess_path,
  396. "--stdin-to-stdout",
  397. NULL,
  398. };
  399. SDL_Process *process1 = NULL;
  400. SDL_Process *process2 = NULL;
  401. SDL_PropertiesID props;
  402. SDL_IOStream *input = NULL;
  403. const char *text_in = "Tests whether we can write to stdin and read from stdout\r\n{'succes': true, 'message': 'Success!'}\r\nYippie ka yee\r\nEOF";
  404. char *buffer;
  405. size_t result;
  406. int exit_code;
  407. process1 = SDL_CreateProcess(process_args, SDL_TRUE);
  408. SDLTest_AssertCheck(process1 != NULL, "SDL_CreateProcess()");
  409. if (!process1) {
  410. goto failed;
  411. }
  412. props = SDL_CreateProperties();
  413. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
  414. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_REDIRECT);
  415. SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_POINTER, SDL_GetPointerProperty(SDL_GetProcessProperties(process1), SDL_PROP_PROCESS_STDOUT_POINTER, NULL));
  416. SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
  417. process2 = SDL_CreateProcessWithProperties(props);
  418. SDL_DestroyProperties(props);
  419. SDLTest_AssertCheck(process2 != NULL, "SDL_CreateProcess()");
  420. if (!process2) {
  421. goto failed;
  422. }
  423. SDLTest_AssertPass("About to write to process");
  424. input = SDL_GetProcessInput(process1);
  425. SDLTest_AssertCheck(input != NULL, "SDL_GetProcessInput()");
  426. result = SDL_WriteIO(input, text_in, SDL_strlen(text_in));
  427. SDLTest_AssertCheck(result == SDL_strlen(text_in), "SDL_WriteIO() wrote %d, expected %d", (int)result, (int)SDL_strlen(text_in));
  428. SDL_CloseIO(input);
  429. exit_code = 0xdeadbeef;
  430. buffer = (char *)SDL_ReadProcess(process2, NULL, &exit_code);
  431. SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
  432. SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
  433. if (!buffer) {
  434. goto failed;
  435. }
  436. SDLTest_Log("Text read from subprocess: %s", buffer);
  437. SDLTest_AssertCheck(SDL_strcmp(buffer, text_in) == 0, "Subprocess stdout should match text written to stdin");
  438. SDL_free(buffer);
  439. SDLTest_AssertPass("About to destroy processes");
  440. SDL_DestroyProcess(process1);
  441. SDL_DestroyProcess(process2);
  442. return TEST_COMPLETED;
  443. failed:
  444. SDL_DestroyProcess(process1);
  445. SDL_DestroyProcess(process2);
  446. return TEST_ABORTED;
  447. }
  448. static const SDLTest_TestCaseReference processTestArguments = {
  449. process_testArguments, "process_testArguments", "Test passing arguments to child process", TEST_ENABLED
  450. };
  451. static const SDLTest_TestCaseReference processTestIneritedEnv = {
  452. process_testInheritedEnv, "process_testInheritedEnv", "Test inheriting environment from parent process", TEST_ENABLED
  453. };
  454. static const SDLTest_TestCaseReference processTestNewEnv = {
  455. process_testNewEnv, "process_testNewEnv", "Test creating new environment for child process", TEST_ENABLED
  456. };
  457. static const SDLTest_TestCaseReference processTestStdinToStdout = {
  458. process_testStdinToStdout, "process_testStdinToStdout", "Test writing to stdin and reading from stdout", TEST_ENABLED
  459. };
  460. static const SDLTest_TestCaseReference processTestSimpleStdinToStdout = {
  461. process_testSimpleStdinToStdout, "process_testSimpleStdinToStdout", "Test writing to stdin and reading from stdout using the simplified API", TEST_ENABLED
  462. };
  463. static const SDLTest_TestCaseReference processTestMultiprocessStdinToStdout = {
  464. process_testMultiprocessStdinToStdout, "process_testMultiprocessStdinToStdout", "Test writing to stdin and reading from stdout using the simplified API", TEST_ENABLED
  465. };
  466. static const SDLTest_TestCaseReference *processTests[] = {
  467. &processTestArguments,
  468. &processTestIneritedEnv,
  469. &processTestNewEnv,
  470. &processTestStdinToStdout,
  471. &processTestSimpleStdinToStdout,
  472. &processTestMultiprocessStdinToStdout,
  473. NULL
  474. };
  475. static SDLTest_TestSuiteReference processTestSuite = {
  476. "Process",
  477. setUpProcess,
  478. processTests,
  479. NULL
  480. };
  481. static SDLTest_TestSuiteReference *testSuites[] = {
  482. &processTestSuite,
  483. NULL
  484. };
  485. int main(int argc, char *argv[])
  486. {
  487. int i;
  488. int result;
  489. SDLTest_CommonState *state;
  490. SDLTest_TestSuiteRunner *runner;
  491. /* Initialize test framework */
  492. state = SDLTest_CommonCreateState(argv, 0);
  493. if (!state) {
  494. return 1;
  495. }
  496. runner = SDLTest_CreateTestSuiteRunner(state, testSuites);
  497. /* Enable standard application logging */
  498. SDL_SetLogPriority(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_INFO);
  499. /* Parse commandline */
  500. for (i = 1; i < argc;) {
  501. int consumed;
  502. consumed = SDLTest_CommonArg(state, i);
  503. if (!consumed) {
  504. if (!parsed_args.childprocess_path) {
  505. parsed_args.childprocess_path = argv[i];
  506. consumed = 1;
  507. }
  508. }
  509. if (consumed <= 0) {
  510. SDLTest_CommonLogUsage(state, argv[0], options);
  511. return 1;
  512. }
  513. i += consumed;
  514. }
  515. if (!parsed_args.childprocess_path) {
  516. SDLTest_CommonLogUsage(state, argv[0], options);
  517. return 1;
  518. }
  519. result = SDLTest_ExecuteTestSuiteRunner(runner);
  520. SDL_Quit();
  521. SDLTest_DestroyTestSuiteRunner(runner);
  522. SDLTest_CommonDestroyState(state);
  523. return result;
  524. }