Line data Source code
1 : /* Copyright (c) 2018-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : /**
5 : * \file test_process.c
6 : * \brief Test cases for the Process API.
7 : */
8 :
9 : #include "orconfig.h"
10 : #include "core/or/or.h"
11 : #include "test/test.h"
12 : #include "lib/process/env.h"
13 :
14 : #define PROCESS_PRIVATE
15 : #include "lib/process/process.h"
16 : #define PROCESS_UNIX_PRIVATE
17 : #include "lib/process/process_unix.h"
18 : #define PROCESS_WIN32_PRIVATE
19 : #include "lib/process/process_win32.h"
20 :
21 : static const char *stdout_read_buffer;
22 : static const char *stderr_read_buffer;
23 :
24 : struct process_data_t {
25 : smartlist_t *stdout_data;
26 : smartlist_t *stderr_data;
27 : smartlist_t *stdin_data;
28 : process_exit_code_t exit_code;
29 : };
30 :
31 : typedef struct process_data_t process_data_t;
32 :
33 : static process_data_t *
34 6 : process_data_new(void)
35 : {
36 6 : process_data_t *process_data = tor_malloc_zero(sizeof(process_data_t));
37 6 : process_data->stdout_data = smartlist_new();
38 6 : process_data->stderr_data = smartlist_new();
39 6 : process_data->stdin_data = smartlist_new();
40 6 : return process_data;
41 : }
42 :
43 : static void
44 6 : process_data_free(process_data_t *process_data)
45 : {
46 6 : if (process_data == NULL)
47 : return;
48 :
49 16 : SMARTLIST_FOREACH(process_data->stdout_data, char *, x, tor_free(x));
50 15 : SMARTLIST_FOREACH(process_data->stderr_data, char *, x, tor_free(x));
51 8 : SMARTLIST_FOREACH(process_data->stdin_data, char *, x, tor_free(x));
52 :
53 6 : smartlist_free(process_data->stdout_data);
54 6 : smartlist_free(process_data->stderr_data);
55 6 : smartlist_free(process_data->stdin_data);
56 6 : tor_free(process_data);
57 : }
58 :
59 : static int
60 7 : process_mocked_read_stdout(process_t *process, buf_t *buffer)
61 : {
62 7 : (void)process;
63 :
64 7 : if (stdout_read_buffer != NULL) {
65 7 : buf_add_string(buffer, stdout_read_buffer);
66 7 : stdout_read_buffer = NULL;
67 : }
68 :
69 7 : return (int)buf_datalen(buffer);
70 : }
71 :
72 : static int
73 7 : process_mocked_read_stderr(process_t *process, buf_t *buffer)
74 : {
75 7 : (void)process;
76 :
77 7 : if (stderr_read_buffer != NULL) {
78 7 : buf_add_string(buffer, stderr_read_buffer);
79 7 : stderr_read_buffer = NULL;
80 : }
81 :
82 7 : return (int)buf_datalen(buffer);
83 : }
84 :
85 : static void
86 4 : process_mocked_write_stdin(process_t *process, buf_t *buffer)
87 : {
88 4 : const size_t size = buf_datalen(buffer);
89 :
90 4 : if (size == 0)
91 : return;
92 :
93 2 : char *data = tor_malloc_zero(size + 1);
94 2 : process_data_t *process_data = process_get_data(process);
95 :
96 2 : buf_get_bytes(buffer, data, size);
97 2 : smartlist_add(process_data->stdin_data, data);
98 : }
99 :
100 : static void
101 10 : process_stdout_callback(process_t *process, const char *data, size_t size)
102 : {
103 10 : tt_ptr_op(process, OP_NE, NULL);
104 10 : tt_ptr_op(data, OP_NE, NULL);
105 10 : tt_int_op(strlen(data), OP_EQ, size);
106 :
107 10 : process_data_t *process_data = process_get_data(process);
108 10 : smartlist_add(process_data->stdout_data, tor_strdup(data));
109 :
110 10 : done:
111 10 : return;
112 : }
113 :
114 : static void
115 9 : process_stderr_callback(process_t *process, const char *data, size_t size)
116 : {
117 9 : tt_ptr_op(process, OP_NE, NULL);
118 9 : tt_ptr_op(data, OP_NE, NULL);
119 9 : tt_int_op(strlen(data), OP_EQ, size);
120 :
121 9 : process_data_t *process_data = process_get_data(process);
122 9 : smartlist_add(process_data->stderr_data, tor_strdup(data));
123 :
124 9 : done:
125 9 : return;
126 : }
127 :
128 : static bool
129 1 : process_exit_callback(process_t *process, process_exit_code_t exit_code)
130 : {
131 1 : tt_ptr_op(process, OP_NE, NULL);
132 :
133 1 : process_data_t *process_data = process_get_data(process);
134 1 : process_data->exit_code = exit_code;
135 :
136 1 : done:
137 : /* Do not free up our process_t. */
138 1 : return false;
139 : }
140 :
141 : static void
142 1 : test_default_values(void *arg)
143 : {
144 1 : (void)arg;
145 1 : process_t *process = process_new("/path/to/nothing");
146 :
147 : /* We are not running by default. */
148 1 : tt_int_op(PROCESS_STATUS_NOT_RUNNING, OP_EQ, process_get_status(process));
149 :
150 : /* We use the line protocol by default. */
151 1 : tt_int_op(PROCESS_PROTOCOL_LINE, OP_EQ, process_get_protocol(process));
152 :
153 : /* We don't set any custom data by default. */
154 1 : tt_ptr_op(NULL, OP_EQ, process_get_data(process));
155 :
156 : /* Our command was given to the process_t's constructor in process_new(). */
157 1 : tt_str_op("/path/to/nothing", OP_EQ, process_get_command(process));
158 :
159 : /* Make sure we are listed in the list of processes. */
160 1 : tt_assert(smartlist_contains(process_get_all_processes(),
161 : process));
162 :
163 : /* Default PID is 0. */
164 1 : tt_u64_op(0, OP_EQ, process_get_pid(process));
165 :
166 : /* Our arguments should be empty. */
167 1 : tt_int_op(0, OP_EQ,
168 : smartlist_len(process_get_arguments(process)));
169 :
170 1 : done:
171 1 : process_free(process);
172 1 : }
173 :
174 : static void
175 1 : test_environment(void *arg)
176 : {
177 1 : (void)arg;
178 :
179 1 : process_t *process = process_new("");
180 1 : process_environment_t *env = NULL;
181 :
182 1 : process_set_environment(process, "E", "F");
183 1 : process_set_environment(process, "C", "D");
184 1 : process_set_environment(process, "A", "B");
185 :
186 1 : env = process_get_environment(process);
187 1 : tt_mem_op(env->windows_environment_block, OP_EQ,
188 1 : "A=B\0C=D\0E=F\0", 12);
189 1 : tt_str_op(env->unixoid_environment_block[0], OP_EQ,
190 : "A=B");
191 1 : tt_str_op(env->unixoid_environment_block[1], OP_EQ,
192 : "C=D");
193 1 : tt_str_op(env->unixoid_environment_block[2], OP_EQ,
194 : "E=F");
195 1 : tt_ptr_op(env->unixoid_environment_block[3], OP_EQ,
196 : NULL);
197 1 : process_environment_free(env);
198 :
199 : /* Reset our environment. */
200 1 : smartlist_t *new_env = smartlist_new();
201 1 : smartlist_add(new_env, (char *)"FOO=bar");
202 1 : smartlist_add(new_env, (char *)"HELLO=world");
203 :
204 1 : process_reset_environment(process, new_env);
205 1 : smartlist_free(new_env);
206 :
207 1 : env = process_get_environment(process);
208 1 : tt_mem_op(env->windows_environment_block, OP_EQ,
209 1 : "FOO=bar\0HELLO=world\0", 20);
210 1 : tt_str_op(env->unixoid_environment_block[0], OP_EQ,
211 : "FOO=bar");
212 1 : tt_str_op(env->unixoid_environment_block[1], OP_EQ,
213 : "HELLO=world");
214 1 : tt_ptr_op(env->unixoid_environment_block[2], OP_EQ,
215 : NULL);
216 :
217 1 : done:
218 1 : process_environment_free(env);
219 1 : process_free(process);
220 1 : }
221 :
222 : static void
223 1 : test_stringified_types(void *arg)
224 : {
225 1 : (void)arg;
226 :
227 : /* process_protocol_t values. */
228 1 : tt_str_op("Raw", OP_EQ, process_protocol_to_string(PROCESS_PROTOCOL_RAW));
229 1 : tt_str_op("Line", OP_EQ, process_protocol_to_string(PROCESS_PROTOCOL_LINE));
230 :
231 : /* process_status_t values. */
232 1 : tt_str_op("not running", OP_EQ,
233 : process_status_to_string(PROCESS_STATUS_NOT_RUNNING));
234 1 : tt_str_op("running", OP_EQ,
235 : process_status_to_string(PROCESS_STATUS_RUNNING));
236 1 : tt_str_op("error", OP_EQ,
237 : process_status_to_string(PROCESS_STATUS_ERROR));
238 :
239 1 : done:
240 1 : return;
241 : }
242 :
243 : static void
244 1 : test_line_protocol_simple(void *arg)
245 : {
246 1 : (void)arg;
247 :
248 1 : process_data_t *process_data = process_data_new();
249 :
250 1 : process_t *process = process_new("");
251 1 : process_set_data(process, process_data);
252 :
253 1 : process_set_stdout_read_callback(process, process_stdout_callback);
254 1 : process_set_stderr_read_callback(process, process_stderr_callback);
255 :
256 1 : MOCK(process_read_stdout, process_mocked_read_stdout);
257 1 : MOCK(process_read_stderr, process_mocked_read_stderr);
258 :
259 : /* Make sure we are running with the line protocol. */
260 1 : tt_int_op(PROCESS_PROTOCOL_LINE, OP_EQ, process_get_protocol(process));
261 :
262 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stdout_data));
263 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stderr_data));
264 :
265 1 : stdout_read_buffer = "Hello stdout\n";
266 1 : process_notify_event_stdout(process);
267 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
268 :
269 1 : stderr_read_buffer = "Hello stderr\r\n";
270 1 : process_notify_event_stderr(process);
271 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
272 :
273 : /* Data should be ready. */
274 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stdout_data));
275 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stderr_data));
276 :
277 : /* Check if the data is correct. */
278 1 : tt_str_op(smartlist_get(process_data->stdout_data, 0), OP_EQ,
279 : "Hello stdout");
280 1 : tt_str_op(smartlist_get(process_data->stderr_data, 0), OP_EQ,
281 : "Hello stderr");
282 :
283 1 : done:
284 1 : process_data_free(process_data);
285 1 : process_free(process);
286 :
287 1 : UNMOCK(process_read_stdout);
288 1 : UNMOCK(process_read_stderr);
289 1 : }
290 :
291 : static void
292 1 : test_line_protocol_multi(void *arg)
293 : {
294 1 : (void)arg;
295 :
296 1 : process_data_t *process_data = process_data_new();
297 :
298 1 : process_t *process = process_new("");
299 1 : process_set_data(process, process_data);
300 1 : process_set_stdout_read_callback(process, process_stdout_callback);
301 1 : process_set_stderr_read_callback(process, process_stderr_callback);
302 :
303 1 : MOCK(process_read_stdout, process_mocked_read_stdout);
304 1 : MOCK(process_read_stderr, process_mocked_read_stderr);
305 :
306 : /* Make sure we are running with the line protocol. */
307 1 : tt_int_op(PROCESS_PROTOCOL_LINE, OP_EQ, process_get_protocol(process));
308 :
309 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stdout_data));
310 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stderr_data));
311 :
312 1 : stdout_read_buffer = "Hello stdout\r\nOnion Onion Onion\nA B C D\r\n\r\n";
313 1 : process_notify_event_stdout(process);
314 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
315 :
316 1 : stderr_read_buffer = "Hello stderr\nFoo bar baz\nOnion Onion Onion\n";
317 1 : process_notify_event_stderr(process);
318 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
319 :
320 : /* Data should be ready. */
321 1 : tt_int_op(4, OP_EQ, smartlist_len(process_data->stdout_data));
322 1 : tt_int_op(3, OP_EQ, smartlist_len(process_data->stderr_data));
323 :
324 : /* Check if the data is correct. */
325 1 : tt_str_op(smartlist_get(process_data->stdout_data, 0), OP_EQ,
326 : "Hello stdout");
327 1 : tt_str_op(smartlist_get(process_data->stdout_data, 1), OP_EQ,
328 : "Onion Onion Onion");
329 1 : tt_str_op(smartlist_get(process_data->stdout_data, 2), OP_EQ,
330 : "A B C D");
331 1 : tt_str_op(smartlist_get(process_data->stdout_data, 3), OP_EQ,
332 : "");
333 :
334 1 : tt_str_op(smartlist_get(process_data->stderr_data, 0), OP_EQ,
335 : "Hello stderr");
336 1 : tt_str_op(smartlist_get(process_data->stderr_data, 1), OP_EQ,
337 : "Foo bar baz");
338 1 : tt_str_op(smartlist_get(process_data->stderr_data, 2), OP_EQ,
339 : "Onion Onion Onion");
340 :
341 1 : done:
342 1 : process_data_free(process_data);
343 1 : process_free(process);
344 :
345 1 : UNMOCK(process_read_stdout);
346 1 : UNMOCK(process_read_stderr);
347 1 : }
348 :
349 : static void
350 1 : test_line_protocol_partial(void *arg)
351 : {
352 1 : (void)arg;
353 :
354 1 : process_data_t *process_data = process_data_new();
355 :
356 1 : process_t *process = process_new("");
357 1 : process_set_data(process, process_data);
358 1 : process_set_stdout_read_callback(process, process_stdout_callback);
359 1 : process_set_stderr_read_callback(process, process_stderr_callback);
360 :
361 1 : MOCK(process_read_stdout, process_mocked_read_stdout);
362 1 : MOCK(process_read_stderr, process_mocked_read_stderr);
363 :
364 : /* Make sure we are running with the line protocol. */
365 1 : tt_int_op(PROCESS_PROTOCOL_LINE, OP_EQ, process_get_protocol(process));
366 :
367 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stdout_data));
368 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stderr_data));
369 :
370 1 : stdout_read_buffer = "Hello stdout this is a partial line ...";
371 1 : process_notify_event_stdout(process);
372 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
373 :
374 1 : stderr_read_buffer = "Hello stderr this is a partial line ...";
375 1 : process_notify_event_stderr(process);
376 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
377 :
378 : /* Data should NOT be ready. */
379 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stdout_data));
380 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stderr_data));
381 :
382 1 : stdout_read_buffer = " the end\nAnother partial string goes here ...";
383 1 : process_notify_event_stdout(process);
384 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
385 :
386 1 : stderr_read_buffer = " the end\nAnother partial string goes here ...";
387 1 : process_notify_event_stderr(process);
388 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
389 :
390 : /* Some data should be ready. */
391 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stdout_data));
392 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stderr_data));
393 :
394 1 : stdout_read_buffer = " the end\nFoo bar baz\n";
395 1 : process_notify_event_stdout(process);
396 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
397 :
398 1 : stderr_read_buffer = " the end\nFoo bar baz\n";
399 1 : process_notify_event_stderr(process);
400 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
401 :
402 : /* Some data should be ready. */
403 1 : tt_int_op(3, OP_EQ, smartlist_len(process_data->stdout_data));
404 1 : tt_int_op(3, OP_EQ, smartlist_len(process_data->stderr_data));
405 :
406 : /* Check if the data is correct. */
407 1 : tt_str_op(smartlist_get(process_data->stdout_data, 0), OP_EQ,
408 : "Hello stdout this is a partial line ... the end");
409 1 : tt_str_op(smartlist_get(process_data->stdout_data, 1), OP_EQ,
410 : "Another partial string goes here ... the end");
411 1 : tt_str_op(smartlist_get(process_data->stdout_data, 2), OP_EQ,
412 : "Foo bar baz");
413 :
414 1 : tt_str_op(smartlist_get(process_data->stderr_data, 0), OP_EQ,
415 : "Hello stderr this is a partial line ... the end");
416 1 : tt_str_op(smartlist_get(process_data->stderr_data, 1), OP_EQ,
417 : "Another partial string goes here ... the end");
418 1 : tt_str_op(smartlist_get(process_data->stderr_data, 2), OP_EQ,
419 : "Foo bar baz");
420 :
421 1 : done:
422 1 : process_data_free(process_data);
423 1 : process_free(process);
424 :
425 1 : UNMOCK(process_read_stdout);
426 1 : UNMOCK(process_read_stderr);
427 1 : }
428 :
429 : static void
430 1 : test_raw_protocol_simple(void *arg)
431 : {
432 1 : (void)arg;
433 :
434 1 : process_data_t *process_data = process_data_new();
435 :
436 1 : process_t *process = process_new("");
437 1 : process_set_data(process, process_data);
438 1 : process_set_protocol(process, PROCESS_PROTOCOL_RAW);
439 :
440 1 : process_set_stdout_read_callback(process, process_stdout_callback);
441 1 : process_set_stderr_read_callback(process, process_stderr_callback);
442 :
443 1 : MOCK(process_read_stdout, process_mocked_read_stdout);
444 1 : MOCK(process_read_stderr, process_mocked_read_stderr);
445 :
446 : /* Make sure we are running with the raw protocol. */
447 1 : tt_int_op(PROCESS_PROTOCOL_RAW, OP_EQ, process_get_protocol(process));
448 :
449 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stdout_data));
450 1 : tt_int_op(0, OP_EQ, smartlist_len(process_data->stderr_data));
451 :
452 1 : stdout_read_buffer = "Hello stdout\n";
453 1 : process_notify_event_stdout(process);
454 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
455 :
456 1 : stderr_read_buffer = "Hello stderr\n";
457 1 : process_notify_event_stderr(process);
458 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
459 :
460 : /* Data should be ready. */
461 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stdout_data));
462 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stderr_data));
463 :
464 1 : stdout_read_buffer = "Hello, again, stdout\nThis contains multiple lines";
465 1 : process_notify_event_stdout(process);
466 1 : tt_ptr_op(NULL, OP_EQ, stdout_read_buffer);
467 :
468 1 : stderr_read_buffer = "Hello, again, stderr\nThis contains multiple lines";
469 1 : process_notify_event_stderr(process);
470 1 : tt_ptr_op(NULL, OP_EQ, stderr_read_buffer);
471 :
472 : /* Data should be ready. */
473 1 : tt_int_op(2, OP_EQ, smartlist_len(process_data->stdout_data));
474 1 : tt_int_op(2, OP_EQ, smartlist_len(process_data->stderr_data));
475 :
476 : /* Check if the data is correct. */
477 1 : tt_str_op(smartlist_get(process_data->stdout_data, 0), OP_EQ,
478 : "Hello stdout\n");
479 1 : tt_str_op(smartlist_get(process_data->stdout_data, 1), OP_EQ,
480 : "Hello, again, stdout\nThis contains multiple lines");
481 :
482 1 : tt_str_op(smartlist_get(process_data->stderr_data, 0), OP_EQ,
483 : "Hello stderr\n");
484 1 : tt_str_op(smartlist_get(process_data->stderr_data, 1), OP_EQ,
485 : "Hello, again, stderr\nThis contains multiple lines");
486 :
487 1 : done:
488 1 : process_data_free(process_data);
489 1 : process_free(process);
490 :
491 1 : UNMOCK(process_read_stdout);
492 1 : UNMOCK(process_read_stderr);
493 1 : }
494 :
495 : static void
496 1 : test_write_simple(void *arg)
497 : {
498 1 : (void)arg;
499 :
500 1 : process_data_t *process_data = process_data_new();
501 :
502 1 : process_t *process = process_new("");
503 1 : process_set_data(process, process_data);
504 :
505 1 : MOCK(process_write_stdin, process_mocked_write_stdin);
506 :
507 1 : process_write(process, (uint8_t *)"Hello world\n", 12);
508 1 : process_notify_event_stdin(process);
509 1 : tt_int_op(1, OP_EQ, smartlist_len(process_data->stdin_data));
510 :
511 1 : process_printf(process, "Hello %s !\n", "moon");
512 1 : process_notify_event_stdin(process);
513 1 : tt_int_op(2, OP_EQ, smartlist_len(process_data->stdin_data));
514 :
515 1 : done:
516 1 : process_data_free(process_data);
517 1 : process_free(process);
518 :
519 1 : UNMOCK(process_write_stdin);
520 1 : }
521 :
522 : static void
523 1 : test_exit_simple(void *arg)
524 : {
525 1 : (void)arg;
526 :
527 1 : process_data_t *process_data = process_data_new();
528 :
529 1 : process_t *process = process_new("");
530 1 : process_set_data(process, process_data);
531 1 : process_set_exit_callback(process, process_exit_callback);
532 :
533 : /* Our default is 0. */
534 1 : tt_u64_op(0, OP_EQ, process_data->exit_code);
535 :
536 : /* Fake that we are a running process. */
537 1 : process_set_status(process, PROCESS_STATUS_RUNNING);
538 1 : tt_int_op(process_get_status(process), OP_EQ, PROCESS_STATUS_RUNNING);
539 :
540 : /* Fake an exit. */
541 1 : process_notify_event_exit(process, 1337);
542 :
543 : /* Check if our state changed and if our callback fired. */
544 1 : tt_int_op(process_get_status(process), OP_EQ, PROCESS_STATUS_NOT_RUNNING);
545 1 : tt_u64_op(1337, OP_EQ, process_data->exit_code);
546 :
547 1 : done:
548 1 : process_set_data(process, process_data);
549 1 : process_data_free(process_data);
550 1 : process_free(process);
551 1 : }
552 :
553 : static void
554 1 : test_argv_simple(void *arg)
555 : {
556 1 : (void)arg;
557 :
558 1 : process_t *process = process_new("/bin/cat");
559 1 : char **argv = NULL;
560 :
561 : /* Setup some arguments. */
562 1 : process_append_argument(process, "foo");
563 1 : process_append_argument(process, "bar");
564 1 : process_append_argument(process, "baz");
565 :
566 : /* Check the number of elements. */
567 1 : tt_int_op(3, OP_EQ,
568 : smartlist_len(process_get_arguments(process)));
569 :
570 : /* Let's try to convert it into a Unix style char **argv. */
571 1 : argv = process_get_argv(process);
572 :
573 : /* Check our values. */
574 1 : tt_str_op(argv[0], OP_EQ, "/bin/cat");
575 1 : tt_str_op(argv[1], OP_EQ, "foo");
576 1 : tt_str_op(argv[2], OP_EQ, "bar");
577 1 : tt_str_op(argv[3], OP_EQ, "baz");
578 1 : tt_ptr_op(argv[4], OP_EQ, NULL);
579 :
580 1 : done:
581 1 : tor_free(argv);
582 1 : process_free(process);
583 1 : }
584 :
585 : static void
586 1 : test_unix(void *arg)
587 : {
588 1 : (void)arg;
589 : #ifndef _WIN32
590 1 : process_t *process = process_new("");
591 :
592 : /* On Unix all processes should have a Unix process handle. */
593 1 : tt_ptr_op(NULL, OP_NE, process_get_unix_process(process));
594 :
595 1 : done:
596 1 : process_free(process);
597 : #endif /* !defined(_WIN32) */
598 1 : }
599 :
600 : static void
601 1 : test_win32(void *arg)
602 : {
603 1 : (void)arg;
604 : #ifdef _WIN32
605 : process_t *process = process_new("");
606 : char *joined_argv = NULL;
607 :
608 : /* On Win32 all processes should have a Win32 process handle. */
609 : tt_ptr_op(NULL, OP_NE, process_get_win32_process(process));
610 :
611 : /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
612 : * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
613 : * will try to only generate simple cases for the child process to parse;
614 : * i.e. we never embed quoted strings in arguments. */
615 :
616 : const char *argvs[][4] = {
617 : {"a", "bb", "CCC", NULL}, // Normal
618 : {NULL, NULL, NULL, NULL}, // Empty argument list
619 : {"", NULL, NULL, NULL}, // Empty argument
620 : {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
621 : {"a\tbc", "dd dd", "E", NULL}, // Whitespace
622 : {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
623 : {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
624 : {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
625 : { NULL } // Terminator
626 : };
627 :
628 : const char *cmdlines[] = {
629 : "a bb CCC",
630 : "",
631 : "\"\"",
632 : "\\\"a b\\\"b CCC\\\"",
633 : "\"a\tbc\" \"dd dd\" E",
634 : "a\\\\\\b \"de fg\" H",
635 : "a\\\\\\\"b \\c D\\",
636 : "\"a\\\\b c\" d E",
637 : NULL // Terminator
638 : };
639 :
640 : int i;
641 :
642 : for (i=0; cmdlines[i]!=NULL; i++) {
643 : log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
644 : joined_argv = tor_join_win_cmdline(argvs[i]);
645 : tt_str_op(cmdlines[i],OP_EQ, joined_argv);
646 : tor_free(joined_argv);
647 : }
648 :
649 : done:
650 : tor_free(joined_argv);
651 : process_free(process);
652 : #endif /* defined(_WIN32) */
653 1 : }
654 :
655 : struct testcase_t process_tests[] = {
656 : { "default_values", test_default_values, TT_FORK, NULL, NULL },
657 : { "environment", test_environment, TT_FORK, NULL, NULL },
658 : { "stringified_types", test_stringified_types, TT_FORK, NULL, NULL },
659 : { "line_protocol_simple", test_line_protocol_simple, TT_FORK, NULL, NULL },
660 : { "line_protocol_multi", test_line_protocol_multi, TT_FORK, NULL, NULL },
661 : { "line_protocol_partial", test_line_protocol_partial, TT_FORK, NULL, NULL },
662 : { "raw_protocol_simple", test_raw_protocol_simple, TT_FORK, NULL, NULL },
663 : { "write_simple", test_write_simple, TT_FORK, NULL, NULL },
664 : { "exit_simple", test_exit_simple, TT_FORK, NULL, NULL },
665 : { "argv_simple", test_argv_simple, TT_FORK, NULL, NULL },
666 : { "unix", test_unix, TT_FORK, NULL, NULL },
667 : { "win32", test_win32, TT_FORK, NULL, NULL },
668 : END_OF_TESTCASES
669 : };
|