LCOV - code coverage report
Current view: top level - test - test_process.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 318 318 100.0 %
Date: 2021-11-24 03:28:48 Functions: 20 20 100.0 %

          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             : };

Generated by: LCOV version 1.14