summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/testprocess.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testprocess.c')
-rw-r--r--src/contrib/SDL-3.2.20/test/testprocess.c1094
1 files changed, 1094 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testprocess.c b/src/contrib/SDL-3.2.20/test/testprocess.c
new file mode 100644
index 0000000..425b445
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/test/testprocess.c
@@ -0,0 +1,1094 @@
1#include <SDL3/SDL.h>
2#include <SDL3/SDL_main.h>
3#include <SDL3/SDL_test.h>
4
5#ifdef SDL_PLATFORM_WINDOWS
6#define EXE ".exe"
7#else
8#define EXE ""
9#endif
10
11/*
12 * FIXME: Additional tests:
13 * - stdin to stderr
14 */
15
16typedef struct {
17 const char *childprocess_path;
18} TestProcessData;
19
20static TestProcessData parsed_args;
21
22static void SDLCALL setUpProcess(void **arg) {
23 *arg = &parsed_args;
24}
25
26static const char *options[] = {
27 "/path/to/childprocess" EXE,
28 NULL
29};
30
31static char **CreateArguments(int ignore, ...) {
32 va_list ap;
33 size_t count = 1;
34 size_t i;
35 char **result;
36
37 va_start(ap, ignore);
38 for (;;) {
39 const char *keyN = va_arg(ap, const char *);
40 if (!keyN) {
41 break;
42 }
43 count += 1;
44 }
45 va_end(ap);
46
47 result = SDL_calloc(count, sizeof(char *));
48
49 i = 0;
50 va_start(ap, ignore);
51 for (;;) {
52 const char *keyN = va_arg(ap, const char *);
53 if (!keyN) {
54 break;
55 }
56 result[i++] = SDL_strdup(keyN);
57 }
58 va_end(ap);
59
60 return result;
61}
62
63static void DestroyStringArray(char **list) {
64 char **current;
65
66 if (!list) {
67 return;
68 }
69 for (current = list; *current; current++) {
70 SDL_free(*current);
71 }
72 SDL_free(list);
73}
74
75static int SDLCALL process_testArguments(void *arg)
76{
77 TestProcessData *data = (TestProcessData *)arg;
78 const char *process_args[] = {
79 data->childprocess_path,
80 "--print-arguments",
81 "--",
82 "",
83 " ",
84 "a b c",
85 "a\tb\tc\t",
86 "\"a b\" c",
87 "'a' 'b' 'c'",
88 "%d%%%s",
89 "\\t\\c",
90 "evil\\",
91 "a\\b\"c\\",
92 "\"\\^&|<>%", /* characters with a special meaning */
93 NULL
94 };
95 SDL_Process *process = NULL;
96 char *buffer;
97 int exit_code;
98 int i;
99 size_t total_read = 0;
100
101 process = SDL_CreateProcess(process_args, true);
102 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
103 if (!process) {
104 goto failed;
105 }
106
107 exit_code = 0xdeadbeef;
108 buffer = (char *)SDL_ReadProcess(process, &total_read, &exit_code);
109 SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
110 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
111 if (!buffer) {
112 goto failed;
113 }
114 SDLTest_LogEscapedString("stdout of process: ", buffer, total_read);
115
116 for (i = 3; process_args[i]; i++) {
117 char line[64];
118 SDL_snprintf(line, sizeof(line), "|%d=%s|", i - 3, process_args[i]);
119 SDLTest_AssertCheck(!!SDL_strstr(buffer, line), "Check %s is in output", line);
120 }
121 SDL_free(buffer);
122
123 SDLTest_AssertPass("About to destroy process");
124 SDL_DestroyProcess(process);
125 return TEST_COMPLETED;
126failed:
127 SDL_DestroyProcess(process);
128 return TEST_ABORTED;
129}
130
131static int SDLCALL process_testexitCode(void *arg)
132{
133 TestProcessData *data = (TestProcessData *)arg;
134 int i;
135 int exit_codes[] = {
136 0, 13, 31, 127, 255
137 };
138
139 for (i = 0; i < SDL_arraysize(exit_codes); i++) {
140 bool wait_result;
141 SDL_Process *process = NULL;
142 char **process_args = NULL;
143 char number_buffer[8];
144 int exit_code;
145
146 SDL_snprintf(number_buffer, sizeof(number_buffer), "%d", exit_codes[i]);
147
148 process_args = CreateArguments(0, data->childprocess_path, "--exit-code", number_buffer, NULL);
149
150 process = SDL_CreateProcess((const char * const *)process_args, false);
151 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
152 if (!process) {
153 goto failed;
154 }
155
156 exit_code = 0xdeadbeef;
157 SDLTest_AssertPass("About to wait on process (first time)");
158 wait_result = SDL_WaitProcess(process, true, &exit_code);
159 SDLTest_AssertCheck(wait_result == true, "SDL_WaitProcess(): Process should have closed immediately");
160 SDLTest_AssertCheck(exit_code == exit_codes[i], "SDL_WaitProcess(): Exit code should be %d, is %d", exit_codes[i], exit_code);
161
162 exit_code = 0xdeadbeef;
163 SDLTest_AssertPass("About to wait on process (second time)");
164 wait_result = SDL_WaitProcess(process, true, &exit_code);
165 SDLTest_AssertCheck(wait_result == true, "SDL_WaitProcess(): Process should have closed immediately");
166 SDLTest_AssertCheck(exit_code == exit_codes[i], "SDL_WaitProcess(): Exit code should be %d, is %d", exit_codes[i], exit_code);
167
168 SDLTest_AssertPass("About to destroy process");
169 SDL_DestroyProcess(process);
170 DestroyStringArray(process_args);
171 continue;
172failed:
173 SDL_DestroyProcess(process);
174 DestroyStringArray(process_args);
175 return TEST_ABORTED;
176 }
177 return TEST_COMPLETED;
178#if 0
179failed:
180 SDL_DestroyProcess(process);
181 DestroyStringArray(process_args);
182 return TEST_ABORTED;
183#endif
184}
185
186static int SDLCALL process_testInheritedEnv(void *arg)
187{
188 TestProcessData *data = (TestProcessData *)arg;
189 const char *process_args[] = {
190 data->childprocess_path,
191 "--print-environment",
192 NULL,
193 };
194 SDL_PropertiesID props;
195 SDL_Process *process = NULL;
196 Sint64 pid;
197 int exit_code;
198 char random_env1[64];
199 char random_env2[64];
200 static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var";
201 static const char *const TEST_ENV_KEY2 = "testprocess_other_var";
202 char *test_env_val1 = NULL;
203 char *test_env_val2 = NULL;
204 char *buffer = NULL;
205
206 test_env_val1 = SDLTest_RandomAsciiStringOfSize(32);
207 SDL_snprintf(random_env1, sizeof(random_env1), "%s=%s", TEST_ENV_KEY1, test_env_val1);
208 SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY1, test_env_val1);
209 SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY1, test_env_val1, true);
210
211 SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY2);
212
213 props = SDL_CreateProperties();
214 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
215 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
216 process = SDL_CreateProcessWithProperties(props);
217 SDL_DestroyProperties(props);
218 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
219 if (!process) {
220 goto failed;
221 }
222
223 test_env_val2 = SDLTest_RandomAsciiStringOfSize(32);
224 SDL_snprintf(random_env2, sizeof(random_env2), "%s=%s", TEST_ENV_KEY2, test_env_val2);
225 SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY2, test_env_val2);
226 SDL_SetEnvironmentVariable(SDL_GetEnvironment(),TEST_ENV_KEY2, test_env_val2, true);
227 SDLTest_AssertCheck(SDL_strcmp(test_env_val1, test_env_val2) != 0, "Sanity checking the 2 random environment variables are not identical");
228
229 props = SDL_GetProcessProperties(process);
230 SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
231
232 pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
233 SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
234
235 exit_code = 0xdeadbeef;
236 buffer = (char *)SDL_ReadProcess(process, NULL, &exit_code);
237 SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
238 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
239
240 SDLTest_AssertCheck(SDL_strstr(buffer, random_env1) != NULL, "Environment of child should contain \"%s\"", test_env_val1);
241 SDLTest_AssertCheck(SDL_strstr(buffer, random_env2) == NULL, "Environment of child should not contain \"%s\"", test_env_val2);
242
243 SDLTest_AssertPass("About to destroy process");
244 SDL_DestroyProcess(process);
245 SDL_free(test_env_val1);
246 SDL_free(test_env_val2);
247 SDL_free(buffer);
248 return TEST_COMPLETED;
249failed:
250 SDL_free(test_env_val1);
251 SDL_free(test_env_val2);
252 SDL_DestroyProcess(process);
253 SDL_free(buffer);
254 return TEST_ABORTED;
255}
256
257static int SDLCALL process_testNewEnv(void *arg)
258{
259 TestProcessData *data = (TestProcessData *)arg;
260 const char *process_args[] = {
261 data->childprocess_path,
262 "--print-environment",
263 NULL,
264 };
265 SDL_Environment *process_env;
266 SDL_PropertiesID props;
267 SDL_Process *process = NULL;
268 Sint64 pid;
269 int exit_code;
270 char random_env1[64];
271 char random_env2[64];
272 static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var";
273 static const char *const TEST_ENV_KEY2 = "testprocess_other_var";
274 char *test_env_val1 = NULL;
275 char *test_env_val2 = NULL;
276 char *buffer = NULL;
277 size_t total_read = 0;
278
279 test_env_val1 = SDLTest_RandomAsciiStringOfSize(32);
280 SDL_snprintf(random_env1, sizeof(random_env1), "%s=%s", TEST_ENV_KEY1, test_env_val1);
281 SDLTest_AssertPass("Unsetting parent environment variable %s", TEST_ENV_KEY1);
282 SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY1);
283
284 process_env = SDL_CreateEnvironment(true);
285 SDL_SetEnvironmentVariable(process_env, "PATH", SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PATH"), true);
286 SDL_SetEnvironmentVariable(process_env, "LD_LIBRARY_PATH", SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LD_LIBRARY_PATH"), true);
287 SDL_SetEnvironmentVariable(process_env, "DYLD_LIBRARY_PATH", SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "DYLD_LIBRARY_PATH"), true);
288 SDL_SetEnvironmentVariable(process_env, TEST_ENV_KEY1, test_env_val1, true);
289
290 test_env_val2 = SDLTest_RandomAsciiStringOfSize(32);
291 SDL_snprintf(random_env2, sizeof(random_env2), "%s=%s", TEST_ENV_KEY2, test_env_val1);
292 SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY2, test_env_val2);
293 SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY2, test_env_val2, true);
294 SDLTest_AssertCheck(SDL_strcmp(test_env_val1, test_env_val2) != 0, "Sanity checking the 2 random environment variables are not identical");
295
296 props = SDL_CreateProperties();
297 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
298 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, process_env);
299 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
300 process = SDL_CreateProcessWithProperties(props);
301 SDL_DestroyProperties(props);
302 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
303 if (!process) {
304 goto failed;
305 }
306
307 props = SDL_GetProcessProperties(process);
308 SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
309
310 pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
311 SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
312
313 exit_code = 0xdeadbeef;
314 buffer = (char *)SDL_ReadProcess(process, &total_read, &exit_code);
315 SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
316 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
317 SDLTest_LogEscapedString("Text read from subprocess: ", buffer, total_read);
318
319 SDLTest_AssertCheck(SDL_strstr(buffer, random_env1) != NULL, "Environment of child should contain \"%s\"", random_env1);
320 SDLTest_AssertCheck(SDL_strstr(buffer, random_env2) == NULL, "Environment of child should not contain \"%s\"", random_env1);
321
322 SDLTest_AssertPass("About to destroy process");
323 SDL_DestroyProcess(process);
324 SDL_DestroyEnvironment(process_env);
325 SDL_free(test_env_val1);
326 SDL_free(test_env_val2);
327 SDL_free(buffer);
328 return TEST_COMPLETED;
329
330failed:
331 SDL_DestroyProcess(process);
332 SDL_DestroyEnvironment(process_env);
333 SDL_free(test_env_val1);
334 SDL_free(test_env_val2);
335 SDL_free(buffer);
336 return TEST_ABORTED;
337}
338
339static int SDLCALL process_testKill(void *arg)
340{
341 TestProcessData *data = (TestProcessData *)arg;
342 const char *process_args[] = {
343 data->childprocess_path,
344 "--stdin",
345 NULL,
346 };
347 SDL_Process *process = NULL;
348 SDL_PropertiesID props;
349 Sint64 pid;
350 int result;
351 int exit_code;
352
353 SDLTest_AssertPass("About to call SDL_CreateProcess(true)");
354 process = SDL_CreateProcess(process_args, true);
355 if (!process) {
356 goto failed;
357 }
358
359 props = SDL_GetProcessProperties(process);
360 SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
361
362 pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
363 SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
364
365 exit_code = 0xdeadbeef;
366 SDLTest_AssertPass("About to call SDL_WaitProcess(false)");
367 result = SDL_WaitProcess(process, false, &exit_code);
368 SDLTest_AssertCheck(result == false, "Process should not have exited yet");
369
370 SDLTest_AssertPass("About to call SDL_KillProcess(false)");
371 result = SDL_KillProcess(process, false);
372 SDLTest_AssertCheck(result == true, "Process should have exited");
373
374 exit_code = 0;
375 SDLTest_AssertPass("About to call SDL_WaitProcess(true)");
376 result = SDL_WaitProcess(process, true, &exit_code);
377 SDLTest_AssertCheck(result == true, "Process should have exited");
378 SDLTest_AssertCheck(exit_code != 0, "Exit code should be non-zero, is %d", exit_code);
379
380 SDLTest_AssertPass("About to destroy process");
381 SDL_DestroyProcess(process);
382 return TEST_COMPLETED;
383
384failed:
385 SDL_DestroyProcess(process);
386 return TEST_ABORTED;
387}
388
389static int process_testStdinToStdout(void *arg)
390{
391 TestProcessData *data = (TestProcessData *)arg;
392 const char *process_args[] = {
393 data->childprocess_path,
394 "--stdin-to-stdout",
395 NULL,
396 };
397 SDL_PropertiesID props;
398 SDL_Process *process = NULL;
399 Sint64 pid;
400 SDL_IOStream *process_stdin = NULL;
401 SDL_IOStream *process_stdout = NULL;
402 SDL_IOStream *process_stderr = NULL;
403 size_t text_in_size = 1 * 1024 * 1024;
404 char *text_in = NULL;
405 size_t total_written;
406 size_t total_read;
407 bool wait_result;
408 int exit_code;
409 SDL_IOStream *stdout_stream = NULL;
410 char *stdout_stream_buf;
411 int iteration_count = 0;
412
413 text_in = SDLTest_RandomAsciiStringOfSize((int)text_in_size);
414 /* Make sure text_in does not contain EOF */
415 for (;;) {
416 char *e = SDL_strstr(text_in, "EOF");
417 if (!e) {
418 break;
419 }
420 e[0] = 'N';
421 }
422 text_in[text_in_size - 3] = 'E';
423 text_in[text_in_size - 2] = 'O';
424 text_in[text_in_size - 1] = 'F';
425
426 stdout_stream = SDL_IOFromDynamicMem();
427
428 props = SDL_CreateProperties();
429 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
430 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP);
431 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
432 process = SDL_CreateProcessWithProperties(props);
433 SDL_DestroyProperties(props);
434 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
435 if (!process) {
436 goto failed;
437 }
438
439 props = SDL_GetProcessProperties(process);
440 SDLTest_AssertCheck(props != 0, "SDL_GetProcessProperties()");
441
442 pid = SDL_GetNumberProperty(props, SDL_PROP_PROCESS_PID_NUMBER, 0);
443 SDLTest_AssertCheck(pid != 0, "Checking process ID, expected non-zero, got %" SDL_PRIs64, pid);
444
445 process_stdin = SDL_GetProcessInput(process);
446 SDLTest_AssertCheck(process_stdin != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDIN_POINTER) returns a valid IO stream");
447 process_stdout = SDL_GetProcessOutput(process);
448 SDLTest_AssertCheck(process_stdout != NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDOUT_POINTER) returns a valid IO stream");
449 process_stderr = (SDL_IOStream *)SDL_GetPointerProperty(props, SDL_PROP_PROCESS_STDERR_POINTER, NULL);
450 SDLTest_AssertCheck(process_stderr == NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDERR_POINTER) returns NULL");
451 if (!process_stdin || !process_stdout) {
452 goto failed;
453 }
454
455 total_written = 0;
456 total_read = 0;
457 for (;;) {
458 int log_this_iteration = (iteration_count % 32) == 32;
459 char local_buffer[16 * 4094];
460 size_t amount_read;
461 SDL_IOStatus io_status;
462 if (total_written != text_in_size) {
463 size_t amount_written;
464 if (log_this_iteration) {
465 SDLTest_AssertPass("About to SDL_WriteIO (%dth time)", iteration_count);
466 }
467 amount_written = SDL_WriteIO(process_stdin, text_in + total_written, text_in_size - total_written);
468 if (log_this_iteration) {
469 SDLTest_Log("SDL_WriteIO() -> %u (%dth time)", (unsigned)amount_written, iteration_count);
470 }
471 if (amount_written == 0) {
472 io_status = SDL_GetIOStatus(process_stdin);
473 if (io_status != SDL_IO_STATUS_NOT_READY) {
474 SDLTest_Log("SDL_GetIOStatus(process_stdin) returns %d, breaking.", io_status);
475 break;
476 }
477 }
478 total_written += amount_written;
479 SDL_FlushIO(process_stdin);
480 }
481
482 /* FIXME: this needs a rate limit */
483 if (log_this_iteration) {
484 SDLTest_AssertPass("About to SDL_ReadIO (%dth time)", iteration_count);
485 }
486 amount_read = SDL_ReadIO(process_stdout, local_buffer, sizeof(local_buffer));
487 if (log_this_iteration) {
488 SDLTest_Log("SDL_ReadIO() -> %u (%dth time)", (unsigned)amount_read, iteration_count);
489 }
490 if (amount_read == 0) {
491 io_status = SDL_GetIOStatus(process_stdout);
492 if (io_status != SDL_IO_STATUS_NOT_READY) {
493 SDLTest_Log("SDL_GetIOStatus(process_stdout) returned %d, breaking.", io_status);
494 break;
495 }
496 } else {
497 total_read += amount_read;
498 SDL_WriteIO(stdout_stream, local_buffer, amount_read);
499 stdout_stream_buf = SDL_GetPointerProperty(SDL_GetIOProperties(stdout_stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL);
500 if (SDL_strstr(stdout_stream_buf, "EOF")) {
501 SDLTest_Log("Found EOF in stdout");
502 break;
503 }
504 }
505 SDL_Delay(10);
506 }
507 SDLTest_Log("Wrote %" SDL_PRIu64 " bytes to process.stdin", (Uint64)total_written);
508 SDLTest_Log("Read %" SDL_PRIu64 " bytes from process.stdout",(Uint64)total_read);
509
510 stdout_stream_buf = SDL_GetPointerProperty(SDL_GetIOProperties(stdout_stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL);
511 SDLTest_CompareMemory(stdout_stream_buf, total_written, text_in, text_in_size);
512
513 exit_code = 0xdeadbeef;
514 wait_result = SDL_WaitProcess(process, false, &exit_code);
515 SDLTest_AssertCheck(wait_result == false, "Process should not have closed yet");
516
517 SDLTest_AssertPass("About to close stdin");
518 /* Closing stdin of `subprocessstdin --stdin-to-stdout` should close the process */
519 SDL_CloseIO(process_stdin);
520
521 process_stdin = SDL_GetProcessInput(process);
522 SDLTest_AssertCheck(process_stdin == NULL, "SDL_GetPointerProperty(SDL_PROP_PROCESS_STDIN_POINTER) is cleared after close");
523
524 SDLTest_AssertPass("About to wait on process");
525 exit_code = 0xdeadbeef;
526 wait_result = SDL_WaitProcess(process, true, &exit_code);
527 SDLTest_AssertCheck(wait_result == true, "Process should have closed when closing stdin");
528 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
529 if (!wait_result) {
530 bool killed;
531 SDL_Log("About to kill process");
532 killed = SDL_KillProcess(process, true);
533 SDLTest_AssertCheck(killed, "SDL_KillProcess succeeded");
534 }
535 SDLTest_AssertPass("About to destroy process");
536 SDL_DestroyProcess(process);
537 SDL_CloseIO(stdout_stream);
538 SDL_free(text_in);
539 return TEST_COMPLETED;
540failed:
541
542 SDL_DestroyProcess(process);
543 SDL_CloseIO(stdout_stream);
544 SDL_free(text_in);
545 return TEST_ABORTED;
546}
547
548static int process_testStdinToStderr(void *arg)
549{
550 TestProcessData *data = (TestProcessData *)arg;
551 const char *process_args[] = {
552 data->childprocess_path,
553 "--stdin-to-stderr",
554 NULL,
555 };
556 SDL_Process *process = NULL;
557 SDL_IOStream *process_stdin = NULL;
558 SDL_IOStream *process_stdout = NULL;
559 SDL_IOStream *process_stderr = NULL;
560 const char *text_in = "Tests whether we can write to stdin and read from stderr\r\n{'succes': true, 'message': 'Success!'}\r\nYippie ka yee\r\nEOF";
561 size_t result;
562 int exit_code;
563 SDL_PropertiesID props;
564 char buffer[256];
565 size_t amount_read;
566
567 props = SDL_CreateProperties();
568 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
569 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP);
570 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_NULL);
571 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_APP);
572 process = SDL_CreateProcessWithProperties(props);
573 SDL_DestroyProperties(props);
574 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties()");
575 if (!process) {
576 goto failed;
577 }
578
579 SDLTest_AssertPass("About to write to process");
580 process_stdin = SDL_GetProcessInput(process);
581 SDLTest_AssertCheck(process_stdin != NULL, "SDL_GetProcessInput()");
582 result = SDL_WriteIO(process_stdin, text_in, SDL_strlen(text_in));
583 SDLTest_AssertCheck(result == SDL_strlen(text_in), "SDL_WriteIO() wrote %d, expected %d", (int)result, (int)SDL_strlen(text_in));
584 SDL_CloseIO(process_stdin);
585
586 process_stdout = SDL_GetProcessOutput(process);
587 SDLTest_AssertCheck(process_stdout == NULL, "Process has no stdout");
588
589 process_stderr = SDL_GetPointerProperty(SDL_GetProcessProperties(process), SDL_PROP_PROCESS_STDERR_POINTER, NULL);
590 SDLTest_AssertCheck(process_stderr != NULL, "Process has stderr");
591
592 exit_code = 0xdeadbeef;
593 result = SDL_WaitProcess(process, true, &exit_code);
594 SDLTest_AssertCheck(result == true, "Process should have finished");
595 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
596
597 amount_read = SDL_ReadIO(process_stderr, buffer, sizeof(buffer));
598 SDLTest_CompareMemory(buffer, amount_read, text_in, SDL_strlen(text_in));
599
600 SDLTest_AssertPass("About to destroy process");
601 SDL_DestroyProcess(process);
602 return TEST_COMPLETED;
603
604failed:
605 SDL_DestroyProcess(process);
606 return TEST_ABORTED;
607}
608
609static int process_testSimpleStdinToStdout(void *arg)
610{
611 TestProcessData *data = (TestProcessData *)arg;
612 const char *process_args[] = {
613 data->childprocess_path,
614 "--stdin-to-stdout",
615 NULL,
616 };
617 SDL_Process *process = NULL;
618 SDL_IOStream *input = NULL;
619 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";
620 char *buffer;
621 size_t result;
622 int exit_code;
623 size_t total_read = 0;
624
625 process = SDL_CreateProcess(process_args, true);
626 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
627 if (!process) {
628 goto failed;
629 }
630
631 SDLTest_AssertPass("About to write to process");
632 input = SDL_GetProcessInput(process);
633 SDLTest_AssertCheck(input != NULL, "SDL_GetProcessInput()");
634 result = SDL_WriteIO(input, text_in, SDL_strlen(text_in));
635 SDLTest_AssertCheck(result == SDL_strlen(text_in), "SDL_WriteIO() wrote %d, expected %d", (int)result, (int)SDL_strlen(text_in));
636 SDL_CloseIO(input);
637
638 input = SDL_GetProcessInput(process);
639 SDLTest_AssertCheck(input == NULL, "SDL_GetProcessInput() after close");
640
641 exit_code = 0xdeadbeef;
642 buffer = (char *)SDL_ReadProcess(process, &total_read, &exit_code);
643 SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
644 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
645 if (!buffer) {
646 goto failed;
647 }
648
649 SDLTest_LogEscapedString("Expected text read from subprocess: %s", text_in, SDL_strlen(text_in));
650 SDLTest_LogEscapedString("Actual text read from subprocess: %s", buffer, total_read);
651 SDLTest_AssertCheck(total_read == SDL_strlen(text_in), "Expected to read %u bytes, actually read %u bytes", (unsigned)SDL_strlen(text_in), (unsigned)total_read);
652 SDLTest_AssertCheck(SDL_strcmp(buffer, text_in) == 0, "Subprocess stdout should match text written to stdin");
653 SDL_free(buffer);
654
655 SDLTest_AssertPass("About to destroy process");
656 SDL_DestroyProcess(process);
657 return TEST_COMPLETED;
658
659failed:
660 SDL_DestroyProcess(process);
661 return TEST_ABORTED;
662}
663
664static int process_testMultiprocessStdinToStdout(void *arg)
665{
666 TestProcessData *data = (TestProcessData *)arg;
667 const char *process_args[] = {
668 data->childprocess_path,
669 "--stdin-to-stdout",
670 "--log-stdin",
671 NULL,
672 NULL,
673 };
674 SDL_Process *process1 = NULL;
675 SDL_Process *process2 = NULL;
676 SDL_PropertiesID props;
677 SDL_IOStream *input = NULL;
678 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";
679 char *buffer;
680 size_t result;
681 int exit_code;
682 size_t total_read = 0;
683 bool finished;
684
685 process_args[3] = "child1-stdin.txt";
686 process1 = SDL_CreateProcess(process_args, true);
687 SDLTest_AssertCheck(process1 != NULL, "SDL_CreateProcess()");
688 if (!process1) {
689 goto failed;
690 }
691
692 props = SDL_CreateProperties();
693 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
694 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_REDIRECT);
695 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_POINTER, SDL_GetPointerProperty(SDL_GetProcessProperties(process1), SDL_PROP_PROCESS_STDOUT_POINTER, NULL));
696 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
697 SDLTest_AssertPass("About to call SDL_CreateProcessWithProperties");
698 process_args[3] = "child2-stdin.txt";
699 process2 = SDL_CreateProcessWithProperties(props);
700 SDL_DestroyProperties(props);
701 SDLTest_AssertCheck(process2 != NULL, "SDL_CreateProcess()");
702 if (!process2) {
703 goto failed;
704 }
705
706 SDLTest_AssertPass("About to write to process");
707 input = SDL_GetProcessInput(process1);
708 SDLTest_AssertCheck(input != NULL, "SDL_GetProcessInput()");
709 result = SDL_WriteIO(input, text_in, SDL_strlen(text_in));
710 SDLTest_AssertCheck(result == SDL_strlen(text_in), "SDL_WriteIO() wrote %d, expected %d", (int)result, (int)SDL_strlen(text_in));
711 SDL_CloseIO(input);
712
713 exit_code = 0xdeadbeef;
714 finished = SDL_WaitProcess(process1, true, &exit_code);
715 SDLTest_AssertCheck(finished == true, "process 1 should have finished");
716 SDLTest_AssertCheck(exit_code == 0, "Exit code of process 1 should be 0, is %d", exit_code);
717
718 exit_code = 0xdeadbeef;
719 buffer = (char *)SDL_ReadProcess(process2, &total_read, &exit_code);
720 SDLTest_AssertCheck(buffer != NULL, "SDL_ReadProcess()");
721 SDLTest_AssertCheck(exit_code == 0, "Exit code of process 2 should be 0, is %d", exit_code);
722 if (!buffer) {
723 goto failed;
724 }
725
726 SDLTest_LogEscapedString("Expected text read from subprocess: ", text_in, SDL_strlen(text_in));
727 SDLTest_LogEscapedString("Actual text read from subprocess: ", buffer, total_read);
728 SDLTest_AssertCheck(total_read == SDL_strlen(text_in), "Expected to read %u bytes, actually read %u bytes", (unsigned)SDL_strlen(text_in), (unsigned)total_read);
729 SDLTest_AssertCheck(SDL_strcmp(buffer, text_in) == 0, "Subprocess stdout should match text written to stdin");
730 SDL_free(buffer);
731 SDLTest_AssertPass("About to destroy processes");
732 SDL_DestroyProcess(process1);
733 SDL_DestroyProcess(process2);
734 return TEST_COMPLETED;
735
736failed:
737 SDL_DestroyProcess(process1);
738 SDL_DestroyProcess(process2);
739 return TEST_ABORTED;
740}
741
742static int process_testWriteToFinishedProcess(void *arg)
743{
744 TestProcessData *data = (TestProcessData *)arg;
745 const char *process_args[] = {
746 data->childprocess_path,
747 NULL,
748 };
749 SDL_Process *process = NULL;
750 bool result;
751 int exit_code;
752 SDL_IOStream *process_stdin;
753 const char *text_in = "text_in";
754
755 SDLTest_AssertPass("About to call SDL_CreateProcess");
756 process = SDL_CreateProcess(process_args, true);
757 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess()");
758 if (!process) {
759 goto failed;
760 }
761
762 exit_code = 0xdeadbeef;
763 SDLTest_AssertPass("About to call SDL_WaitProcess");
764 result = SDL_WaitProcess(process, true, &exit_code);
765 SDLTest_AssertCheck(result, "SDL_WaitProcess()");
766 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
767
768 process_stdin = SDL_GetProcessInput(process);
769 SDLTest_AssertCheck(process_stdin != NULL, "SDL_GetProcessInput returns non-Null SDL_IOStream");
770 SDLTest_AssertPass("About to call SDL_WriteIO on dead child process");
771 SDL_WriteIO(process_stdin, text_in, SDL_strlen(text_in));
772
773 SDLTest_AssertPass("About to destroy process");
774 SDL_DestroyProcess(process);
775 return TEST_COMPLETED;
776
777failed:
778 SDL_DestroyProcess(process);
779 return TEST_ABORTED;
780}
781
782static int process_testNonExistingExecutable(void *arg)
783{
784 static const int STEM_LENGTH = 16;
785 char **process_args;
786 char *random_stem;
787 char *random_path;
788 SDL_Process *process = NULL;
789
790 random_stem = SDLTest_RandomAsciiStringOfSize(STEM_LENGTH);
791 random_path = SDL_malloc(STEM_LENGTH + SDL_strlen(EXE) + 1);
792 SDL_snprintf(random_path, STEM_LENGTH + SDL_strlen(EXE) + 1, "%s%s", random_stem, EXE);
793 SDL_free(random_stem);
794 SDLTest_AssertCheck(!SDL_GetPathInfo(random_path, NULL), "%s does not exist", random_path);
795
796 process_args = CreateArguments(0, random_path, NULL);
797 SDL_free(random_path);
798
799 SDLTest_AssertPass("About to call SDL_CreateProcess");
800 process = SDL_CreateProcess((const char * const *)process_args, false);
801 SDLTest_AssertCheck(process == NULL, "SDL_CreateProcess() should have failed (%s)", SDL_GetError());
802
803 DestroyStringArray(process_args);
804 return TEST_COMPLETED;
805}
806
807static int process_testBatBadButVulnerability(void *arg)
808{
809 TestProcessData *data = (TestProcessData *)arg;
810 char *inject_arg = NULL;
811 char **process_args = NULL;
812 char *text_out = NULL;
813 size_t len_text_out;
814 int exitcode;
815 SDL_Process *process = NULL;
816 SDL_IOStream *child_bat;
817 char buffer[256];
818
819#ifndef SDL_PLATFORM_WINDOWS
820 SDLTest_AssertPass("The BatBadBut vulnerability only applied to Windows");
821 return TEST_SKIPPED;
822#endif
823 /* FIXME: remove child.bat at end of loop and/or create in temporary directory */
824 child_bat = SDL_IOFromFile("child_batbadbut.bat", "w");
825 SDL_IOprintf(child_bat, "@echo off\necho Hello from child_batbadbut.bat\necho \"|bat1=%%1|\"\n");
826 SDL_CloseIO(child_bat);
827
828 inject_arg = SDL_malloc(SDL_strlen(data->childprocess_path) + 100);
829 SDL_snprintf(inject_arg, SDL_strlen(data->childprocess_path) + 100, "\"&%s --version --print-arguments --stdout OWNEDSTDOUT\"", data->childprocess_path);
830 process_args = CreateArguments(0, "child_batbadbut.bat", inject_arg, NULL);
831
832 SDLTest_AssertPass("About to call SDL_CreateProcess");
833 process = SDL_CreateProcess((const char * const*)process_args, true);
834 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcess");
835 if (!process) {
836 goto cleanup;
837 }
838 text_out = SDL_ReadProcess(process, &len_text_out, &exitcode);
839 SDLTest_AssertCheck(exitcode == 0, "process exited with exitcode 0, was %d", exitcode);
840 SDLTest_AssertCheck(text_out != NULL, "SDL_ReadProcess returned data");
841 SDLTest_LogEscapedString("Output: ", text_out, len_text_out);
842 if (!text_out) {
843 goto cleanup;
844 }
845
846 SDLTest_AssertCheck(SDL_strstr(text_out, "Hello from child_batbadbut") != NULL, "stdout contains 'Hello from child'");
847 SDLTest_AssertCheck(SDL_strstr(text_out, "SDL version") == NULL, "stdout should not contain SDL version");
848 SDL_snprintf(buffer, sizeof(buffer), "|bat1=\"\"\"&%s\"\"|", process_args[1] + 2);
849 SDLTest_LogEscapedString("stdout should contain: ", buffer, SDL_strlen(buffer));
850 SDLTest_AssertCheck(SDL_strstr(text_out, buffer) != NULL, "Verify first argument");
851
852cleanup:
853 SDL_free(text_out);
854 SDL_DestroyProcess(process);
855 SDL_free(inject_arg);
856 DestroyStringArray(process_args);
857 return TEST_COMPLETED;
858}
859
860static int process_testFileRedirection(void *arg)
861{
862 TestProcessData *data = (TestProcessData *)arg;
863 SDL_PropertiesID props = 0;
864 const char * process_args[] = {
865 data->childprocess_path,
866 "--stdin-to-stdout",
867 "--stdin-to-stderr",
868 NULL,
869 };
870 const char TEXT_REF[] = "This is input for the child process";
871 static const char *PATH_STDIN = "test_redirection_stdin.txt";
872 static const char *PATH_STDOUT = "test_redirection_stdout.txt";
873 static const char *PATH_STDERR = "test_redirection_stderr.txt";
874 char *text_out = NULL;
875 size_t len_text_out;
876 int exitcode;
877 bool result;
878 SDL_Process *process = NULL;
879 SDL_IOStream *stream;
880 SDL_IOStream *input_stream = NULL;
881 SDL_IOStream *output_stream = NULL;
882 SDL_IOStream *error_stream = NULL;
883
884 stream = SDL_IOFromFile(PATH_STDIN, "w");
885 SDLTest_AssertCheck(stream != NULL, "SDL_IOFromFile(\"%s\", \"w\")", PATH_STDIN);
886 if (!stream) {
887 goto cleanup;
888 }
889 SDL_WriteIO(stream, TEXT_REF, sizeof(TEXT_REF));
890 SDL_CloseIO(stream);
891
892 input_stream = SDL_IOFromFile(PATH_STDIN, "r");
893 SDLTest_AssertCheck(input_stream != NULL, "SDL_IOFromFile(\"%s\", \"r\")", PATH_STDIN);
894 if (!input_stream) {
895 goto cleanup;
896 }
897
898 output_stream = SDL_IOFromFile(PATH_STDOUT, "w");
899 SDLTest_AssertCheck(output_stream != NULL, "SDL_IOFromFile(\"%s\", \"w\")", PATH_STDOUT);
900 if (!output_stream) {
901 goto cleanup;
902 }
903
904 error_stream = SDL_IOFromFile(PATH_STDERR, "w");
905 SDLTest_AssertCheck(error_stream != NULL, "SDL_IOFromFile(\"%s\", \"w\")", PATH_STDERR);
906 if (!error_stream) {
907 goto cleanup;
908 }
909
910 props = SDL_CreateProperties();
911 SDLTest_AssertCheck(props != 0, "SDL_CreateProperties()");
912 if (!props) {
913 goto cleanup;
914 }
915 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
916 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_REDIRECT);
917 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_POINTER, (void *)input_stream);
918 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_REDIRECT);
919 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_POINTER, (void *)output_stream);
920 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_REDIRECT);
921 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_POINTER, (void *)error_stream);
922 process = SDL_CreateProcessWithProperties(props);
923 SDL_DestroyProperties(props);
924 SDLTest_AssertCheck(process != NULL, "SDL_CreateProcessWithProperties (%s)", SDL_GetError());
925 if (!process) {
926 goto cleanup;
927 }
928
929 exitcode = 0xdeadbeef;
930 text_out = SDL_ReadProcess(process, &len_text_out, &exitcode);
931 SDLTest_AssertCheck(text_out == NULL, "SDL_ReadProcess should not be able to close a redirected process (%s)", SDL_GetError());
932 SDLTest_AssertCheck(len_text_out == 0, "length written by SDL_ReadProcess should be 0");
933 SDL_free(text_out);
934 text_out = NULL;
935
936 exitcode = 0xdeadbeef;
937 result = SDL_WaitProcess(process, true, &exitcode);
938 SDLTest_AssertCheck(result, "process must have exited");
939 SDLTest_AssertCheck(exitcode == 0, "process exited with exitcode 0, was %d", exitcode);
940
941 SDL_CloseIO(input_stream);
942 input_stream = NULL;
943 SDL_CloseIO(output_stream);
944 output_stream = NULL;
945 SDL_CloseIO(error_stream);
946 error_stream = NULL;
947
948 text_out = SDL_LoadFile(PATH_STDOUT, &len_text_out);
949 SDLTest_AssertCheck(text_out != NULL, "SDL_LoadFile(\"%s\") succeeded (%s)", PATH_STDOUT, SDL_GetError());
950 SDLTest_AssertPass("Comparing stdout with reference");
951 SDLTest_CompareMemory(text_out, len_text_out, TEXT_REF, sizeof(TEXT_REF));
952 SDL_free(text_out);
953
954 text_out = SDL_LoadFile(PATH_STDERR, &len_text_out);
955 SDLTest_AssertCheck(text_out != NULL, "SDL_LoadFile(\"%s\") succeeded (%s)", PATH_STDERR, SDL_GetError());
956 SDLTest_AssertPass("Comparing stderr with reference");
957 SDLTest_CompareMemory(text_out, len_text_out, TEXT_REF, sizeof(TEXT_REF));
958 SDL_free(text_out);
959
960cleanup:
961 SDL_CloseIO(input_stream);
962 SDL_CloseIO(output_stream);
963 SDL_CloseIO(error_stream);
964 SDL_DestroyProcess(process);
965 return TEST_COMPLETED;
966}
967
968static const SDLTest_TestCaseReference processTestArguments = {
969 process_testArguments, "process_testArguments", "Test passing arguments to child process", TEST_ENABLED
970};
971
972static const SDLTest_TestCaseReference processTestExitCode = {
973 process_testexitCode, "process_testExitCode", "Test exit codes", TEST_ENABLED
974};
975
976static const SDLTest_TestCaseReference processTestInheritedEnv = {
977 process_testInheritedEnv, "process_testInheritedEnv", "Test inheriting environment from parent process", TEST_ENABLED
978};
979
980static const SDLTest_TestCaseReference processTestNewEnv = {
981 process_testNewEnv, "process_testNewEnv", "Test creating new environment for child process", TEST_ENABLED
982};
983
984static const SDLTest_TestCaseReference processTestKill = {
985 process_testKill, "process_testKill", "Test Killing a child process", TEST_ENABLED
986};
987
988static const SDLTest_TestCaseReference processTestStdinToStdout = {
989 process_testStdinToStdout, "process_testStdinToStdout", "Test writing to stdin and reading from stdout", TEST_ENABLED
990};
991
992static const SDLTest_TestCaseReference processTestStdinToStderr = {
993 process_testStdinToStderr, "process_testStdinToStderr", "Test writing to stdin and reading from stderr", TEST_ENABLED
994};
995
996static const SDLTest_TestCaseReference processTestSimpleStdinToStdout = {
997 process_testSimpleStdinToStdout, "process_testSimpleStdinToStdout", "Test writing to stdin and reading from stdout using the simplified API", TEST_ENABLED
998};
999
1000static const SDLTest_TestCaseReference processTestMultiprocessStdinToStdout = {
1001 process_testMultiprocessStdinToStdout, "process_testMultiprocessStdinToStdout", "Test writing to stdin and reading from stdout using the simplified API", TEST_ENABLED
1002};
1003
1004static const SDLTest_TestCaseReference processTestWriteToFinishedProcess = {
1005 process_testWriteToFinishedProcess, "process_testWriteToFinishedProcess", "Test writing to stdin of terminated process", TEST_ENABLED
1006};
1007
1008static const SDLTest_TestCaseReference processTestNonExistingExecutable = {
1009 process_testNonExistingExecutable, "process_testNonExistingExecutable", "Test running a non-existing executable", TEST_ENABLED
1010};
1011
1012static const SDLTest_TestCaseReference processTestBatBadButVulnerability = {
1013 process_testBatBadButVulnerability, "process_testBatBadButVulnerability", "Test BatBadBut vulnerability: command injection through cmd.exe", TEST_ENABLED
1014};
1015
1016static const SDLTest_TestCaseReference processTestFileRedirection = {
1017 process_testFileRedirection, "process_testFileRedirection", "Test redirection from/to files", TEST_ENABLED
1018};
1019
1020static const SDLTest_TestCaseReference *processTests[] = {
1021 &processTestArguments,
1022 &processTestExitCode,
1023 &processTestInheritedEnv,
1024 &processTestNewEnv,
1025 &processTestKill,
1026 &processTestStdinToStdout,
1027 &processTestStdinToStderr,
1028 &processTestSimpleStdinToStdout,
1029 &processTestMultiprocessStdinToStdout,
1030 &processTestWriteToFinishedProcess,
1031 &processTestNonExistingExecutable,
1032 &processTestBatBadButVulnerability,
1033 &processTestFileRedirection,
1034 NULL
1035};
1036
1037static SDLTest_TestSuiteReference processTestSuite = {
1038 "Process",
1039 setUpProcess,
1040 processTests,
1041 NULL
1042};
1043
1044static SDLTest_TestSuiteReference *testSuites[] = {
1045 &processTestSuite,
1046 NULL
1047};
1048
1049int main(int argc, char *argv[])
1050{
1051 int i;
1052 int result;
1053 SDLTest_CommonState *state;
1054 SDLTest_TestSuiteRunner *runner;
1055
1056 /* Initialize test framework */
1057 state = SDLTest_CommonCreateState(argv, 0);
1058 if (!state) {
1059 return 1;
1060 }
1061
1062 runner = SDLTest_CreateTestSuiteRunner(state, testSuites);
1063
1064 /* Parse commandline */
1065 for (i = 1; i < argc;) {
1066 int consumed;
1067
1068 consumed = SDLTest_CommonArg(state, i);
1069 if (!consumed) {
1070 if (!parsed_args.childprocess_path) {
1071 parsed_args.childprocess_path = argv[i];
1072 consumed = 1;
1073 }
1074 }
1075 if (consumed <= 0) {
1076 SDLTest_CommonLogUsage(state, argv[0], options);
1077 return 1;
1078 }
1079
1080 i += consumed;
1081 }
1082
1083 if (!parsed_args.childprocess_path) {
1084 SDLTest_CommonLogUsage(state, argv[0], options);
1085 return 1;
1086 }
1087
1088 result = SDLTest_ExecuteTestSuiteRunner(runner);
1089
1090 SDL_Quit();
1091 SDLTest_DestroyTestSuiteRunner(runner);
1092 SDLTest_CommonDestroyState(state);
1093 return result;
1094}