1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- /* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #define CONSDIFF_PRIVATE
- #include "or.h"
- #include "test.h"
- #include "consdiff.h"
- #include "log_test_helpers.h"
- static void
- test_consdiff_smartlist_slice(void *arg)
- {
- smartlist_t *sl = smartlist_new();
- smartlist_slice_t *sls;
- /* Create a regular smartlist. */
- (void)arg;
- smartlist_add(sl, (void*)1);
- smartlist_add(sl, (void*)2);
- smartlist_add(sl, (void*)3);
- smartlist_add(sl, (void*)4);
- smartlist_add(sl, (void*)5);
- /* See if the slice was done correctly. */
- sls = smartlist_slice(sl, 2, 5);
- tt_ptr_op(sl, OP_EQ, sls->list);
- tt_ptr_op((void*)3, OP_EQ, smartlist_get(sls->list, sls->offset));
- tt_ptr_op((void*)5, OP_EQ,
- smartlist_get(sls->list, sls->offset + (sls->len-1)));
- tor_free(sls);
- /* See that using -1 as the end does get to the last element. */
- sls = smartlist_slice(sl, 2, -1);
- tt_ptr_op(sl, OP_EQ, sls->list);
- tt_ptr_op((void*)3, OP_EQ, smartlist_get(sls->list, sls->offset));
- tt_ptr_op((void*)5, OP_EQ,
- smartlist_get(sls->list, sls->offset + (sls->len-1)));
- done:
- tor_free(sls);
- smartlist_free(sl);
- }
- static void
- test_consdiff_smartlist_slice_string_pos(void *arg)
- {
- smartlist_t *sl = smartlist_new();
- smartlist_slice_t *sls;
- /* Create a regular smartlist. */
- (void)arg;
- smartlist_split_string(sl, "a:d:c:a:b", ":", 0, 0);
- /* See that smartlist_slice_string_pos respects the bounds of the slice. */
- sls = smartlist_slice(sl, 2, 5);
- tt_int_op(3, OP_EQ, smartlist_slice_string_pos(sls, "a"));
- tt_int_op(-1, OP_EQ, smartlist_slice_string_pos(sls, "d"));
- done:
- tor_free(sls);
- if (sl) SMARTLIST_FOREACH(sl, char*, line, tor_free(line));
- smartlist_free(sl);
- }
- static void
- test_consdiff_lcs_lengths(void *arg)
- {
- smartlist_t *sl1 = smartlist_new();
- smartlist_t *sl2 = smartlist_new();
- smartlist_slice_t *sls1, *sls2;
- int *lengths1, *lengths2;
- /* Expected lcs lengths in regular and reverse order. */
- int e_lengths1[] = { 0, 1, 2, 3, 3, 4 };
- int e_lengths2[] = { 0, 1, 1, 2, 3, 4 };
- (void)arg;
- smartlist_split_string(sl1, "a:b:c:d:e", ":", 0, 0);
- smartlist_split_string(sl2, "a:c:d:i:e", ":", 0, 0);
- sls1 = smartlist_slice(sl1, 0, -1);
- sls2 = smartlist_slice(sl2, 0, -1);
- lengths1 = lcs_lengths(sls1, sls2, 1);
- lengths2 = lcs_lengths(sls1, sls2, -1);
- tt_mem_op(e_lengths1, OP_EQ, lengths1, sizeof(int) * 6);
- tt_mem_op(e_lengths2, OP_EQ, lengths2, sizeof(int) * 6);
- done:
- tor_free(lengths1);
- tor_free(lengths2);
- tor_free(sls1);
- tor_free(sls2);
- if (sl1) SMARTLIST_FOREACH(sl1, char*, line, tor_free(line));
- if (sl2) SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- smartlist_free(sl1);
- smartlist_free(sl2);
- }
- static void
- test_consdiff_trim_slices(void *arg)
- {
- smartlist_t *sl1 = smartlist_new();
- smartlist_t *sl2 = smartlist_new();
- smartlist_t *sl3 = smartlist_new();
- smartlist_t *sl4 = smartlist_new();
- smartlist_slice_t *sls1, *sls2, *sls3, *sls4;
- (void)arg;
- smartlist_split_string(sl1, "a:b:b:b:d", ":", 0, 0);
- smartlist_split_string(sl2, "a:c:c:c:d", ":", 0, 0);
- smartlist_split_string(sl3, "a:b:b:b:a", ":", 0, 0);
- smartlist_split_string(sl4, "c:b:b:b:c", ":", 0, 0);
- sls1 = smartlist_slice(sl1, 0, -1);
- sls2 = smartlist_slice(sl2, 0, -1);
- sls3 = smartlist_slice(sl3, 0, -1);
- sls4 = smartlist_slice(sl4, 0, -1);
- /* They should be trimmed by one line at each end. */
- tt_int_op(5, OP_EQ, sls1->len);
- tt_int_op(5, OP_EQ, sls2->len);
- trim_slices(sls1, sls2);
- tt_int_op(3, OP_EQ, sls1->len);
- tt_int_op(3, OP_EQ, sls2->len);
- /* They should not be trimmed at all. */
- tt_int_op(5, OP_EQ, sls3->len);
- tt_int_op(5, OP_EQ, sls4->len);
- trim_slices(sls3, sls4);
- tt_int_op(5, OP_EQ, sls3->len);
- tt_int_op(5, OP_EQ, sls4->len);
- done:
- tor_free(sls1);
- tor_free(sls2);
- tor_free(sls3);
- tor_free(sls4);
- if (sl1) SMARTLIST_FOREACH(sl1, char*, line, tor_free(line));
- if (sl2) SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- if (sl3) SMARTLIST_FOREACH(sl3, char*, line, tor_free(line));
- if (sl4) SMARTLIST_FOREACH(sl4, char*, line, tor_free(line));
- smartlist_free(sl1);
- smartlist_free(sl2);
- smartlist_free(sl3);
- smartlist_free(sl4);
- }
- static void
- test_consdiff_set_changed(void *arg)
- {
- smartlist_t *sl1 = smartlist_new();
- smartlist_t *sl2 = smartlist_new();
- bitarray_t *changed1 = bitarray_init_zero(4);
- bitarray_t *changed2 = bitarray_init_zero(4);
- smartlist_slice_t *sls1, *sls2;
- (void)arg;
- smartlist_split_string(sl1, "a:b:a:a", ":", 0, 0);
- smartlist_split_string(sl2, "a:a:a:a", ":", 0, 0);
- /* Length of sls1 is 0. */
- sls1 = smartlist_slice(sl1, 0, 0);
- sls2 = smartlist_slice(sl2, 1, 3);
- set_changed(changed1, changed2, sls1, sls2);
- /* The former is not changed, the latter changes all of its elements. */
- tt_assert(!bitarray_is_set(changed1, 0));
- tt_assert(!bitarray_is_set(changed1, 1));
- tt_assert(!bitarray_is_set(changed1, 2));
- tt_assert(!bitarray_is_set(changed1, 3));
- tt_assert(!bitarray_is_set(changed2, 0));
- tt_assert(bitarray_is_set(changed2, 1));
- tt_assert(bitarray_is_set(changed2, 2));
- tt_assert(!bitarray_is_set(changed2, 3));
- bitarray_clear(changed2, 1);
- bitarray_clear(changed2, 2);
- /* Length of sls1 is 1 and its element is in sls2. */
- tor_free(sls1);
- sls1 = smartlist_slice(sl1, 0, 1);
- set_changed(changed1, changed2, sls1, sls2);
- /* The latter changes all elements but the (first) common one. */
- tt_assert(!bitarray_is_set(changed1, 0));
- tt_assert(!bitarray_is_set(changed1, 1));
- tt_assert(!bitarray_is_set(changed1, 2));
- tt_assert(!bitarray_is_set(changed1, 3));
- tt_assert(!bitarray_is_set(changed2, 0));
- tt_assert(!bitarray_is_set(changed2, 1));
- tt_assert(bitarray_is_set(changed2, 2));
- tt_assert(!bitarray_is_set(changed2, 3));
- bitarray_clear(changed2, 2);
- /* Length of sls1 is 1 and its element is not in sls2. */
- tor_free(sls1);
- sls1 = smartlist_slice(sl1, 1, 2);
- set_changed(changed1, changed2, sls1, sls2);
- /* The former changes its element, the latter changes all elements. */
- tt_assert(!bitarray_is_set(changed1, 0));
- tt_assert(bitarray_is_set(changed1, 1));
- tt_assert(!bitarray_is_set(changed1, 2));
- tt_assert(!bitarray_is_set(changed1, 3));
- tt_assert(!bitarray_is_set(changed2, 0));
- tt_assert(bitarray_is_set(changed2, 1));
- tt_assert(bitarray_is_set(changed2, 2));
- tt_assert(!bitarray_is_set(changed2, 3));
- done:
- bitarray_free(changed1);
- bitarray_free(changed2);
- if (sl1) SMARTLIST_FOREACH(sl1, char*, line, tor_free(line));
- if (sl2) SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- smartlist_free(sl1);
- smartlist_free(sl2);
- tor_free(sls1);
- tor_free(sls2);
- }
- static void
- test_consdiff_calc_changes(void *arg)
- {
- smartlist_t *sl1 = smartlist_new();
- smartlist_t *sl2 = smartlist_new();
- smartlist_slice_t *sls1, *sls2;
- bitarray_t *changed1 = bitarray_init_zero(4);
- bitarray_t *changed2 = bitarray_init_zero(4);
- (void)arg;
- smartlist_split_string(sl1, "a:a:a:a", ":", 0, 0);
- smartlist_split_string(sl2, "a:a:a:a", ":", 0, 0);
- sls1 = smartlist_slice(sl1, 0, -1);
- sls2 = smartlist_slice(sl2, 0, -1);
- calc_changes(sls1, sls2, changed1, changed2);
- /* Nothing should be set to changed. */
- tt_assert(!bitarray_is_set(changed1, 0));
- tt_assert(!bitarray_is_set(changed1, 1));
- tt_assert(!bitarray_is_set(changed1, 2));
- tt_assert(!bitarray_is_set(changed1, 3));
- tt_assert(!bitarray_is_set(changed2, 0));
- tt_assert(!bitarray_is_set(changed2, 1));
- tt_assert(!bitarray_is_set(changed2, 2));
- tt_assert(!bitarray_is_set(changed2, 3));
- SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- smartlist_clear(sl2);
- smartlist_split_string(sl2, "a:b:a:b", ":", 0, 0);
- tor_free(sls1);
- tor_free(sls2);
- sls1 = smartlist_slice(sl1, 0, -1);
- sls2 = smartlist_slice(sl2, 0, -1);
- calc_changes(sls1, sls2, changed1, changed2);
- /* Two elements are changed. */
- tt_assert(!bitarray_is_set(changed1, 0));
- tt_assert(bitarray_is_set(changed1, 1));
- tt_assert(bitarray_is_set(changed1, 2));
- tt_assert(!bitarray_is_set(changed1, 3));
- bitarray_clear(changed1, 1);
- bitarray_clear(changed1, 2);
- tt_assert(!bitarray_is_set(changed2, 0));
- tt_assert(bitarray_is_set(changed2, 1));
- tt_assert(!bitarray_is_set(changed2, 2));
- tt_assert(bitarray_is_set(changed2, 3));
- bitarray_clear(changed1, 1);
- bitarray_clear(changed1, 3);
- SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- smartlist_clear(sl2);
- smartlist_split_string(sl2, "b:b:b:b", ":", 0, 0);
- tor_free(sls1);
- tor_free(sls2);
- sls1 = smartlist_slice(sl1, 0, -1);
- sls2 = smartlist_slice(sl2, 0, -1);
- calc_changes(sls1, sls2, changed1, changed2);
- /* All elements are changed. */
- tt_assert(bitarray_is_set(changed1, 0));
- tt_assert(bitarray_is_set(changed1, 1));
- tt_assert(bitarray_is_set(changed1, 2));
- tt_assert(bitarray_is_set(changed1, 3));
- tt_assert(bitarray_is_set(changed2, 0));
- tt_assert(bitarray_is_set(changed2, 1));
- tt_assert(bitarray_is_set(changed2, 2));
- tt_assert(bitarray_is_set(changed2, 3));
- done:
- bitarray_free(changed1);
- bitarray_free(changed2);
- if (sl1) SMARTLIST_FOREACH(sl1, char*, line, tor_free(line));
- if (sl2) SMARTLIST_FOREACH(sl2, char*, line, tor_free(line));
- smartlist_free(sl1);
- smartlist_free(sl2);
- tor_free(sls1);
- tor_free(sls2);
- }
- static void
- test_consdiff_get_id_hash(void *arg)
- {
- const char *line, *e_hash;
- /* No hash. */
- (void)arg;
- tt_ptr_op(NULL, OP_EQ, get_id_hash("r name"));
- /* The hash contains characters that are not base64. */
- tt_ptr_op(NULL, OP_EQ, get_id_hash( "r name _hash_isnt_base64 etc"));
- line = "r name hash+valid+base64 etc";
- e_hash = line+7;
- tt_ptr_op(e_hash, OP_EQ, get_id_hash(line));
- done:
- ;
- }
- static void
- test_consdiff_is_valid_router_entry(void *arg)
- {
- /* Doesn't start with "r ". */
- (void)arg;
- tt_int_op(0, OP_EQ, is_valid_router_entry("foo"));
- /* These are already tested with get_id_hash, but make sure it's run
- * properly. */
- tt_int_op(0, OP_EQ, is_valid_router_entry("r name"));
- tt_int_op(0, OP_EQ, is_valid_router_entry("r name _hash_isnt_base64 etc"));
- tt_int_op(1, OP_EQ, is_valid_router_entry("r name hash+valid+base64 etc"));
- done:
- ;
- }
- static void
- test_consdiff_next_router(void *arg)
- {
- smartlist_t *sl = smartlist_new();
- (void)arg;
- smartlist_add(sl, (char*)"foo");
- smartlist_add(sl,
- (char*)"r name hash+longer+than+27+chars+and+valid+base64 etc");
- smartlist_add(sl, (char*)"foo");
- smartlist_add(sl, (char*)"foo");
- smartlist_add(sl,
- (char*)"r name hash+longer+than+27+chars+and+valid+base64 etc");
- smartlist_add(sl, (char*)"foo");
- /* Not currently on a router entry line, finding the next one. */
- tt_int_op(1, OP_EQ, next_router(sl, 0));
- tt_int_op(4, OP_EQ, next_router(sl, 2));
- /* Already at the beginning of a router entry line, ignore it. */
- tt_int_op(4, OP_EQ, next_router(sl, 1));
- /* There are no more router entries, so return the line after the last. */
- tt_int_op(6, OP_EQ, next_router(sl, 4));
- tt_int_op(6, OP_EQ, next_router(sl, 5));
- done:
- smartlist_free(sl);
- }
- static void
- test_consdiff_base64cmp(void *arg)
- {
- /* NULL arguments. */
- (void)arg;
- tt_int_op(0, OP_EQ, base64cmp(NULL, NULL));
- tt_int_op(-1, OP_EQ, base64cmp(NULL, "foo"));
- tt_int_op(1, OP_EQ, base64cmp("bar", NULL));
- /* Nil base64 values. */
- tt_int_op(0, OP_EQ, base64cmp("", ""));
- tt_int_op(0, OP_EQ, base64cmp("_", "&"));
- /* Exact same valid strings. */
- tt_int_op(0, OP_EQ, base64cmp("abcABC/+", "abcABC/+"));
- /* Both end with an invalid base64 char other than '\0'. */
- tt_int_op(0, OP_EQ, base64cmp("abcABC/+ ", "abcABC/+ "));
- /* Only one ends with an invalid base64 char other than '\0'. */
- tt_int_op(0, OP_EQ, base64cmp("abcABC/+ ", "abcABC/+"));
- /* Comparisons that would return differently with strcmp(). */
- tt_int_op(-1, OP_EQ, strcmp("/foo", "Afoo"));
- tt_int_op(1, OP_EQ, base64cmp("/foo", "Afoo"));
- tt_int_op(1, OP_EQ, strcmp("Afoo", "0foo"));
- tt_int_op(-1, OP_EQ, base64cmp("Afoo", "0foo"));
- /* Comparisons that would return the same as with strcmp(). */
- tt_int_op(1, OP_EQ, strcmp("afoo", "Afoo"));
- tt_int_op(1, OP_EQ, base64cmp("afoo", "Afoo"));
- /* Different lengths */
- tt_int_op(-1, OP_EQ, base64cmp("afoo", "afooo"));
- tt_int_op(1, OP_EQ, base64cmp("afooo", "afoo"));
- done:
- ;
- }
- static void
- test_consdiff_gen_ed_diff(void *arg)
- {
- smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
- int i;
- int free_cons_entries = 0;/* 1 if the cons1 and cons2 contents are
- * heap-allocated */
- setup_capture_of_logs(LOG_WARN);
- (void)arg;
- cons1 = smartlist_new();
- cons2 = smartlist_new();
- /* Identity hashes are not sorted properly, return NULL. */
- smartlist_add(cons1, (char*)"r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
- smartlist_add(cons1, (char*)"foo");
- smartlist_add(cons1, (char*)"r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
- smartlist_add(cons1, (char*)"bar");
- smartlist_add(cons2, (char*)"r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
- smartlist_add(cons2, (char*)"foo");
- smartlist_add(cons2, (char*)"r name ccccccccccccccccccccccccccc etc");
- smartlist_add(cons2, (char*)"bar");
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because the base consensus doesn't have its router entries sorted "
- "properly.");
- /* Same, but now with the second consensus. */
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons2, cons1);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because the target consensus doesn't have its router entries sorted "
- "properly.");
- /* Same as the two above, but with the reversed thing immediately after a
- match. (The code handles this differently) */
- smartlist_del(cons1, 0);
- smartlist_add(cons1, (char*)"r name aaaaaaaaaaaaaaaaaaaaaaaaaaa etc");
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because the base consensus doesn't have its router entries sorted "
- "properly.");
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons2, cons1);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because the target consensus doesn't have its router entries sorted "
- "properly.");
- /* Identity hashes are repeated, return NULL. */
- smartlist_clear(cons1);
- smartlist_add(cons1, (char*)"r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
- smartlist_add(cons1, (char*)"foo");
- smartlist_add(cons1, (char*)"r name bbbbbbbbbbbbbbbbbbbbbbbbbbb etc");
- smartlist_add(cons1, (char*)"bar");
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because the base consensus doesn't have its router entries sorted "
- "properly.");
- /* We have to add a line that is just a dot, return NULL. */
- smartlist_clear(cons1);
- smartlist_clear(cons2);
- smartlist_add(cons1, (char*)"foo1");
- smartlist_add(cons1, (char*)"foo2");
- smartlist_add(cons2, (char*)"foo1");
- smartlist_add(cons2, (char*)".");
- smartlist_add(cons2, (char*)"foo2");
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Cannot generate consensus diff "
- "because one of the lines to be added is \".\".");
- #define MAX_LINE_COUNT (10000)
- /* Too many lines to be fed to the quadratic-time function. */
- smartlist_clear(cons1);
- smartlist_clear(cons2);
- for (i=0; i < MAX_LINE_COUNT; ++i) smartlist_add(cons1, (char*)"a");
- for (i=0; i < MAX_LINE_COUNT; ++i) smartlist_add(cons1, (char*)"b");
- mock_clean_saved_logs();
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_EQ, diff);
- expect_single_log_msg_containing("Refusing to generate consensus diff "
- "because we found too few common router ids.");
- /* We have dot lines, but they don't interfere with the script format. */
- smartlist_clear(cons1);
- smartlist_clear(cons2);
- smartlist_add(cons1, (char*)"foo1");
- smartlist_add(cons1, (char*)".");
- smartlist_add(cons1, (char*)".");
- smartlist_add(cons1, (char*)"foo2");
- smartlist_add(cons2, (char*)"foo1");
- smartlist_add(cons2, (char*)".");
- smartlist_add(cons2, (char*)"foo2");
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- /* Empty diff tests. */
- smartlist_clear(cons1);
- smartlist_clear(cons2);
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(0, OP_EQ, smartlist_len(diff));
- smartlist_free(diff);
- smartlist_add(cons1, (char*)"foo");
- smartlist_add(cons1, (char*)"bar");
- smartlist_add(cons2, (char*)"foo");
- smartlist_add(cons2, (char*)"bar");
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(0, OP_EQ, smartlist_len(diff));
- smartlist_free(diff);
- /* Everything is deleted. */
- smartlist_clear(cons2);
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(1, OP_EQ, smartlist_len(diff));
- tt_str_op("1,2d", OP_EQ, smartlist_get(diff, 0));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- /* Everything is added. */
- diff = gen_ed_diff(cons2, cons1);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(4, OP_EQ, smartlist_len(diff));
- tt_str_op("0a", OP_EQ, smartlist_get(diff, 0));
- tt_str_op("foo", OP_EQ, smartlist_get(diff, 1));
- tt_str_op("bar", OP_EQ, smartlist_get(diff, 2));
- tt_str_op(".", OP_EQ, smartlist_get(diff, 3));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- /* Everything is changed. */
- smartlist_add(cons2, (char*)"foo2");
- smartlist_add(cons2, (char*)"bar2");
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(4, OP_EQ, smartlist_len(diff));
- tt_str_op("1,2c", OP_EQ, smartlist_get(diff, 0));
- tt_str_op("foo2", OP_EQ, smartlist_get(diff, 1));
- tt_str_op("bar2", OP_EQ, smartlist_get(diff, 2));
- tt_str_op(".", OP_EQ, smartlist_get(diff, 3));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- /* Test 'a', 'c' and 'd' together. See that it is done in reverse order. */
- smartlist_clear(cons1);
- smartlist_clear(cons2);
- smartlist_split_string(cons1, "A:B:C:D:E", ":", 0, 0);
- smartlist_split_string(cons2, "A:C:O:E:U", ":", 0, 0);
- free_cons_entries = 1;
- diff = gen_ed_diff(cons1, cons2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(7, OP_EQ, smartlist_len(diff));
- tt_str_op("5a", OP_EQ, smartlist_get(diff, 0));
- tt_str_op("U", OP_EQ, smartlist_get(diff, 1));
- tt_str_op(".", OP_EQ, smartlist_get(diff, 2));
- tt_str_op("4c", OP_EQ, smartlist_get(diff, 3));
- tt_str_op("O", OP_EQ, smartlist_get(diff, 4));
- tt_str_op(".", OP_EQ, smartlist_get(diff, 5));
- tt_str_op("2d", OP_EQ, smartlist_get(diff, 6));
- /* TODO: small real use-cases, i.e. consensuses. */
- done:
- teardown_capture_of_logs();
- if (free_cons_entries) {
- if (cons1) SMARTLIST_FOREACH(cons1, char*, line, tor_free(line));
- if (cons2) SMARTLIST_FOREACH(cons2, char*, line, tor_free(line));
- }
- smartlist_free(cons1);
- smartlist_free(cons2);
- if (diff) SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- }
- static void
- test_consdiff_apply_ed_diff(void *arg)
- {
- smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
- (void)arg;
- cons1 = smartlist_new();
- diff = smartlist_new();
- setup_capture_of_logs(LOG_WARN);
- smartlist_split_string(cons1, "A:B:C:D:E", ":", 0, 0);
- /* Command without range. */
- smartlist_add(diff, (char*)"a");
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- smartlist_clear(diff);
- expect_single_log_msg_containing("an ed command was missing a line number");
- /* Range without command. */
- smartlist_add(diff, (char*)"1");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("a line with no ed command was found");
- smartlist_clear(diff);
- /* Range without end. */
- smartlist_add(diff, (char*)"1,");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("an ed command was missing a range "
- "end line number.");
- smartlist_clear(diff);
- /* Incoherent ranges. */
- smartlist_add(diff, (char*)"1,1");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("an invalid range was found");
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"3,2");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("an invalid range was found");
- smartlist_clear(diff);
- /* Script is not in reverse order. */
- smartlist_add(diff, (char*)"1d");
- smartlist_add(diff, (char*)"3d");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("its commands are not properly sorted");
- smartlist_clear(diff);
- /* Script contains unrecognised commands longer than one char. */
- smartlist_add(diff, (char*)"1foo");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("an ed command longer than one char was "
- "found");
- smartlist_clear(diff);
- /* Script contains unrecognised commands. */
- smartlist_add(diff, (char*)"1e");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("an unrecognised ed command was found");
- smartlist_clear(diff);
- /* Command that should be followed by at least one line and a ".", but
- * isn't. */
- smartlist_add(diff, (char*)"0a");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("it has an ed command that tries to "
- "insert zero lines.");
- /* Now it is followed by a ".", but it inserts zero lines. */
- smartlist_add(diff, (char*)".");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("it has an ed command that tries to "
- "insert zero lines.");
- smartlist_clear(diff);
- /* Now it it inserts something, but has no terminator. */
- smartlist_add(diff, (char*)"0a");
- smartlist_add(diff, (char*)"hello");
- mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("lines to be inserted that don't end with "
- "a \".\".");
- smartlist_clear(diff);
- /* Test appending text, 'a'. */
- smartlist_split_string(diff, "3a:U:O:.:0a:V:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_int_op(8, OP_EQ, smartlist_len(cons2));
- tt_str_op("V", OP_EQ, smartlist_get(cons2, 0));
- tt_str_op("A", OP_EQ, smartlist_get(cons2, 1));
- tt_str_op("B", OP_EQ, smartlist_get(cons2, 2));
- tt_str_op("C", OP_EQ, smartlist_get(cons2, 3));
- tt_str_op("U", OP_EQ, smartlist_get(cons2, 4));
- tt_str_op("O", OP_EQ, smartlist_get(cons2, 5));
- tt_str_op("D", OP_EQ, smartlist_get(cons2, 6));
- tt_str_op("E", OP_EQ, smartlist_get(cons2, 7));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_clear(diff);
- SMARTLIST_FOREACH(cons2, char*, line, tor_free(line));
- smartlist_free(cons2);
- /* Test deleting text, 'd'. */
- smartlist_split_string(diff, "4d:1,2d", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_int_op(2, OP_EQ, smartlist_len(cons2));
- tt_str_op("C", OP_EQ, smartlist_get(cons2, 0));
- tt_str_op("E", OP_EQ, smartlist_get(cons2, 1));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_clear(diff);
- SMARTLIST_FOREACH(cons2, char*, line, tor_free(line));
- smartlist_free(cons2);
- /* Test changing text, 'c'. */
- smartlist_split_string(diff, "4c:T:X:.:1, 2c:M:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_int_op(5, OP_EQ, smartlist_len(cons2));
- tt_str_op("M", OP_EQ, smartlist_get(cons2, 0));
- tt_str_op("C", OP_EQ, smartlist_get(cons2, 1));
- tt_str_op("T", OP_EQ, smartlist_get(cons2, 2));
- tt_str_op("X", OP_EQ, smartlist_get(cons2, 3));
- tt_str_op("E", OP_EQ, smartlist_get(cons2, 4));
- SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_clear(diff);
- SMARTLIST_FOREACH(cons2, char*, line, tor_free(line));
- smartlist_free(cons2);
- /* Test 'a', 'd' and 'c' together. */
- smartlist_split_string(diff, "4c:T:X:.:2d:0a:M:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff, 0);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_int_op(6, OP_EQ, smartlist_len(cons2));
- tt_str_op("M", OP_EQ, smartlist_get(cons2, 0));
- tt_str_op("A", OP_EQ, smartlist_get(cons2, 1));
- tt_str_op("C", OP_EQ, smartlist_get(cons2, 2));
- tt_str_op("T", OP_EQ, smartlist_get(cons2, 3));
- tt_str_op("X", OP_EQ, smartlist_get(cons2, 4));
- tt_str_op("E", OP_EQ, smartlist_get(cons2, 5));
- done:
- teardown_capture_of_logs();
- if (cons1) SMARTLIST_FOREACH(cons1, char*, line, tor_free(line));
- if (cons2) SMARTLIST_FOREACH(cons2, char*, line, tor_free(line));
- smartlist_free(cons1);
- smartlist_free(cons2);
- if (diff) SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- }
- static void
- test_consdiff_gen_diff(void *arg)
- {
- char *cons1_str=NULL, *cons2_str=NULL;
- smartlist_t *cons1=NULL, *cons2=NULL, *diff=NULL;
- consensus_digest_t digests1, digests2;
- (void)arg;
- cons1 = smartlist_new();
- cons2 = smartlist_new();
- /* Identity hashes are not sorted properly, return NULL.
- * Already tested in gen_ed_diff, but see that a NULL ed diff also makes
- * gen_diff return NULL. */
- cons1_str = tor_strdup(
- "network-status-version foo\n"
- "r name bbbbbbbbbbbbbbbbb etc\nfoo\n"
- "r name aaaaaaaaaaaaaaaaa etc\nbar\n"
- "directory-signature foo bar\nbar\n"
- );
- cons2_str = tor_strdup(
- "network-status-version foo\n"
- "r name aaaaaaaaaaaaaaaaa etc\nfoo\n"
- "r name ccccccccccccccccc etc\nbar\n"
- "directory-signature foo bar\nbar\n"
- );
- tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons1_str, &digests1));
- tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons2_str, &digests2));
- tor_split_lines(cons1, cons1_str, (int)strlen(cons1_str));
- tor_split_lines(cons2, cons2_str, (int)strlen(cons2_str));
- diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2);
- tt_ptr_op(NULL, OP_EQ, diff);
- /* Check that the headers are done properly. */
- tor_free(cons1_str);
- cons1_str = tor_strdup(
- "network-status-version foo\n"
- "r name ccccccccccccccccc etc\nfoo\n"
- "r name eeeeeeeeeeeeeeeee etc\nbar\n"
- "directory-signature foo bar\nbar\n"
- );
- tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons1_str, &digests1));
- smartlist_clear(cons1);
- tor_split_lines(cons1, cons1_str, (int)strlen(cons1_str));
- diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2);
- tt_ptr_op(NULL, OP_NE, diff);
- tt_int_op(7, OP_EQ, smartlist_len(diff));
- tt_str_op("network-status-diff-version 1", OP_EQ, smartlist_get(diff, 0));
- tt_str_op("hash "
- "06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4 "
- "7AFECEFA4599BA33D603653E3D2368F648DF4AC4723929B0F7CF39281596B0C1",
- OP_EQ, smartlist_get(diff, 1));
- tt_str_op("3,4d", OP_EQ, smartlist_get(diff, 2));
- tt_str_op("1a", OP_EQ, smartlist_get(diff, 3));
- tt_str_op("r name aaaaaaaaaaaaaaaaa etc", OP_EQ, smartlist_get(diff, 4));
- tt_str_op("foo", OP_EQ, smartlist_get(diff, 5));
- tt_str_op(".", OP_EQ, smartlist_get(diff, 6));
- /* TODO: small real use-cases, i.e. consensuses. */
- done:
- tor_free(cons1_str);
- tor_free(cons2_str);
- smartlist_free(cons1);
- smartlist_free(cons2);
- if (diff) SMARTLIST_FOREACH(diff, char*, line, tor_free(line));
- smartlist_free(diff);
- }
- static void
- test_consdiff_apply_diff(void *arg)
- {
- smartlist_t *cons1=NULL, *diff=NULL;
- char *cons1_str=NULL, *cons2 = NULL;
- consensus_digest_t digests1;
- (void)arg;
- cons1 = smartlist_new();
- diff = smartlist_new();
- setup_capture_of_logs(LOG_INFO);
- cons1_str = tor_strdup(
- "network-status-version foo\n"
- "r name ccccccccccccccccc etc\nfoo\n"
- "r name eeeeeeeeeeeeeeeee etc\nbar\n"
- "directory-signature foo bar\nbar\n"
- );
- tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons1_str, &digests1));
- tor_split_lines(cons1, cons1_str, (int)strlen(cons1_str));
- /* diff doesn't have enough lines. */
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("too short")
- /* first line doesn't match format-version string. */
- smartlist_add(diff, (char*)"foo-bar");
- smartlist_add(diff, (char*)"header-line");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("format is not known")
- /* The first word of the second header line is not "hash". */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"word a b");
- smartlist_add(diff, (char*)"x");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("does not include the necessary digests")
- /* Wrong number of words after "hash". */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash a b c");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("does not include the necessary digests")
- /* base16 digests do not have the expected length. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash aaa bbb");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("includes base16-encoded digests of "
- "incorrect size")
- /* base16 digests contain non-base16 characters. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- " ????????????????????????????????????????????????????????????????"
- " ----------------------------------------------------------------");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("includes malformed digests")
- /* Invalid ed diff.
- * As tested in apply_ed_diff, but check that apply_diff does return NULL if
- * the ed diff can't be applied. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* sha3 of cons1. */
- " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
- /* sha256 of cons2. */
- " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
- smartlist_add(diff, (char*)"foobar");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_single_log_msg_containing("because an ed command was missing a line "
- "number")
- /* Base consensus doesn't match its digest as found in the diff. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* bogus sha256. */
- " 3333333333333333333333333333333333333333333333333333333333333333"
- /* sha256 of cons2. */
- " 635D34593020C08E5ECD865F9986E29D50028EFA62843766A8197AD228A7F6AA");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_log_msg_containing("base consensus doesn't match the digest "
- "as found");
- /* Resulting consensus doesn't match its digest as found in the diff. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* sha3 of cons1. */
- " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
- /* bogus sha3. */
- " 3333333333333333333333333333333333333333333333333333333333333333");
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_log_msg_containing("resulting consensus doesn't match the "
- "digest as found");
- #if 0
- /* XXXX No longer possible, since we aren't using the other algorithm. */
- /* Resulting consensus digest cannot be computed */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* sha3 of cons1. */
- " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
- /* bogus sha3. */
- " 3333333333333333333333333333333333333333333333333333333333333333");
- smartlist_add(diff, (char*)"1,2d"); // remove starting line
- mock_clean_saved_logs();
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_EQ, cons2);
- expect_log_msg_containing("Could not compute digests of the consensus "
- "resulting from applying a consensus diff.");
- #endif
- /* Very simple test, only to see that nothing errors. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* sha3 of cons1. */
- " 06646D6CF563A41869D3B02E73254372AE3140046C5E7D83C9F71E54976AF9B4"
- /* sha3 of cons2. */
- " 90A418881B2FCAB3D9E60EE02E4D666D56CFA38F8A3B7AA3E0ADBA530DDA9353");
- smartlist_add(diff, (char*)"3c");
- smartlist_add(diff, (char*)"sample");
- smartlist_add(diff, (char*)".");
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_str_op(
- "network-status-version foo\n"
- "r name ccccccccccccccccc etc\nsample\n"
- "r name eeeeeeeeeeeeeeeee etc\nbar\n"
- "directory-signature foo bar\nbar\n", OP_EQ,
- cons2);
- tor_free(cons2);
- /* Check that lowercase letters in base16-encoded digests work too. */
- smartlist_clear(diff);
- smartlist_add(diff, (char*)"network-status-diff-version 1");
- smartlist_add(diff, (char*)"hash"
- /* sha3 of cons1. */
- " 06646d6cf563a41869d3b02e73254372ae3140046c5e7d83c9f71e54976af9b4"
- /* sha3 of cons2. */
- " 90a418881b2fcab3d9e60ee02e4d666d56cfa38f8a3b7aa3e0adba530dda9353");
- smartlist_add(diff, (char*)"3c");
- smartlist_add(diff, (char*)"sample");
- smartlist_add(diff, (char*)".");
- cons2 = consdiff_apply_diff(cons1, diff, &digests1);
- tt_ptr_op(NULL, OP_NE, cons2);
- tt_str_op(
- "network-status-version foo\n"
- "r name ccccccccccccccccc etc\nsample\n"
- "r name eeeeeeeeeeeeeeeee etc\nbar\n"
- "directory-signature foo bar\nbar\n", OP_EQ,
- cons2);
- tor_free(cons2);
- smartlist_clear(diff);
- done:
- teardown_capture_of_logs();
- tor_free(cons1_str);
- smartlist_free(cons1);
- smartlist_free(diff);
- }
- #define CONSDIFF_LEGACY(name) \
- { #name, test_consdiff_ ## name , 0, NULL, NULL }
- struct testcase_t consdiff_tests[] = {
- CONSDIFF_LEGACY(smartlist_slice),
- CONSDIFF_LEGACY(smartlist_slice_string_pos),
- CONSDIFF_LEGACY(lcs_lengths),
- CONSDIFF_LEGACY(trim_slices),
- CONSDIFF_LEGACY(set_changed),
- CONSDIFF_LEGACY(calc_changes),
- CONSDIFF_LEGACY(get_id_hash),
- CONSDIFF_LEGACY(is_valid_router_entry),
- CONSDIFF_LEGACY(next_router),
- CONSDIFF_LEGACY(base64cmp),
- CONSDIFF_LEGACY(gen_ed_diff),
- CONSDIFF_LEGACY(apply_ed_diff),
- CONSDIFF_LEGACY(gen_diff),
- CONSDIFF_LEGACY(apply_diff),
- END_OF_TESTCASES
- };
|