testprocess.c 21 KB

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