test_process.c 20 KB

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