test_process.c 20 KB

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