Line data Source code
1 : /* Copyright (c) 2007-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : /**
5 : * \file test_nodelist.c
6 : * \brief Unit tests for nodelist related functions.
7 : **/
8 :
9 : #define NODELIST_PRIVATE
10 : #define NETWORKSTATUS_PRIVATE
11 :
12 : #include "core/or/or.h"
13 : #include "lib/crypt_ops/crypto_rand.h"
14 : #include "lib/crypt_ops/crypto_format.h"
15 : #include "feature/nodelist/describe.h"
16 : #include "feature/nodelist/networkstatus.h"
17 : #include "feature/nodelist/nodefamily.h"
18 : #include "feature/nodelist/nodelist.h"
19 : #include "feature/nodelist/torcert.h"
20 :
21 : #include "core/or/extend_info_st.h"
22 : #include "feature/dirauth/dirvote.h"
23 : #include "feature/nodelist/fmt_routerstatus.h"
24 : #include "feature/nodelist/microdesc_st.h"
25 : #include "feature/nodelist/networkstatus_st.h"
26 : #include "feature/nodelist/node_st.h"
27 : #include "feature/nodelist/nodefamily_st.h"
28 : #include "feature/nodelist/routerinfo_st.h"
29 : #include "feature/nodelist/routerstatus_st.h"
30 :
31 : #include "test/test.h"
32 : #include "test/log_test_helpers.h"
33 :
34 : /** Test the case when node_get_by_id() returns NULL,
35 : * node_get_verbose_nickname_by_id should return the base 16 encoding
36 : * of the id.
37 : */
38 : static void
39 1 : test_nodelist_node_get_verbose_nickname_by_id_null_node(void *arg)
40 : {
41 1 : char vname[MAX_VERBOSE_NICKNAME_LEN+1];
42 1 : const char ID[] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
43 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
44 1 : (void) arg;
45 :
46 : /* make sure node_get_by_id returns NULL */
47 1 : tt_assert(!node_get_by_id(ID));
48 1 : node_get_verbose_nickname_by_id(ID, vname);
49 1 : tt_str_op(vname,OP_EQ, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
50 1 : done:
51 1 : return;
52 : }
53 :
54 : /** For routers without named flag, get_verbose_nickname should return
55 : * "Fingerprint~Nickname"
56 : */
57 : static void
58 1 : test_nodelist_node_get_verbose_nickname_not_named(void *arg)
59 : {
60 1 : node_t mock_node;
61 1 : routerstatus_t mock_rs;
62 :
63 1 : char vname[MAX_VERBOSE_NICKNAME_LEN+1];
64 :
65 1 : (void) arg;
66 :
67 1 : memset(&mock_node, 0, sizeof(node_t));
68 1 : memset(&mock_rs, 0, sizeof(routerstatus_t));
69 :
70 : /* verbose nickname should use ~ instead of = for unnamed routers */
71 1 : strlcpy(mock_rs.nickname, "TestOR", sizeof(mock_rs.nickname));
72 1 : mock_node.rs = &mock_rs;
73 1 : memcpy(mock_node.identity,
74 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
75 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
76 : DIGEST_LEN);
77 1 : node_get_verbose_nickname(&mock_node, vname);
78 1 : tt_str_op(vname,OP_EQ, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR");
79 :
80 1 : done:
81 1 : return;
82 : }
83 :
84 : /** A node should be considered a directory server if it has an open dirport
85 : * or it accepts tunnelled directory requests.
86 : */
87 : static void
88 1 : test_nodelist_node_is_dir(void *arg)
89 : {
90 1 : (void)arg;
91 :
92 1 : routerstatus_t rs;
93 1 : routerinfo_t ri;
94 1 : node_t node;
95 1 : memset(&node, 0, sizeof(node_t));
96 1 : memset(&rs, 0, sizeof(routerstatus_t));
97 1 : memset(&ri, 0, sizeof(routerinfo_t));
98 :
99 1 : tt_assert(!node_is_dir(&node));
100 :
101 1 : node.rs = &rs;
102 1 : tt_assert(!node_is_dir(&node));
103 :
104 1 : rs.is_v2_dir = 1;
105 1 : tt_assert(node_is_dir(&node));
106 :
107 1 : rs.is_v2_dir = 0;
108 1 : rs.ipv4_dirport = 1;
109 1 : tt_assert(! node_is_dir(&node));
110 :
111 1 : node.rs = NULL;
112 1 : tt_assert(!node_is_dir(&node));
113 1 : node.ri = &ri;
114 1 : ri.supports_tunnelled_dir_requests = 1;
115 1 : tt_assert(node_is_dir(&node));
116 1 : ri.supports_tunnelled_dir_requests = 0;
117 1 : ri.ipv4_dirport = 1;
118 1 : tt_assert(! node_is_dir(&node));
119 :
120 1 : done:
121 1 : return;
122 : }
123 :
124 : static networkstatus_t *dummy_ns = NULL;
125 : static networkstatus_t *
126 1 : mock_networkstatus_get_latest_consensus(void)
127 : {
128 1 : return dummy_ns;
129 : }
130 : static networkstatus_t *
131 3 : mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
132 : {
133 3 : tor_assert(f == FLAV_MICRODESC);
134 3 : return dummy_ns;
135 : }
136 :
137 : static void
138 1 : test_nodelist_ed_id(void *arg)
139 : {
140 : #define N_NODES 5
141 1 : routerstatus_t *rs[N_NODES];
142 1 : microdesc_t *md[N_NODES];
143 1 : routerinfo_t *ri[N_NODES];
144 1 : networkstatus_t *ns;
145 1 : int i;
146 1 : (void)arg;
147 :
148 1 : ns = tor_malloc_zero(sizeof(networkstatus_t));
149 1 : ns->flavor = FLAV_MICRODESC;
150 1 : ns->routerstatus_list = smartlist_new();
151 1 : dummy_ns = ns;
152 1 : MOCK(networkstatus_get_latest_consensus,
153 : mock_networkstatus_get_latest_consensus);
154 1 : MOCK(networkstatus_get_latest_consensus_by_flavor,
155 : mock_networkstatus_get_latest_consensus_by_flavor);
156 :
157 : /* Make a bunch of dummy objects that we can play around with. Only set the
158 : necessary fields */
159 :
160 6 : for (i = 0; i < N_NODES; ++i) {
161 5 : rs[i] = tor_malloc_zero(sizeof(*rs[i]));
162 5 : md[i] = tor_malloc_zero(sizeof(*md[i]));
163 5 : ri[i] = tor_malloc_zero(sizeof(*ri[i]));
164 :
165 5 : crypto_rand(md[i]->digest, sizeof(md[i]->digest));
166 5 : md[i]->ed25519_identity_pkey = tor_malloc(sizeof(ed25519_public_key_t));
167 5 : crypto_rand((char*)md[i]->ed25519_identity_pkey,
168 : sizeof(ed25519_public_key_t));
169 5 : crypto_rand(rs[i]->identity_digest, sizeof(rs[i]->identity_digest));
170 5 : memcpy(ri[i]->cache_info.identity_digest, rs[i]->identity_digest,
171 : DIGEST_LEN);
172 5 : memcpy(rs[i]->descriptor_digest, md[i]->digest, DIGEST256_LEN);
173 5 : ri[i]->cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t));
174 5 : memcpy(&ri[i]->cache_info.signing_key_cert->signing_key,
175 5 : md[i]->ed25519_identity_pkey, sizeof(ed25519_public_key_t));
176 :
177 5 : if (i < 3)
178 3 : smartlist_add(ns->routerstatus_list, rs[i]);
179 : }
180 :
181 1 : tt_int_op(0, OP_EQ, smartlist_len(nodelist_get_list()));
182 :
183 1 : nodelist_set_consensus(ns);
184 :
185 1 : tt_int_op(3, OP_EQ, smartlist_len(nodelist_get_list()));
186 :
187 : /* No Ed25519 info yet, so nothing has an ED id. */
188 1 : tt_ptr_op(NULL, OP_EQ, node_get_by_ed25519_id(md[0]->ed25519_identity_pkey));
189 :
190 : /* Register the first one by md, then look it up. */
191 1 : node_t *n = nodelist_add_microdesc(md[0]);
192 1 : tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[0]->ed25519_identity_pkey));
193 :
194 : /* Register the second by ri, then look it up. */
195 1 : routerinfo_t *ri_old = NULL;
196 1 : n = nodelist_set_routerinfo(ri[1], &ri_old);
197 1 : tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[1]->ed25519_identity_pkey));
198 1 : tt_ptr_op(ri_old, OP_EQ, NULL);
199 :
200 : /* Register it by md too. */
201 1 : node_t *n2 = nodelist_add_microdesc(md[1]);
202 1 : tt_ptr_op(n2, OP_EQ, n);
203 1 : tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[1]->ed25519_identity_pkey));
204 :
205 : /* Register the 4th by ri only -- we never put it into the networkstatus,
206 : * so it has to be independent */
207 1 : node_t *n3 = nodelist_set_routerinfo(ri[3], &ri_old);
208 1 : tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey));
209 1 : tt_ptr_op(ri_old, OP_EQ, NULL);
210 1 : tt_int_op(4, OP_EQ, smartlist_len(nodelist_get_list()));
211 :
212 : /* Register the 5th by ri only, and rewrite its ed25519 pubkey to be
213 : * the same as the 4th, to test the duplicate ed25519 key logging in
214 : * nodelist.c */
215 1 : memcpy(md[4]->ed25519_identity_pkey, md[3]->ed25519_identity_pkey,
216 : sizeof(ed25519_public_key_t));
217 1 : memcpy(&ri[4]->cache_info.signing_key_cert->signing_key,
218 1 : md[3]->ed25519_identity_pkey, sizeof(ed25519_public_key_t));
219 :
220 1 : setup_capture_of_logs(LOG_NOTICE);
221 1 : node_t *n4 = nodelist_set_routerinfo(ri[4], &ri_old);
222 1 : tt_ptr_op(ri_old, OP_EQ, NULL);
223 1 : tt_int_op(5, OP_EQ, smartlist_len(nodelist_get_list()));
224 1 : tt_ptr_op(n4, OP_NE, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey));
225 1 : tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey));
226 1 : expect_log_msg_containing("Reused ed25519_id");
227 :
228 1 : done:
229 1 : teardown_capture_of_logs();
230 7 : for (i = 0; i < N_NODES; ++i) {
231 5 : tor_free(rs[i]);
232 5 : tor_free(md[i]->ed25519_identity_pkey);
233 5 : tor_free(md[i]);
234 5 : tor_free(ri[i]->cache_info.signing_key_cert);
235 5 : tor_free(ri[i]);
236 : }
237 1 : smartlist_clear(ns->routerstatus_list);
238 1 : networkstatus_vote_free(ns);
239 1 : UNMOCK(networkstatus_get_latest_consensus);
240 1 : UNMOCK(networkstatus_get_latest_consensus_by_flavor);
241 : #undef N_NODES
242 1 : }
243 :
244 : static void
245 1 : test_nodelist_nodefamily(void *arg)
246 : {
247 1 : (void)arg;
248 : /* hex ID digests */
249 1 : const char h1[] = "5B435D6869206861206C65207363617270652070";
250 1 : const char h2[] = "75C3B220616E6461726520696E206769726F2061";
251 1 : const char h3[] = "2074726F766172206461206D616E67696172652C";
252 1 : const char h4[] = "206D656E747265206E6F6E2076616C65206C2769";
253 1 : const char h5[] = "6E766572736F2E202D2D5072696D6F204C657669";
254 :
255 : /* binary ID digests */
256 1 : uint8_t d1[DIGEST_LEN], d2[DIGEST_LEN], d3[DIGEST_LEN], d4[DIGEST_LEN],
257 : d5[DIGEST_LEN];
258 1 : base16_decode((char*)d1, sizeof(d1), h1, strlen(h1));
259 1 : base16_decode((char*)d2, sizeof(d2), h2, strlen(h2));
260 1 : base16_decode((char*)d3, sizeof(d3), h3, strlen(h3));
261 1 : base16_decode((char*)d4, sizeof(d4), h4, strlen(h4));
262 1 : base16_decode((char*)d5, sizeof(d5), h5, strlen(h5));
263 :
264 1 : char *enc=NULL, *enc2=NULL;
265 :
266 1 : nodefamily_t *nf1 = NULL;
267 1 : nodefamily_t *nf2 = NULL;
268 1 : nodefamily_t *nf3 = NULL;
269 :
270 1 : enc = nodefamily_format(NULL);
271 1 : tt_str_op(enc, OP_EQ, "");
272 1 : tor_free(enc);
273 :
274 : /* Make sure that sorting and de-duplication work. */
275 1 : tor_asprintf(&enc, "$%s hello", h1);
276 1 : nf1 = nodefamily_parse(enc, NULL, 0);
277 1 : tt_assert(nf1);
278 1 : tor_free(enc);
279 :
280 1 : tor_asprintf(&enc, "hello hello $%s hello", h1);
281 1 : nf2 = nodefamily_parse(enc, NULL, 0);
282 1 : tt_assert(nf2);
283 1 : tt_ptr_op(nf1, OP_EQ, nf2);
284 1 : tor_free(enc);
285 :
286 1 : tor_asprintf(&enc, "%s $%s hello", h1, h1);
287 1 : nf3 = nodefamily_parse(enc, NULL, 0);
288 1 : tt_assert(nf3);
289 1 : tt_ptr_op(nf1, OP_EQ, nf3);
290 1 : tor_free(enc);
291 :
292 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d1));
293 1 : tt_assert(! nodefamily_contains_rsa_id(nf1, d2));
294 1 : tt_assert(nodefamily_contains_nickname(nf1, "hello"));
295 1 : tt_assert(nodefamily_contains_nickname(nf1, "HELLO"));
296 1 : tt_assert(! nodefamily_contains_nickname(nf1, "goodbye"));
297 :
298 1 : tt_int_op(nf1->refcnt, OP_EQ, 3);
299 1 : nodefamily_free(nf3);
300 1 : tt_int_op(nf1->refcnt, OP_EQ, 2);
301 :
302 : /* Try parsing with a provided self RSA digest. */
303 1 : nf3 = nodefamily_parse("hello ", d1, 0);
304 1 : tt_assert(nf3);
305 1 : tt_ptr_op(nf1, OP_EQ, nf3);
306 :
307 : /* Do we get the expected result when we re-encode? */
308 1 : tor_asprintf(&enc, "$%s hello", h1);
309 1 : enc2 = nodefamily_format(nf1);
310 1 : tt_str_op(enc2, OP_EQ, enc);
311 1 : tor_free(enc2);
312 1 : tor_free(enc);
313 :
314 : /* Make sure that we get a different result if we give a different digest. */
315 1 : nodefamily_free(nf3);
316 1 : tor_asprintf(&enc, "hello $%s hello", h3);
317 1 : nf3 = nodefamily_parse(enc, NULL, 0);
318 1 : tt_assert(nf3);
319 1 : tt_ptr_op(nf1, OP_NE, nf3);
320 1 : tor_free(enc);
321 :
322 1 : tt_assert(nodefamily_contains_rsa_id(nf3, d3));
323 1 : tt_assert(! nodefamily_contains_rsa_id(nf3, d2));
324 1 : tt_assert(! nodefamily_contains_rsa_id(nf3, d1));
325 1 : tt_assert(nodefamily_contains_nickname(nf3, "hello"));
326 1 : tt_assert(! nodefamily_contains_nickname(nf3, "goodbye"));
327 :
328 1 : nodefamily_free(nf1);
329 1 : nodefamily_free(nf2);
330 1 : nodefamily_free(nf3);
331 :
332 : /* Try one with several digests, all with nicknames appended, in different
333 : formats. */
334 1 : tor_asprintf(&enc, "%s $%s $%s=res $%s~ist", h1, h2, h3, h4);
335 1 : nf1 = nodefamily_parse(enc, d5, 0);
336 1 : tt_assert(nf1);
337 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d1));
338 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d2));
339 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d3));
340 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d4));
341 1 : tt_assert(nodefamily_contains_rsa_id(nf1, d5));
342 : /* Nicknames aren't preserved when ids are present, since node naming is
343 : * deprecated */
344 1 : tt_assert(! nodefamily_contains_nickname(nf3, "res"));
345 1 : tor_free(enc);
346 1 : tor_asprintf(&enc, "$%s $%s $%s $%s $%s", h4, h3, h1, h5, h2);
347 1 : enc2 = nodefamily_format(nf1);
348 1 : tt_str_op(enc, OP_EQ, enc2);
349 1 : tor_free(enc);
350 1 : tor_free(enc2);
351 :
352 : /* Try ones where we parse the empty string. */
353 1 : nf2 = nodefamily_parse("", NULL, 0);
354 1 : nf3 = nodefamily_parse("", d4, 0);
355 1 : tt_assert(nf2);
356 1 : tt_assert(nf3);
357 1 : tt_ptr_op(nf2, OP_NE, nf3);
358 :
359 1 : tt_assert(! nodefamily_contains_rsa_id(nf2, d4));
360 1 : tt_assert(nodefamily_contains_rsa_id(nf3, d4));
361 1 : tt_assert(! nodefamily_contains_rsa_id(nf2, d5));
362 1 : tt_assert(! nodefamily_contains_rsa_id(nf3, d5));
363 1 : tt_assert(! nodefamily_contains_nickname(nf2, "fred"));
364 1 : tt_assert(! nodefamily_contains_nickname(nf3, "bosco"));
365 :
366 : /* The NULL family should contain nothing. */
367 1 : tt_assert(! nodefamily_contains_rsa_id(NULL, d4));
368 1 : tt_assert(! nodefamily_contains_rsa_id(NULL, d5));
369 :
370 1 : done:
371 1 : tor_free(enc);
372 1 : tor_free(enc2);
373 1 : nodefamily_free(nf1);
374 1 : nodefamily_free(nf2);
375 1 : nodefamily_free(nf3);
376 1 : nodefamily_free_all();
377 1 : }
378 :
379 : static void
380 1 : test_nodelist_nodefamily_parse_err(void *arg)
381 : {
382 1 : (void)arg;
383 1 : nodefamily_t *nf1 = NULL;
384 1 : char *enc = NULL;
385 1 : const char *semibogus =
386 : "sdakljfdslkfjdsaklfjdkl9sdf " // too long for nickname
387 : "$jkASDFLkjsadfjhkl " // not hex
388 : "$7468696e67732d696e2d7468656d73656c766573 " // ok
389 : "reticulatogranulate "// ok
390 : "$73656d69616e7468726f706f6c6f676963616c6c79 " // too long for hex
391 : "$616273656e746d696e6465646e6573736573" // too short for hex
392 : ;
393 :
394 1 : setup_capture_of_logs(LOG_WARN);
395 :
396 : // We only get two items when we parse this.
397 3 : for (int reject = 0; reject <= 1; ++reject) {
398 6 : for (int log_at_warn = 0; log_at_warn <= 1; ++log_at_warn) {
399 4 : unsigned flags = log_at_warn ? NF_WARN_MALFORMED : 0;
400 4 : flags |= reject ? NF_REJECT_MALFORMED : 0;
401 4 : nf1 = nodefamily_parse(semibogus, NULL, flags);
402 4 : if (reject) {
403 2 : tt_assert(nf1 == NULL);
404 : } else {
405 2 : tt_assert(nf1);
406 2 : enc = nodefamily_format(nf1);
407 2 : tt_str_op(enc, OP_EQ,
408 : "$7468696E67732D696E2D7468656D73656C766573 "
409 : "reticulatogranulate");
410 2 : tor_free(enc);
411 : }
412 :
413 4 : if (log_at_warn) {
414 2 : expect_log_msg_containing("$616273656e746d696e6465646e6573736573");
415 2 : expect_log_msg_containing("sdakljfdslkfjdsaklfjdkl9sdf");
416 : } else {
417 2 : tt_int_op(mock_saved_log_n_entries(), OP_EQ, 0);
418 : }
419 4 : mock_clean_saved_logs();
420 : }
421 : }
422 :
423 1 : done:
424 1 : tor_free(enc);
425 1 : nodefamily_free(nf1);
426 1 : teardown_capture_of_logs();
427 1 : }
428 :
429 : static const node_t *
430 4 : mock_node_get_by_id(const char *id)
431 : {
432 4 : if (fast_memeq(id, "!!!!!!!!!!!!!!!!!!!!", DIGEST_LEN))
433 : return NULL;
434 :
435 : // use tor_free, not node_free.
436 3 : node_t *fake_node = tor_malloc_zero(sizeof(node_t));
437 3 : memcpy(fake_node->identity, id, DIGEST_LEN);
438 3 : return fake_node;
439 : }
440 :
441 : static const node_t *
442 5 : mock_node_get_by_nickname(const char *nn, unsigned flags)
443 : {
444 5 : (void)flags;
445 5 : if (!strcmp(nn, "nonesuch"))
446 : return NULL;
447 :
448 : // use tor_free, not node_free.
449 4 : node_t *fake_node = tor_malloc_zero(sizeof(node_t));
450 4 : strlcpy(fake_node->identity, nn, DIGEST_LEN);
451 4 : return fake_node;
452 : }
453 :
454 : static void
455 1 : test_nodelist_nodefamily_lookup(void *arg)
456 : {
457 1 : (void)arg;
458 1 : MOCK(node_get_by_nickname, mock_node_get_by_nickname);
459 1 : MOCK(node_get_by_id, mock_node_get_by_id);
460 1 : smartlist_t *sl = smartlist_new();
461 1 : nodefamily_t *nf1 = NULL;
462 1 : char *mem_op_hex_tmp = NULL;
463 :
464 : // 'null' is allowed.
465 1 : nodefamily_add_nodes_to_smartlist(NULL, sl);
466 1 : tt_int_op(smartlist_len(sl), OP_EQ, 0);
467 :
468 : // Try a real family
469 1 : nf1 = nodefamily_parse("$EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE "
470 : "$2121212121212121212121212121212121212121 "
471 : "$3333333333333333333333333333333333333333 "
472 : "erewhon nonesuch", NULL, 0);
473 1 : tt_assert(nf1);
474 1 : nodefamily_add_nodes_to_smartlist(nf1, sl);
475 : // There were 5 elements; 2 were dropped because the mocked lookup failed.
476 1 : tt_int_op(smartlist_len(sl), OP_EQ, 3);
477 :
478 1 : const node_t *n = smartlist_get(sl, 0);
479 1 : test_memeq_hex(n->identity, "3333333333333333333333333333333333333333");
480 1 : n = smartlist_get(sl, 1);
481 1 : test_memeq_hex(n->identity, "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE");
482 1 : n = smartlist_get(sl, 2);
483 1 : tt_str_op(n->identity, OP_EQ, "erewhon");
484 :
485 1 : done:
486 1 : UNMOCK(node_get_by_nickname);
487 1 : UNMOCK(node_get_by_id);
488 4 : SMARTLIST_FOREACH(sl, node_t *, fake_node, tor_free(fake_node));
489 1 : smartlist_free(sl);
490 1 : nodefamily_free(nf1);
491 1 : tor_free(mem_op_hex_tmp);
492 1 : }
493 :
494 : static void
495 1 : test_nodelist_nickname_matches(void *arg)
496 : {
497 1 : (void)arg;
498 1 : node_t mock_node;
499 1 : routerstatus_t mock_rs;
500 1 : memset(&mock_node, 0, sizeof(mock_node));
501 1 : memset(&mock_rs, 0, sizeof(mock_rs));
502 :
503 1 : strlcpy(mock_rs.nickname, "evilgeniuses", sizeof(mock_rs.nickname));
504 1 : mock_node.rs = &mock_rs;
505 1 : memcpy(mock_node.identity, ".forabettertomorrow.", DIGEST_LEN);
506 :
507 : #define match(x) tt_assert(node_nickname_matches(&mock_node, (x)))
508 : #define no_match(x) tt_assert(! node_nickname_matches(&mock_node, (x)))
509 :
510 1 : match("evilgeniuses");
511 1 : match("EvilGeniuses");
512 1 : match("EvilGeniuses");
513 1 : match("2e666f7261626574746572746f6d6f72726f772e");
514 1 : match("2E666F7261626574746572746F6D6F72726F772E");
515 1 : match("$2e666f7261626574746572746f6d6f72726f772e");
516 1 : match("$2E666F7261626574746572746F6D6F72726F772E");
517 1 : match("$2E666F7261626574746572746F6D6F72726F772E~evilgeniuses");
518 1 : match("$2E666F7261626574746572746F6D6F72726F772E~EVILGENIUSES");
519 :
520 1 : no_match("evilgenius");
521 1 : no_match("evilgeniuseses");
522 1 : no_match("evil.genius");
523 1 : no_match("$2E666F7261626574746572746F6D6F72726FFFFF");
524 1 : no_match("2E666F7261626574746572746F6D6F72726FFFFF");
525 1 : no_match("$2E666F7261626574746572746F6D6F72726F772E~fred");
526 1 : no_match("$2E666F7261626574746572746F6D6F72726F772E=EVILGENIUSES");
527 1 : done:
528 1 : ;
529 1 : }
530 :
531 : static void
532 1 : test_nodelist_node_nodefamily(void *arg)
533 : {
534 1 : (void)arg;
535 1 : node_t mock_node1;
536 1 : routerstatus_t mock_rs;
537 1 : microdesc_t mock_md;
538 :
539 1 : node_t mock_node2;
540 1 : routerinfo_t mock_ri;
541 :
542 1 : smartlist_t *nodes=smartlist_new();
543 :
544 1 : memset(&mock_node1, 0, sizeof(mock_node1));
545 1 : memset(&mock_node2, 0, sizeof(mock_node2));
546 1 : memset(&mock_rs, 0, sizeof(mock_rs));
547 1 : memset(&mock_md, 0, sizeof(mock_md));
548 1 : memset(&mock_ri, 0, sizeof(mock_ri));
549 :
550 1 : mock_node1.rs = &mock_rs;
551 1 : mock_node1.md = &mock_md;
552 :
553 1 : mock_node2.ri = &mock_ri;
554 :
555 1 : strlcpy(mock_rs.nickname, "nodeone", sizeof(mock_rs.nickname));
556 1 : mock_ri.nickname = tor_strdup("nodetwo");
557 :
558 1 : memcpy(mock_node1.identity, "NodeOneNode1NodeOne1", DIGEST_LEN);
559 1 : memcpy(mock_node2.identity, "SecondNodeWe'reTestn", DIGEST_LEN);
560 :
561 : // empty families.
562 1 : tt_assert(! node_family_contains(&mock_node1, &mock_node2));
563 1 : tt_assert(! node_family_contains(&mock_node2, &mock_node1));
564 :
565 : // Families contain nodes, but not these nodes
566 1 : mock_ri.declared_family = smartlist_new();
567 1 : smartlist_add(mock_ri.declared_family, (char*)"NodeThree");
568 1 : mock_md.family = nodefamily_parse("NodeFour", NULL, 0);
569 1 : tt_assert(! node_family_contains(&mock_node1, &mock_node2));
570 1 : tt_assert(! node_family_contains(&mock_node2, &mock_node1));
571 :
572 : // Families contain one another.
573 1 : smartlist_add(mock_ri.declared_family, (char*)
574 : "4e6f64654f6e654e6f6465314e6f64654f6e6531");
575 1 : tt_assert(! node_family_contains(&mock_node1, &mock_node2));
576 1 : tt_assert(node_family_contains(&mock_node2, &mock_node1));
577 :
578 1 : nodefamily_free(mock_md.family);
579 1 : mock_md.family = nodefamily_parse(
580 : "NodeFour "
581 : "5365636f6e644e6f64655765277265546573746e", NULL, 0);
582 1 : tt_assert(node_family_contains(&mock_node1, &mock_node2));
583 1 : tt_assert(node_family_contains(&mock_node2, &mock_node1));
584 :
585 : // Try looking up families now.
586 1 : MOCK(node_get_by_nickname, mock_node_get_by_nickname);
587 1 : MOCK(node_get_by_id, mock_node_get_by_id);
588 :
589 1 : node_lookup_declared_family(nodes, &mock_node1);
590 1 : tt_int_op(smartlist_len(nodes), OP_EQ, 2);
591 1 : const node_t *n = smartlist_get(nodes, 0);
592 1 : tt_mem_op(n->identity, OP_EQ, "SecondNodeWe'reTestn", DIGEST_LEN);
593 1 : n = smartlist_get(nodes, 1);
594 1 : tt_str_op(n->identity, OP_EQ, "nodefour");
595 :
596 : // free, try the other one.
597 3 : SMARTLIST_FOREACH(nodes, node_t *, x, tor_free(x));
598 1 : smartlist_clear(nodes);
599 :
600 1 : node_lookup_declared_family(nodes, &mock_node2);
601 1 : tt_int_op(smartlist_len(nodes), OP_EQ, 2);
602 1 : n = smartlist_get(nodes, 0);
603 : // This gets a truncated hex hex ID since it was looked up by name
604 1 : tt_str_op(n->identity, OP_EQ, "NodeThree");
605 1 : n = smartlist_get(nodes, 1);
606 1 : tt_str_op(n->identity, OP_EQ, "4e6f64654f6e654e6f6");
607 :
608 1 : done:
609 1 : UNMOCK(node_get_by_nickname);
610 1 : UNMOCK(node_get_by_id);
611 1 : smartlist_free(mock_ri.declared_family);
612 1 : nodefamily_free(mock_md.family);
613 1 : tor_free(mock_ri.nickname);
614 : // use tor_free, these aren't real nodes
615 3 : SMARTLIST_FOREACH(nodes, node_t *, x, tor_free(x));
616 1 : smartlist_free(nodes);
617 1 : }
618 :
619 : static void
620 1 : test_nodelist_nodefamily_canonicalize(void *arg)
621 : {
622 1 : (void)arg;
623 1 : char *c = NULL;
624 :
625 1 : c = nodefamily_canonicalize("", NULL, 0);
626 1 : tt_str_op(c, OP_EQ, "");
627 1 : tor_free(c);
628 :
629 1 : uint8_t own_id[20];
630 1 : memset(own_id, 0, sizeof(own_id));
631 1 : c = nodefamily_canonicalize(
632 : "alice BOB caroL %potrzebie !!!@#@# "
633 : "$bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=fred "
634 : "ffffffffffffffffffffffffffffffffffffffff "
635 : "$cccccccccccccccccccccccccccccccccccccccc ", own_id, 0);
636 1 : tt_str_op(c, OP_EQ,
637 : "!!!@#@# "
638 : "$0000000000000000000000000000000000000000 "
639 : "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "
640 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC "
641 : "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF "
642 : "%potrzebie "
643 : "alice bob carol");
644 :
645 1 : done:
646 1 : tor_free(c);
647 1 : }
648 :
649 : /** format_node_description() should return
650 : * "Fingerprint~Nickname at IPv4 and [IPv6]".
651 : * The nickname and addresses are optional.
652 : */
653 : static void
654 1 : test_nodelist_format_node_description(void *arg)
655 : {
656 1 : char mock_digest[DIGEST_LEN];
657 1 : char mock_nickname[MAX_NICKNAME_LEN+1];
658 1 : tor_addr_t mock_null_ip;
659 1 : tor_addr_t mock_ipv4;
660 1 : tor_addr_t mock_ipv6;
661 1 : ed25519_public_key_t ed_id;
662 :
663 1 : char ndesc[NODE_DESC_BUF_LEN];
664 1 : const char *rv = NULL;
665 :
666 1 : (void) arg;
667 :
668 : /* Clear variables */
669 1 : memset(ndesc, 0, sizeof(ndesc));
670 1 : memset(mock_digest, 0, sizeof(mock_digest));
671 1 : memset(mock_nickname, 0, sizeof(mock_nickname));
672 1 : memset(&mock_null_ip, 0, sizeof(mock_null_ip));
673 1 : memset(&mock_ipv4, 0, sizeof(mock_ipv4));
674 1 : memset(&mock_ipv6, 0, sizeof(mock_ipv6));
675 :
676 : /* Set variables */
677 1 : memcpy(mock_digest,
678 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
679 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
680 : sizeof(mock_digest));
681 1 : strlcpy(mock_nickname, "TestOR7890123456789", sizeof(mock_nickname));
682 1 : tor_addr_parse(&mock_ipv4, "111.222.233.244");
683 1 : tor_addr_parse(&mock_ipv6, "[1111:2222:3333:4444:5555:6666:7777:8888]");
684 :
685 : /* Test function with variables */
686 1 : rv = format_node_description(ndesc,
687 : mock_digest,
688 : NULL,
689 : NULL,
690 : NULL,
691 : NULL);
692 1 : tt_ptr_op(rv, OP_EQ, ndesc);
693 1 : tt_str_op(ndesc, OP_EQ, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
694 :
695 : /* format node description should use ~ because named is deprecated */
696 1 : rv = format_node_description(ndesc,
697 : mock_digest,
698 : NULL,
699 : mock_nickname,
700 : NULL,
701 : NULL);
702 1 : tt_ptr_op(rv, OP_EQ, ndesc);
703 1 : tt_str_op(ndesc, OP_EQ,
704 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~""TestOR7890123456789");
705 :
706 : /* Try a null IP address, rather than NULL */
707 1 : rv = format_node_description(ndesc,
708 : mock_digest,
709 : NULL,
710 : mock_nickname,
711 : NULL,
712 : &mock_null_ip);
713 1 : tt_ptr_op(rv, OP_EQ, ndesc);
714 1 : tt_str_op(ndesc, OP_EQ,
715 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789");
716 :
717 : /* Try some real IP addresses */
718 1 : rv = format_node_description(ndesc,
719 : mock_digest,
720 : NULL,
721 : NULL,
722 : &mock_ipv4,
723 : NULL);
724 1 : tt_ptr_op(rv, OP_EQ, ndesc);
725 1 : tt_str_op(ndesc, OP_EQ,
726 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA at 111.222.233.244");
727 :
728 1 : rv = format_node_description(ndesc,
729 : mock_digest,
730 : NULL,
731 : mock_nickname,
732 : NULL,
733 : &mock_ipv6);
734 1 : tt_ptr_op(rv, OP_EQ, ndesc);
735 1 : tt_str_op(ndesc, OP_EQ,
736 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
737 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
738 :
739 1 : rv = format_node_description(ndesc,
740 : mock_digest,
741 : NULL,
742 : mock_nickname,
743 : &mock_ipv4,
744 : &mock_ipv6);
745 1 : tt_ptr_op(rv, OP_EQ, ndesc);
746 1 : tt_str_op(ndesc, OP_EQ,
747 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
748 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
749 :
750 : /* Try some ed25519 keys. */
751 1 : int n = ed25519_public_from_base64(&ed_id,
752 : "+wBP6WVZzqKK+eTdwU7Hhb80xEm40FSZDBMNozTJpDE");
753 1 : tt_int_op(n,OP_EQ,0);
754 1 : rv = format_node_description(ndesc,
755 : mock_digest,
756 : &ed_id,
757 : mock_nickname,
758 : &mock_ipv4,
759 : &mock_ipv6);
760 1 : tt_str_op(ndesc, OP_EQ,
761 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 "
762 : "[+wBP6WVZzqKK+eTdwU7Hhb80xEm40FSZDBMNozTJpDE] at "
763 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
764 :
765 : /* test NULL handling */
766 1 : rv = format_node_description(NULL, NULL, NULL, NULL, NULL, NULL);
767 1 : tt_str_op(rv, OP_EQ, "<NULL BUFFER>");
768 :
769 1 : rv = format_node_description(ndesc, NULL, NULL, NULL, NULL, NULL);
770 1 : tt_ptr_op(rv, OP_EQ, ndesc);
771 1 : tt_str_op(rv, OP_EQ, "<NULL ID DIGEST>");
772 :
773 1 : done:
774 1 : return;
775 : }
776 :
777 : /** router_describe() is a wrapper for format_node_description(), see that
778 : * test for details.
779 : *
780 : * The routerinfo-only node_describe() tests are in this function,
781 : * so we can re-use the same mocked variables.
782 : */
783 : static void
784 1 : test_nodelist_router_describe(void *arg)
785 : {
786 1 : char mock_nickname[MAX_NICKNAME_LEN+1];
787 1 : routerinfo_t mock_ri_ipv4;
788 1 : routerinfo_t mock_ri_ipv6;
789 1 : routerinfo_t mock_ri_dual;
790 :
791 1 : const char *rv = NULL;
792 :
793 1 : (void) arg;
794 :
795 : /* Clear variables */
796 1 : memset(mock_nickname, 0, sizeof(mock_nickname));
797 1 : memset(&mock_ri_ipv4, 0, sizeof(mock_ri_ipv4));
798 1 : memset(&mock_ri_ipv6, 0, sizeof(mock_ri_ipv6));
799 1 : memset(&mock_ri_dual, 0, sizeof(mock_ri_dual));
800 :
801 : /* Set up the dual-stack routerinfo */
802 1 : memcpy(mock_ri_dual.cache_info.identity_digest,
803 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
804 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
805 : sizeof(mock_ri_dual.cache_info.identity_digest));
806 1 : strlcpy(mock_nickname, "TestOR7890123456789", sizeof(mock_nickname));
807 1 : mock_ri_dual.nickname = mock_nickname;
808 1 : tor_addr_parse(&mock_ri_dual.ipv4_addr, "111.222.233.244");
809 1 : tor_addr_parse(&mock_ri_dual.ipv6_addr,
810 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
811 :
812 : /* Create and modify the other routerinfos.
813 : * mock_nickname is referenced from all 3 routerinfos.
814 : * That's ok, all their memory is static. */
815 1 : memcpy(&mock_ri_ipv4, &mock_ri_dual, sizeof(mock_ri_ipv4));
816 1 : memcpy(&mock_ri_ipv6, &mock_ri_dual, sizeof(mock_ri_ipv6));
817 : /* Clear the unnecessary addresses */
818 1 : memset(&mock_ri_ipv4.ipv6_addr, 0, sizeof(mock_ri_ipv4.ipv6_addr));
819 1 : tor_addr_make_unspec(&mock_ri_ipv6.ipv4_addr);
820 :
821 : /* We don't test the no-nickname and no-IP cases, because they're covered by
822 : * format_node_description(), and we don't expect to see them in Tor code. */
823 :
824 : /* Try some real IP addresses */
825 1 : rv = router_describe(&mock_ri_ipv4);
826 1 : tt_str_op(rv, OP_EQ,
827 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
828 : "111.222.233.244");
829 :
830 1 : rv = router_describe(&mock_ri_ipv6);
831 1 : tt_str_op(rv, OP_EQ,
832 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
833 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
834 :
835 1 : rv = router_describe(&mock_ri_dual);
836 1 : tt_str_op(rv, OP_EQ,
837 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
838 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
839 :
840 : /* test NULL handling */
841 1 : rv = router_describe(NULL);
842 1 : tt_str_op(rv, OP_EQ, "<null>");
843 :
844 : /* Now test a node with only these routerinfos */
845 1 : node_t mock_node;
846 1 : memset(&mock_node, 0, sizeof(mock_node));
847 1 : memcpy(mock_node.identity,
848 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
849 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
850 : sizeof(mock_node.identity));
851 :
852 : /* Try some real IP addresses */
853 1 : mock_node.ri = &mock_ri_ipv4;
854 1 : rv = node_describe(&mock_node);
855 1 : tt_str_op(rv, OP_EQ,
856 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
857 : "111.222.233.244");
858 :
859 1 : mock_node.ri = &mock_ri_ipv6;
860 1 : rv = node_describe(&mock_node);
861 1 : tt_str_op(rv, OP_EQ,
862 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
863 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
864 :
865 1 : mock_node.ri = &mock_ri_dual;
866 1 : rv = node_describe(&mock_node);
867 1 : tt_str_op(rv, OP_EQ,
868 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
869 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
870 :
871 1 : done:
872 1 : return;
873 : }
874 :
875 : /** node_describe() is a wrapper for format_node_description(), see that
876 : * test for details.
877 : *
878 : * The routerinfo-only and routerstatus-only node_describe() tests are in
879 : * test_nodelist_router_describe() and test_nodelist_routerstatus_describe(),
880 : * so we can re-use their mocked variables.
881 : */
882 : static void
883 1 : test_nodelist_node_describe(void *arg)
884 : {
885 1 : char mock_nickname[MAX_NICKNAME_LEN+1];
886 :
887 1 : const char *rv = NULL;
888 :
889 1 : (void) arg;
890 :
891 : /* Routerinfos */
892 1 : routerinfo_t mock_ri_dual;
893 :
894 : /* Clear variables */
895 1 : memset(mock_nickname, 0, sizeof(mock_nickname));
896 1 : memset(&mock_ri_dual, 0, sizeof(mock_ri_dual));
897 :
898 : /* Set up the dual-stack routerinfo */
899 1 : memcpy(mock_ri_dual.cache_info.identity_digest,
900 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
901 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
902 : sizeof(mock_ri_dual.cache_info.identity_digest));
903 1 : strlcpy(mock_nickname, "TestOR7890123456789", sizeof(mock_nickname));
904 1 : mock_ri_dual.nickname = mock_nickname;
905 1 : tor_addr_parse(&mock_ri_dual.ipv4_addr, "111.222.233.244");
906 1 : tor_addr_parse(&mock_ri_dual.ipv6_addr,
907 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
908 :
909 : /* Routerstatuses */
910 1 : routerstatus_t mock_rs_ipv4;
911 1 : routerstatus_t mock_rs_dual;
912 :
913 : /* Clear variables */
914 1 : memset(&mock_rs_ipv4, 0, sizeof(mock_rs_ipv4));
915 1 : memset(&mock_rs_dual, 0, sizeof(mock_rs_dual));
916 :
917 : /* Set up the dual-stack routerstatus */
918 1 : memcpy(mock_rs_dual.identity_digest,
919 : "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"
920 : "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB",
921 : sizeof(mock_rs_dual.identity_digest));
922 1 : strlcpy(mock_rs_dual.nickname, "Bbb",
923 : sizeof(mock_rs_dual.nickname));
924 1 : tor_addr_parse(&mock_rs_dual.ipv4_addr, "2.2.2.2");
925 1 : tor_addr_parse(&mock_rs_dual.ipv6_addr,
926 : "[bbbb::bbbb]");
927 :
928 : /* Create and modify the other routerstatus. */
929 1 : memcpy(&mock_rs_ipv4, &mock_rs_dual, sizeof(mock_rs_ipv4));
930 : /* Clear the unnecessary IPv6 address */
931 1 : memset(&mock_rs_ipv4.ipv6_addr, 0, sizeof(mock_rs_ipv4.ipv6_addr));
932 :
933 : /* Microdescs */
934 1 : microdesc_t mock_md_null;
935 1 : microdesc_t mock_md_ipv6;
936 :
937 : /* Clear variables */
938 1 : memset(&mock_md_null, 0, sizeof(mock_md_null));
939 1 : memset(&mock_md_ipv6, 0, sizeof(mock_md_ipv6));
940 :
941 : /* Set up the microdesc */
942 1 : tor_addr_parse(&mock_md_ipv6.ipv6_addr,
943 : "[eeee::6000:6000]");
944 :
945 : /* Set up the node */
946 1 : node_t mock_node;
947 1 : memset(&mock_node, 0, sizeof(mock_node));
948 1 : memcpy(mock_node.identity,
949 : "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
950 : "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC",
951 : sizeof(mock_node.identity));
952 :
953 : /* Test that the routerinfo and routerstatus work separately, but the
954 : * identity comes from the node */
955 1 : mock_node.ri = &mock_ri_dual;
956 1 : mock_node.rs = NULL;
957 1 : mock_node.md = NULL;
958 1 : rv = node_describe(&mock_node);
959 1 : tt_str_op(rv, OP_EQ,
960 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~TestOR7890123456789 at "
961 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
962 :
963 1 : mock_node.ri = NULL;
964 1 : mock_node.rs = &mock_rs_ipv4;
965 1 : mock_node.md = NULL;
966 1 : rv = node_describe(&mock_node);
967 1 : tt_str_op(rv, OP_EQ,
968 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
969 : "2.2.2.2");
970 :
971 1 : mock_node.ri = NULL;
972 1 : mock_node.rs = &mock_rs_dual;
973 1 : mock_node.md = NULL;
974 1 : rv = node_describe(&mock_node);
975 1 : tt_str_op(rv, OP_EQ,
976 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
977 : "2.2.2.2 and [bbbb::bbbb]");
978 :
979 : /* Test that the routerstatus overrides the routerinfo */
980 1 : mock_node.ri = &mock_ri_dual;
981 1 : mock_node.rs = &mock_rs_ipv4;
982 1 : mock_node.md = NULL;
983 1 : rv = node_describe(&mock_node);
984 1 : tt_str_op(rv, OP_EQ,
985 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
986 : "2.2.2.2");
987 :
988 1 : mock_node.ri = &mock_ri_dual;
989 1 : mock_node.rs = &mock_rs_dual;
990 1 : mock_node.md = NULL;
991 1 : rv = node_describe(&mock_node);
992 1 : tt_str_op(rv, OP_EQ,
993 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
994 : "2.2.2.2 and [bbbb::bbbb]");
995 :
996 : /* Test that the microdesc IPv6 is used if the routerinfo doesn't have IPv6
997 : */
998 1 : mock_node.ri = NULL;
999 1 : mock_node.rs = &mock_rs_ipv4;
1000 1 : mock_node.md = &mock_md_ipv6;
1001 1 : rv = node_describe(&mock_node);
1002 1 : tt_str_op(rv, OP_EQ,
1003 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1004 : "2.2.2.2 and [eeee::6000:6000]");
1005 :
1006 1 : mock_node.ri = NULL;
1007 1 : mock_node.rs = &mock_rs_ipv4;
1008 1 : mock_node.md = &mock_md_null;
1009 1 : rv = node_describe(&mock_node);
1010 1 : tt_str_op(rv, OP_EQ,
1011 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1012 : "2.2.2.2");
1013 :
1014 1 : mock_node.ri = NULL;
1015 1 : mock_node.rs = &mock_rs_dual;
1016 1 : mock_node.md = &mock_md_ipv6;
1017 1 : rv = node_describe(&mock_node);
1018 1 : tt_str_op(rv, OP_EQ,
1019 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1020 : "2.2.2.2 and [bbbb::bbbb]");
1021 :
1022 1 : mock_node.ri = NULL;
1023 1 : mock_node.rs = &mock_rs_dual;
1024 1 : mock_node.md = &mock_md_null;
1025 1 : rv = node_describe(&mock_node);
1026 1 : tt_str_op(rv, OP_EQ,
1027 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1028 : "2.2.2.2 and [bbbb::bbbb]");
1029 :
1030 : /* Test that the routerinfo doesn't change the results above
1031 : */
1032 1 : mock_node.ri = &mock_ri_dual;
1033 1 : mock_node.rs = &mock_rs_ipv4;
1034 1 : mock_node.md = &mock_md_ipv6;
1035 1 : rv = node_describe(&mock_node);
1036 1 : tt_str_op(rv, OP_EQ,
1037 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1038 : "2.2.2.2 and [eeee::6000:6000]");
1039 :
1040 1 : mock_node.ri = &mock_ri_dual;
1041 1 : mock_node.rs = &mock_rs_ipv4;
1042 1 : mock_node.md = &mock_md_null;
1043 1 : rv = node_describe(&mock_node);
1044 1 : tt_str_op(rv, OP_EQ,
1045 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1046 : "2.2.2.2");
1047 :
1048 1 : mock_node.ri = &mock_ri_dual;
1049 1 : mock_node.rs = &mock_rs_dual;
1050 1 : mock_node.md = &mock_md_ipv6;
1051 1 : rv = node_describe(&mock_node);
1052 1 : tt_str_op(rv, OP_EQ,
1053 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1054 : "2.2.2.2 and [bbbb::bbbb]");
1055 :
1056 1 : mock_node.ri = &mock_ri_dual;
1057 1 : mock_node.rs = &mock_rs_dual;
1058 1 : mock_node.md = &mock_md_null;
1059 1 : rv = node_describe(&mock_node);
1060 1 : tt_str_op(rv, OP_EQ,
1061 : "$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC~Bbb at "
1062 : "2.2.2.2 and [bbbb::bbbb]");
1063 :
1064 : /* test NULL handling */
1065 1 : rv = node_describe(NULL);
1066 1 : tt_str_op(rv, OP_EQ, "<null>");
1067 :
1068 1 : mock_node.ri = NULL;
1069 1 : mock_node.rs = NULL;
1070 1 : mock_node.md = NULL;
1071 1 : rv = node_describe(&mock_node);
1072 1 : tt_str_op(rv, OP_EQ,
1073 : "<null rs and ri>");
1074 :
1075 1 : done:
1076 1 : return;
1077 : }
1078 :
1079 : /** routerstatus_describe() is a wrapper for format_node_description(), see
1080 : * that test for details.
1081 : *
1082 : * The routerstatus-only node_describe() tests are in this function,
1083 : * so we can re-use the same mocked variables.
1084 : */
1085 : static void
1086 1 : test_nodelist_routerstatus_describe(void *arg)
1087 : {
1088 1 : routerstatus_t mock_rs_ipv4;
1089 1 : routerstatus_t mock_rs_ipv6;
1090 1 : routerstatus_t mock_rs_dual;
1091 :
1092 1 : const char *rv = NULL;
1093 :
1094 1 : (void) arg;
1095 :
1096 : /* Clear variables */
1097 1 : memset(&mock_rs_ipv4, 0, sizeof(mock_rs_ipv4));
1098 1 : memset(&mock_rs_ipv6, 0, sizeof(mock_rs_ipv6));
1099 1 : memset(&mock_rs_dual, 0, sizeof(mock_rs_dual));
1100 :
1101 : /* Set up the dual-stack routerstatus */
1102 1 : memcpy(mock_rs_dual.identity_digest,
1103 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
1104 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
1105 : sizeof(mock_rs_dual.identity_digest));
1106 1 : strlcpy(mock_rs_dual.nickname, "TestOR7890123456789",
1107 : sizeof(mock_rs_dual.nickname));
1108 1 : tor_addr_parse(&mock_rs_dual.ipv4_addr, "111.222.233.244");
1109 1 : tor_addr_parse(&mock_rs_dual.ipv6_addr,
1110 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
1111 :
1112 : /* Create and modify the other routerstatuses. */
1113 1 : memcpy(&mock_rs_ipv4, &mock_rs_dual, sizeof(mock_rs_ipv4));
1114 1 : memcpy(&mock_rs_ipv6, &mock_rs_dual, sizeof(mock_rs_ipv6));
1115 : /* Clear the unnecessary addresses */
1116 1 : memset(&mock_rs_ipv4.ipv6_addr, 0, sizeof(mock_rs_ipv4.ipv6_addr));
1117 1 : tor_addr_make_unspec(&mock_rs_ipv6.ipv4_addr);
1118 :
1119 : /* We don't test the no-nickname and no-IP cases, because they're covered by
1120 : * format_node_description(), and we don't expect to see them in Tor code. */
1121 :
1122 : /* Try some real IP addresses */
1123 1 : rv = routerstatus_describe(&mock_rs_ipv4);
1124 1 : tt_str_op(rv, OP_EQ,
1125 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1126 : "111.222.233.244");
1127 :
1128 1 : rv = routerstatus_describe(&mock_rs_ipv6);
1129 1 : tt_str_op(rv, OP_EQ,
1130 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1131 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
1132 :
1133 1 : rv = routerstatus_describe(&mock_rs_dual);
1134 1 : tt_str_op(rv, OP_EQ,
1135 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1136 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
1137 :
1138 : /* test NULL handling */
1139 1 : rv = routerstatus_describe(NULL);
1140 1 : tt_str_op(rv, OP_EQ, "<null>");
1141 :
1142 : /* Now test a node with only these routerstatuses */
1143 1 : node_t mock_node;
1144 1 : memset(&mock_node, 0, sizeof(mock_node));
1145 1 : memcpy(mock_node.identity,
1146 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
1147 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
1148 : sizeof(mock_node.identity));
1149 :
1150 : /* Try some real IP addresses */
1151 1 : mock_node.rs = &mock_rs_ipv4;
1152 1 : rv = node_describe(&mock_node);
1153 1 : tt_str_op(rv, OP_EQ,
1154 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1155 : "111.222.233.244");
1156 :
1157 1 : mock_node.rs = &mock_rs_ipv6;
1158 1 : rv = node_describe(&mock_node);
1159 1 : tt_str_op(rv, OP_EQ,
1160 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1161 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
1162 :
1163 1 : mock_node.rs = &mock_rs_dual;
1164 1 : rv = node_describe(&mock_node);
1165 1 : tt_str_op(rv, OP_EQ,
1166 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1167 : "111.222.233.244 and [1111:2222:3333:4444:5555:6666:7777:8888]");
1168 :
1169 1 : done:
1170 1 : return;
1171 : }
1172 :
1173 : /** extend_info_describe() is a wrapper for format_node_description(), see
1174 : * that test for details.
1175 : */
1176 : static void
1177 1 : test_nodelist_extend_info_describe(void *arg)
1178 : {
1179 1 : extend_info_t mock_ei_ipv4;
1180 1 : extend_info_t mock_ei_ipv6;
1181 :
1182 1 : const char *rv = NULL;
1183 :
1184 1 : (void) arg;
1185 :
1186 : /* Clear variables */
1187 1 : memset(&mock_ei_ipv4, 0, sizeof(mock_ei_ipv4));
1188 1 : memset(&mock_ei_ipv6, 0, sizeof(mock_ei_ipv6));
1189 :
1190 : /* Set up the IPv4 extend info */
1191 1 : memcpy(mock_ei_ipv4.identity_digest,
1192 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
1193 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
1194 : sizeof(mock_ei_ipv4.identity_digest));
1195 1 : strlcpy(mock_ei_ipv4.nickname, "TestOR7890123456789",
1196 : sizeof(mock_ei_ipv4.nickname));
1197 1 : tor_addr_parse(&mock_ei_ipv4.orports[0].addr, "111.222.233.244");
1198 :
1199 : /* Create and modify the other extend info. */
1200 1 : memcpy(&mock_ei_ipv6, &mock_ei_ipv4, sizeof(mock_ei_ipv6));
1201 1 : tor_addr_parse(&mock_ei_ipv6.orports[0].addr,
1202 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
1203 :
1204 : /* We don't test the no-nickname and no-IP cases, because they're covered by
1205 : * format_node_description(), and we don't expect to see them in Tor code. */
1206 :
1207 : /* Try some real IP addresses */
1208 1 : rv = extend_info_describe(&mock_ei_ipv4);
1209 1 : tt_str_op(rv, OP_EQ,
1210 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1211 : "111.222.233.244");
1212 :
1213 1 : rv = extend_info_describe(&mock_ei_ipv6);
1214 1 : tt_str_op(rv, OP_EQ,
1215 : "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR7890123456789 at "
1216 : "[1111:2222:3333:4444:5555:6666:7777:8888]");
1217 :
1218 : /* Extend infos only have one IP address, so there is no dual case */
1219 :
1220 : /* test NULL handling */
1221 1 : rv = extend_info_describe(NULL);
1222 1 : tt_str_op(rv, OP_EQ, "<null>");
1223 :
1224 1 : done:
1225 1 : return;
1226 : }
1227 :
1228 : /** router_get_verbose_nickname() should return "Fingerprint~Nickname"
1229 : */
1230 : static void
1231 1 : test_nodelist_router_get_verbose_nickname(void *arg)
1232 : {
1233 1 : routerinfo_t mock_ri;
1234 1 : char mock_nickname[MAX_NICKNAME_LEN+1];
1235 :
1236 1 : char vname[MAX_VERBOSE_NICKNAME_LEN+1];
1237 :
1238 1 : (void) arg;
1239 :
1240 1 : memset(&mock_ri, 0, sizeof(routerinfo_t));
1241 1 : memset(mock_nickname, 0, sizeof(mock_nickname));
1242 1 : mock_ri.nickname = mock_nickname;
1243 :
1244 : /* verbose nickname should use ~ because named is deprecated */
1245 1 : strlcpy(mock_nickname, "TestOR", sizeof(mock_nickname));
1246 1 : memcpy(mock_ri.cache_info.identity_digest,
1247 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
1248 : "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
1249 : DIGEST_LEN);
1250 1 : router_get_verbose_nickname(vname, &mock_ri);
1251 1 : tt_str_op(vname, OP_EQ, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR");
1252 :
1253 : /* test NULL router handling */
1254 1 : router_get_verbose_nickname(vname, NULL);
1255 1 : tt_str_op(vname, OP_EQ, "<null>");
1256 :
1257 1 : router_get_verbose_nickname(NULL, &mock_ri);
1258 1 : router_get_verbose_nickname(NULL, NULL);
1259 :
1260 1 : done:
1261 1 : return;
1262 : }
1263 :
1264 : static void
1265 1 : test_nodelist_routerstatus_has_visibly_changed(void *arg)
1266 : {
1267 1 : (void)arg;
1268 1 : routerstatus_t rs_orig, rs;
1269 1 : char *fmt_orig = NULL, *fmt = NULL;
1270 1 : memset(&rs_orig, 0, sizeof(rs_orig));
1271 1 : strlcpy(rs_orig.nickname, "friendly", sizeof(rs_orig.nickname));
1272 1 : memcpy(rs_orig.identity_digest, "abcdefghijklmnopqrst", 20);
1273 1 : memcpy(rs_orig.descriptor_digest, "abcdefghijklmnopqrst", 20);
1274 1 : tor_addr_from_ipv4h(&rs_orig.ipv4_addr, 0x7f000001);
1275 1 : rs_orig.ipv4_orport = 3;
1276 1 : rs_orig.published_on = time(NULL);
1277 1 : rs_orig.has_bandwidth = 1;
1278 1 : rs_orig.bandwidth_kb = 20;
1279 :
1280 : #define COPY() memcpy(&rs, &rs_orig, sizeof(rs))
1281 : #define FORMAT() \
1282 : STMT_BEGIN \
1283 : tor_free(fmt_orig); \
1284 : tor_free(fmt); \
1285 : fmt_orig = routerstatus_format_entry(&rs_orig, NULL, NULL, \
1286 : NS_CONTROL_PORT, \
1287 : NULL); \
1288 : fmt = routerstatus_format_entry(&rs, NULL, NULL, NS_CONTROL_PORT, \
1289 : NULL); \
1290 : tt_assert(fmt_orig); \
1291 : tt_assert(fmt); \
1292 : STMT_END
1293 : #define ASSERT_SAME() \
1294 : STMT_BEGIN \
1295 : tt_assert(! routerstatus_has_visibly_changed(&rs_orig, &rs)); \
1296 : FORMAT(); \
1297 : tt_str_op(fmt_orig, OP_EQ, fmt); \
1298 : COPY(); \
1299 : STMT_END
1300 : #define ASSERT_CHANGED() \
1301 : STMT_BEGIN \
1302 : tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
1303 : FORMAT(); \
1304 : tt_str_op(fmt_orig, OP_NE, fmt); \
1305 : COPY(); \
1306 : STMT_END
1307 : #define ASSERT_CHANGED_NO_FORMAT() \
1308 : STMT_BEGIN \
1309 : tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
1310 : COPY(); \
1311 : STMT_END
1312 :
1313 1 : COPY();
1314 1 : ASSERT_SAME();
1315 :
1316 1 : tor_addr_from_ipv4h(&rs.ipv4_addr, 0x7f000002);
1317 1 : ASSERT_CHANGED();
1318 :
1319 1 : strlcpy(rs.descriptor_digest, "hello world", sizeof(rs.descriptor_digest));
1320 1 : ASSERT_CHANGED();
1321 :
1322 1 : strlcpy(rs.nickname, "fr1end1y", sizeof(rs.nickname));
1323 1 : ASSERT_CHANGED();
1324 :
1325 1 : rs.published_on += 3600;
1326 1 : ASSERT_CHANGED();
1327 :
1328 1 : rs.ipv4_orport = 55;
1329 1 : ASSERT_CHANGED();
1330 :
1331 1 : rs.ipv4_dirport = 9999;
1332 1 : ASSERT_CHANGED();
1333 :
1334 1 : tor_addr_parse(&rs.ipv6_addr, "1234::56");
1335 1 : ASSERT_CHANGED();
1336 :
1337 1 : tor_addr_parse(&rs_orig.ipv6_addr, "1234::56");
1338 1 : rs_orig.ipv6_orport = 99;
1339 1 : COPY();
1340 1 : rs.ipv6_orport = 22;
1341 1 : ASSERT_CHANGED();
1342 :
1343 1 : rs.is_authority = 1;
1344 1 : ASSERT_CHANGED();
1345 :
1346 1 : rs.is_exit = 1;
1347 1 : ASSERT_CHANGED();
1348 :
1349 1 : rs.is_stable = 1;
1350 1 : ASSERT_CHANGED();
1351 :
1352 1 : rs.is_fast = 1;
1353 1 : ASSERT_CHANGED();
1354 :
1355 1 : rs.is_flagged_running = 1;
1356 1 : ASSERT_CHANGED();
1357 :
1358 : // This option is obsolete and not actually formatted.
1359 1 : rs.is_named = 1;
1360 1 : ASSERT_CHANGED_NO_FORMAT();
1361 :
1362 : // This option is obsolete and not actually formatted.
1363 1 : rs.is_unnamed = 1;
1364 1 : ASSERT_CHANGED_NO_FORMAT();
1365 :
1366 1 : rs.is_valid = 1;
1367 1 : ASSERT_CHANGED();
1368 :
1369 1 : rs.is_possible_guard = 1;
1370 1 : ASSERT_CHANGED();
1371 :
1372 1 : rs.is_bad_exit = 1;
1373 1 : ASSERT_CHANGED();
1374 :
1375 1 : rs.is_hs_dir = 1;
1376 1 : ASSERT_CHANGED();
1377 :
1378 1 : rs.is_v2_dir = 1;
1379 1 : ASSERT_CHANGED();
1380 :
1381 1 : rs.is_staledesc = 1;
1382 1 : ASSERT_CHANGED();
1383 :
1384 : // Setting this to zero crashes us with an assertion failure in
1385 : // routerstatus_format_entry() if we don't have a descriptor.
1386 1 : rs.has_bandwidth = 0;
1387 1 : ASSERT_CHANGED_NO_FORMAT();
1388 :
1389 : // Does not actually matter; not visible to controller.
1390 1 : rs.has_exitsummary = 1;
1391 1 : ASSERT_SAME();
1392 :
1393 : // Does not actually matter; not visible to the controller.
1394 1 : rs.bw_is_unmeasured = 1;
1395 1 : ASSERT_SAME();
1396 :
1397 1 : rs.bandwidth_kb = 2000;
1398 1 : ASSERT_CHANGED();
1399 :
1400 : // not visible to the controller.
1401 1 : rs.has_guardfraction = 1;
1402 1 : rs.guardfraction_percentage = 22;
1403 1 : ASSERT_SAME();
1404 :
1405 : // not visible to the controller.
1406 1 : rs_orig.has_guardfraction = 1;
1407 1 : rs_orig.guardfraction_percentage = 20;
1408 1 : COPY();
1409 1 : rs.guardfraction_percentage = 25;
1410 1 : ASSERT_SAME();
1411 :
1412 : // not visible to the controller.
1413 1 : rs.exitsummary = (char*)"accept 1-2";
1414 1 : ASSERT_SAME();
1415 :
1416 1 : done:
1417 : #undef COPY
1418 : #undef ASSERT_SAME
1419 : #undef ASSERT_CHANGED
1420 1 : tor_free(fmt_orig);
1421 1 : tor_free(fmt);
1422 1 : return;
1423 : }
1424 :
1425 : #define NODE(name, flags) \
1426 : { #name, test_nodelist_##name, (flags), NULL, NULL }
1427 :
1428 : struct testcase_t nodelist_tests[] = {
1429 : NODE(node_get_verbose_nickname_by_id_null_node, TT_FORK),
1430 : NODE(node_get_verbose_nickname_not_named, TT_FORK),
1431 : NODE(node_is_dir, TT_FORK),
1432 : NODE(ed_id, TT_FORK),
1433 : NODE(nodefamily, TT_FORK),
1434 : NODE(nodefamily_parse_err, TT_FORK),
1435 : NODE(nodefamily_lookup, TT_FORK),
1436 : NODE(nickname_matches, 0),
1437 : NODE(node_nodefamily, TT_FORK),
1438 : NODE(nodefamily_canonicalize, 0),
1439 : NODE(format_node_description, 0),
1440 : NODE(router_describe, 0),
1441 : NODE(node_describe, 0),
1442 : NODE(routerstatus_describe, 0),
1443 : NODE(extend_info_describe, 0),
1444 : NODE(router_get_verbose_nickname, 0),
1445 : NODE(routerstatus_has_visibly_changed, 0),
1446 : END_OF_TESTCASES
1447 : };
|