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 = ¶ms->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 : };
|