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

          Line data    Source code
       1             : /* Copyright (c) 2015-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : #define CONTROL_CMD_PRIVATE
       5             : #define CONTROL_GETINFO_PRIVATE
       6             : #include "core/or/or.h"
       7             : #include "app/config/config.h"
       8             : #include "lib/crypt_ops/crypto_ed25519.h"
       9             : #include "feature/client/bridges.h"
      10             : #include "feature/control/control.h"
      11             : #include "feature/control/control_cmd.h"
      12             : #include "feature/control/control_getinfo.h"
      13             : #include "feature/control/control_proto.h"
      14             : #include "feature/client/entrynodes.h"
      15             : #include "feature/dircache/cached_dir_st.h"
      16             : #include "feature/dircache/dirserv.h"
      17             : #include "feature/hs/hs_common.h"
      18             : #include "feature/nodelist/networkstatus.h"
      19             : #include "feature/nodelist/authcert.h"
      20             : #include "feature/nodelist/nodelist.h"
      21             : #include "feature/stats/rephist.h"
      22             : #include "test/test.h"
      23             : #include "test/test_helpers.h"
      24             : #include "lib/net/resolve.h"
      25             : #include "lib/encoding/confline.h"
      26             : #include "lib/encoding/kvline.h"
      27             : 
      28             : #include "feature/control/control_connection_st.h"
      29             : #include "feature/control/control_cmd_args_st.h"
      30             : #include "feature/dirclient/download_status_st.h"
      31             : #include "feature/nodelist/microdesc_st.h"
      32             : #include "feature/nodelist/node_st.h"
      33             : 
      34             : typedef struct {
      35             :   const char *input;
      36             :   const char *expected_parse;
      37             :   const char *expected_error;
      38             : } parser_testcase_t;
      39             : 
      40             : typedef struct {
      41             :   const control_cmd_syntax_t *syntax;
      42             :   size_t n_testcases;
      43             :   const parser_testcase_t *testcases;
      44             : } parse_test_params_t;
      45             : 
      46             : static char *
      47          17 : control_cmd_dump_args(const control_cmd_args_t *result)
      48             : {
      49          17 :   buf_t *buf = buf_new();
      50          17 :   buf_add_string(buf, "{ args=[");
      51          17 :   if (result->args) {
      52          17 :     if (smartlist_len(result->args)) {
      53           9 :         buf_add_string(buf, " ");
      54             :     }
      55          32 :     SMARTLIST_FOREACH_BEGIN(result->args, const char *, s) {
      56          15 :       const bool last = (s_sl_idx == smartlist_len(result->args)-1);
      57          21 :       buf_add_printf(buf, "%s%s ",
      58             :                      escaped(s),
      59             :                      last ? "" : ",");
      60          15 :     } SMARTLIST_FOREACH_END(s);
      61             :   }
      62          17 :   buf_add_string(buf, "]");
      63          17 :   if (result->cmddata) {
      64           4 :     buf_add_string(buf, ", obj=");
      65           4 :     buf_add_string(buf, escaped(result->cmddata));
      66             :   }
      67          17 :   if (result->kwargs) {
      68           4 :     buf_add_string(buf, ", { ");
      69           4 :     const config_line_t *line;
      70          12 :     for (line = result->kwargs; line; line = line->next) {
      71           8 :       const bool last = (line->next == NULL);
      72          12 :       buf_add_printf(buf, "%s=%s%s ", line->key, escaped(line->value),
      73             :                      last ? "" : ",");
      74             :     }
      75           4 :     buf_add_string(buf, "}");
      76             :   }
      77          17 :   buf_add_string(buf, " }");
      78             : 
      79          17 :   char *encoded = buf_extract(buf, NULL);
      80          17 :   buf_free(buf);
      81          17 :   return encoded;
      82             : }
      83             : 
      84             : static void
      85           4 : test_controller_parse_cmd(void *arg)
      86             : {
      87           4 :   const parse_test_params_t *params = arg;
      88           4 :   control_cmd_args_t *result = NULL;
      89           4 :   char *error = NULL;
      90           4 :   char *encoded = NULL;
      91             : 
      92          30 :   for (size_t i = 0; i < params->n_testcases; ++i) {
      93          26 :     const parser_testcase_t *t = &params->testcases[i];
      94          52 :     result = control_cmd_parse_args("EXAMPLE",
      95          26 :                                     params->syntax,
      96             :                                     strlen(t->input),
      97          26 :                                     t->input,
      98             :                                     &error);
      99             :     // A valid test should expect exactly one parse or error.
     100          26 :     tt_int_op((t->expected_parse == NULL), OP_NE,
     101             :               (t->expected_error == NULL));
     102             :     // We get a result or an error, not both.
     103          26 :     tt_int_op((result == NULL), OP_EQ, (error != NULL));
     104             :     // We got the one we expected.
     105          26 :     tt_int_op((result == NULL), OP_EQ, (t->expected_parse == NULL));
     106             : 
     107          26 :     if (result) {
     108          17 :       encoded = control_cmd_dump_args(result);
     109          17 :       tt_str_op(encoded, OP_EQ, t->expected_parse);
     110             :     } else {
     111           9 :       tt_str_op(error, OP_EQ, t->expected_error);
     112             :     }
     113             : 
     114          26 :     tor_free(error);
     115          26 :     tor_free(encoded);
     116          26 :     control_cmd_args_free(result);
     117             :   }
     118             : 
     119           4 :  done:
     120           4 :   tor_free(error);
     121           4 :   tor_free(encoded);
     122           4 :   control_cmd_args_free(result);
     123           4 : }
     124             : 
     125             : #ifndef COCCI
     126             : #define OK(inp, out) \
     127             :   { inp "\r\n", out, NULL }
     128             : #define ERR(inp, err) \
     129             :   { inp "\r\n", NULL, err }
     130             : 
     131             : #define TESTPARAMS(syntax, array)                \
     132             :   { &syntax,                                     \
     133             :       ARRAY_LENGTH(array),                       \
     134             :       array }
     135             : #endif /* !defined(COCCI) */
     136             : 
     137             : static const parser_testcase_t one_to_three_tests[] = {
     138             :    ERR("", "Need at least 1 argument(s)"),
     139             :    ERR("   \t", "Need at least 1 argument(s)"),
     140             :    OK("hello", "{ args=[ \"hello\" ] }"),
     141             :    OK("hello world", "{ args=[ \"hello\", \"world\" ] }"),
     142             :    OK("hello  world", "{ args=[ \"hello\", \"world\" ] }"),
     143             :    OK("  hello  world", "{ args=[ \"hello\", \"world\" ] }"),
     144             :    OK("  hello  world      ", "{ args=[ \"hello\", \"world\" ] }"),
     145             :    OK("hello there world", "{ args=[ \"hello\", \"there\", \"world\" ] }"),
     146             :    ERR("why hello there world", "Cannot accept more than 3 argument(s)"),
     147             :    ERR("hello\r\nworld.\r\n.", "Unexpected body"),
     148             : };
     149             : 
     150             : static const control_cmd_syntax_t one_to_three_syntax = {
     151             :    .min_args=1, .max_args=3
     152             : };
     153             : 
     154             : static const parse_test_params_t parse_one_to_three_params =
     155             :   TESTPARAMS( one_to_three_syntax, one_to_three_tests );
     156             : 
     157             : // =
     158             : static const parser_testcase_t no_args_one_obj_tests[] = {
     159             :   ERR("Hi there!\r\n.", "Cannot accept more than 0 argument(s)"),
     160             :   ERR("", "Empty body"),
     161             :   OK("\r\n", "{ args=[], obj=\"\\n\" }"),
     162             :   OK("\r\nHello world\r\n", "{ args=[], obj=\"Hello world\\n\\n\" }"),
     163             :   OK("\r\nHello\r\nworld\r\n", "{ args=[], obj=\"Hello\\nworld\\n\\n\" }"),
     164             :   OK("\r\nHello\r\n..\r\nworld\r\n",
     165             :      "{ args=[], obj=\"Hello\\n.\\nworld\\n\\n\" }"),
     166             : };
     167             : static const control_cmd_syntax_t no_args_one_obj_syntax = {
     168             :    .min_args=0, .max_args=0,
     169             :    .want_cmddata=true,
     170             : };
     171             : static const parse_test_params_t parse_no_args_one_obj_params =
     172             :   TESTPARAMS( no_args_one_obj_syntax, no_args_one_obj_tests );
     173             : 
     174             : static const parser_testcase_t no_args_kwargs_tests[] = {
     175             :   OK("", "{ args=[] }"),
     176             :   OK(" ", "{ args=[] }"),
     177             :   OK("hello there=world", "{ args=[], { hello=\"\", there=\"world\" } }"),
     178             :   OK("hello there=world today",
     179             :      "{ args=[], { hello=\"\", there=\"world\", today=\"\" } }"),
     180             :   ERR("=Foo", "Cannot parse keyword argument(s)"),
     181             : };
     182             : static const control_cmd_syntax_t no_args_kwargs_syntax = {
     183             :    .min_args=0, .max_args=0,
     184             :    .accept_keywords=true,
     185             :    .kvline_flags=KV_OMIT_VALS
     186             : };
     187             : static const parse_test_params_t parse_no_args_kwargs_params =
     188             :   TESTPARAMS( no_args_kwargs_syntax, no_args_kwargs_tests );
     189             : 
     190             : static const char *one_arg_kwargs_allow_keywords[] = {
     191             :   "Hello", "world", NULL
     192             : };
     193             : static const parser_testcase_t one_arg_kwargs_tests[] = {
     194             :   ERR("", "Need at least 1 argument(s)"),
     195             :   OK("Hi", "{ args=[ \"Hi\" ] }"),
     196             :   ERR("hello there=world", "Unrecognized keyword argument \"there\""),
     197             :   OK("Hi HELLO=foo", "{ args=[ \"Hi\" ], { HELLO=\"foo\" } }"),
     198             :   OK("Hi world=\"bar baz\" hello  ",
     199             :      "{ args=[ \"Hi\" ], { world=\"bar baz\", hello=\"\" } }"),
     200             : };
     201             : static const control_cmd_syntax_t one_arg_kwargs_syntax = {
     202             :    .min_args=1, .max_args=1,
     203             :    .accept_keywords=true,
     204             :    .allowed_keywords=one_arg_kwargs_allow_keywords,
     205             :    .kvline_flags=KV_OMIT_VALS|KV_QUOTED,
     206             : };
     207             : static const parse_test_params_t parse_one_arg_kwargs_params =
     208             :   TESTPARAMS( one_arg_kwargs_syntax, one_arg_kwargs_tests );
     209             : 
     210             : static char *reply_str = NULL;
     211             : /* Mock for control_write_reply that copies the string for inspection
     212             :  * by tests */
     213             : static void
     214           2 : mock_control_write_reply(control_connection_t *conn, int code, int c,
     215             :                                 const char *s)
     216             : {
     217           2 :   (void)conn;
     218           2 :   (void)code;
     219           2 :   (void)c;
     220           2 :   tor_free(reply_str);
     221           2 :   reply_str = tor_strdup(s);
     222           2 : }
     223             : 
     224             : static void
     225           1 : test_add_onion_helper_keyarg_v3(void *arg)
     226             : {
     227           1 :   int ret, hs_version;
     228           1 :   add_onion_secret_key_t pk;
     229           1 :   char *key_new_blob = NULL;
     230           1 :   const char *key_new_alg = NULL;
     231             : 
     232           1 :   (void) arg;
     233           1 :   MOCK(control_write_reply, mock_control_write_reply);
     234             : 
     235           1 :   memset(&pk, 0, sizeof(pk));
     236             : 
     237             :   /* Test explicit ED25519-V3 key generation. */
     238           1 :   tor_free(reply_str);
     239           1 :   ret = add_onion_helper_keyarg("NEW:ED25519-V3", 0, &key_new_alg,
     240             :                                 &key_new_blob, &pk, &hs_version,
     241             :                                 NULL);
     242           1 :   tt_int_op(ret, OP_EQ, 0);
     243           1 :   tt_int_op(hs_version, OP_EQ, HS_VERSION_THREE);
     244           1 :   tt_assert(pk.v3);
     245           1 :   tt_str_op(key_new_alg, OP_EQ, "ED25519-V3");
     246           1 :   tt_assert(key_new_blob);
     247           1 :   tt_ptr_op(reply_str, OP_EQ, NULL);
     248           1 :   tor_free(pk.v3); pk.v3 = NULL;
     249           1 :   tor_free(key_new_blob);
     250             : 
     251             :   /* Test "BEST" key generation (Assumes BEST = ED25519-V3). */
     252           1 :   tor_free(pk.v3); pk.v3 = NULL;
     253           1 :   tor_free(key_new_blob);
     254           1 :   ret = add_onion_helper_keyarg("NEW:BEST", 0, &key_new_alg, &key_new_blob,
     255             :                                 &pk, &hs_version, NULL);
     256           1 :   tt_int_op(ret, OP_EQ, 0);
     257           1 :   tt_int_op(hs_version, OP_EQ, HS_VERSION_THREE);
     258           1 :   tt_assert(pk.v3);
     259           1 :   tt_str_op(key_new_alg, OP_EQ, "ED25519-V3");
     260           1 :   tt_assert(key_new_blob);
     261           1 :   tt_ptr_op(reply_str, OP_EQ, NULL);
     262             : 
     263             :   /* Test discarding the private key. */
     264           1 :   tor_free(reply_str);
     265           1 :   tor_free(pk.v3); pk.v3 = NULL;
     266           1 :   tor_free(key_new_blob);
     267           1 :   ret = add_onion_helper_keyarg("NEW:ED25519-V3", 1, &key_new_alg,
     268             :                                 &key_new_blob, &pk, &hs_version,
     269             :                                 NULL);
     270           1 :   tt_int_op(ret, OP_EQ, 0);
     271           1 :   tt_int_op(hs_version, OP_EQ, HS_VERSION_THREE);
     272           1 :   tt_assert(pk.v3);
     273           1 :   tt_ptr_op(key_new_alg, OP_EQ, NULL);
     274           1 :   tt_ptr_op(key_new_blob, OP_EQ, NULL);
     275           1 :   tt_ptr_op(reply_str, OP_EQ, NULL);
     276           1 :   tor_free(pk.v3); pk.v3 = NULL;
     277           1 :   tor_free(key_new_blob);
     278             : 
     279             :   /* Test passing a key blob. */
     280             :   {
     281             :     /* The base64 key and hex key are the same. Hex key is 64 bytes long. The
     282             :      * sk has been generated randomly using python3. */
     283           1 :     const char *base64_sk =
     284             :       "a9bT19PqGC9Y+BmOo1IQvCGjjwxMiaaxEXZ+FKMxpEQW"
     285             :       "6AmSV5roThUGMRCaqQSCnR2jI1vL2QxHORzI4RxMmw==";
     286           1 :     const char *hex_sk =
     287             :       "\x6b\xd6\xd3\xd7\xd3\xea\x18\x2f\x58\xf8\x19\x8e\xa3\x52\x10\xbc"
     288             :       "\x21\xa3\x8f\x0c\x4c\x89\xa6\xb1\x11\x76\x7e\x14\xa3\x31\xa4\x44"
     289             :       "\x16\xe8\x09\x92\x57\x9a\xe8\x4e\x15\x06\x31\x10\x9a\xa9\x04\x82"
     290             :       "\x9d\x1d\xa3\x23\x5b\xcb\xd9\x0c\x47\x39\x1c\xc8\xe1\x1c\x4c\x9b";
     291           1 :     char *key_blob = NULL;
     292             : 
     293           1 :     tor_asprintf(&key_blob, "ED25519-V3:%s", base64_sk);
     294           1 :     tt_assert(key_blob);
     295           1 :     tor_free(reply_str);
     296           1 :     ret = add_onion_helper_keyarg(key_blob, 1, &key_new_alg,
     297             :                                   &key_new_blob, &pk, &hs_version,
     298             :                                   NULL);
     299           1 :     tor_free(key_blob);
     300           1 :     tt_int_op(ret, OP_EQ, 0);
     301           1 :     tt_int_op(hs_version, OP_EQ, HS_VERSION_THREE);
     302           1 :     tt_assert(pk.v3);
     303           1 :     tt_mem_op(pk.v3, OP_EQ, hex_sk, 64);
     304           1 :     tt_ptr_op(key_new_alg, OP_EQ, NULL);
     305           1 :     tt_ptr_op(key_new_blob, OP_EQ, NULL);
     306           1 :     tt_ptr_op(reply_str, OP_EQ, NULL);
     307           1 :     tor_free(pk.v3); pk.v3 = NULL;
     308           1 :     tor_free(key_new_blob);
     309             :   }
     310             : 
     311           1 :  done:
     312           1 :   tor_free(pk.v3);
     313           1 :   tor_free(key_new_blob);
     314           1 :   tor_free(reply_str);
     315           1 :   UNMOCK(control_write_reply);
     316           1 : }
     317             : 
     318             : static void
     319           1 : test_getinfo_helper_onion(void *arg)
     320             : {
     321           1 :   (void)arg;
     322           1 :   control_connection_t dummy;
     323             :   /* Get results out */
     324           1 :   char *answer = NULL;
     325           1 :   const char *errmsg = NULL;
     326           1 :   char *service_id = NULL;
     327           1 :   int rt = 0;
     328             : 
     329           1 :   dummy.ephemeral_onion_services = NULL;
     330             : 
     331             :   /* successfully get an empty answer */
     332           1 :   rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
     333           1 :   tt_int_op(rt, OP_EQ, 0);
     334           1 :   tt_str_op(answer, OP_EQ, "");
     335           1 :   tor_free(answer);
     336             : 
     337             :   /* successfully get an empty answer */
     338           1 :   rt = getinfo_helper_onions(&dummy, "onions/detached", &answer, &errmsg);
     339           1 :   tt_int_op(rt, OP_EQ, 0);
     340           1 :   tt_str_op(answer, OP_EQ, "");
     341           1 :   tor_free(answer);
     342             : 
     343             :   /* get an answer for one onion service */
     344           1 :   service_id = tor_strdup("dummy_onion_id");
     345           1 :   dummy.ephemeral_onion_services = smartlist_new();
     346           1 :   smartlist_add(dummy.ephemeral_onion_services, service_id);
     347           1 :   rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
     348           1 :   tt_int_op(rt, OP_EQ, 0);
     349           1 :   tt_str_op(answer, OP_EQ, "dummy_onion_id");
     350             : 
     351           1 :  done:
     352           1 :   tor_free(answer);
     353           1 :   tor_free(service_id);
     354           1 :   smartlist_free(dummy.ephemeral_onion_services);
     355           1 : }
     356             : 
     357             : static void
     358           1 : test_hs_parse_port_config(void *arg)
     359             : {
     360           1 :   const char *sep = ",";
     361           1 :   hs_port_config_t *cfg = NULL;
     362           1 :   char *err_msg = NULL;
     363             : 
     364           1 :   (void)arg;
     365             : 
     366             :   /* Test "VIRTPORT" only. */
     367           1 :   cfg = hs_parse_port_config("80", sep, &err_msg);
     368           1 :   tt_assert(cfg);
     369           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     370             : 
     371             :   /* Test "VIRTPORT,TARGET" (Target is port). */
     372           1 :   hs_port_config_free(cfg);
     373           1 :   cfg = hs_parse_port_config("80,8080", sep, &err_msg);
     374           1 :   tt_assert(cfg);
     375           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     376             : 
     377             :   /* Test "VIRTPORT,TARGET" (Target is IPv4:port). */
     378           1 :   hs_port_config_free(cfg);
     379           1 :   cfg = hs_parse_port_config("80,192.0.2.1:8080", sep, &err_msg);
     380           1 :   tt_assert(cfg);
     381           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     382             : 
     383             :   /* Test "VIRTPORT,TARGET" (Target is IPv6:port). */
     384           1 :   hs_port_config_free(cfg);
     385           1 :   cfg = hs_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg);
     386           1 :   tt_assert(cfg);
     387           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     388           1 :   hs_port_config_free(cfg);
     389           1 :   cfg = NULL;
     390             : 
     391             :   /* XXX: Someone should add tests for AF_UNIX targets if supported. */
     392             : 
     393             :   /* Test empty config. */
     394           1 :   hs_port_config_free(cfg);
     395           1 :   cfg = hs_parse_port_config("", sep, &err_msg);
     396           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     397           1 :   tt_assert(err_msg);
     398             : 
     399             :   /* Test invalid port. */
     400           1 :   tor_free(err_msg);
     401           1 :   cfg = hs_parse_port_config("90001", sep, &err_msg);
     402           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     403           1 :   tt_assert(err_msg);
     404           1 :   tor_free(err_msg);
     405             : 
     406             :   /* unix port */
     407           1 :   cfg = NULL;
     408             : 
     409             :   /* quoted unix port */
     410           1 :   tor_free(err_msg);
     411           1 :   cfg = hs_parse_port_config("100 unix:\"/tmp/foo bar\"",
     412             :                                        " ", &err_msg);
     413           1 :   tt_assert(cfg);
     414           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     415           1 :   hs_port_config_free(cfg);
     416           1 :   cfg = NULL;
     417             : 
     418             :   /* quoted unix port */
     419           1 :   tor_free(err_msg);
     420           1 :   cfg = hs_parse_port_config("100 unix:\"/tmp/foo bar\"",
     421             :                                        " ", &err_msg);
     422           1 :   tt_assert(cfg);
     423           1 :   tt_ptr_op(err_msg, OP_EQ, NULL);
     424           1 :   hs_port_config_free(cfg);
     425           1 :   cfg = NULL;
     426             : 
     427             :   /* quoted unix port, missing end quote */
     428           1 :   cfg = hs_parse_port_config("100 unix:\"/tmp/foo bar",
     429             :                                        " ", &err_msg);
     430           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     431           1 :   tt_str_op(err_msg, OP_EQ, "Couldn't process address <unix:\"/tmp/foo bar> "
     432             :             "from hidden service configuration");
     433           1 :   tor_free(err_msg);
     434             : 
     435             :   /* bogus IP address */
     436           1 :   MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
     437           1 :   cfg = hs_parse_port_config("100 foo!!.example.com:9000",
     438             :                                        " ", &err_msg);
     439           1 :   UNMOCK(tor_addr_lookup);
     440           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     441           1 :   tt_str_op(err_msg, OP_EQ, "Unparseable address in hidden service port "
     442             :             "configuration.");
     443           1 :   tor_free(err_msg);
     444             : 
     445             :   /* bogus port port */
     446           1 :   cfg = hs_parse_port_config("100 99999",
     447             :                                        " ", &err_msg);
     448           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     449           1 :   tt_str_op(err_msg, OP_EQ, "Unparseable or out-of-range port \"99999\" "
     450             :             "in hidden service port configuration.");
     451           1 :   tor_free(err_msg);
     452             : 
     453             :   /* Wrong target address and port separation */
     454           1 :   cfg = hs_parse_port_config("80,127.0.0.1 1234", sep,
     455             :                                        &err_msg);
     456           1 :   tt_ptr_op(cfg, OP_EQ, NULL);
     457           1 :   tt_assert(err_msg);
     458           1 :   tor_free(err_msg);
     459             : 
     460           1 :  done:
     461           1 :   hs_port_config_free(cfg);
     462           1 :   tor_free(err_msg);
     463           1 : }
     464             : 
     465             : /* Mocks and data/variables used for GETINFO download status tests */
     466             : 
     467             : static const download_status_t dl_status_default =
     468             :   { 0, 0, 0, DL_SCHED_CONSENSUS, DL_WANT_ANY_DIRSERVER,
     469             :     DL_SCHED_INCREMENT_FAILURE, 0, 0 };
     470             : static download_status_t ns_dl_status[N_CONSENSUS_FLAVORS];
     471             : static download_status_t ns_dl_status_bootstrap[N_CONSENSUS_FLAVORS];
     472             : static download_status_t ns_dl_status_running[N_CONSENSUS_FLAVORS];
     473             : 
     474             : /*
     475             :  * These should explore all the possible cases of download_status_to_string()
     476             :  * in control.c
     477             :  */
     478             : static const download_status_t dls_sample_1 =
     479             :   { 1467163900, 0, 0, DL_SCHED_GENERIC, DL_WANT_ANY_DIRSERVER,
     480             :     DL_SCHED_INCREMENT_FAILURE, 0, 0 };
     481             : static const char * dls_sample_1_str =
     482             :     "next-attempt-at 2016-06-29 01:31:40\n"
     483             :     "n-download-failures 0\n"
     484             :     "n-download-attempts 0\n"
     485             :     "schedule DL_SCHED_GENERIC\n"
     486             :     "want-authority DL_WANT_ANY_DIRSERVER\n"
     487             :     "increment-on DL_SCHED_INCREMENT_FAILURE\n"
     488             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     489             :     "last-backoff-position 0\n"
     490             :     "last-delay-used 0\n";
     491             : static const download_status_t dls_sample_2 =
     492             :   { 1467164400, 1, 2, DL_SCHED_CONSENSUS, DL_WANT_AUTHORITY,
     493             :     DL_SCHED_INCREMENT_FAILURE, 0, 0 };
     494             : static const char * dls_sample_2_str =
     495             :     "next-attempt-at 2016-06-29 01:40:00\n"
     496             :     "n-download-failures 1\n"
     497             :     "n-download-attempts 2\n"
     498             :     "schedule DL_SCHED_CONSENSUS\n"
     499             :     "want-authority DL_WANT_AUTHORITY\n"
     500             :     "increment-on DL_SCHED_INCREMENT_FAILURE\n"
     501             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     502             :     "last-backoff-position 0\n"
     503             :     "last-delay-used 0\n";
     504             : static const download_status_t dls_sample_3 =
     505             :   { 1467154400, 12, 25, DL_SCHED_BRIDGE, DL_WANT_ANY_DIRSERVER,
     506             :     DL_SCHED_INCREMENT_ATTEMPT, 0, 0 };
     507             : static const char * dls_sample_3_str =
     508             :     "next-attempt-at 2016-06-28 22:53:20\n"
     509             :     "n-download-failures 12\n"
     510             :     "n-download-attempts 25\n"
     511             :     "schedule DL_SCHED_BRIDGE\n"
     512             :     "want-authority DL_WANT_ANY_DIRSERVER\n"
     513             :     "increment-on DL_SCHED_INCREMENT_ATTEMPT\n"
     514             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     515             :     "last-backoff-position 0\n"
     516             :     "last-delay-used 0\n";
     517             : static const download_status_t dls_sample_4 =
     518             :   { 1467166600, 3, 0, DL_SCHED_GENERIC, DL_WANT_ANY_DIRSERVER,
     519             :     DL_SCHED_INCREMENT_FAILURE, 0, 0 };
     520             : static const char * dls_sample_4_str =
     521             :     "next-attempt-at 2016-06-29 02:16:40\n"
     522             :     "n-download-failures 3\n"
     523             :     "n-download-attempts 0\n"
     524             :     "schedule DL_SCHED_GENERIC\n"
     525             :     "want-authority DL_WANT_ANY_DIRSERVER\n"
     526             :     "increment-on DL_SCHED_INCREMENT_FAILURE\n"
     527             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     528             :     "last-backoff-position 0\n"
     529             :     "last-delay-used 0\n";
     530             : static const download_status_t dls_sample_5 =
     531             :   { 1467164600, 3, 7, DL_SCHED_CONSENSUS, DL_WANT_ANY_DIRSERVER,
     532             :     DL_SCHED_INCREMENT_FAILURE, 1, 2112, };
     533             : static const char * dls_sample_5_str =
     534             :     "next-attempt-at 2016-06-29 01:43:20\n"
     535             :     "n-download-failures 3\n"
     536             :     "n-download-attempts 7\n"
     537             :     "schedule DL_SCHED_CONSENSUS\n"
     538             :     "want-authority DL_WANT_ANY_DIRSERVER\n"
     539             :     "increment-on DL_SCHED_INCREMENT_FAILURE\n"
     540             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     541             :     "last-backoff-position 1\n"
     542             :     "last-delay-used 2112\n";
     543             : static const download_status_t dls_sample_6 =
     544             :   { 1467164200, 4, 9, DL_SCHED_CONSENSUS, DL_WANT_AUTHORITY,
     545             :     DL_SCHED_INCREMENT_ATTEMPT, 3, 432 };
     546             : static const char * dls_sample_6_str =
     547             :     "next-attempt-at 2016-06-29 01:36:40\n"
     548             :     "n-download-failures 4\n"
     549             :     "n-download-attempts 9\n"
     550             :     "schedule DL_SCHED_CONSENSUS\n"
     551             :     "want-authority DL_WANT_AUTHORITY\n"
     552             :     "increment-on DL_SCHED_INCREMENT_ATTEMPT\n"
     553             :     "backoff DL_SCHED_RANDOM_EXPONENTIAL\n"
     554             :     "last-backoff-position 3\n"
     555             :     "last-delay-used 432\n";
     556             : 
     557             : /* Simulated auth certs */
     558             : static const char *auth_id_digest_1_str =
     559             :     "63CDD326DFEF0CA020BDD3FEB45A3286FE13A061";
     560             : static download_status_t auth_def_cert_download_status_1;
     561             : static const char *auth_id_digest_2_str =
     562             :     "2C209FCDD8D48DC049777B8DC2C0F94A0408BE99";
     563             : static download_status_t auth_def_cert_download_status_2;
     564             : /* Expected form of digest list returned for GETINFO downloads/cert/fps */
     565             : static const char *auth_id_digest_expected_list =
     566             :     "63CDD326DFEF0CA020BDD3FEB45A3286FE13A061\n"
     567             :     "2C209FCDD8D48DC049777B8DC2C0F94A0408BE99\n";
     568             : 
     569             : /* Signing keys for simulated auth 1 */
     570             : static const char *auth_1_sk_1_str =
     571             :     "AA69566029B1F023BA09451B8F1B10952384EB58";
     572             : static download_status_t auth_1_sk_1_dls;
     573             : static const char *auth_1_sk_2_str =
     574             :     "710865C7F06B73C5292695A8C34F1C94F769FF72";
     575             : static download_status_t auth_1_sk_2_dls;
     576             : /*
     577             :  * Expected form of sk digest list for
     578             :  * GETINFO downloads/cert/<auth_id_digest_1_str>/sks
     579             :  */
     580             : static const char *auth_1_sk_digest_expected_list =
     581             :     "AA69566029B1F023BA09451B8F1B10952384EB58\n"
     582             :     "710865C7F06B73C5292695A8C34F1C94F769FF72\n";
     583             : 
     584             : /* Signing keys for simulated auth 2 */
     585             : static const char *auth_2_sk_1_str =
     586             :     "4299047E00D070AD6703FE00BE7AA756DB061E62";
     587             : static download_status_t auth_2_sk_1_dls;
     588             : static const char *auth_2_sk_2_str =
     589             :     "9451B8F1B10952384EB58B5F230C0BB701626C9B";
     590             : static download_status_t auth_2_sk_2_dls;
     591             : /*
     592             :  * Expected form of sk digest list for
     593             :  * GETINFO downloads/cert/<auth_id_digest_2_str>/sks
     594             :  */
     595             : static const char *auth_2_sk_digest_expected_list =
     596             :     "4299047E00D070AD6703FE00BE7AA756DB061E62\n"
     597             :     "9451B8F1B10952384EB58B5F230C0BB701626C9B\n";
     598             : 
     599             : /* Simulated router descriptor digests or bridge identity digests */
     600             : static const char *descbr_digest_1_str =
     601             :     "616408544C7345822696074A1A3DFA16AB381CBD";
     602             : static download_status_t descbr_digest_1_dl;
     603             : static const char *descbr_digest_2_str =
     604             :     "06E8067246967265DBCB6641631B530EFEC12DC3";
     605             : static download_status_t descbr_digest_2_dl;
     606             : /* Expected form of digest list returned for GETINFO downloads/desc/descs */
     607             : static const char *descbr_expected_list =
     608             :     "616408544C7345822696074A1A3DFA16AB381CBD\n"
     609             :     "06E8067246967265DBCB6641631B530EFEC12DC3\n";
     610             : /*
     611             :  * Flag to make all descbr queries fail, to simulate not being
     612             :  * configured such that such queries make sense.
     613             :  */
     614             : static int disable_descbr = 0;
     615             : 
     616             : static void
     617           4 : reset_mocked_dl_statuses(void)
     618             : {
     619           4 :   int i;
     620             : 
     621          12 :   for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
     622           8 :     memcpy(&(ns_dl_status[i]), &dl_status_default,
     623             :            sizeof(download_status_t));
     624           8 :     memcpy(&(ns_dl_status_bootstrap[i]), &dl_status_default,
     625             :            sizeof(download_status_t));
     626           8 :     memcpy(&(ns_dl_status_running[i]), &dl_status_default,
     627             :            sizeof(download_status_t));
     628             :   }
     629             : 
     630           4 :   memcpy(&auth_def_cert_download_status_1, &dl_status_default,
     631             :          sizeof(download_status_t));
     632           4 :   memcpy(&auth_def_cert_download_status_2, &dl_status_default,
     633             :          sizeof(download_status_t));
     634           4 :   memcpy(&auth_1_sk_1_dls, &dl_status_default,
     635             :          sizeof(download_status_t));
     636           4 :   memcpy(&auth_1_sk_2_dls, &dl_status_default,
     637             :          sizeof(download_status_t));
     638           4 :   memcpy(&auth_2_sk_1_dls, &dl_status_default,
     639             :          sizeof(download_status_t));
     640           4 :   memcpy(&auth_2_sk_2_dls, &dl_status_default,
     641             :          sizeof(download_status_t));
     642             : 
     643           4 :   memcpy(&descbr_digest_1_dl, &dl_status_default,
     644             :          sizeof(download_status_t));
     645           4 :   memcpy(&descbr_digest_2_dl, &dl_status_default,
     646             :          sizeof(download_status_t));
     647           4 : }
     648             : 
     649             : static download_status_t *
     650           2 : ns_dl_status_mock(consensus_flavor_t flavor)
     651             : {
     652           2 :   return &(ns_dl_status[flavor]);
     653             : }
     654             : 
     655             : static download_status_t *
     656           2 : ns_dl_status_bootstrap_mock(consensus_flavor_t flavor)
     657             : {
     658           2 :   return &(ns_dl_status_bootstrap[flavor]);
     659             : }
     660             : 
     661             : static download_status_t *
     662           2 : ns_dl_status_running_mock(consensus_flavor_t flavor)
     663             : {
     664           2 :   return &(ns_dl_status_running[flavor]);
     665             : }
     666             : 
     667             : static void
     668           1 : setup_ns_mocks(void)
     669             : {
     670           1 :   MOCK(networkstatus_get_dl_status_by_flavor, ns_dl_status_mock);
     671           1 :   MOCK(networkstatus_get_dl_status_by_flavor_bootstrap,
     672             :        ns_dl_status_bootstrap_mock);
     673           1 :   MOCK(networkstatus_get_dl_status_by_flavor_running,
     674             :        ns_dl_status_running_mock);
     675           1 :   reset_mocked_dl_statuses();
     676           1 : }
     677             : 
     678             : static void
     679           1 : clear_ns_mocks(void)
     680             : {
     681           1 :   UNMOCK(networkstatus_get_dl_status_by_flavor);
     682           1 :   UNMOCK(networkstatus_get_dl_status_by_flavor_bootstrap);
     683           1 :   UNMOCK(networkstatus_get_dl_status_by_flavor_running);
     684           1 : }
     685             : 
     686             : static smartlist_t *
     687           1 : cert_dl_status_auth_ids_mock(void)
     688             : {
     689           1 :   char digest[DIGEST_LEN], *tmp;
     690           1 :   int len;
     691           1 :   smartlist_t *list = NULL;
     692             : 
     693             :   /* Just pretend we have only the two hard-coded digests listed above */
     694           1 :   list = smartlist_new();
     695           1 :   len = base16_decode(digest, DIGEST_LEN,
     696             :                       auth_id_digest_1_str, strlen(auth_id_digest_1_str));
     697           1 :   tt_int_op(len, OP_EQ, DIGEST_LEN);
     698           1 :   tmp = tor_malloc(DIGEST_LEN);
     699           1 :   memcpy(tmp, digest, DIGEST_LEN);
     700           1 :   smartlist_add(list, tmp);
     701           1 :   len = base16_decode(digest, DIGEST_LEN,
     702             :                       auth_id_digest_2_str, strlen(auth_id_digest_2_str));
     703           1 :   tt_int_op(len, OP_EQ, DIGEST_LEN);
     704           1 :   tmp = tor_malloc(DIGEST_LEN);
     705           1 :   memcpy(tmp, digest, DIGEST_LEN);
     706           1 :   smartlist_add(list, tmp);
     707             : 
     708           1 :  done:
     709           1 :   return list;
     710             : }
     711             : 
     712             : static download_status_t *
     713           3 : cert_dl_status_def_for_auth_mock(const char *digest)
     714             : {
     715           3 :   download_status_t *dl = NULL;
     716           3 :   char digest_str[HEX_DIGEST_LEN+1];
     717             : 
     718           3 :   tt_ptr_op(digest, OP_NE, NULL);
     719           3 :   base16_encode(digest_str, HEX_DIGEST_LEN + 1,
     720             :                 digest, DIGEST_LEN);
     721           3 :   digest_str[HEX_DIGEST_LEN] = '\0';
     722             : 
     723           3 :   if (strcmp(digest_str, auth_id_digest_1_str) == 0) {
     724             :     dl = &auth_def_cert_download_status_1;
     725           2 :   } else if (strcmp(digest_str, auth_id_digest_2_str) == 0) {
     726           1 :     dl = &auth_def_cert_download_status_2;
     727             :   }
     728             : 
     729           1 :  done:
     730           3 :   return dl;
     731             : }
     732             : 
     733             : static smartlist_t *
     734           3 : cert_dl_status_sks_for_auth_id_mock(const char *digest)
     735             : {
     736           3 :   smartlist_t *list = NULL;
     737           3 :   char sk[DIGEST_LEN];
     738           3 :   char digest_str[HEX_DIGEST_LEN+1];
     739           3 :   char *tmp;
     740           3 :   int len;
     741             : 
     742           3 :   tt_ptr_op(digest, OP_NE, NULL);
     743           3 :   base16_encode(digest_str, HEX_DIGEST_LEN + 1,
     744             :                 digest, DIGEST_LEN);
     745           3 :   digest_str[HEX_DIGEST_LEN] = '\0';
     746             : 
     747             :   /*
     748             :    * Build a list of two hard-coded digests, depending on what we
     749             :    * were just passed.
     750             :    */
     751           3 :   if (strcmp(digest_str, auth_id_digest_1_str) == 0) {
     752           1 :     list = smartlist_new();
     753           1 :     len = base16_decode(sk, DIGEST_LEN,
     754             :                         auth_1_sk_1_str, strlen(auth_1_sk_1_str));
     755           1 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     756           1 :     tmp = tor_malloc(DIGEST_LEN);
     757           1 :     memcpy(tmp, sk, DIGEST_LEN);
     758           1 :     smartlist_add(list, tmp);
     759           1 :     len = base16_decode(sk, DIGEST_LEN,
     760             :                         auth_1_sk_2_str, strlen(auth_1_sk_2_str));
     761           1 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     762           1 :     tmp = tor_malloc(DIGEST_LEN);
     763           1 :     memcpy(tmp, sk, DIGEST_LEN);
     764           1 :     smartlist_add(list, tmp);
     765           2 :   } else if (strcmp(digest_str, auth_id_digest_2_str) == 0) {
     766           1 :     list = smartlist_new();
     767           1 :     len = base16_decode(sk, DIGEST_LEN,
     768             :                         auth_2_sk_1_str, strlen(auth_2_sk_1_str));
     769           1 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     770           1 :     tmp = tor_malloc(DIGEST_LEN);
     771           1 :     memcpy(tmp, sk, DIGEST_LEN);
     772           1 :     smartlist_add(list, tmp);
     773           1 :     len = base16_decode(sk, DIGEST_LEN,
     774             :                         auth_2_sk_2_str, strlen(auth_2_sk_2_str));
     775           1 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     776           1 :     tmp = tor_malloc(DIGEST_LEN);
     777           1 :     memcpy(tmp, sk, DIGEST_LEN);
     778           1 :     smartlist_add(list, tmp);
     779             :   }
     780             : 
     781           1 :  done:
     782           3 :   return list;
     783             : }
     784             : 
     785             : static download_status_t *
     786           7 : cert_dl_status_fp_sk_mock(const char *fp_digest, const char *sk_digest)
     787             : {
     788           7 :   download_status_t *dl = NULL;
     789           7 :   char fp_digest_str[HEX_DIGEST_LEN+1], sk_digest_str[HEX_DIGEST_LEN+1];
     790             : 
     791             :   /*
     792             :    * Unpack the digests so we can compare them and figure out which
     793             :    * dl status we want.
     794             :    */
     795             : 
     796           7 :   tt_ptr_op(fp_digest, OP_NE, NULL);
     797           7 :   base16_encode(fp_digest_str, HEX_DIGEST_LEN + 1,
     798             :                 fp_digest, DIGEST_LEN);
     799           7 :   fp_digest_str[HEX_DIGEST_LEN] = '\0';
     800           7 :   tt_ptr_op(sk_digest, OP_NE, NULL);
     801           7 :   base16_encode(sk_digest_str, HEX_DIGEST_LEN + 1,
     802             :                 sk_digest, DIGEST_LEN);
     803           7 :   sk_digest_str[HEX_DIGEST_LEN] = '\0';
     804             : 
     805           7 :   if (strcmp(fp_digest_str, auth_id_digest_1_str) == 0) {
     806           4 :     if (strcmp(sk_digest_str, auth_1_sk_1_str) == 0) {
     807             :       dl = &auth_1_sk_1_dls;
     808           3 :     } else if (strcmp(sk_digest_str, auth_1_sk_2_str) == 0) {
     809           1 :       dl = &auth_1_sk_2_dls;
     810             :     }
     811           3 :   } else if (strcmp(fp_digest_str, auth_id_digest_2_str) == 0) {
     812           2 :     if (strcmp(sk_digest_str, auth_2_sk_1_str) == 0) {
     813             :       dl = &auth_2_sk_1_dls;
     814           1 :     } else if (strcmp(sk_digest_str, auth_2_sk_2_str) == 0) {
     815           1 :       dl = &auth_2_sk_2_dls;
     816             :     }
     817             :   }
     818             : 
     819           1 :  done:
     820           7 :   return dl;
     821             : }
     822             : 
     823             : static void
     824           1 : setup_cert_mocks(void)
     825             : {
     826           1 :   MOCK(list_authority_ids_with_downloads, cert_dl_status_auth_ids_mock);
     827           1 :   MOCK(id_only_download_status_for_authority_id,
     828             :        cert_dl_status_def_for_auth_mock);
     829           1 :   MOCK(list_sk_digests_for_authority_id,
     830             :        cert_dl_status_sks_for_auth_id_mock);
     831           1 :   MOCK(download_status_for_authority_id_and_sk,
     832             :        cert_dl_status_fp_sk_mock);
     833           1 :   reset_mocked_dl_statuses();
     834           1 : }
     835             : 
     836             : static void
     837           1 : clear_cert_mocks(void)
     838             : {
     839           1 :   UNMOCK(list_authority_ids_with_downloads);
     840           1 :   UNMOCK(id_only_download_status_for_authority_id);
     841           1 :   UNMOCK(list_sk_digests_for_authority_id);
     842           1 :   UNMOCK(download_status_for_authority_id_and_sk);
     843           1 : }
     844             : 
     845             : static smartlist_t *
     846           4 : descbr_get_digests_mock(void)
     847             : {
     848           4 :   char digest[DIGEST_LEN], *tmp;
     849           4 :   int len;
     850           4 :   smartlist_t *list = NULL;
     851             : 
     852           4 :   if (!disable_descbr) {
     853             :     /* Just pretend we have only the two hard-coded digests listed above */
     854           2 :     list = smartlist_new();
     855           2 :     len = base16_decode(digest, DIGEST_LEN,
     856             :                         descbr_digest_1_str, strlen(descbr_digest_1_str));
     857           2 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     858           2 :     tmp = tor_malloc(DIGEST_LEN);
     859           2 :     memcpy(tmp, digest, DIGEST_LEN);
     860           2 :     smartlist_add(list, tmp);
     861           2 :     len = base16_decode(digest, DIGEST_LEN,
     862             :                         descbr_digest_2_str, strlen(descbr_digest_2_str));
     863           2 :     tt_int_op(len, OP_EQ, DIGEST_LEN);
     864           2 :     tmp = tor_malloc(DIGEST_LEN);
     865           2 :     memcpy(tmp, digest, DIGEST_LEN);
     866           2 :     smartlist_add(list, tmp);
     867             :   }
     868             : 
     869           2 :  done:
     870           4 :   return list;
     871             : }
     872             : 
     873             : static download_status_t *
     874           6 : descbr_get_dl_by_digest_mock(const char *digest)
     875             : {
     876           6 :   download_status_t *dl = NULL;
     877           6 :   char digest_str[HEX_DIGEST_LEN+1];
     878             : 
     879           6 :   if (!disable_descbr) {
     880           6 :     tt_ptr_op(digest, OP_NE, NULL);
     881           6 :     base16_encode(digest_str, HEX_DIGEST_LEN + 1,
     882             :                   digest, DIGEST_LEN);
     883           6 :     digest_str[HEX_DIGEST_LEN] = '\0';
     884             : 
     885           6 :     if (strcmp(digest_str, descbr_digest_1_str) == 0) {
     886             :       dl = &descbr_digest_1_dl;
     887           4 :     } else if (strcmp(digest_str, descbr_digest_2_str) == 0) {
     888           2 :       dl = &descbr_digest_2_dl;
     889             :     }
     890             :   }
     891             : 
     892           2 :  done:
     893           6 :   return dl;
     894             : }
     895             : 
     896             : static void
     897           1 : setup_desc_mocks(void)
     898             : {
     899           1 :   MOCK(router_get_descriptor_digests,
     900             :        descbr_get_digests_mock);
     901           1 :   MOCK(router_get_dl_status_by_descriptor_digest,
     902             :        descbr_get_dl_by_digest_mock);
     903           1 :   reset_mocked_dl_statuses();
     904           1 : }
     905             : 
     906             : static void
     907           1 : clear_desc_mocks(void)
     908             : {
     909           1 :   UNMOCK(router_get_descriptor_digests);
     910           1 :   UNMOCK(router_get_dl_status_by_descriptor_digest);
     911           1 : }
     912             : 
     913             : static void
     914           1 : setup_bridge_mocks(void)
     915             : {
     916           1 :   disable_descbr = 0;
     917             : 
     918           1 :   MOCK(list_bridge_identities,
     919             :        descbr_get_digests_mock);
     920           1 :   MOCK(get_bridge_dl_status_by_id,
     921             :        descbr_get_dl_by_digest_mock);
     922           1 :   reset_mocked_dl_statuses();
     923           1 : }
     924             : 
     925             : static void
     926           1 : clear_bridge_mocks(void)
     927             : {
     928           1 :   UNMOCK(list_bridge_identities);
     929           1 :   UNMOCK(get_bridge_dl_status_by_id);
     930             : 
     931           1 :   disable_descbr = 0;
     932           1 : }
     933             : 
     934             : static void
     935           1 : test_download_status_consensus(void *arg)
     936             : {
     937             :   /* We just need one of these to pass, it doesn't matter what's in it */
     938           1 :   control_connection_t dummy;
     939             :   /* Get results out */
     940           1 :   char *answer = NULL;
     941           1 :   const char *errmsg = NULL;
     942             : 
     943           1 :   (void)arg;
     944             : 
     945             :   /* Check that the unknown prefix case works; no mocks needed yet */
     946           1 :   getinfo_helper_downloads(&dummy, "downloads/foo", &answer, &errmsg);
     947           1 :   tt_ptr_op(answer, OP_EQ, NULL);
     948           1 :   tt_str_op(errmsg, OP_EQ, "Unknown download status query");
     949             : 
     950           1 :   setup_ns_mocks();
     951             : 
     952             :   /*
     953             :    * Check returning serialized dlstatuses, and implicitly also test
     954             :    * download_status_to_string().
     955             :    */
     956             : 
     957             :   /* Case 1 default/FLAV_NS*/
     958           1 :   memcpy(&(ns_dl_status[FLAV_NS]), &dls_sample_1,
     959             :          sizeof(download_status_t));
     960           1 :   getinfo_helper_downloads(&dummy, "downloads/networkstatus/ns",
     961             :                            &answer, &errmsg);
     962           1 :   tt_ptr_op(answer, OP_NE, NULL);
     963           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
     964           1 :   tt_str_op(answer, OP_EQ, dls_sample_1_str);
     965           1 :   tor_free(answer);
     966           1 :   errmsg = NULL;
     967             : 
     968             :   /* Case 2 default/FLAV_MICRODESC */
     969           1 :   memcpy(&(ns_dl_status[FLAV_MICRODESC]), &dls_sample_2,
     970             :          sizeof(download_status_t));
     971           1 :   getinfo_helper_downloads(&dummy, "downloads/networkstatus/microdesc",
     972             :                            &answer, &errmsg);
     973           1 :   tt_ptr_op(answer, OP_NE, NULL);
     974           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
     975           1 :   tt_str_op(answer, OP_EQ, dls_sample_2_str);
     976           1 :   tor_free(answer);
     977           1 :   errmsg = NULL;
     978             : 
     979             :   /* Case 3 bootstrap/FLAV_NS */
     980           1 :   memcpy(&(ns_dl_status_bootstrap[FLAV_NS]), &dls_sample_3,
     981             :          sizeof(download_status_t));
     982           1 :   getinfo_helper_downloads(&dummy, "downloads/networkstatus/ns/bootstrap",
     983             :                            &answer, &errmsg);
     984           1 :   tt_ptr_op(answer, OP_NE, NULL);
     985           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
     986           1 :   tt_str_op(answer, OP_EQ, dls_sample_3_str);
     987           1 :   tor_free(answer);
     988           1 :   errmsg = NULL;
     989             : 
     990             :   /* Case 4 bootstrap/FLAV_MICRODESC */
     991           1 :   memcpy(&(ns_dl_status_bootstrap[FLAV_MICRODESC]), &dls_sample_4,
     992             :          sizeof(download_status_t));
     993           1 :   getinfo_helper_downloads(&dummy,
     994             :                            "downloads/networkstatus/microdesc/bootstrap",
     995             :                            &answer, &errmsg);
     996           1 :   tt_ptr_op(answer, OP_NE, NULL);
     997           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
     998           1 :   tt_str_op(answer, OP_EQ, dls_sample_4_str);
     999           1 :   tor_free(answer);
    1000           1 :   errmsg = NULL;
    1001             : 
    1002             :   /* Case 5 running/FLAV_NS */
    1003           1 :   memcpy(&(ns_dl_status_running[FLAV_NS]), &dls_sample_5,
    1004             :          sizeof(download_status_t));
    1005           1 :   getinfo_helper_downloads(&dummy,
    1006             :                            "downloads/networkstatus/ns/running",
    1007             :                            &answer, &errmsg);
    1008           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1009           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1010           1 :   tt_str_op(answer, OP_EQ, dls_sample_5_str);
    1011           1 :   tor_free(answer);
    1012           1 :   errmsg = NULL;
    1013             : 
    1014             :   /* Case 6 running/FLAV_MICRODESC */
    1015           1 :   memcpy(&(ns_dl_status_running[FLAV_MICRODESC]), &dls_sample_6,
    1016             :          sizeof(download_status_t));
    1017           1 :   getinfo_helper_downloads(&dummy,
    1018             :                            "downloads/networkstatus/microdesc/running",
    1019             :                            &answer, &errmsg);
    1020           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1021           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1022           1 :   tt_str_op(answer, OP_EQ, dls_sample_6_str);
    1023           1 :   tor_free(answer);
    1024           1 :   errmsg = NULL;
    1025             : 
    1026             :   /* Now check the error case */
    1027           1 :   getinfo_helper_downloads(&dummy, "downloads/networkstatus/foo",
    1028             :                            &answer, &errmsg);
    1029           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1030           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1031           1 :   tt_str_op(errmsg, OP_EQ, "Unknown flavor");
    1032           1 :   errmsg = NULL;
    1033             : 
    1034           1 :  done:
    1035           1 :   clear_ns_mocks();
    1036           1 :   tor_free(answer);
    1037             : 
    1038           1 :   return;
    1039             : }
    1040             : 
    1041             : static void
    1042           1 : test_download_status_cert(void *arg)
    1043             : {
    1044             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1045           1 :   control_connection_t dummy;
    1046             :   /* Get results out */
    1047           1 :   char *question = NULL;
    1048           1 :   char *answer = NULL;
    1049           1 :   const char *errmsg = NULL;
    1050             : 
    1051           1 :   (void)arg;
    1052             : 
    1053           1 :   setup_cert_mocks();
    1054             : 
    1055             :   /*
    1056             :    * Check returning serialized dlstatuses and digest lists, and implicitly
    1057             :    * also test download_status_to_string() and digest_list_to_string().
    1058             :    */
    1059             : 
    1060             :   /* Case 1 - list of authority identity fingerprints */
    1061           1 :   getinfo_helper_downloads(&dummy,
    1062             :                            "downloads/cert/fps",
    1063             :                            &answer, &errmsg);
    1064           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1065           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1066           1 :   tt_str_op(answer, OP_EQ, auth_id_digest_expected_list);
    1067           1 :   tor_free(answer);
    1068           1 :   errmsg = NULL;
    1069             : 
    1070             :   /* Case 2 - download status for default cert for 1st auth id */
    1071           1 :   memcpy(&auth_def_cert_download_status_1, &dls_sample_1,
    1072             :          sizeof(download_status_t));
    1073           1 :   tor_asprintf(&question, "downloads/cert/fp/%s", auth_id_digest_1_str);
    1074           1 :   tt_ptr_op(question, OP_NE, NULL);
    1075           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1076           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1077           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1078           1 :   tt_str_op(answer, OP_EQ, dls_sample_1_str);
    1079           1 :   tor_free(question);
    1080           1 :   tor_free(answer);
    1081           1 :   errmsg = NULL;
    1082             : 
    1083             :   /* Case 3 - download status for default cert for 2nd auth id */
    1084           1 :   memcpy(&auth_def_cert_download_status_2, &dls_sample_2,
    1085             :          sizeof(download_status_t));
    1086           1 :   tor_asprintf(&question, "downloads/cert/fp/%s", auth_id_digest_2_str);
    1087           1 :   tt_ptr_op(question, OP_NE, NULL);
    1088           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1089           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1090           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1091           1 :   tt_str_op(answer, OP_EQ, dls_sample_2_str);
    1092           1 :   tor_free(question);
    1093           1 :   tor_free(answer);
    1094           1 :   errmsg = NULL;
    1095             : 
    1096             :   /* Case 4 - list of signing key digests for 1st auth id */
    1097           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/sks", auth_id_digest_1_str);
    1098           1 :   tt_ptr_op(question, OP_NE, NULL);
    1099           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1100           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1101           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1102           1 :   tt_str_op(answer, OP_EQ, auth_1_sk_digest_expected_list);
    1103           1 :   tor_free(question);
    1104           1 :   tor_free(answer);
    1105           1 :   errmsg = NULL;
    1106             : 
    1107             :   /* Case 5 - list of signing key digests for 2nd auth id */
    1108           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/sks", auth_id_digest_2_str);
    1109           1 :   tt_ptr_op(question, OP_NE, NULL);
    1110           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1111           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1112           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1113           1 :   tt_str_op(answer, OP_EQ, auth_2_sk_digest_expected_list);
    1114           1 :   tor_free(question);
    1115           1 :   tor_free(answer);
    1116           1 :   errmsg = NULL;
    1117             : 
    1118             :   /* Case 6 - download status for 1st auth id, 1st sk */
    1119           1 :   memcpy(&auth_1_sk_1_dls, &dls_sample_3,
    1120             :          sizeof(download_status_t));
    1121           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/%s",
    1122             :                auth_id_digest_1_str, auth_1_sk_1_str);
    1123           1 :   tt_ptr_op(question, OP_NE, NULL);
    1124           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1125           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1126           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1127           1 :   tt_str_op(answer, OP_EQ, dls_sample_3_str);
    1128           1 :   tor_free(question);
    1129           1 :   tor_free(answer);
    1130           1 :   errmsg = NULL;
    1131             : 
    1132             :   /* Case 7 - download status for 1st auth id, 2nd sk */
    1133           1 :   memcpy(&auth_1_sk_2_dls, &dls_sample_4,
    1134             :          sizeof(download_status_t));
    1135           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/%s",
    1136             :                auth_id_digest_1_str, auth_1_sk_2_str);
    1137           1 :   tt_ptr_op(question, OP_NE, NULL);
    1138           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1139           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1140           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1141           1 :   tt_str_op(answer, OP_EQ, dls_sample_4_str);
    1142           1 :   tor_free(question);
    1143           1 :   tor_free(answer);
    1144           1 :   errmsg = NULL;
    1145             : 
    1146             :   /* Case 8 - download status for 2nd auth id, 1st sk */
    1147           1 :   memcpy(&auth_2_sk_1_dls, &dls_sample_5,
    1148             :          sizeof(download_status_t));
    1149           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/%s",
    1150             :                auth_id_digest_2_str, auth_2_sk_1_str);
    1151           1 :   tt_ptr_op(question, OP_NE, NULL);
    1152           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1153           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1154           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1155           1 :   tt_str_op(answer, OP_EQ, dls_sample_5_str);
    1156           1 :   tor_free(question);
    1157           1 :   tor_free(answer);
    1158           1 :   errmsg = NULL;
    1159             : 
    1160             :   /* Case 9 - download status for 2nd auth id, 2nd sk */
    1161           1 :   memcpy(&auth_2_sk_2_dls, &dls_sample_6,
    1162             :          sizeof(download_status_t));
    1163           1 :   tor_asprintf(&question, "downloads/cert/fp/%s/%s",
    1164             :                auth_id_digest_2_str, auth_2_sk_2_str);
    1165           1 :   tt_ptr_op(question, OP_NE, NULL);
    1166           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1167           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1168           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1169           1 :   tt_str_op(answer, OP_EQ, dls_sample_6_str);
    1170           1 :   tor_free(question);
    1171           1 :   tor_free(answer);
    1172           1 :   errmsg = NULL;
    1173             : 
    1174             :   /* Now check the error cases */
    1175             : 
    1176             :   /* Case 1 - query is garbage after downloads/cert/ part */
    1177           1 :   getinfo_helper_downloads(&dummy, "downloads/cert/blahdeblah",
    1178             :                            &answer, &errmsg);
    1179           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1180           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1181           1 :   tt_str_op(errmsg, OP_EQ, "Unknown certificate download status query");
    1182           1 :   errmsg = NULL;
    1183             : 
    1184             :   /*
    1185             :    * Case 2 - looks like downloads/cert/fp/<fp>, but <fp> isn't even
    1186             :    * the right length for a digest.
    1187             :    */
    1188           1 :   getinfo_helper_downloads(&dummy, "downloads/cert/fp/2B1D36D32B2942406",
    1189             :                            &answer, &errmsg);
    1190           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1191           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1192           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a digest");
    1193           1 :   errmsg = NULL;
    1194             : 
    1195             :   /*
    1196             :    * Case 3 - looks like downloads/cert/fp/<fp>, and <fp> is digest-sized,
    1197             :    * but not parseable as one.
    1198             :    */
    1199           1 :   getinfo_helper_downloads(&dummy,
    1200             :       "downloads/cert/fp/82F52AF55D250115FE44D3GC81D49643241D56A1",
    1201             :       &answer, &errmsg);
    1202           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1203           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1204           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a digest");
    1205           1 :   errmsg = NULL;
    1206             : 
    1207             :   /*
    1208             :    * Case 4 - downloads/cert/fp/<fp>, and <fp> is not a known authority
    1209             :    * identity digest
    1210             :    */
    1211           1 :   getinfo_helper_downloads(&dummy,
    1212             :       "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61",
    1213             :       &answer, &errmsg);
    1214           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1215           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1216           1 :   tt_str_op(errmsg, OP_EQ,
    1217             :       "Failed to get download status for this authority identity digest");
    1218           1 :   errmsg = NULL;
    1219             : 
    1220             :   /*
    1221             :    * Case 5 - looks like downloads/cert/fp/<fp>/<anything>, but <fp> doesn't
    1222             :    * parse as a sensible digest.
    1223             :    */
    1224           1 :   getinfo_helper_downloads(&dummy,
    1225             :       "downloads/cert/fp/82F52AF55D250115FE44D3GC81D49643241D56A1/blah",
    1226             :       &answer, &errmsg);
    1227           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1228           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1229           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like an identity digest");
    1230           1 :   errmsg = NULL;
    1231             : 
    1232             :   /*
    1233             :    * Case 6 - looks like downloads/cert/fp/<fp>/<anything>, but <fp> doesn't
    1234             :    * parse as a sensible digest.
    1235             :    */
    1236           1 :   getinfo_helper_downloads(&dummy,
    1237             :       "downloads/cert/fp/82F52AF55D25/blah",
    1238             :       &answer, &errmsg);
    1239           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1240           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1241           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like an identity digest");
    1242           1 :   errmsg = NULL;
    1243             : 
    1244             :   /*
    1245             :    * Case 7 - downloads/cert/fp/<fp>/sks, and <fp> is not a known authority
    1246             :    * digest.
    1247             :    */
    1248           1 :   getinfo_helper_downloads(&dummy,
    1249             :       "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/sks",
    1250             :       &answer, &errmsg);
    1251           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1252           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1253           1 :   tt_str_op(errmsg, OP_EQ,
    1254             :       "Failed to get list of signing key digests for this authority "
    1255             :       "identity digest");
    1256           1 :   errmsg = NULL;
    1257             : 
    1258             :   /*
    1259             :    * Case 8 - looks like downloads/cert/fp/<fp>/<sk>, but <sk> doesn't
    1260             :    * parse as a signing key digest.
    1261             :    */
    1262           1 :   getinfo_helper_downloads(&dummy,
    1263             :       "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/"
    1264             :       "82F52AF55D250115FE44D3GC81D49643241D56A1",
    1265             :       &answer, &errmsg);
    1266           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1267           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1268           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a signing key digest");
    1269           1 :   errmsg = NULL;
    1270             : 
    1271             :   /*
    1272             :    * Case 9 - looks like downloads/cert/fp/<fp>/<sk>, but <sk> doesn't
    1273             :    * parse as a signing key digest.
    1274             :    */
    1275           1 :   getinfo_helper_downloads(&dummy,
    1276             :       "downloads/cert/fp/AC4F23B5745BDD2A77997B85B1FD85D05C2E0F61/"
    1277             :       "82F52AF55D250115FE44D",
    1278             :       &answer, &errmsg);
    1279           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1280           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1281           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a signing key digest");
    1282           1 :   errmsg = NULL;
    1283             : 
    1284             :   /*
    1285             :    * Case 10 - downloads/cert/fp/<fp>/<sk>, but <fp> isn't a known
    1286             :    * authority identity digest.
    1287             :    */
    1288           1 :   getinfo_helper_downloads(&dummy,
    1289             :       "downloads/cert/fp/C6B05DF332F74DB9A13498EE3BBC7AA2F69FCB45/"
    1290             :       "3A214FC21AE25B012C2ECCB5F4EC8A3602D0545D",
    1291             :       &answer, &errmsg);
    1292           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1293           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1294           1 :   tt_str_op(errmsg, OP_EQ,
    1295             :       "Failed to get download status for this identity/"
    1296             :       "signing key digest pair");
    1297           1 :   errmsg = NULL;
    1298             : 
    1299             :   /*
    1300             :    * Case 11 - downloads/cert/fp/<fp>/<sk>, but <sk> isn't a known
    1301             :    * signing key digest.
    1302             :    */
    1303           1 :   getinfo_helper_downloads(&dummy,
    1304             :       "downloads/cert/fp/63CDD326DFEF0CA020BDD3FEB45A3286FE13A061/"
    1305             :       "3A214FC21AE25B012C2ECCB5F4EC8A3602D0545D",
    1306             :       &answer, &errmsg);
    1307           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1308           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1309           1 :   tt_str_op(errmsg, OP_EQ,
    1310             :       "Failed to get download status for this identity/"
    1311             :       "signing key digest pair");
    1312           1 :   errmsg = NULL;
    1313             : 
    1314             :   /*
    1315             :    * Case 12 - downloads/cert/fp/<fp>/<sk>, but <sk> is on the list for
    1316             :    * a different authority identity digest.
    1317             :    */
    1318           1 :   getinfo_helper_downloads(&dummy,
    1319             :       "downloads/cert/fp/63CDD326DFEF0CA020BDD3FEB45A3286FE13A061/"
    1320             :       "9451B8F1B10952384EB58B5F230C0BB701626C9B",
    1321             :       &answer, &errmsg);
    1322           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1323           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1324           1 :   tt_str_op(errmsg, OP_EQ,
    1325             :       "Failed to get download status for this identity/"
    1326             :       "signing key digest pair");
    1327           1 :   errmsg = NULL;
    1328             : 
    1329           1 :  done:
    1330           1 :   clear_cert_mocks();
    1331           1 :   tor_free(answer);
    1332             : 
    1333           1 :   return;
    1334             : }
    1335             : 
    1336             : static void
    1337           1 : test_download_status_desc(void *arg)
    1338             : {
    1339             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1340           1 :   control_connection_t dummy;
    1341             :   /* Get results out */
    1342           1 :   char *question = NULL;
    1343           1 :   char *answer = NULL;
    1344           1 :   const char *errmsg = NULL;
    1345             : 
    1346           1 :   (void)arg;
    1347             : 
    1348           1 :   setup_desc_mocks();
    1349             : 
    1350             :   /*
    1351             :    * Check returning serialized dlstatuses and digest lists, and implicitly
    1352             :    * also test download_status_to_string() and digest_list_to_string().
    1353             :    */
    1354             : 
    1355             :   /* Case 1 - list of router descriptor digests */
    1356           1 :   getinfo_helper_downloads(&dummy,
    1357             :                            "downloads/desc/descs",
    1358             :                            &answer, &errmsg);
    1359           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1360           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1361           1 :   tt_str_op(answer, OP_EQ, descbr_expected_list);
    1362           1 :   tor_free(answer);
    1363           1 :   errmsg = NULL;
    1364             : 
    1365             :   /* Case 2 - get download status for router descriptor 1 */
    1366           1 :   memcpy(&descbr_digest_1_dl, &dls_sample_1,
    1367             :          sizeof(download_status_t));
    1368           1 :   tor_asprintf(&question, "downloads/desc/%s", descbr_digest_1_str);
    1369           1 :   tt_ptr_op(question, OP_NE, NULL);
    1370           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1371           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1372           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1373           1 :   tt_str_op(answer, OP_EQ, dls_sample_1_str);
    1374           1 :   tor_free(question);
    1375           1 :   tor_free(answer);
    1376           1 :   errmsg = NULL;
    1377             : 
    1378             :   /* Case 3 - get download status for router descriptor 1 */
    1379           1 :   memcpy(&descbr_digest_2_dl, &dls_sample_2,
    1380             :          sizeof(download_status_t));
    1381           1 :   tor_asprintf(&question, "downloads/desc/%s", descbr_digest_2_str);
    1382           1 :   tt_ptr_op(question, OP_NE, NULL);
    1383           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1384           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1385           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1386           1 :   tt_str_op(answer, OP_EQ, dls_sample_2_str);
    1387           1 :   tor_free(question);
    1388           1 :   tor_free(answer);
    1389           1 :   errmsg = NULL;
    1390             : 
    1391             :   /* Now check the error cases */
    1392             : 
    1393             :   /* Case 1 - non-digest-length garbage after downloads/desc */
    1394           1 :   getinfo_helper_downloads(&dummy, "downloads/desc/blahdeblah",
    1395             :                            &answer, &errmsg);
    1396           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1397           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1398           1 :   tt_str_op(errmsg, OP_EQ, "Unknown router descriptor download status query");
    1399           1 :   errmsg = NULL;
    1400             : 
    1401             :   /* Case 2 - nonparseable digest-shaped thing */
    1402           1 :   getinfo_helper_downloads(
    1403             :     &dummy,
    1404             :     "downloads/desc/774EC52FD9A5B80A6FACZE536616E8022E3470AG",
    1405             :     &answer, &errmsg);
    1406           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1407           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1408           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a digest");
    1409           1 :   errmsg = NULL;
    1410             : 
    1411             :   /* Case 3 - digest we have no descriptor for */
    1412           1 :   getinfo_helper_downloads(
    1413             :     &dummy,
    1414             :     "downloads/desc/B05B46135B0B2C04EBE1DD6A6AE4B12D7CD2226A",
    1415             :     &answer, &errmsg);
    1416           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1417           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1418           1 :   tt_str_op(errmsg, OP_EQ, "No such descriptor digest found");
    1419           1 :   errmsg = NULL;
    1420             : 
    1421             :   /* Case 4 - microdescs only */
    1422           1 :   disable_descbr = 1;
    1423           1 :   getinfo_helper_downloads(&dummy,
    1424             :                            "downloads/desc/descs",
    1425             :                            &answer, &errmsg);
    1426           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1427           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1428           1 :   tt_str_op(errmsg, OP_EQ,
    1429             :             "We don't seem to have a networkstatus-flavored consensus");
    1430           1 :   errmsg = NULL;
    1431           1 :   disable_descbr = 0;
    1432             : 
    1433           1 :  done:
    1434           1 :   clear_desc_mocks();
    1435           1 :   tor_free(answer);
    1436             : 
    1437           1 :   return;
    1438             : }
    1439             : 
    1440             : static void
    1441           1 : test_download_status_bridge(void *arg)
    1442             : {
    1443             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1444           1 :   control_connection_t dummy;
    1445             :   /* Get results out */
    1446           1 :   char *question = NULL;
    1447           1 :   char *answer = NULL;
    1448           1 :   const char *errmsg = NULL;
    1449             : 
    1450           1 :   (void)arg;
    1451             : 
    1452           1 :   setup_bridge_mocks();
    1453             : 
    1454             :   /*
    1455             :    * Check returning serialized dlstatuses and digest lists, and implicitly
    1456             :    * also test download_status_to_string() and digest_list_to_string().
    1457             :    */
    1458             : 
    1459             :   /* Case 1 - list of bridge identity digests */
    1460           1 :   getinfo_helper_downloads(&dummy,
    1461             :                            "downloads/bridge/bridges",
    1462             :                            &answer, &errmsg);
    1463           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1464           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1465           1 :   tt_str_op(answer, OP_EQ, descbr_expected_list);
    1466           1 :   tor_free(answer);
    1467           1 :   errmsg = NULL;
    1468             : 
    1469             :   /* Case 2 - get download status for bridge descriptor 1 */
    1470           1 :   memcpy(&descbr_digest_1_dl, &dls_sample_3,
    1471             :          sizeof(download_status_t));
    1472           1 :   tor_asprintf(&question, "downloads/bridge/%s", descbr_digest_1_str);
    1473           1 :   tt_ptr_op(question, OP_NE, NULL);
    1474           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1475           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1476           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1477           1 :   tt_str_op(answer, OP_EQ, dls_sample_3_str);
    1478           1 :   tor_free(question);
    1479           1 :   tor_free(answer);
    1480           1 :   errmsg = NULL;
    1481             : 
    1482             :   /* Case 3 - get download status for router descriptor 1 */
    1483           1 :   memcpy(&descbr_digest_2_dl, &dls_sample_4,
    1484             :          sizeof(download_status_t));
    1485           1 :   tor_asprintf(&question, "downloads/bridge/%s", descbr_digest_2_str);
    1486           1 :   tt_ptr_op(question, OP_NE, NULL);
    1487           1 :   getinfo_helper_downloads(&dummy, question, &answer, &errmsg);
    1488           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1489           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1490           1 :   tt_str_op(answer, OP_EQ, dls_sample_4_str);
    1491           1 :   tor_free(question);
    1492           1 :   tor_free(answer);
    1493           1 :   errmsg = NULL;
    1494             : 
    1495             :   /* Now check the error cases */
    1496             : 
    1497             :   /* Case 1 - non-digest-length garbage after downloads/bridge */
    1498           1 :   getinfo_helper_downloads(&dummy, "downloads/bridge/blahdeblah",
    1499             :                            &answer, &errmsg);
    1500           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1501           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1502           1 :   tt_str_op(errmsg, OP_EQ, "Unknown bridge descriptor download status query");
    1503           1 :   errmsg = NULL;
    1504             : 
    1505             :   /* Case 2 - nonparseable digest-shaped thing */
    1506           1 :   getinfo_helper_downloads(
    1507             :     &dummy,
    1508             :     "downloads/bridge/774EC52FD9A5B80A6FACZE536616E8022E3470AG",
    1509             :     &answer, &errmsg);
    1510           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1511           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1512           1 :   tt_str_op(errmsg, OP_EQ, "That didn't look like a digest");
    1513           1 :   errmsg = NULL;
    1514             : 
    1515             :   /* Case 3 - digest we have no descriptor for */
    1516           1 :   getinfo_helper_downloads(
    1517             :     &dummy,
    1518             :     "downloads/bridge/B05B46135B0B2C04EBE1DD6A6AE4B12D7CD2226A",
    1519             :     &answer, &errmsg);
    1520           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1521           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1522           1 :   tt_str_op(errmsg, OP_EQ, "No such bridge identity digest found");
    1523           1 :   errmsg = NULL;
    1524             : 
    1525             :   /* Case 4 - bridges disabled */
    1526           1 :   disable_descbr = 1;
    1527           1 :   getinfo_helper_downloads(&dummy,
    1528             :                            "downloads/bridge/bridges",
    1529             :                            &answer, &errmsg);
    1530           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    1531           1 :   tt_ptr_op(errmsg, OP_NE, NULL);
    1532           1 :   tt_str_op(errmsg, OP_EQ, "We don't seem to be using bridges");
    1533           1 :   errmsg = NULL;
    1534           1 :   disable_descbr = 0;
    1535             : 
    1536           1 :  done:
    1537           1 :   clear_bridge_mocks();
    1538           1 :   tor_free(answer);
    1539             : 
    1540           1 :   return;
    1541             : }
    1542             : 
    1543             : /** Mock cached consensus */
    1544             : static cached_dir_t *mock_ns_consensus_cache;
    1545             : static cached_dir_t *mock_microdesc_consensus_cache;
    1546             : 
    1547             : /**  Mock the function that retrieves consensus from cache. These use a
    1548             :  * global variable so that they can be cleared from within the test.
    1549             :  * The actual code retains the pointer to the consensus data, but
    1550             :  * we are doing this here, to prevent memory leaks
    1551             :  * from within the tests */
    1552             : static cached_dir_t *
    1553           2 : mock_dirserv_get_consensus(const char *flavor_name)
    1554             : {
    1555           2 :   if (!strcmp(flavor_name, "ns")) {
    1556           1 :     mock_ns_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
    1557           1 :     mock_ns_consensus_cache->dir = tor_strdup("mock_ns_consensus");
    1558           1 :     return mock_ns_consensus_cache;
    1559             :   } else {
    1560           1 :     mock_microdesc_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
    1561           1 :     mock_microdesc_consensus_cache->dir = tor_strdup(
    1562             :                                             "mock_microdesc_consensus");
    1563           1 :     return mock_microdesc_consensus_cache;
    1564             :   }
    1565             : }
    1566             : 
    1567             : /** Mock the function that retrieves consensuses
    1568             :  *  from a files in the directory. */
    1569             : static tor_mmap_t *
    1570           2 : mock_tor_mmap_file(const char* filename)
    1571             : {
    1572           2 :   tor_mmap_t *res;
    1573           2 :   res = tor_malloc_zero(sizeof(tor_mmap_t));
    1574           2 :   if (strstr(filename, "cached-consensus") != NULL) {
    1575           1 :     res->data = "mock_ns_consensus";
    1576           1 :   } else if (strstr(filename, "cached-microdesc-consensus") != NULL) {
    1577           1 :     res->data = "mock_microdesc_consensus";
    1578             :   } else {
    1579           0 :     res->data = ".";
    1580             :   }
    1581           2 :   res->size = strlen(res->data);
    1582           2 :   return res;
    1583             : }
    1584             : 
    1585             : /** Mock the function that clears file data
    1586             :  * loaded into the memory */
    1587             : static int
    1588           2 : mock_tor_munmap_file(tor_mmap_t *handle)
    1589             : {
    1590           2 :   tor_free(handle);
    1591           2 :   return 0;
    1592             : }
    1593             : 
    1594             : static void
    1595           1 : test_getinfo_helper_current_consensus_from_file(void *arg)
    1596             : {
    1597             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1598           1 :   control_connection_t dummy;
    1599             :   /* Get results out */
    1600           1 :   char *answer = NULL;
    1601           1 :   const char *errmsg = NULL;
    1602             : 
    1603           1 :   (void)arg;
    1604             : 
    1605           1 :   MOCK(tor_mmap_file, mock_tor_mmap_file);
    1606           1 :   MOCK(tor_munmap_file, mock_tor_munmap_file);
    1607             : 
    1608           1 :   getinfo_helper_dir(&dummy,
    1609             :                      "dir/status-vote/current/consensus",
    1610             :                      &answer,
    1611             :                      &errmsg);
    1612           1 :   tt_str_op(answer, OP_EQ, "mock_ns_consensus");
    1613           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1614           1 :   tor_free(answer);
    1615           1 :   errmsg = NULL;
    1616             : 
    1617           1 :   getinfo_helper_dir(&dummy,
    1618             :                      "dir/status-vote/current/consensus-microdesc",
    1619             :                      &answer,
    1620             :                      &errmsg);
    1621           1 :   tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
    1622           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1623           1 :   errmsg = NULL;
    1624             : 
    1625           1 :  done:
    1626           1 :   tor_free(answer);
    1627           1 :   UNMOCK(tor_mmap_file);
    1628           1 :   UNMOCK(tor_munmap_file);
    1629           1 :   return;
    1630             : }
    1631             : 
    1632             : static void
    1633           1 : test_getinfo_helper_current_consensus_from_cache(void *arg)
    1634             : {
    1635             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1636           1 :   control_connection_t dummy;
    1637             :   /* Get results out */
    1638           1 :   char *answer = NULL;
    1639           1 :   const char *errmsg = NULL;
    1640             : 
    1641           1 :   (void)arg;
    1642           1 :   or_options_t *options = get_options_mutable();
    1643           1 :   options->FetchUselessDescriptors = 1;
    1644           1 :   MOCK(dirserv_get_consensus, mock_dirserv_get_consensus);
    1645             : 
    1646           1 :   getinfo_helper_dir(&dummy,
    1647             :                      "dir/status-vote/current/consensus",
    1648             :                      &answer,
    1649             :                      &errmsg);
    1650           1 :   tt_str_op(answer, OP_EQ, "mock_ns_consensus");
    1651           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1652           1 :   tor_free(answer);
    1653           1 :   tor_free(mock_ns_consensus_cache->dir);
    1654           1 :   tor_free(mock_ns_consensus_cache);
    1655           1 :   errmsg = NULL;
    1656             : 
    1657           1 :   getinfo_helper_dir(&dummy,
    1658             :                      "dir/status-vote/current/consensus-microdesc",
    1659             :                      &answer,
    1660             :                      &errmsg);
    1661           1 :   tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
    1662           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1663           1 :   tor_free(mock_microdesc_consensus_cache->dir);
    1664           1 :   tor_free(answer);
    1665           1 :   errmsg = NULL;
    1666             : 
    1667           1 :  done:
    1668           1 :   options->FetchUselessDescriptors = 0;
    1669           1 :   tor_free(answer);
    1670           1 :   tor_free(mock_microdesc_consensus_cache);
    1671           1 :   UNMOCK(dirserv_get_consensus);
    1672           1 :   return;
    1673             : }
    1674             : 
    1675             : /** Set timeval to a mock date and time. This is necessary
    1676             :  * to make tor_gettimeofday() mockable. */
    1677             : static void
    1678           3 : mock_tor_gettimeofday(struct timeval *timeval)
    1679             : {
    1680           3 :   timeval->tv_sec = 1523405073;
    1681           3 :   timeval->tv_usec = 271645;
    1682           3 : }
    1683             : 
    1684             : static void
    1685           1 : test_current_time(void *arg)
    1686             : {
    1687             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1688           1 :   control_connection_t dummy;
    1689             :   /* Get results out */
    1690           1 :   char *answer = NULL;
    1691           1 :   const char *errmsg = NULL;
    1692             : 
    1693           1 :   (void)arg;
    1694             : 
    1695             :   /* We need these for storing the (mock) time. */
    1696           1 :   MOCK(tor_gettimeofday, mock_tor_gettimeofday);
    1697           1 :   struct timeval now;
    1698           1 :   tor_gettimeofday(&now);
    1699           1 :   char timebuf[ISO_TIME_LEN+1];
    1700             : 
    1701             :   /* Case 1 - local time */
    1702           1 :   format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec);
    1703           1 :   getinfo_helper_current_time(&dummy,
    1704             :                               "current-time/local",
    1705             :                               &answer, &errmsg);
    1706           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1707           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1708           1 :   tt_str_op(answer, OP_EQ, timebuf);
    1709           1 :   tor_free(answer);
    1710           1 :   errmsg = NULL;
    1711             : 
    1712             :   /* Case 2 - UTC time */
    1713           1 :   format_iso_time_nospace(timebuf, (time_t)now.tv_sec);
    1714           1 :   getinfo_helper_current_time(&dummy,
    1715             :                               "current-time/utc",
    1716             :                               &answer, &errmsg);
    1717           1 :   tt_ptr_op(answer, OP_NE, NULL);
    1718           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    1719           1 :   tt_str_op(answer, OP_EQ, timebuf);
    1720           1 :   tor_free(answer);
    1721           1 :   errmsg = NULL;
    1722             : 
    1723           1 :  done:
    1724           1 :   UNMOCK(tor_gettimeofday);
    1725           1 :   tor_free(answer);
    1726             : 
    1727           1 :   return;
    1728             : }
    1729             : 
    1730             : static size_t n_nodelist_get_list = 0;
    1731             : static smartlist_t *nodes = NULL;
    1732             : 
    1733             : static const smartlist_t *
    1734           2 : mock_nodelist_get_list(void)
    1735             : {
    1736           2 :   n_nodelist_get_list++;
    1737           2 :   tor_assert(nodes);
    1738             : 
    1739           2 :   return nodes;
    1740             : }
    1741             : 
    1742             : static void
    1743           1 : test_getinfo_md_all(void *arg)
    1744             : {
    1745           1 :   char *answer = NULL;
    1746           1 :   const char *errmsg = NULL;
    1747           1 :   int retval = 0;
    1748             : 
    1749           1 :   (void)arg;
    1750             : 
    1751           1 :   node_t *node1 = tor_malloc(sizeof(node_t));
    1752           1 :   memset(node1, 0, sizeof(node_t));
    1753           1 :   node1->md = tor_malloc(sizeof(microdesc_t));
    1754           1 :   memset(node1->md, 0, sizeof(microdesc_t));
    1755           1 :   node1->md->body = tor_strdup("md1\n");
    1756           1 :   node1->md->bodylen = 4;
    1757             : 
    1758           1 :   node_t *node2 = tor_malloc(sizeof(node_t));
    1759           1 :   memset(node2, 0, sizeof(node_t));
    1760           1 :   node2->md = tor_malloc(sizeof(microdesc_t));
    1761           1 :   memset(node2->md, 0, sizeof(microdesc_t));
    1762           1 :   node2->md->body = tor_strdup("md2\n");
    1763           1 :   node2->md->bodylen = 4;
    1764             : 
    1765           1 :   MOCK(nodelist_get_list, mock_nodelist_get_list);
    1766             : 
    1767           1 :   nodes = smartlist_new();
    1768             : 
    1769           1 :   retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
    1770             : 
    1771           1 :   tt_int_op(n_nodelist_get_list, OP_EQ, 1);
    1772           1 :   tt_int_op(retval, OP_EQ, 0);
    1773           1 :   tt_assert(answer != NULL);
    1774           1 :   tt_assert(errmsg == NULL);
    1775           1 :   tt_str_op(answer, OP_EQ, "");
    1776             : 
    1777           1 :   tor_free(answer);
    1778             : 
    1779           1 :   smartlist_add(nodes, node1);
    1780           1 :   smartlist_add(nodes, node2);
    1781             : 
    1782           1 :   retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
    1783             : 
    1784           1 :   tt_int_op(n_nodelist_get_list, OP_EQ, 2);
    1785           1 :   tt_int_op(retval, OP_EQ, 0);
    1786           1 :   tt_assert(answer != NULL);
    1787           1 :   tt_assert(errmsg == NULL);
    1788             : 
    1789           1 :   tt_str_op(answer, OP_EQ, "md1\nmd2\n");
    1790             : 
    1791           1 :  done:
    1792           1 :   UNMOCK(nodelist_get_list);
    1793           1 :   tor_free(node1->md->body);
    1794           1 :   tor_free(node1->md);
    1795           1 :   tor_free(node1);
    1796           1 :   tor_free(node2->md->body);
    1797           1 :   tor_free(node2->md);
    1798           1 :   tor_free(node2);
    1799           1 :   tor_free(answer);
    1800           1 :   smartlist_free(nodes);
    1801           1 :   return;
    1802             : }
    1803             : 
    1804             : static smartlist_t *reply_strs;
    1805             : 
    1806             : static void
    1807          13 : mock_control_write_reply_list(control_connection_t *conn, int code, int c,
    1808             :                               const char *s)
    1809             : {
    1810          13 :   (void)conn;
    1811             :   /* To make matching easier, don't append "\r\n" */
    1812          13 :   smartlist_add_asprintf(reply_strs, "%03d%c%s", code, c, s);
    1813          13 : }
    1814             : 
    1815             : static void
    1816           1 : test_control_reply(void *arg)
    1817             : {
    1818           1 :   (void)arg;
    1819           1 :   smartlist_t *lines = smartlist_new();
    1820             : 
    1821           1 :   MOCK(control_write_reply, mock_control_write_reply);
    1822             : 
    1823           1 :   tor_free(reply_str);
    1824           1 :   control_reply_clear(lines);
    1825           1 :   control_reply_add_str(lines, 250, "FOO");
    1826           1 :   control_write_reply_lines(NULL, lines);
    1827           1 :   tt_str_op(reply_str, OP_EQ, "FOO");
    1828             : 
    1829           1 :   tor_free(reply_str);
    1830           1 :   control_reply_clear(lines);
    1831           1 :   control_reply_add_done(lines);
    1832           1 :   control_write_reply_lines(NULL, lines);
    1833           1 :   tt_str_op(reply_str, OP_EQ, "OK");
    1834             : 
    1835           1 :   tor_free(reply_str);
    1836           1 :   control_reply_clear(lines);
    1837           1 :   UNMOCK(control_write_reply);
    1838           1 :   MOCK(control_write_reply, mock_control_write_reply_list);
    1839           1 :   reply_strs = smartlist_new();
    1840           1 :   control_reply_add_one_kv(lines, 250, 0, "A", "B");
    1841           1 :   control_reply_add_one_kv(lines, 250, 0, "C", "D");
    1842           1 :   control_write_reply_lines(NULL, lines);
    1843           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
    1844           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-A=B");
    1845           1 :   tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 C=D");
    1846             : 
    1847           1 :   control_reply_clear(lines);
    1848           3 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1849           1 :   smartlist_clear(reply_strs);
    1850           1 :   control_reply_add_printf(lines, 250, "PROTOCOLINFO %d", 1);
    1851           1 :   control_reply_add_one_kv(lines, 250, KV_OMIT_VALS|KV_RAW, "AUTH", "");
    1852           1 :   control_reply_append_kv(lines, "METHODS", "COOKIE");
    1853           1 :   control_reply_append_kv(lines, "COOKIEFILE", escaped("/tmp/cookie"));
    1854           1 :   control_reply_add_done(lines);
    1855           1 :   control_write_reply_lines(NULL, lines);
    1856           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 3);
    1857           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0),
    1858             :             OP_EQ, "250-PROTOCOLINFO 1");
    1859           1 :   tt_str_op((char *)smartlist_get(reply_strs, 1),
    1860             :             OP_EQ, "250-AUTH METHODS=COOKIE COOKIEFILE=\"/tmp/cookie\"");
    1861           1 :   tt_str_op((char *)smartlist_get(reply_strs, 2),
    1862             :             OP_EQ, "250 OK");
    1863             : 
    1864           1 :  done:
    1865           1 :   UNMOCK(control_write_reply);
    1866           1 :   tor_free(reply_str);
    1867           1 :   control_reply_free(lines);
    1868           1 :   if (reply_strs)
    1869           4 :     SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1870           1 :   smartlist_free(reply_strs);
    1871           1 :   return;
    1872             : }
    1873             : 
    1874             : static void
    1875           1 : test_control_getconf(void *arg)
    1876             : {
    1877           1 :   (void)arg;
    1878           1 :   control_connection_t conn;
    1879           1 :   char *args = NULL;
    1880           1 :   int r = -1;
    1881             : 
    1882           1 :   memset(&conn, 0, sizeof(conn));
    1883           1 :   conn.current_cmd = tor_strdup("GETCONF");
    1884             : 
    1885           1 :   MOCK(control_write_reply, mock_control_write_reply_list);
    1886           1 :   reply_strs = smartlist_new();
    1887             : 
    1888           1 :   args = tor_strdup("");
    1889           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1890           1 :   tt_int_op(r, OP_EQ, 0);
    1891           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
    1892           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 OK");
    1893           2 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1894           1 :   smartlist_clear(reply_strs);
    1895           1 :   tor_free(args);
    1896             : 
    1897           1 :   args = tor_strdup("NoSuch");
    1898           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1899           1 :   tt_int_op(r, OP_EQ, 0);
    1900           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
    1901           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
    1902             :             "552 Unrecognized configuration key \"NoSuch\"");
    1903           1 :   tor_free(args);
    1904           2 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1905           1 :   smartlist_clear(reply_strs);
    1906             : 
    1907           1 :   args = tor_strdup("NoSuch1 NoSuch2");
    1908           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1909           1 :   tt_int_op(r, OP_EQ, 0);
    1910           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
    1911           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
    1912             :             "552-Unrecognized configuration key \"NoSuch1\"");
    1913           1 :   tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ,
    1914             :             "552 Unrecognized configuration key \"NoSuch2\"");
    1915           1 :   tor_free(args);
    1916           3 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1917           1 :   smartlist_clear(reply_strs);
    1918             : 
    1919           1 :   args = tor_strdup("ControlPort NoSuch");
    1920           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1921           1 :   tt_int_op(r, OP_EQ, 0);
    1922             :   /* Valid keys ignored if there are any invalid ones */
    1923           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
    1924           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
    1925             :             "552 Unrecognized configuration key \"NoSuch\"");
    1926           1 :   tor_free(args);
    1927           2 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1928           1 :   smartlist_clear(reply_strs);
    1929             : 
    1930           1 :   args = tor_strdup("ClientOnly");
    1931           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1932           1 :   tt_int_op(r, OP_EQ, 0);
    1933           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
    1934             :   /* According to config.c, this is an exception for the unit tests */
    1935           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 ClientOnly=0");
    1936           1 :   tor_free(args);
    1937           2 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1938           1 :   smartlist_clear(reply_strs);
    1939             : 
    1940           1 :   args = tor_strdup("BridgeRelay ClientOnly");
    1941           1 :   r = handle_control_command(&conn, (uint32_t)strlen(args), args);
    1942           1 :   tt_int_op(r, OP_EQ, 0);
    1943           1 :   tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
    1944             :   /* Change if config.c changes BridgeRelay default (unlikely) */
    1945           1 :   tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-BridgeRelay=0");
    1946           1 :   tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 ClientOnly=0");
    1947           1 :   tor_free(args);
    1948           3 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1949           1 :   smartlist_clear(reply_strs);
    1950             : 
    1951           1 :  done:
    1952           1 :   tor_free(conn.current_cmd);
    1953           1 :   tor_free(args);
    1954           1 :   UNMOCK(control_write_reply);
    1955           1 :   SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
    1956           1 :   smartlist_free(reply_strs);
    1957           1 : }
    1958             : 
    1959             : static int
    1960           4 : mock_rep_hist_get_circuit_handshake(uint16_t type)
    1961             : {
    1962           4 :   int ret;
    1963             : 
    1964           4 :   switch (type) {
    1965             :     case ONION_HANDSHAKE_TYPE_NTOR:
    1966             :       ret = 80;
    1967             :       break;
    1968           2 :     case ONION_HANDSHAKE_TYPE_TAP:
    1969           2 :       ret = 86;
    1970           2 :       break;
    1971           0 :     default:
    1972           0 :       ret = 0;
    1973           0 :       break;
    1974             :   }
    1975             : 
    1976           4 :   return ret;
    1977             : }
    1978             : 
    1979             : static void
    1980           1 : test_stats(void *arg)
    1981             : {
    1982             :   /* We just need one of these to pass, it doesn't matter what's in it */
    1983           1 :   control_connection_t dummy;
    1984             :   /* Get results out */
    1985           1 :   char *answer = NULL;
    1986           1 :   const char *errmsg = NULL;
    1987             : 
    1988           1 :   (void) arg;
    1989             : 
    1990             :   /* We need these for returning the (mock) rephist. */
    1991           1 :   MOCK(rep_hist_get_circuit_handshake_requested,
    1992             :        mock_rep_hist_get_circuit_handshake);
    1993           1 :   MOCK(rep_hist_get_circuit_handshake_assigned,
    1994             :        mock_rep_hist_get_circuit_handshake);
    1995             : 
    1996             :   /* NTor tests */
    1997           1 :   getinfo_helper_rephist(&dummy, "stats/ntor/requested",
    1998             :                          &answer, &errmsg);
    1999           1 :   tt_ptr_op(answer, OP_NE, NULL);
    2000           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    2001           1 :   tt_str_op(answer, OP_EQ, "80");
    2002           1 :   tor_free(answer);
    2003           1 :   errmsg = NULL;
    2004             : 
    2005           1 :   getinfo_helper_rephist(&dummy, "stats/ntor/assigned",
    2006             :                          &answer, &errmsg);
    2007           1 :   tt_ptr_op(answer, OP_NE, NULL);
    2008           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    2009           1 :   tt_str_op(answer, OP_EQ, "80");
    2010           1 :   tor_free(answer);
    2011           1 :   errmsg = NULL;
    2012             : 
    2013             :   /* TAP tests */
    2014           1 :   getinfo_helper_rephist(&dummy, "stats/tap/requested",
    2015             :                          &answer, &errmsg);
    2016           1 :   tt_ptr_op(answer, OP_NE, NULL);
    2017           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    2018           1 :   tt_str_op(answer, OP_EQ, "86");
    2019           1 :   tor_free(answer);
    2020           1 :   errmsg = NULL;
    2021             : 
    2022           1 :   getinfo_helper_rephist(&dummy, "stats/tap/assigned",
    2023             :                          &answer, &errmsg);
    2024           1 :   tt_ptr_op(answer, OP_NE, NULL);
    2025           1 :   tt_ptr_op(errmsg, OP_EQ, NULL);
    2026           1 :   tt_str_op(answer, OP_EQ, "86");
    2027           1 :   tor_free(answer);
    2028           1 :   errmsg = NULL;
    2029             : 
    2030           1 :   getinfo_helper_rephist(&dummy, "stats/tap/onion_circuits_ddosed",
    2031             :                          &answer, &errmsg);
    2032           1 :   tt_ptr_op(answer, OP_EQ, NULL);
    2033           1 :   tt_str_op(errmsg, OP_EQ, "Unrecognized handshake type");
    2034           1 :   errmsg = NULL;
    2035             : 
    2036           1 :  done:
    2037           1 :   UNMOCK(rep_hist_get_circuit_handshake_requested);
    2038           1 :   UNMOCK(rep_hist_get_circuit_handshake_assigned);
    2039           1 :   tor_free(answer);
    2040             : 
    2041           1 :   return;
    2042             : }
    2043             : 
    2044             : #ifndef COCCI
    2045             : #define PARSER_TEST(type)                                             \
    2046             :   { "parse/" #type, test_controller_parse_cmd, 0, &passthrough_setup, \
    2047             :       (void*)&parse_ ## type ## _params }
    2048             : #endif
    2049             : 
    2050             : struct testcase_t controller_tests[] = {
    2051             :   PARSER_TEST(one_to_three),
    2052             :   PARSER_TEST(no_args_one_obj),
    2053             :   PARSER_TEST(no_args_kwargs),
    2054             :   PARSER_TEST(one_arg_kwargs),
    2055             :   { "add_onion_helper_keyarg_v3", test_add_onion_helper_keyarg_v3, 0,
    2056             :     NULL, NULL },
    2057             :   { "getinfo_helper_onion", test_getinfo_helper_onion, 0, NULL, NULL },
    2058             :   { "hs_parse_port_config", test_hs_parse_port_config, 0,
    2059             :     NULL, NULL },
    2060             :   { "download_status_consensus", test_download_status_consensus, 0, NULL,
    2061             :     NULL },
    2062             :   {"getinfo_helper_current_consensus_from_cache",
    2063             :    test_getinfo_helper_current_consensus_from_cache, 0, NULL, NULL },
    2064             :   {"getinfo_helper_current_consensus_from_file",
    2065             :    test_getinfo_helper_current_consensus_from_file, 0, NULL, NULL },
    2066             :   { "download_status_cert", test_download_status_cert, 0, NULL,
    2067             :     NULL },
    2068             :   { "download_status_desc", test_download_status_desc, 0, NULL, NULL },
    2069             :   { "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
    2070             :   { "current_time", test_current_time, 0, NULL, NULL },
    2071             :   { "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL },
    2072             :   { "control_reply", test_control_reply, 0, NULL, NULL },
    2073             :   { "control_getconf", test_control_getconf, 0, NULL, NULL },
    2074             :   { "stats", test_stats, 0, NULL, NULL },
    2075             :   END_OF_TESTCASES
    2076             : };

Generated by: LCOV version 1.14