test_process.c 20 KB

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