tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_pt.c (23717B)


      1 /* Copyright (c) 2001-2004, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 #include "orconfig.h"
      7 #define PT_PRIVATE
      8 #define STATEFILE_PRIVATE
      9 #define CONTROL_EVENTS_PRIVATE
     10 #define PROCESS_PRIVATE
     11 #include "core/or/or.h"
     12 #include "app/config/config.h"
     13 #include "lib/confmgt/confmgt.h"
     14 #include "feature/control/control.h"
     15 #include "feature/control/control_events.h"
     16 #include "feature/client/transports.h"
     17 #include "core/or/circuitbuild.h"
     18 #include "app/config/statefile.h"
     19 #include "test/test.h"
     20 #include "lib/encoding/confline.h"
     21 #include "lib/net/resolve.h"
     22 #include "lib/process/process.h"
     23 
     24 #include "app/config/or_state_st.h"
     25 
     26 #include "test/log_test_helpers.h"
     27 
     28 static void
     29 reset_mp(managed_proxy_t *mp)
     30 {
     31  mp->conf_state = PT_PROTO_LAUNCHED;
     32  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
     33  smartlist_clear(mp->transports);
     34 
     35  tor_free(mp->version);
     36  tor_free(mp->implementation);
     37 }
     38 
     39 static void
     40 test_pt_parsing(void *arg)
     41 {
     42  char line[200];
     43  transport_t *transport = NULL;
     44  tor_addr_t test_addr;
     45 
     46  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
     47  (void)arg;
     48  mp->conf_state = PT_PROTO_INFANT;
     49  mp->transports = smartlist_new();
     50 
     51  /* incomplete cmethod */
     52  strlcpy(line,"CMETHOD trebuchet",sizeof(line));
     53  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
     54 
     55  reset_mp(mp);
     56 
     57  /* wrong proxy type */
     58  strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line));
     59  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
     60 
     61  reset_mp(mp);
     62 
     63  /* wrong addrport */
     64  strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line));
     65  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
     66 
     67  reset_mp(mp);
     68 
     69  /* correct line */
     70  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
     71  tt_int_op(parse_cmethod_line(line, mp), OP_EQ, 0);
     72  tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
     73  transport = smartlist_get(mp->transports, 0);
     74  /* test registered address of transport */
     75  tor_addr_parse(&test_addr, "127.0.0.1");
     76  tt_assert(tor_addr_eq(&test_addr, &transport->addr));
     77  /* test registered port of transport */
     78  tt_uint_op(transport->port, OP_EQ, 1999);
     79  /* test registered SOCKS version of transport */
     80  tt_int_op(transport->socks_version, OP_EQ, PROXY_SOCKS5);
     81  /* test registered name of transport */
     82  tt_str_op(transport->name,OP_EQ, "trebuchet");
     83 
     84  reset_mp(mp);
     85 
     86  /* incomplete smethod */
     87  strlcpy(line,"SMETHOD trebuchet",sizeof(line));
     88  tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);
     89 
     90  reset_mp(mp);
     91 
     92  /* wrong addr type */
     93  strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line));
     94  tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);
     95 
     96  reset_mp(mp);
     97 
     98  /* cowwect */
     99  strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line));
    100  tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
    101  tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
    102  transport = smartlist_get(mp->transports, 0);
    103  /* test registered address of transport */
    104  tor_addr_parse(&test_addr, "127.0.0.2");
    105  tt_assert(tor_addr_eq(&test_addr, &transport->addr));
    106  /* test registered port of transport */
    107  tt_uint_op(transport->port, OP_EQ, 2999);
    108  /* test registered name of transport */
    109  tt_str_op(transport->name,OP_EQ, "trebuchy");
    110 
    111  reset_mp(mp);
    112 
    113  /* Include some arguments. Good ones. */
    114  strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 "
    115          "ARGS:counterweight=3,sling=snappy",
    116          sizeof(line));
    117  tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
    118  tt_int_op(1, OP_EQ, smartlist_len(mp->transports));
    119  {
    120    const transport_t *transport_ = smartlist_get(mp->transports, 0);
    121    tt_assert(transport_);
    122    tt_str_op(transport_->name, OP_EQ, "trebuchet");
    123    tt_int_op(transport_->port, OP_EQ, 9999);
    124    tt_str_op(fmt_addr(&transport_->addr), OP_EQ, "127.0.0.1");
    125    tt_str_op(transport_->extra_info_args, OP_EQ,
    126              "counterweight=3,sling=snappy");
    127  }
    128  reset_mp(mp);
    129 
    130  /* unsupported version */
    131  strlcpy(line,"VERSION 666",sizeof(line));
    132  tt_int_op(parse_version(line, mp), OP_LT, 0);
    133 
    134  /* incomplete VERSION */
    135  strlcpy(line,"VERSION ",sizeof(line));
    136  tt_int_op(parse_version(line, mp), OP_LT, 0);
    137 
    138  /* correct VERSION */
    139  strlcpy(line,"VERSION 1",sizeof(line));
    140  tt_int_op(parse_version(line, mp), OP_EQ, 0);
    141 
    142 done:
    143  reset_mp(mp);
    144  smartlist_free(mp->transports);
    145  tor_free(mp);
    146 }
    147 
    148 static void
    149 test_pt_status_parsing(void *arg)
    150 {
    151  char line[200];
    152  char *test_binary = tor_strdup("test-pt");
    153  char *argv[] = {
    154    test_binary,
    155    NULL,
    156  };
    157 
    158  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
    159  (void)arg;
    160  mp->conf_state = PT_PROTO_INFANT;
    161  mp->transports = smartlist_new();
    162  mp->argv = argv;
    163 
    164  /* STATUS TYPE=version messages. */
    165  tt_ptr_op(mp->version, OP_EQ, NULL);
    166  tt_ptr_op(mp->implementation, OP_EQ, NULL);
    167 
    168  /* Normal case. */
    169  strlcpy(line, "STATUS "
    170                "IMPLEMENTATION=xyz "
    171                "TYPE=version "
    172                "VERSION=\"1.33.7-hax beta\"",
    173                sizeof(line));
    174  handle_proxy_line(line, mp);
    175 
    176  tt_str_op(mp->version, OP_EQ, "1.33.7-hax beta");
    177  tt_str_op(mp->implementation, OP_EQ, "xyz");
    178  reset_mp(mp);
    179 
    180  /* Normal case but different case for TYPE value. */
    181  strlcpy(line, "STATUS "
    182                "IMPLEMENTATION=xyz "
    183                "TYPE=vErSiON "
    184                "VERSION=\"1.33.7-hax beta\"",
    185                sizeof(line));
    186  handle_proxy_line(line, mp);
    187 
    188  tt_str_op(mp->version, OP_EQ, "1.33.7-hax beta");
    189  tt_str_op(mp->implementation, OP_EQ, "xyz");
    190  reset_mp(mp);
    191 
    192  /* IMPLEMENTATION and VERSION set but no TYPE. */
    193  strlcpy(line, "STATUS "
    194                "IMPLEMENTATION=xyz "
    195                "VERSION=\"1.33.7-hax beta\"",
    196                sizeof(line));
    197  handle_proxy_line(line, mp);
    198 
    199  tt_assert(mp->version == NULL);
    200  tt_assert(mp->implementation == NULL);
    201  reset_mp(mp);
    202 
    203  /* Multiple TYPE= is not allowed. */
    204  strlcpy(line, "STATUS "
    205                "IMPLEMENTATION=xyz "
    206                "TYPE=version "
    207                "VERSION=\"1.33.7-hax beta\" "
    208                "TYPE=nothing",
    209                sizeof(line));
    210  handle_proxy_line(line, mp);
    211 
    212  tt_assert(mp->version == NULL);
    213  tt_assert(mp->implementation == NULL);
    214  reset_mp(mp);
    215 
    216  /* Multiple TYPE= is not allowed. */
    217  strlcpy(line, "STATUS "
    218                "IMPLEMENTATION=xyz "
    219                "TYPE=version "
    220                "VERSION=\"1.33.7-hax beta\" "
    221                "TYPE=version",
    222                sizeof(line));
    223  handle_proxy_line(line, mp);
    224 
    225  tt_assert(mp->version == NULL);
    226  tt_assert(mp->implementation == NULL);
    227  reset_mp(mp);
    228 
    229  /* Missing VERSION. */
    230  strlcpy(line, "STATUS "
    231                "TYPE=version "
    232                "IMPLEMENTATION=xyz ",
    233                sizeof(line));
    234  handle_proxy_line(line, mp);
    235 
    236  tt_assert(mp->version == NULL);
    237  tt_assert(mp->implementation == NULL);
    238  reset_mp(mp);
    239 
    240  /* Many IMPLEMENTATION and VERSION. First found are used. */
    241  strlcpy(line, "STATUS "
    242                "TYPE=version "
    243                "IMPLEMENTATION=xyz "
    244                "VERSION=\"1.33.7-hax beta\" "
    245                "IMPLEMENTATION=abc "
    246                "VERSION=\"2.33.7-hax beta\" ",
    247                sizeof(line));
    248  handle_proxy_line(line, mp);
    249 
    250  tt_str_op(mp->version, OP_EQ, "1.33.7-hax beta");
    251  tt_str_op(mp->implementation, OP_EQ, "xyz");
    252  reset_mp(mp);
    253 
    254  /* Control characters. Invalid input. */
    255  strlcpy(line, "STATUS "
    256                "TYPE=version "
    257                "IMPLEMENTATION=xyz\0abc "
    258                "VERSION=\"1.33.7-hax beta\"\0.3 ",
    259                sizeof(line));
    260  handle_proxy_line(line, mp);
    261 
    262  tt_assert(mp->version == NULL);
    263  tt_assert(mp->implementation == NULL);
    264  reset_mp(mp);
    265 
    266 done:
    267  reset_mp(mp);
    268  smartlist_free(mp->transports);
    269  tor_free(mp);
    270  tor_free(test_binary);
    271 }
    272 
    273 static void
    274 test_pt_get_transport_options(void *arg)
    275 {
    276  char **execve_args;
    277  smartlist_t *transport_list = smartlist_new();
    278  managed_proxy_t *mp;
    279  or_options_t *options = get_options_mutable();
    280  char *opt_str = NULL;
    281  config_line_t *cl = NULL;
    282  (void)arg;
    283 
    284  execve_args = tor_malloc(sizeof(char*)*2);
    285  execve_args[0] = tor_strdup("cheeseshop");
    286  execve_args[1] = NULL;
    287 
    288  mp = managed_proxy_create(transport_list, execve_args, 1);
    289  tt_ptr_op(mp, OP_NE, NULL);
    290  opt_str = get_transport_options_for_server_proxy(mp);
    291  tt_ptr_op(opt_str, OP_EQ, NULL);
    292 
    293  smartlist_add_strdup(mp->transports_to_launch, "gruyere");
    294  smartlist_add_strdup(mp->transports_to_launch, "roquefort");
    295  smartlist_add_strdup(mp->transports_to_launch, "stnectaire");
    296 
    297  tt_assert(options);
    298 
    299  cl = tor_malloc_zero(sizeof(config_line_t));
    300  cl->value = tor_strdup("gruyere melty=10 hardness=se;ven");
    301  options->ServerTransportOptions = cl;
    302 
    303  cl = tor_malloc_zero(sizeof(config_line_t));
    304  cl->value = tor_strdup("stnectaire melty=4 hardness=three");
    305  cl->next = options->ServerTransportOptions;
    306  options->ServerTransportOptions = cl;
    307 
    308  cl = tor_malloc_zero(sizeof(config_line_t));
    309  cl->value = tor_strdup("pepperjack melty=12 hardness=five");
    310  cl->next = options->ServerTransportOptions;
    311  options->ServerTransportOptions = cl;
    312 
    313  opt_str = get_transport_options_for_server_proxy(mp);
    314  tt_str_op(opt_str, OP_EQ,
    315            "gruyere:melty=10;gruyere:hardness=se\\;ven;"
    316            "stnectaire:melty=4;stnectaire:hardness=three");
    317 
    318 done:
    319  tor_free(opt_str);
    320  config_free_lines(cl);
    321  managed_proxy_destroy(mp, 0);
    322  smartlist_free(transport_list);
    323 }
    324 
    325 static void
    326 test_pt_protocol(void *arg)
    327 {
    328  char line[200];
    329 
    330  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
    331  (void)arg;
    332  mp->conf_state = PT_PROTO_LAUNCHED;
    333  mp->transports = smartlist_new();
    334  mp->argv = tor_calloc(2, sizeof(char *));
    335  mp->argv[0] = tor_strdup("<testcase>");
    336 
    337  /* various wrong protocol runs: */
    338 
    339  strlcpy(line,"VERSION 1",sizeof(line));
    340  handle_proxy_line(line, mp);
    341  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
    342 
    343  strlcpy(line,"VERSION 1",sizeof(line));
    344  handle_proxy_line(line, mp);
    345  tt_assert(mp->conf_state == PT_PROTO_BROKEN);
    346 
    347  reset_mp(mp);
    348 
    349  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
    350  handle_proxy_line(line, mp);
    351  tt_assert(mp->conf_state == PT_PROTO_BROKEN);
    352 
    353  reset_mp(mp);
    354 
    355  /* correct protocol run: */
    356  strlcpy(line,"VERSION 1",sizeof(line));
    357  handle_proxy_line(line, mp);
    358  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
    359 
    360  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
    361  handle_proxy_line(line, mp);
    362  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
    363 
    364  strlcpy(line,"CMETHOD-ERROR fakename not supported",sizeof(line));
    365  handle_proxy_line(line, mp);
    366  tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
    367 
    368  strlcpy(line,"CMETHODS DONE",sizeof(line));
    369  handle_proxy_line(line, mp);
    370  tt_assert(mp->conf_state == PT_PROTO_CONFIGURED);
    371 
    372 done:
    373  reset_mp(mp);
    374  smartlist_free(mp->transports);
    375  tor_free(mp->argv[0]);
    376  tor_free(mp->argv);
    377  tor_free(mp);
    378 }
    379 
    380 static void
    381 test_pt_get_extrainfo_string(void *arg)
    382 {
    383  managed_proxy_t *mp1 = NULL, *mp2 = NULL;
    384  char **argv1, **argv2;
    385  smartlist_t *t1 = smartlist_new(), *t2 = smartlist_new();
    386  int r;
    387  char *s = NULL;
    388  (void) arg;
    389 
    390  argv1 = tor_malloc_zero(sizeof(char*)*3);
    391  argv1[0] = tor_strdup("ewige");
    392  argv1[1] = tor_strdup("Blumenkraft");
    393  argv1[2] = NULL;
    394  argv2 = tor_malloc_zero(sizeof(char*)*4);
    395  argv2[0] = tor_strdup("und");
    396  argv2[1] = tor_strdup("ewige");
    397  argv2[2] = tor_strdup("Schlangenkraft");
    398  argv2[3] = NULL;
    399 
    400  mp1 = managed_proxy_create(t1, argv1, 1);
    401  mp2 = managed_proxy_create(t2, argv2, 1);
    402 
    403  r = parse_smethod_line("SMETHOD hagbard 127.0.0.1:5555", mp1);
    404  tt_int_op(r, OP_EQ, 0);
    405  r = parse_smethod_line("SMETHOD celine 127.0.0.1:1723 ARGS:card=no-enemy",
    406                         mp2);
    407  tt_int_op(r, OP_EQ, 0);
    408 
    409  /* Force these proxies to look "completed" or they won't generate output. */
    410  mp1->conf_state = mp2->conf_state = PT_PROTO_COMPLETED;
    411 
    412  s = pt_get_extra_info_descriptor_string();
    413  tt_assert(s);
    414  tt_str_op(s, OP_EQ,
    415            "transport hagbard 127.0.0.1:5555\n"
    416            "transport-info\n"
    417            "transport celine 127.0.0.1:1723 card=no-enemy\n"
    418            "transport-info\n");
    419 
    420 done:
    421  /* XXXX clean up better */
    422  smartlist_free(t1);
    423  smartlist_free(t2);
    424  tor_free(s);
    425 }
    426 
    427 static int
    428 process_read_stdout_replacement(process_t *process, buf_t *buffer)
    429 {
    430  (void)process;
    431  static int times_called = 0;
    432 
    433  /* Generate some dummy CMETHOD lines the first 5 times. The 6th
    434     time, send 'CMETHODS DONE' to finish configuring the proxy. */
    435  times_called++;
    436 
    437  if (times_called <= 5) {
    438    buf_add_printf(buffer, "SMETHOD mock%d 127.0.0.1:555%d\n",
    439                           times_called, times_called);
    440  } else if (times_called <= 6) {
    441    buf_add_string(buffer, "SMETHODS DONE\n");
    442  } else if (times_called <= 7) {
    443    buf_add_string(buffer, "LOG SEVERITY=error MESSAGE=\"Oh noes, something "
    444                           "bad happened. What do we do!?\"\n");
    445    buf_add_string(buffer, "LOG SEVERITY=warning MESSAGE=\"warning msg\"\n");
    446    buf_add_string(buffer, "LOG SEVERITY=notice MESSAGE=\"notice msg\"\n");
    447    buf_add_string(buffer, "LOG SEVERITY=info MESSAGE=\"info msg\"\n");
    448    buf_add_string(buffer, "LOG SEVERITY=debug MESSAGE=\"debug msg\"\n");
    449  } else if (times_called <= 8) {
    450    buf_add_string(buffer, "STATUS TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\n");
    451    buf_add_string(buffer, "STATUS TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\n");
    452    buf_add_string(buffer, "STATUS TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\n");
    453  }
    454 
    455  return (int)buf_datalen(buffer);
    456 }
    457 
    458 static or_state_t *dummy_state = NULL;
    459 
    460 static or_state_t *
    461 get_or_state_replacement(void)
    462 {
    463  return dummy_state;
    464 }
    465 
    466 static int controlevent_n = 0;
    467 static uint16_t controlevent_event = 0;
    468 static smartlist_t *controlevent_msgs = NULL;
    469 
    470 static void
    471 queue_control_event_string_replacement(uint16_t event, char *msg)
    472 {
    473  ++controlevent_n;
    474  controlevent_event = event;
    475  if (!controlevent_msgs)
    476    controlevent_msgs = smartlist_new();
    477  smartlist_add(controlevent_msgs, msg);
    478 }
    479 
    480 /* Test the configure_proxy() function. */
    481 static void
    482 test_pt_configure_proxy(void *arg)
    483 {
    484  int i, retval;
    485  managed_proxy_t *mp = NULL;
    486  (void) arg;
    487 
    488  dummy_state = or_state_new();
    489 
    490  MOCK(process_read_stdout, process_read_stdout_replacement);
    491  MOCK(get_or_state,
    492       get_or_state_replacement);
    493  MOCK(queue_control_event_string,
    494       queue_control_event_string_replacement);
    495 
    496  control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);
    497 
    498  mp = tor_malloc_zero(sizeof(managed_proxy_t));
    499  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
    500  mp->transports = smartlist_new();
    501  mp->transports_to_launch = smartlist_new();
    502  mp->argv = tor_malloc_zero(sizeof(char*)*2);
    503  mp->argv[0] = tor_strdup("<testcase>");
    504  mp->is_server = 1;
    505 
    506  /* Configure the process. */
    507  mp->process = process_new("");
    508  process_set_stdout_read_callback(mp->process, managed_proxy_stdout_callback);
    509  process_set_data(mp->process, mp);
    510 
    511  /* Test the return value of configure_proxy() by calling it some
    512     times while it is uninitialized and then finally finalizing its
    513     configuration. */
    514  for (i = 0 ; i < 5 ; i++) {
    515    /* force a read from our mocked stdout reader. */
    516    process_notify_event_stdout(mp->process);
    517    /* try to configure our proxy. */
    518    retval = configure_proxy(mp);
    519    /* retval should be zero because proxy hasn't finished configuring yet */
    520    tt_int_op(retval, OP_EQ, 0);
    521    /* check the number of registered transports */
    522    tt_int_op(smartlist_len(mp->transports), OP_EQ, i+1);
    523    /* check that the mp is still waiting for transports */
    524    tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
    525  }
    526 
    527  /* Get the SMETHOD DONE written to the process. */
    528  process_notify_event_stdout(mp->process);
    529 
    530  /* this last configure_proxy() should finalize the proxy configuration. */
    531  retval = configure_proxy(mp);
    532  /* retval should be 1 since the proxy finished configuring */
    533  tt_int_op(retval, OP_EQ, 1);
    534  /* check the mp state */
    535  tt_assert(mp->conf_state == PT_PROTO_COMPLETED);
    536 
    537  tt_int_op(controlevent_n, OP_EQ, 5);
    538  tt_int_op(controlevent_event, OP_EQ, EVENT_TRANSPORT_LAUNCHED);
    539  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 5);
    540  smartlist_sort_strings(controlevent_msgs);
    541  tt_str_op(smartlist_get(controlevent_msgs, 0), OP_EQ,
    542            "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
    543  tt_str_op(smartlist_get(controlevent_msgs, 1), OP_EQ,
    544            "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
    545  tt_str_op(smartlist_get(controlevent_msgs, 2), OP_EQ,
    546            "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
    547  tt_str_op(smartlist_get(controlevent_msgs, 3), OP_EQ,
    548            "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
    549  tt_str_op(smartlist_get(controlevent_msgs, 4), OP_EQ,
    550            "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");
    551 
    552  /* Get the log message out. */
    553  setup_full_capture_of_logs(LOG_ERR);
    554  process_notify_event_stdout(mp->process);
    555  expect_single_log_msg_containing("Oh noes, something bad happened");
    556  teardown_capture_of_logs();
    557 
    558  tt_int_op(controlevent_n, OP_EQ, 10);
    559  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_LOG);
    560  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 10);
    561  tt_str_op(smartlist_get(controlevent_msgs, 5), OP_EQ,
    562            "650 PT_LOG PT=<testcase> SEVERITY=error "
    563            "MESSAGE=\"Oh noes, "
    564            "something bad happened. What do we do!?\"\r\n");
    565  tt_str_op(smartlist_get(controlevent_msgs, 6), OP_EQ,
    566            "650 PT_LOG PT=<testcase> SEVERITY=warning "
    567            "MESSAGE=\"warning msg\"\r\n");
    568  tt_str_op(smartlist_get(controlevent_msgs, 7), OP_EQ,
    569            "650 PT_LOG PT=<testcase> SEVERITY=notice "
    570            "MESSAGE=\"notice msg\"\r\n");
    571  tt_str_op(smartlist_get(controlevent_msgs, 8), OP_EQ,
    572            "650 PT_LOG PT=<testcase> SEVERITY=info "
    573            "MESSAGE=\"info msg\"\r\n");
    574  tt_str_op(smartlist_get(controlevent_msgs, 9), OP_EQ,
    575            "650 PT_LOG PT=<testcase> SEVERITY=debug "
    576            "MESSAGE=\"debug msg\"\r\n");
    577 
    578  /* Get the STATUS messages out. */
    579  process_notify_event_stdout(mp->process);
    580 
    581  tt_int_op(controlevent_n, OP_EQ, 13);
    582  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_STATUS);
    583  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 13);
    584 
    585  tt_str_op(smartlist_get(controlevent_msgs, 10), OP_EQ,
    586            "650 PT_STATUS "
    587            "PT=<testcase> TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
    588  tt_str_op(smartlist_get(controlevent_msgs, 11), OP_EQ,
    589            "650 PT_STATUS "
    590            "PT=<testcase> TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
    591  tt_str_op(smartlist_get(controlevent_msgs, 12), OP_EQ,
    592            "650 PT_STATUS "
    593            "PT=<testcase> TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\r\n");
    594 
    595  { /* check that the transport info were saved properly in the tor state */
    596    config_line_t *transport_in_state = NULL;
    597    smartlist_t *transport_info_sl = smartlist_new();
    598    char *name_of_transport = NULL;
    599    char *bindaddr = NULL;
    600 
    601    /* Get the bindaddr for "mock1" and check it against the bindaddr
    602       that the mocked tor_get_lines_from_handle() generated. */
    603    transport_in_state = get_transport_in_state_by_name("mock1");
    604    tt_assert(transport_in_state);
    605    smartlist_split_string(transport_info_sl, transport_in_state->value,
    606                           NULL, 0, 0);
    607    name_of_transport = smartlist_get(transport_info_sl, 0);
    608    bindaddr = smartlist_get(transport_info_sl, 1);
    609    tt_str_op(name_of_transport, OP_EQ, "mock1");
    610    tt_str_op(bindaddr, OP_EQ, "127.0.0.1:5551");
    611 
    612    SMARTLIST_FOREACH(transport_info_sl, char *, cp, tor_free(cp));
    613    smartlist_free(transport_info_sl);
    614  }
    615 
    616 done:
    617  teardown_capture_of_logs();
    618  or_state_free(dummy_state);
    619  UNMOCK(process_read_stdout);
    620  UNMOCK(get_or_state);
    621  UNMOCK(queue_control_event_string);
    622  if (controlevent_msgs) {
    623    SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
    624    smartlist_free(controlevent_msgs);
    625    controlevent_msgs = NULL;
    626  }
    627  if (mp->transports) {
    628    SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
    629    smartlist_free(mp->transports);
    630  }
    631  smartlist_free(mp->transports_to_launch);
    632  process_free(mp->process);
    633  tor_free(mp->argv[0]);
    634  tor_free(mp->argv);
    635  tor_free(mp);
    636 }
    637 
    638 /* Test the get_pt_proxy_uri() function. */
    639 static void
    640 test_get_pt_proxy_uri(void *arg)
    641 {
    642  or_options_t *options = get_options_mutable();
    643  char *uri = NULL;
    644  int ret;
    645  (void) arg;
    646 
    647  /* Test with no proxy. */
    648  uri = get_pt_proxy_uri();
    649  tt_ptr_op(uri, OP_EQ, NULL);
    650 
    651  /* Test with a SOCKS4 proxy. */
    652  options->Socks4Proxy = tor_strdup("192.0.2.1:1080");
    653  ret = tor_addr_port_lookup(options->Socks4Proxy,
    654                             &options->Socks4ProxyAddr,
    655                             &options->Socks4ProxyPort);
    656  tt_int_op(ret, OP_EQ, 0);
    657  uri = get_pt_proxy_uri();
    658  tt_str_op(uri, OP_EQ, "socks4a://192.0.2.1:1080");
    659  tor_free(uri);
    660  tor_free(options->Socks4Proxy);
    661 
    662  /* Test with a SOCKS5 proxy, no username/password. */
    663  options->Socks5Proxy = tor_strdup("192.0.2.1:1080");
    664  ret = tor_addr_port_lookup(options->Socks5Proxy,
    665                             &options->Socks5ProxyAddr,
    666                             &options->Socks5ProxyPort);
    667  tt_int_op(ret, OP_EQ, 0);
    668  uri = get_pt_proxy_uri();
    669  tt_str_op(uri, OP_EQ, "socks5://192.0.2.1:1080");
    670  tor_free(uri);
    671 
    672  /* Test with a SOCKS5 proxy, with username/password. */
    673  options->Socks5ProxyUsername = tor_strdup("hwest");
    674  options->Socks5ProxyPassword = tor_strdup("r34n1m470r");
    675  uri = get_pt_proxy_uri();
    676  tt_str_op(uri, OP_EQ, "socks5://hwest:r34n1m470r@192.0.2.1:1080");
    677  tor_free(uri);
    678  tor_free(options->Socks5Proxy);
    679  tor_free(options->Socks5ProxyUsername);
    680  tor_free(options->Socks5ProxyPassword);
    681 
    682  /* Test with a HTTPS proxy, no authenticator. */
    683  options->HTTPSProxy = tor_strdup("192.0.2.1:80");
    684  ret = tor_addr_port_lookup(options->HTTPSProxy,
    685                             &options->HTTPSProxyAddr,
    686                             &options->HTTPSProxyPort);
    687  tt_int_op(ret, OP_EQ, 0);
    688  uri = get_pt_proxy_uri();
    689  tt_str_op(uri, OP_EQ, "http://192.0.2.1:80");
    690  tor_free(uri);
    691 
    692  /* Test with a HTTPS proxy, with authenticator. */
    693  options->HTTPSProxyAuthenticator = tor_strdup("hwest:r34n1m470r");
    694  uri = get_pt_proxy_uri();
    695  tt_str_op(uri, OP_EQ, "http://hwest:r34n1m470r@192.0.2.1:80");
    696  tor_free(uri);
    697  tor_free(options->HTTPSProxy);
    698  tor_free(options->HTTPSProxyAuthenticator);
    699 
    700  /* Token nod to the fact that IPv6 exists. */
    701  options->Socks4Proxy = tor_strdup("[2001:db8::1]:1080");
    702  ret = tor_addr_port_lookup(options->Socks4Proxy,
    703                             &options->Socks4ProxyAddr,
    704                             &options->Socks4ProxyPort);
    705  tt_int_op(ret, OP_EQ, 0);
    706  uri = get_pt_proxy_uri();
    707  tt_str_op(uri, OP_EQ, "socks4a://[2001:db8::1]:1080");
    708  tor_free(uri);
    709  tor_free(options->Socks4Proxy);
    710 
    711 done:
    712  if (uri)
    713    tor_free(uri);
    714 }
    715 
    716 #ifndef COCCI
    717 #define PT_LEGACY(name)                                               \
    718  { (#name), test_pt_ ## name , 0, NULL, NULL }
    719 #endif
    720 
    721 struct testcase_t pt_tests[] = {
    722  PT_LEGACY(parsing),
    723  PT_LEGACY(status_parsing),
    724  PT_LEGACY(protocol),
    725  { "get_transport_options", test_pt_get_transport_options, TT_FORK,
    726    NULL, NULL },
    727  { "get_extrainfo_string", test_pt_get_extrainfo_string, TT_FORK,
    728    NULL, NULL },
    729  { "configure_proxy",test_pt_configure_proxy, TT_FORK,
    730    NULL, NULL },
    731  { "get_pt_proxy_uri", test_get_pt_proxy_uri, TT_FORK,
    732    NULL, NULL },
    733  END_OF_TESTCASES
    734 };