1 /* Copyright (c) 2014, Daniel MartÃ
2 * Copyright (c) 2014-2019, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
5 #define CONSDIFF_PRIVATE
7 #include "core/or/or.h"
10 #include "feature/dircommon/consdiff.h"
11 #include "lib/memarea/memarea.h"
12 #include "test/log_test_helpers.h"
14 #define tt_str_eq_line(a,b) \
15 tt_assert(line_str_eq((b),(a)))
18 consensus_split_lines_(smartlist_t
*out
, const char *s
, memarea_t
*area
)
20 size_t len
= strlen(s
);
21 return consensus_split_lines(out
, s
, len
, area
);
25 consensus_compute_digest_(const char *cons
,
26 consensus_digest_t
*digest_out
)
28 size_t len
= strlen(cons
);
29 char *tmp
= tor_memdup(cons
, len
);
30 // We use memdup here to ensure that the input is NOT nul-terminated.
31 // This makes it likelier for us to spot bugs.
32 int r
= consensus_compute_digest(tmp
, len
, digest_out
);
38 consensus_compute_digest_as_signed_(const char *cons
,
39 consensus_digest_t
*digest_out
)
41 size_t len
= strlen(cons
);
42 char *tmp
= tor_memdup(cons
, len
);
43 // We use memdup here to ensure that the input is NOT nul-terminated.
44 // This makes it likelier for us to spot bugs.
45 int r
= consensus_compute_digest_as_signed(tmp
, len
, digest_out
);
51 test_consdiff_smartlist_slice(void *arg
)
53 smartlist_t
*sl
= smartlist_new();
54 smartlist_slice_t
*sls
;
55 int items
[6] = {0,0,0,0,0,0};
57 /* Create a regular smartlist. */
59 smartlist_add(sl
, &items
[1]);
60 smartlist_add(sl
, &items
[2]);
61 smartlist_add(sl
, &items
[3]);
62 smartlist_add(sl
, &items
[4]);
63 smartlist_add(sl
, &items
[5]);
65 /* See if the slice was done correctly. */
66 sls
= smartlist_slice(sl
, 2, 5);
67 tt_ptr_op(sl
, OP_EQ
, sls
->list
);
68 tt_ptr_op(&items
[3], OP_EQ
, smartlist_get(sls
->list
, sls
->offset
));
69 tt_ptr_op(&items
[5], OP_EQ
,
70 smartlist_get(sls
->list
, sls
->offset
+ (sls
->len
-1)));
73 /* See that using -1 as the end does get to the last element. */
74 sls
= smartlist_slice(sl
, 2, -1);
75 tt_ptr_op(sl
, OP_EQ
, sls
->list
);
76 tt_ptr_op(&items
[3], OP_EQ
, smartlist_get(sls
->list
, sls
->offset
));
77 tt_ptr_op(&items
[5], OP_EQ
,
78 smartlist_get(sls
->list
, sls
->offset
+ (sls
->len
-1)));
86 test_consdiff_smartlist_slice_string_pos(void *arg
)
88 smartlist_t
*sl
= smartlist_new();
89 smartlist_slice_t
*sls
;
90 memarea_t
*area
= memarea_new();
92 /* Create a regular smartlist. */
94 consensus_split_lines_(sl
, "a\nd\nc\na\nb\n", area
);
96 /* See that smartlist_slice_string_pos respects the bounds of the slice. */
97 sls
= smartlist_slice(sl
, 2, 5);
98 cdline_t a_line
= { "a", 1 };
99 tt_int_op(3, OP_EQ
, smartlist_slice_string_pos(sls
, &a_line
));
100 cdline_t d_line
= { "d", 1 };
101 tt_int_op(-1, OP_EQ
, smartlist_slice_string_pos(sls
, &d_line
));
106 memarea_drop_all(area
);
110 test_consdiff_lcs_lengths(void *arg
)
112 smartlist_t
*sl1
= smartlist_new();
113 smartlist_t
*sl2
= smartlist_new();
114 smartlist_slice_t
*sls1
, *sls2
;
115 int *lengths1
, *lengths2
;
116 memarea_t
*area
= memarea_new();
118 /* Expected lcs lengths in regular and reverse order. */
119 int e_lengths1
[] = { 0, 1, 2, 3, 3, 4 };
120 int e_lengths2
[] = { 0, 1, 1, 2, 3, 4 };
123 consensus_split_lines_(sl1
, "a\nb\nc\nd\ne\n", area
);
124 consensus_split_lines_(sl2
, "a\nc\nd\ni\ne\n", area
);
126 sls1
= smartlist_slice(sl1
, 0, -1);
127 sls2
= smartlist_slice(sl2
, 0, -1);
129 lengths1
= lcs_lengths(sls1
, sls2
, 1);
130 lengths2
= lcs_lengths(sls1
, sls2
, -1);
131 tt_mem_op(e_lengths1
, OP_EQ
, lengths1
, sizeof(int) * 6);
132 tt_mem_op(e_lengths2
, OP_EQ
, lengths2
, sizeof(int) * 6);
141 memarea_drop_all(area
);
145 test_consdiff_trim_slices(void *arg
)
147 smartlist_t
*sl1
= smartlist_new();
148 smartlist_t
*sl2
= smartlist_new();
149 smartlist_t
*sl3
= smartlist_new();
150 smartlist_t
*sl4
= smartlist_new();
151 smartlist_slice_t
*sls1
, *sls2
, *sls3
, *sls4
;
152 memarea_t
*area
= memarea_new();
155 consensus_split_lines_(sl1
, "a\nb\nb\nb\nd\n", area
);
156 consensus_split_lines_(sl2
, "a\nc\nc\nc\nd\n", area
);
157 consensus_split_lines_(sl3
, "a\nb\nb\nb\na\n", area
);
158 consensus_split_lines_(sl4
, "c\nb\nb\nb\nc\n", area
);
159 sls1
= smartlist_slice(sl1
, 0, -1);
160 sls2
= smartlist_slice(sl2
, 0, -1);
161 sls3
= smartlist_slice(sl3
, 0, -1);
162 sls4
= smartlist_slice(sl4
, 0, -1);
164 /* They should be trimmed by one line at each end. */
165 tt_int_op(5, OP_EQ
, sls1
->len
);
166 tt_int_op(5, OP_EQ
, sls2
->len
);
167 trim_slices(sls1
, sls2
);
168 tt_int_op(3, OP_EQ
, sls1
->len
);
169 tt_int_op(3, OP_EQ
, sls2
->len
);
171 /* They should not be trimmed at all. */
172 tt_int_op(5, OP_EQ
, sls3
->len
);
173 tt_int_op(5, OP_EQ
, sls4
->len
);
174 trim_slices(sls3
, sls4
);
175 tt_int_op(5, OP_EQ
, sls3
->len
);
176 tt_int_op(5, OP_EQ
, sls4
->len
);
187 memarea_drop_all(area
);
191 test_consdiff_set_changed(void *arg
)
193 smartlist_t
*sl1
= smartlist_new();
194 smartlist_t
*sl2
= smartlist_new();
195 bitarray_t
*changed1
= bitarray_init_zero(4);
196 bitarray_t
*changed2
= bitarray_init_zero(4);
197 smartlist_slice_t
*sls1
, *sls2
;
198 memarea_t
*area
= memarea_new();
201 consensus_split_lines_(sl1
, "a\nb\na\na\n", area
);
202 consensus_split_lines_(sl2
, "a\na\na\na\n", area
);
204 /* Length of sls1 is 0. */
205 sls1
= smartlist_slice(sl1
, 0, 0);
206 sls2
= smartlist_slice(sl2
, 1, 3);
207 set_changed(changed1
, changed2
, sls1
, sls2
);
209 /* The former is not changed, the latter changes all of its elements. */
210 tt_assert(!bitarray_is_set(changed1
, 0));
211 tt_assert(!bitarray_is_set(changed1
, 1));
212 tt_assert(!bitarray_is_set(changed1
, 2));
213 tt_assert(!bitarray_is_set(changed1
, 3));
215 tt_assert(!bitarray_is_set(changed2
, 0));
216 tt_assert(bitarray_is_set(changed2
, 1));
217 tt_assert(bitarray_is_set(changed2
, 2));
218 tt_assert(!bitarray_is_set(changed2
, 3));
219 bitarray_clear(changed2
, 1);
220 bitarray_clear(changed2
, 2);
222 /* Length of sls1 is 1 and its element is in sls2. */
224 sls1
= smartlist_slice(sl1
, 0, 1);
225 set_changed(changed1
, changed2
, sls1
, sls2
);
227 /* The latter changes all elements but the (first) common one. */
228 tt_assert(!bitarray_is_set(changed1
, 0));
229 tt_assert(!bitarray_is_set(changed1
, 1));
230 tt_assert(!bitarray_is_set(changed1
, 2));
231 tt_assert(!bitarray_is_set(changed1
, 3));
233 tt_assert(!bitarray_is_set(changed2
, 0));
234 tt_assert(!bitarray_is_set(changed2
, 1));
235 tt_assert(bitarray_is_set(changed2
, 2));
236 tt_assert(!bitarray_is_set(changed2
, 3));
237 bitarray_clear(changed2
, 2);
239 /* Length of sls1 is 1 and its element is not in sls2. */
241 sls1
= smartlist_slice(sl1
, 1, 2);
242 set_changed(changed1
, changed2
, sls1
, sls2
);
244 /* The former changes its element, the latter changes all elements. */
245 tt_assert(!bitarray_is_set(changed1
, 0));
246 tt_assert(bitarray_is_set(changed1
, 1));
247 tt_assert(!bitarray_is_set(changed1
, 2));
248 tt_assert(!bitarray_is_set(changed1
, 3));
250 tt_assert(!bitarray_is_set(changed2
, 0));
251 tt_assert(bitarray_is_set(changed2
, 1));
252 tt_assert(bitarray_is_set(changed2
, 2));
253 tt_assert(!bitarray_is_set(changed2
, 3));
256 bitarray_free(changed1
);
257 bitarray_free(changed2
);
262 memarea_drop_all(area
);
266 test_consdiff_calc_changes(void *arg
)
268 smartlist_t
*sl1
= smartlist_new();
269 smartlist_t
*sl2
= smartlist_new();
270 smartlist_slice_t
*sls1
, *sls2
;
271 bitarray_t
*changed1
= bitarray_init_zero(4);
272 bitarray_t
*changed2
= bitarray_init_zero(4);
273 memarea_t
*area
= memarea_new();
276 consensus_split_lines_(sl1
, "a\na\na\na\n", area
);
277 consensus_split_lines_(sl2
, "a\na\na\na\n", area
);
279 sls1
= smartlist_slice(sl1
, 0, -1);
280 sls2
= smartlist_slice(sl2
, 0, -1);
281 calc_changes(sls1
, sls2
, changed1
, changed2
);
283 /* Nothing should be set to changed. */
284 tt_assert(!bitarray_is_set(changed1
, 0));
285 tt_assert(!bitarray_is_set(changed1
, 1));
286 tt_assert(!bitarray_is_set(changed1
, 2));
287 tt_assert(!bitarray_is_set(changed1
, 3));
289 tt_assert(!bitarray_is_set(changed2
, 0));
290 tt_assert(!bitarray_is_set(changed2
, 1));
291 tt_assert(!bitarray_is_set(changed2
, 2));
292 tt_assert(!bitarray_is_set(changed2
, 3));
294 smartlist_clear(sl2
);
295 consensus_split_lines_(sl2
, "a\nb\na\nb\n", area
);
298 sls1
= smartlist_slice(sl1
, 0, -1);
299 sls2
= smartlist_slice(sl2
, 0, -1);
300 calc_changes(sls1
, sls2
, changed1
, changed2
);
302 /* Two elements are changed. */
303 tt_assert(!bitarray_is_set(changed1
, 0));
304 tt_assert(bitarray_is_set(changed1
, 1));
305 tt_assert(bitarray_is_set(changed1
, 2));
306 tt_assert(!bitarray_is_set(changed1
, 3));
307 bitarray_clear(changed1
, 1);
308 bitarray_clear(changed1
, 2);
310 tt_assert(!bitarray_is_set(changed2
, 0));
311 tt_assert(bitarray_is_set(changed2
, 1));
312 tt_assert(!bitarray_is_set(changed2
, 2));
313 tt_assert(bitarray_is_set(changed2
, 3));
314 bitarray_clear(changed1
, 1);
315 bitarray_clear(changed1
, 3);
317 smartlist_clear(sl2
);
318 consensus_split_lines_(sl2
, "b\nb\nb\nb\n", area
);
321 sls1
= smartlist_slice(sl1
, 0, -1);
322 sls2
= smartlist_slice(sl2
, 0, -1);
323 calc_changes(sls1
, sls2
, changed1
, changed2
);
325 /* All elements are changed. */
326 tt_assert(bitarray_is_set(changed1
, 0));
327 tt_assert(bitarray_is_set(changed1
, 1));
328 tt_assert(bitarray_is_set(changed1
, 2));
329 tt_assert(bitarray_is_set(changed1
, 3));
331 tt_assert(bitarray_is_set(changed2
, 0));
332 tt_assert(bitarray_is_set(changed2
, 1));
333 tt_assert(bitarray_is_set(changed2
, 2));
334 tt_assert(bitarray_is_set(changed2
, 3));
337 bitarray_free(changed1
);
338 bitarray_free(changed2
);
343 memarea_drop_all(area
);
347 test_consdiff_get_id_hash(void *arg
)
351 cdline_t line1
= { "r name", 6 };
352 cdline_t line2
= { "r name _hash_isnt_base64 etc", 28 };
353 cdline_t line3
= { "r name hash+valid+base64 etc", 28 };
357 tt_int_op(-1, OP_EQ
, get_id_hash(&line1
, &tmp
));
358 /* The hash contains characters that are not base64. */
359 tt_int_op(-1, OP_EQ
, get_id_hash(&line2
, &tmp
));
362 tt_int_op(0, OP_EQ
, get_id_hash(&line3
, &tmp
));
363 tt_ptr_op(tmp
.s
, OP_EQ
, line3
.s
+ 7);
364 tt_uint_op(tmp
.len
, OP_EQ
, line3
.len
- 11);
371 test_consdiff_is_valid_router_entry(void *arg
)
373 /* Doesn't start with "r ". */
375 cdline_t line0
= { "foo", 3 };
376 tt_int_op(0, OP_EQ
, is_valid_router_entry(&line0
));
378 /* These are already tested with get_id_hash, but make sure it's run
381 cdline_t line1
= { "r name", 6 };
382 cdline_t line2
= { "r name _hash_isnt_base64 etc", 28 };
383 cdline_t line3
= { "r name hash+valid+base64 etc", 28 };
384 tt_int_op(0, OP_EQ
, is_valid_router_entry(&line1
));
385 tt_int_op(0, OP_EQ
, is_valid_router_entry(&line2
));
386 tt_int_op(1, OP_EQ
, is_valid_router_entry(&line3
));
393 test_consdiff_next_router(void *arg
)
395 smartlist_t
*sl
= smartlist_new();
396 memarea_t
*area
= memarea_new();
398 smartlist_add_linecpy(sl
, area
, "foo");
399 smartlist_add_linecpy(sl
, area
,
400 "r name hash+longer+than+27+chars+and+valid+base64 etc");
401 smartlist_add_linecpy(sl
, area
, "foo");
402 smartlist_add_linecpy(sl
, area
, "foo");
403 smartlist_add_linecpy(sl
, area
,
404 "r name hash+longer+than+27+chars+and+valid+base64 etc");
405 smartlist_add_linecpy(sl
, area
, "foo");
407 /* Not currently on a router entry line, finding the next one. */
408 tt_int_op(1, OP_EQ
, next_router(sl
, 0));
409 tt_int_op(4, OP_EQ
, next_router(sl
, 2));
411 /* Already at the beginning of a router entry line, ignore it. */
412 tt_int_op(4, OP_EQ
, next_router(sl
, 1));
414 /* There are no more router entries, so return the line after the last. */
415 tt_int_op(6, OP_EQ
, next_router(sl
, 4));
416 tt_int_op(6, OP_EQ
, next_router(sl
, 5));
420 memarea_drop_all(area
);
424 base64cmp_wrapper(const char *a
, const char *b
)
426 cdline_t aa
= { a
, a
? (uint32_t) strlen(a
) : 0 };
427 cdline_t bb
= { b
, b
? (uint32_t) strlen(b
) : 0 };
428 return base64cmp(&aa
, &bb
);
432 test_consdiff_base64cmp(void *arg
)
434 /* NULL arguments. */
436 tt_int_op(0, OP_EQ
, base64cmp_wrapper(NULL
, NULL
));
437 tt_int_op(-1, OP_EQ
, base64cmp_wrapper(NULL
, "foo"));
438 tt_int_op(1, OP_EQ
, base64cmp_wrapper("bar", NULL
));
440 /* Nil base64 values. */
441 tt_int_op(0, OP_EQ
, base64cmp_wrapper("", ""));
442 tt_int_op(0, OP_EQ
, base64cmp_wrapper("_", "&"));
444 /* Exact same valid strings. */
445 tt_int_op(0, OP_EQ
, base64cmp_wrapper("abcABC/+", "abcABC/+"));
446 /* Both end with an invalid base64 char other than '\0'. */
447 tt_int_op(0, OP_EQ
, base64cmp_wrapper("abcABC/+ ", "abcABC/+ "));
448 /* Only one ends with an invalid base64 char other than '\0'. */
449 tt_int_op(-1, OP_EQ
, base64cmp_wrapper("abcABC/+ ", "abcABC/+a"));
451 /* Comparisons that would return differently with strcmp(). */
452 tt_int_op(strcmp("/foo", "Afoo"), OP_LT
, 0);
453 tt_int_op(base64cmp_wrapper("/foo", "Afoo"), OP_GT
, 0);
454 tt_int_op(strcmp("Afoo", "0foo"), OP_GT
, 0);
455 tt_int_op(base64cmp_wrapper("Afoo", "0foo"), OP_LT
, 0);
457 /* Comparisons that would return the same as with strcmp(). */
458 tt_int_op(strcmp("afoo", "Afoo"), OP_GT
, 0);
459 tt_int_op(base64cmp_wrapper("afoo", "Afoo"), OP_GT
, 0);
461 /* Different lengths */
462 tt_int_op(base64cmp_wrapper("afoo", "afooo"), OP_LT
, 0);
463 tt_int_op(base64cmp_wrapper("afooo", "afoo"), OP_GT
, 0);
470 test_consdiff_gen_ed_diff(void *arg
)
472 smartlist_t
*cons1
=NULL
, *cons2
=NULL
, *diff
=NULL
;
474 memarea_t
*area
= memarea_new();
475 setup_capture_of_logs(LOG_WARN
);
478 cons1
= smartlist_new();
479 cons2
= smartlist_new();
481 /* Identity hashes are not sorted properly, return NULL. */
482 smartlist_add_linecpy(cons1
, area
, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
483 smartlist_add_linecpy(cons1
, area
, "foo");
484 smartlist_add_linecpy(cons1
, area
, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
485 smartlist_add_linecpy(cons1
, area
, "bar");
487 smartlist_add_linecpy(cons2
, area
, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
488 smartlist_add_linecpy(cons2
, area
, "foo");
489 smartlist_add_linecpy(cons2
, area
, "r name ccccccccccccccccccccccccccc etc");
490 smartlist_add_linecpy(cons2
, area
, "bar");
492 diff
= gen_ed_diff(cons1
, cons2
, area
);
493 tt_ptr_op(NULL
, OP_EQ
, diff
);
494 expect_single_log_msg_containing("Refusing to generate consensus diff "
495 "because the base consensus doesn't have its router entries sorted "
498 /* Same, but now with the second consensus. */
499 mock_clean_saved_logs();
500 diff
= gen_ed_diff(cons2
, cons1
, area
);
501 tt_ptr_op(NULL
, OP_EQ
, diff
);
502 expect_single_log_msg_containing("Refusing to generate consensus diff "
503 "because the target consensus doesn't have its router entries sorted "
506 /* Same as the two above, but with the reversed thing immediately after a
507 match. (The code handles this differently) */
508 smartlist_del(cons1
, 0);
509 smartlist_add_linecpy(cons1
, area
, "r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
511 mock_clean_saved_logs();
512 diff
= gen_ed_diff(cons1
, cons2
, area
);
513 tt_ptr_op(NULL
, OP_EQ
, diff
);
514 expect_single_log_msg_containing("Refusing to generate consensus diff "
515 "because the base consensus doesn't have its router entries sorted "
518 mock_clean_saved_logs();
519 diff
= gen_ed_diff(cons2
, cons1
, area
);
520 tt_ptr_op(NULL
, OP_EQ
, diff
);
521 expect_single_log_msg_containing("Refusing to generate consensus diff "
522 "because the target consensus doesn't have its router entries sorted "
525 /* Identity hashes are repeated, return NULL. */
526 smartlist_clear(cons1
);
528 smartlist_add_linecpy(cons1
, area
, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
529 smartlist_add_linecpy(cons1
, area
, "foo");
530 smartlist_add_linecpy(cons1
, area
, "r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
531 smartlist_add_linecpy(cons1
, area
, "bar");
533 mock_clean_saved_logs();
534 diff
= gen_ed_diff(cons1
, cons2
, area
);
535 tt_ptr_op(NULL
, OP_EQ
, diff
);
536 expect_single_log_msg_containing("Refusing to generate consensus diff "
537 "because the base consensus doesn't have its router entries sorted "
540 /* We have to add a line that is just a dot, return NULL. */
541 smartlist_clear(cons1
);
542 smartlist_clear(cons2
);
544 smartlist_add_linecpy(cons1
, area
, "foo1");
545 smartlist_add_linecpy(cons1
, area
, "foo2");
547 smartlist_add_linecpy(cons2
, area
, "foo1");
548 smartlist_add_linecpy(cons2
, area
, ".");
549 smartlist_add_linecpy(cons2
, area
, "foo2");
551 mock_clean_saved_logs();
552 diff
= gen_ed_diff(cons1
, cons2
, area
);
553 tt_ptr_op(NULL
, OP_EQ
, diff
);
554 expect_single_log_msg_containing("Cannot generate consensus diff "
555 "because one of the lines to be added is \".\".");
557 #define MAX_LINE_COUNT (10000)
558 /* Too many lines to be fed to the quadratic-time function. */
559 smartlist_clear(cons1
);
560 smartlist_clear(cons2
);
562 for (i
=0; i
< MAX_LINE_COUNT
; ++i
) smartlist_add_linecpy(cons1
, area
, "a");
563 for (i
=0; i
< MAX_LINE_COUNT
; ++i
) smartlist_add_linecpy(cons1
, area
, "b");
565 mock_clean_saved_logs();
566 diff
= gen_ed_diff(cons1
, cons2
, area
);
568 tt_ptr_op(NULL
, OP_EQ
, diff
);
569 expect_single_log_msg_containing("Refusing to generate consensus diff "
570 "because we found too few common router ids.");
572 /* We have dot lines, but they don't interfere with the script format. */
573 smartlist_clear(cons1
);
574 smartlist_clear(cons2
);
576 smartlist_add_linecpy(cons1
, area
, "foo1");
577 smartlist_add_linecpy(cons1
, area
, ".");
578 smartlist_add_linecpy(cons1
, area
, ".");
579 smartlist_add_linecpy(cons1
, area
, "foo2");
581 smartlist_add_linecpy(cons2
, area
, "foo1");
582 smartlist_add_linecpy(cons2
, area
, ".");
583 smartlist_add_linecpy(cons2
, area
, "foo2");
585 diff
= gen_ed_diff(cons1
, cons2
, area
);
586 tt_ptr_op(NULL
, OP_NE
, diff
);
587 smartlist_free(diff
);
589 /* Empty diff tests. */
590 smartlist_clear(cons1
);
591 smartlist_clear(cons2
);
593 diff
= gen_ed_diff(cons1
, cons2
, area
);
594 tt_ptr_op(NULL
, OP_NE
, diff
);
595 tt_int_op(0, OP_EQ
, smartlist_len(diff
));
596 smartlist_free(diff
);
598 smartlist_add_linecpy(cons1
, area
, "foo");
599 smartlist_add_linecpy(cons1
, area
, "bar");
601 smartlist_add_linecpy(cons2
, area
, "foo");
602 smartlist_add_linecpy(cons2
, area
, "bar");
604 diff
= gen_ed_diff(cons1
, cons2
, area
);
605 tt_ptr_op(NULL
, OP_NE
, diff
);
606 tt_int_op(0, OP_EQ
, smartlist_len(diff
));
607 smartlist_free(diff
);
609 /* Everything is deleted. */
610 smartlist_clear(cons2
);
612 diff
= gen_ed_diff(cons1
, cons2
, area
);
613 tt_ptr_op(NULL
, OP_NE
, diff
);
614 tt_int_op(1, OP_EQ
, smartlist_len(diff
));
615 tt_str_eq_line("1,2d", smartlist_get(diff
, 0));
617 smartlist_free(diff
);
619 /* Everything is added. */
620 diff
= gen_ed_diff(cons2
, cons1
, area
);
621 tt_ptr_op(NULL
, OP_NE
, diff
);
622 tt_int_op(4, OP_EQ
, smartlist_len(diff
));
623 tt_str_eq_line("0a", smartlist_get(diff
, 0));
624 tt_str_eq_line("foo", smartlist_get(diff
, 1));
625 tt_str_eq_line("bar", smartlist_get(diff
, 2));
626 tt_str_eq_line(".", smartlist_get(diff
, 3));
628 smartlist_free(diff
);
630 /* Everything is changed. */
631 smartlist_add_linecpy(cons2
, area
, "foo2");
632 smartlist_add_linecpy(cons2
, area
, "bar2");
633 diff
= gen_ed_diff(cons1
, cons2
, area
);
634 tt_ptr_op(NULL
, OP_NE
, diff
);
635 tt_int_op(4, OP_EQ
, smartlist_len(diff
));
636 tt_str_eq_line("1,2c", smartlist_get(diff
, 0));
637 tt_str_eq_line("foo2", smartlist_get(diff
, 1));
638 tt_str_eq_line("bar2", smartlist_get(diff
, 2));
639 tt_str_eq_line(".", smartlist_get(diff
, 3));
641 smartlist_free(diff
);
643 /* Test 'a', 'c' and 'd' together. See that it is done in reverse order. */
644 smartlist_clear(cons1
);
645 smartlist_clear(cons2
);
646 consensus_split_lines_(cons1
, "A\nB\nC\nD\nE\n", area
);
647 consensus_split_lines_(cons2
, "A\nC\nO\nE\nU\n", area
);
648 diff
= gen_ed_diff(cons1
, cons2
, area
);
649 tt_ptr_op(NULL
, OP_NE
, diff
);
650 tt_int_op(7, OP_EQ
, smartlist_len(diff
));
651 tt_str_eq_line("5a", smartlist_get(diff
, 0));
652 tt_str_eq_line("U", smartlist_get(diff
, 1));
653 tt_str_eq_line(".", smartlist_get(diff
, 2));
654 tt_str_eq_line("4c", smartlist_get(diff
, 3));
655 tt_str_eq_line("O", smartlist_get(diff
, 4));
656 tt_str_eq_line(".", smartlist_get(diff
, 5));
657 tt_str_eq_line("2d", smartlist_get(diff
, 6));
659 smartlist_free(diff
);
661 smartlist_clear(cons1
);
662 smartlist_clear(cons2
);
663 consensus_split_lines_(cons1
, "B\n", area
);
664 consensus_split_lines_(cons2
, "A\nB\n", area
);
665 diff
= gen_ed_diff(cons1
, cons2
, area
);
666 tt_ptr_op(NULL
, OP_NE
, diff
);
667 tt_int_op(3, OP_EQ
, smartlist_len(diff
));
668 tt_str_eq_line("0a", smartlist_get(diff
, 0));
669 tt_str_eq_line("A", smartlist_get(diff
, 1));
670 tt_str_eq_line(".", smartlist_get(diff
, 2));
672 /* TODO: small real use-cases, i.e. consensuses. */
675 teardown_capture_of_logs();
676 smartlist_free(cons1
);
677 smartlist_free(cons2
);
678 smartlist_free(diff
);
679 memarea_drop_all(area
);
683 test_consdiff_apply_ed_diff(void *arg
)
685 smartlist_t
*cons1
=NULL
, *cons2
=NULL
, *diff
=NULL
;
686 memarea_t
*area
= memarea_new();
688 cons1
= smartlist_new();
689 diff
= smartlist_new();
690 setup_capture_of_logs(LOG_WARN
);
692 consensus_split_lines_(cons1
, "A\nB\nC\nD\nE\n", area
);
694 /* Command without range. */
695 smartlist_add_linecpy(diff
, area
, "a");
696 cons2
= apply_ed_diff(cons1
, diff
, 0);
697 tt_ptr_op(NULL
, OP_EQ
, cons2
);
698 smartlist_clear(diff
);
699 expect_single_log_msg_containing("an ed command was missing a line number");
701 /* Range without command. */
702 smartlist_add_linecpy(diff
, area
, "1");
703 mock_clean_saved_logs();
704 cons2
= apply_ed_diff(cons1
, diff
, 0);
705 tt_ptr_op(NULL
, OP_EQ
, cons2
);
706 expect_single_log_msg_containing("a line with no ed command was found");
708 smartlist_clear(diff
);
710 /* Range without end. */
711 smartlist_add_linecpy(diff
, area
, "1,");
712 mock_clean_saved_logs();
713 cons2
= apply_ed_diff(cons1
, diff
, 0);
714 tt_ptr_op(NULL
, OP_EQ
, cons2
);
715 expect_single_log_msg_containing("an ed command was missing a range "
718 smartlist_clear(diff
);
720 /* Incoherent ranges. */
721 smartlist_add_linecpy(diff
, area
, "1,1");
722 mock_clean_saved_logs();
723 cons2
= apply_ed_diff(cons1
, diff
, 0);
724 tt_ptr_op(NULL
, OP_EQ
, cons2
);
725 expect_single_log_msg_containing("an invalid range was found");
727 smartlist_clear(diff
);
729 smartlist_add_linecpy(diff
, area
, "3,2");
730 mock_clean_saved_logs();
731 cons2
= apply_ed_diff(cons1
, diff
, 0);
732 tt_ptr_op(NULL
, OP_EQ
, cons2
);
733 expect_single_log_msg_containing("an invalid range was found");
735 smartlist_clear(diff
);
737 /* Unexpected range for add command. */
738 smartlist_add_linecpy(diff
, area
, "1,2a");
739 mock_clean_saved_logs();
740 cons2
= apply_ed_diff(cons1
, diff
, 0);
741 tt_ptr_op(NULL
, OP_EQ
, cons2
);
742 expect_single_log_msg_containing("add lines after a range");
744 smartlist_clear(diff
);
746 /* $ for a non-delete command. */
747 smartlist_add_linecpy(diff
, area
, "1,$c");
748 mock_clean_saved_logs();
749 cons2
= apply_ed_diff(cons1
, diff
, 0);
750 tt_ptr_op(NULL
, OP_EQ
, cons2
);
751 expect_single_log_msg_containing("it wanted to use $ with a command "
752 "other than delete");
754 smartlist_clear(diff
);
756 /* Script is not in reverse order. */
757 smartlist_add_linecpy(diff
, area
, "1d");
758 smartlist_add_linecpy(diff
, area
, "3d");
759 mock_clean_saved_logs();
760 cons2
= apply_ed_diff(cons1
, diff
, 0);
761 tt_ptr_op(NULL
, OP_EQ
, cons2
);
762 expect_single_log_msg_containing("its commands are not properly sorted");
764 smartlist_clear(diff
);
766 /* Script contains unrecognised commands longer than one char. */
767 smartlist_add_linecpy(diff
, area
, "1foo");
768 mock_clean_saved_logs();
769 cons2
= apply_ed_diff(cons1
, diff
, 0);
770 tt_ptr_op(NULL
, OP_EQ
, cons2
);
771 expect_single_log_msg_containing("an ed command longer than one char was "
774 smartlist_clear(diff
);
776 /* Script contains unrecognised commands. */
777 smartlist_add_linecpy(diff
, area
, "1e");
778 mock_clean_saved_logs();
779 cons2
= apply_ed_diff(cons1
, diff
, 0);
780 tt_ptr_op(NULL
, OP_EQ
, cons2
);
781 expect_single_log_msg_containing("an unrecognised ed command was found");
783 smartlist_clear(diff
);
785 /* Command that should be followed by at least one line and a ".", but
787 smartlist_add_linecpy(diff
, area
, "0a");
788 mock_clean_saved_logs();
789 cons2
= apply_ed_diff(cons1
, diff
, 0);
790 tt_ptr_op(NULL
, OP_EQ
, cons2
);
791 expect_single_log_msg_containing("it has an ed command that tries to "
792 "insert zero lines.");
794 /* Now it is followed by a ".", but it inserts zero lines. */
795 smartlist_add_linecpy(diff
, area
, ".");
796 mock_clean_saved_logs();
797 cons2
= apply_ed_diff(cons1
, diff
, 0);
798 tt_ptr_op(NULL
, OP_EQ
, cons2
);
799 expect_single_log_msg_containing("it has an ed command that tries to "
800 "insert zero lines.");
802 smartlist_clear(diff
);
804 /* Now it it inserts something, but has no terminator. */
805 smartlist_add_linecpy(diff
, area
, "0a");
806 smartlist_add_linecpy(diff
, area
, "hello");
807 mock_clean_saved_logs();
808 cons2
= apply_ed_diff(cons1
, diff
, 0);
809 tt_ptr_op(NULL
, OP_EQ
, cons2
);
810 expect_single_log_msg_containing("lines to be inserted that don't end with "
813 smartlist_clear(diff
);
815 /* Ranges must be numeric only and cannot contain spaces. */
816 smartlist_add_linecpy(diff
, area
, "0, 4d");
817 mock_clean_saved_logs();
818 cons2
= apply_ed_diff(cons1
, diff
, 0);
819 tt_ptr_op(NULL
, OP_EQ
, cons2
);
820 expect_single_log_msg_containing("an ed command was missing a range "
823 smartlist_clear(diff
);
825 /* '+' is not a number. */
826 smartlist_add_linecpy(diff
, area
, "+0,4d");
827 mock_clean_saved_logs();
828 cons2
= apply_ed_diff(cons1
, diff
, 0);
829 tt_ptr_op(NULL
, OP_EQ
, cons2
);
830 expect_single_log_msg_containing("an ed command was missing a line number");
832 smartlist_clear(diff
);
834 /* range duplication */
835 smartlist_add_linecpy(diff
, area
, "0,4d,5d");
836 mock_clean_saved_logs();
837 cons2
= apply_ed_diff(cons1
, diff
, 0);
838 tt_ptr_op(NULL
, OP_EQ
, cons2
);
839 expect_single_log_msg_containing("an ed command longer than one char was "
842 smartlist_clear(diff
);
844 /* space before command */
845 smartlist_add_linecpy(diff
, area
, "0,4 d");
846 mock_clean_saved_logs();
847 cons2
= apply_ed_diff(cons1
, diff
, 0);
848 tt_ptr_op(NULL
, OP_EQ
, cons2
);
849 expect_single_log_msg_containing("an ed command longer than one char was "
852 smartlist_clear(diff
);
854 /* space inside number */
855 smartlist_add_linecpy(diff
, area
, "0,4 5d");
856 mock_clean_saved_logs();
857 cons2
= apply_ed_diff(cons1
, diff
, 0);
858 tt_ptr_op(NULL
, OP_EQ
, cons2
);
859 expect_single_log_msg_containing("an ed command longer than one char was "
862 smartlist_clear(diff
);
864 /* Test appending text, 'a'. */
865 consensus_split_lines_(diff
, "3a\nU\nO\n.\n0a\nV\n.\n", area
);
866 cons2
= apply_ed_diff(cons1
, diff
, 0);
867 tt_ptr_op(NULL
, OP_NE
, cons2
);
868 tt_int_op(8, OP_EQ
, smartlist_len(cons2
));
869 tt_str_eq_line("V", smartlist_get(cons2
, 0));
870 tt_str_eq_line("A", smartlist_get(cons2
, 1));
871 tt_str_eq_line("B", smartlist_get(cons2
, 2));
872 tt_str_eq_line("C", smartlist_get(cons2
, 3));
873 tt_str_eq_line("U", smartlist_get(cons2
, 4));
874 tt_str_eq_line("O", smartlist_get(cons2
, 5));
875 tt_str_eq_line("D", smartlist_get(cons2
, 6));
876 tt_str_eq_line("E", smartlist_get(cons2
, 7));
878 smartlist_clear(diff
);
879 smartlist_free(cons2
);
881 /* Test deleting text, 'd'. */
882 consensus_split_lines_(diff
, "4d\n1,2d\n", area
);
883 cons2
= apply_ed_diff(cons1
, diff
, 0);
884 tt_ptr_op(NULL
, OP_NE
, cons2
);
885 tt_int_op(2, OP_EQ
, smartlist_len(cons2
));
886 tt_str_eq_line("C", smartlist_get(cons2
, 0));
887 tt_str_eq_line("E", smartlist_get(cons2
, 1));
889 smartlist_clear(diff
);
890 smartlist_free(cons2
);
892 /* Test changing text, 'c'. */
893 consensus_split_lines_(diff
, "4c\nT\nX\n.\n1,2c\nM\n.\n", area
);
894 cons2
= apply_ed_diff(cons1
, diff
, 0);
895 tt_ptr_op(NULL
, OP_NE
, cons2
);
896 tt_int_op(5, OP_EQ
, smartlist_len(cons2
));
897 tt_str_eq_line("M", smartlist_get(cons2
, 0));
898 tt_str_eq_line("C", smartlist_get(cons2
, 1));
899 tt_str_eq_line("T", smartlist_get(cons2
, 2));
900 tt_str_eq_line("X", smartlist_get(cons2
, 3));
901 tt_str_eq_line("E", smartlist_get(cons2
, 4));
903 smartlist_clear(diff
);
904 smartlist_free(cons2
);
906 /* Test 'a', 'd' and 'c' together. */
907 consensus_split_lines_(diff
, "4c\nT\nX\n.\n2d\n0a\nM\n.\n", area
);
908 cons2
= apply_ed_diff(cons1
, diff
, 0);
909 tt_ptr_op(NULL
, OP_NE
, cons2
);
910 tt_int_op(6, OP_EQ
, smartlist_len(cons2
));
911 tt_str_eq_line("M", smartlist_get(cons2
, 0));
912 tt_str_eq_line("A", smartlist_get(cons2
, 1));
913 tt_str_eq_line("C", smartlist_get(cons2
, 2));
914 tt_str_eq_line("T", smartlist_get(cons2
, 3));
915 tt_str_eq_line("X", smartlist_get(cons2
, 4));
916 tt_str_eq_line("E", smartlist_get(cons2
, 5));
919 teardown_capture_of_logs();
920 smartlist_free(cons1
);
921 smartlist_free(cons2
);
922 smartlist_free(diff
);
923 memarea_drop_all(area
);
927 test_consdiff_gen_diff(void *arg
)
929 char *cons1_str
=NULL
, *cons2_str
=NULL
;
930 smartlist_t
*cons1
=NULL
, *cons2
=NULL
, *diff
=NULL
;
931 consensus_digest_t digests1
, digests2
;
932 memarea_t
*area
= memarea_new();
934 cons1
= smartlist_new();
935 cons2
= smartlist_new();
937 /* Identity hashes are not sorted properly, return NULL.
938 * Already tested in gen_ed_diff, but see that a NULL ed diff also makes
939 * gen_diff return NULL. */
940 cons1_str
= tor_strdup(
941 "network-status-version foo\n"
942 "r name bbbbbbbbbbbbbbbbb etc\nfoo\n"
943 "r name aaaaaaaaaaaaaaaaa etc\nbar\n"
944 "directory-signature foo bar\nbar\n"
946 cons2_str
= tor_strdup(
947 "network-status-version foo\n"
948 "r name aaaaaaaaaaaaaaaaa etc\nfoo\n"
949 "r name ccccccccccccccccc etc\nbar\n"
950 "directory-signature foo bar\nbar\n"
954 consensus_compute_digest_as_signed_(cons1_str
, &digests1
));
956 consensus_compute_digest_(cons2_str
, &digests2
));
958 consensus_split_lines_(cons1
, cons1_str
, area
);
959 consensus_split_lines_(cons2
, cons2_str
, area
);
961 diff
= consdiff_gen_diff(cons1
, cons2
, &digests1
, &digests2
, area
);
962 tt_ptr_op(NULL
, OP_EQ
, diff
);
964 /* Check that the headers are done properly. */
966 cons1_str
= tor_strdup(
967 "network-status-version foo\n"
968 "r name ccccccccccccccccc etc\nfoo\n"
969 "r name eeeeeeeeeeeeeeeee etc\nbar\n"
970 "directory-signature foo bar\nbar\n"
973 consensus_compute_digest_as_signed_(cons1_str
, &digests1
));
974 smartlist_clear(cons1
);
975 consensus_split_lines_(cons1
, cons1_str
, area
);
976 diff
= consdiff_gen_diff(cons1
, cons2
, &digests1
, &digests2
, area
);
977 tt_ptr_op(NULL
, OP_NE
, diff
);
978 tt_int_op(11, OP_EQ
, smartlist_len(diff
));
979 tt_assert(line_str_eq(smartlist_get(diff
, 0),
980 "network-status-diff-version 1"));
981 tt_assert(line_str_eq(smartlist_get(diff
, 1), "hash "
982 "95D70F5A3CC65F920AA8B44C4563D7781A082674329661884E19E94B79D539C2 "
983 "7AFECEFA4599BA33D603653E3D2368F648DF4AC4723929B0F7CF39281596B0C1"));
984 tt_assert(line_str_eq(smartlist_get(diff
, 2), "6,$d"));
985 tt_assert(line_str_eq(smartlist_get(diff
, 3), "3,4c"));
986 tt_assert(line_str_eq(smartlist_get(diff
, 4), "bar"));
987 tt_assert(line_str_eq(smartlist_get(diff
, 5),
988 "directory-signature foo bar"));
989 tt_assert(line_str_eq(smartlist_get(diff
, 6),
991 tt_assert(line_str_eq(smartlist_get(diff
, 7), "1a"));
992 tt_assert(line_str_eq(smartlist_get(diff
, 8),
993 "r name aaaaaaaaaaaaaaaaa etc"));
994 tt_assert(line_str_eq(smartlist_get(diff
, 9), "foo"));
995 tt_assert(line_str_eq(smartlist_get(diff
, 10), "."));
997 /* TODO: small real use-cases, i.e. consensuses. */
1000 tor_free(cons1_str
);
1001 tor_free(cons2_str
);
1002 smartlist_free(cons1
);
1003 smartlist_free(cons2
);
1004 smartlist_free(diff
);
1005 memarea_drop_all(area
);
1009 test_consdiff_apply_diff(void *arg
)
1011 smartlist_t
*cons1
=NULL
, *diff
=NULL
;
1012 char *cons1_str
=NULL
, *cons2
= NULL
;
1013 consensus_digest_t digests1
;
1015 memarea_t
*area
= memarea_new();
1016 cons1
= smartlist_new();
1017 diff
= smartlist_new();
1018 setup_capture_of_logs(LOG_INFO
);
1020 cons1_str
= tor_strdup(
1021 "network-status-version foo\n"
1022 "r name ccccccccccccccccc etc\nfoo\n"
1023 "r name eeeeeeeeeeeeeeeee etc\nbar\n"
1024 "directory-signature foo bar\nbar\n"
1027 consensus_compute_digest_(cons1_str
, &digests1
));
1028 consensus_split_lines_(cons1
, cons1_str
, area
);
1030 /* diff doesn't have enough lines. */
1031 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1032 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1033 expect_single_log_msg_containing("too short")
1035 /* first line doesn't match format-version string. */
1036 smartlist_add_linecpy(diff
, area
, "foo-bar");
1037 smartlist_add_linecpy(diff
, area
, "header-line");
1038 mock_clean_saved_logs();
1039 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1040 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1041 expect_single_log_msg_containing("format is not known")
1043 /* The first word of the second header line is not "hash". */
1044 smartlist_clear(diff
);
1045 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1046 smartlist_add_linecpy(diff
, area
, "word a b");
1047 smartlist_add_linecpy(diff
, area
, "x");
1048 mock_clean_saved_logs();
1049 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1050 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1051 expect_single_log_msg_containing("does not include the necessary digests")
1053 /* Wrong number of words after "hash". */
1054 smartlist_clear(diff
);
1055 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1056 smartlist_add_linecpy(diff
, area
, "hash a b c");
1057 mock_clean_saved_logs();
1058 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1059 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1060 expect_single_log_msg_containing("does not include the necessary digests")
1062 /* base16 digests do not have the expected length. */
1063 smartlist_clear(diff
);
1064 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1065 smartlist_add_linecpy(diff
, area
, "hash aaa bbb");
1066 mock_clean_saved_logs();
1067 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1068 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1069 expect_single_log_msg_containing("includes base16-encoded digests of "
1072 /* base16 digests contain non-base16 characters. */
1073 smartlist_clear(diff
);
1074 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1075 smartlist_add_linecpy(diff
, area
, "hash"
1076 " ????????????????????????????????????????????????????????????????"
1077 " ----------------------------------------------------------------");
1078 mock_clean_saved_logs();
1079 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1080 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1081 expect_single_log_msg_containing("includes malformed digests")
1084 * As tested in apply_ed_diff, but check that apply_diff does return NULL if
1085 * the ed diff can't be applied. */
1086 smartlist_clear(diff
);
1087 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1088 smartlist_add_linecpy(diff
, area
, "hash"
1089 /* sha3 of cons1. */
1090 " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
1091 /* sha256 of cons2. */
1092 " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
1093 smartlist_add_linecpy(diff
, area
, "foobar");
1094 mock_clean_saved_logs();
1095 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1096 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1097 expect_single_log_msg_containing("because an ed command was missing a line "
1100 /* Base consensus doesn't match its digest as found in the diff. */
1101 smartlist_clear(diff
);
1102 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1103 smartlist_add_linecpy(diff
, area
, "hash"
1105 " 3333333333333333333333333333333333333333333333333333333333333333"
1106 /* sha256 of cons2. */
1107 " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
1108 mock_clean_saved_logs();
1109 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1110 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1111 expect_log_msg_containing("base consensus doesn't match the digest "
1114 /* Resulting consensus doesn't match its digest as found in the diff. */
1115 smartlist_clear(diff
);
1116 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1117 smartlist_add_linecpy(diff
, area
, "hash"
1118 /* sha3 of cons1. */
1119 " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
1121 " 3333333333333333333333333333333333333333333333333333333333333333");
1122 mock_clean_saved_logs();
1123 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1124 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1125 expect_log_msg_containing("resulting consensus doesn't match the "
1129 /* XXXX No longer possible, since we aren't using the other algorithm. */
1130 /* Resulting consensus digest cannot be computed */
1131 smartlist_clear(diff
);
1132 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1133 smartlist_add_linecpy(diff
, area
, "hash"
1134 /* sha3 of cons1. */
1135 " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
1137 " 3333333333333333333333333333333333333333333333333333333333333333");
1138 smartlist_add_linecpy(diff
, area
, "1,2d"); // remove starting line
1139 mock_clean_saved_logs();
1140 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1141 tt_ptr_op(NULL
, OP_EQ
, cons2
);
1142 expect_log_msg_containing("Could not compute digests of the consensus "
1143 "resulting from applying a consensus diff.");
1146 /* Very simple test, only to see that nothing errors. */
1147 smartlist_clear(diff
);
1148 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1149 smartlist_add_linecpy(diff
, area
, "hash"
1150 /* sha3 of cons1. */
1151 " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
1152 /* sha3 of cons2. */
1153 " 90A418881B2FCAB3D9E60EE02E4D666D56CFA38F8A3B7AA3E0ADBA530DDA9353");
1154 smartlist_add_linecpy(diff
, area
, "3c");
1155 smartlist_add_linecpy(diff
, area
, "sample");
1156 smartlist_add_linecpy(diff
, area
, ".");
1157 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1158 tt_ptr_op(NULL
, OP_NE
, cons2
);
1160 "network-status-version foo\n"
1161 "r name ccccccccccccccccc etc\nsample\n"
1162 "r name eeeeeeeeeeeeeeeee etc\nbar\n"
1163 "directory-signature foo bar\nbar\n", OP_EQ
,
1167 /* Check that lowercase letters in base16-encoded digests work too. */
1168 smartlist_clear(diff
);
1169 smartlist_add_linecpy(diff
, area
, "network-status-diff-version 1");
1170 smartlist_add_linecpy(diff
, area
, "hash"
1171 /* sha3 of cons1. */
1172 " 06646d6cf563a41869d3b02e73254372ae3140046c5e7d83c9f71e54976af9b4"
1173 /* sha3 of cons2. */
1174 " 90a418881b2fcab3d9e60ee02e4d666d56cfa38f8a3b7aa3e0adba530dda9353");
1175 smartlist_add_linecpy(diff
, area
, "3c");
1176 smartlist_add_linecpy(diff
, area
, "sample");
1177 smartlist_add_linecpy(diff
, area
, ".");
1178 cons2
= consdiff_apply_diff(cons1
, diff
, &digests1
);
1179 tt_ptr_op(NULL
, OP_NE
, cons2
);
1181 "network-status-version foo\n"
1182 "r name ccccccccccccccccc etc\nsample\n"
1183 "r name eeeeeeeeeeeeeeeee etc\nbar\n"
1184 "directory-signature foo bar\nbar\n", OP_EQ
,
1188 smartlist_clear(diff
);
1191 teardown_capture_of_logs();
1192 tor_free(cons1_str
);
1193 smartlist_free(cons1
);
1194 smartlist_free(diff
);
1195 memarea_drop_all(area
);
1198 #define CONSDIFF_LEGACY(name) \
1199 { #name, test_consdiff_ ## name , 0, NULL, NULL }
1201 struct testcase_t consdiff_tests
[] = {
1202 CONSDIFF_LEGACY(smartlist_slice
),
1203 CONSDIFF_LEGACY(smartlist_slice_string_pos
),
1204 CONSDIFF_LEGACY(lcs_lengths
),
1205 CONSDIFF_LEGACY(trim_slices
),
1206 CONSDIFF_LEGACY(set_changed
),
1207 CONSDIFF_LEGACY(calc_changes
),
1208 CONSDIFF_LEGACY(get_id_hash
),
1209 CONSDIFF_LEGACY(is_valid_router_entry
),
1210 CONSDIFF_LEGACY(next_router
),
1211 CONSDIFF_LEGACY(base64cmp
),
1212 CONSDIFF_LEGACY(gen_ed_diff
),
1213 CONSDIFF_LEGACY(apply_ed_diff
),
1214 CONSDIFF_LEGACY(gen_diff
),
1215 CONSDIFF_LEGACY(apply_diff
),