/** Run unit tests for smartlist set manipulation functions. */ static void test_container_smartlist_overlap(void *unused) { smartlist_t *sl = smartlist_create(); smartlist_t *ints = smartlist_create(); smartlist_t *odds = smartlist_create(); smartlist_t *evens = smartlist_create(); smartlist_t *primes = smartlist_create(); int i; for (i=1; i < 10; i += 2) smartlist_add(odds, (void*)(uintptr_t)i); for (i=0; i < 10; i += 2) smartlist_add(evens, (void*)(uintptr_t)i); /* add_all */ smartlist_add_all(ints, odds); smartlist_add_all(ints, evens); tt_int_op(smartlist_len(ints), ==, 10); smartlist_add(primes, (void*)2); smartlist_add(primes, (void*)3); smartlist_add(primes, (void*)5); smartlist_add(primes, (void*)7); /* overlap */ tt_assert(smartlist_overlap(ints, odds)); tt_assert(smartlist_overlap(odds, primes)); tt_assert(smartlist_overlap(evens, primes)); tt_assert(!smartlist_overlap(odds, evens)); /* intersect */ smartlist_add_all(sl, odds); smartlist_intersect(sl, primes); tt_int_op(smartlist_len(sl), ==, 3); tt_assert(smartlist_isin(sl, (void*)3)); tt_assert(smartlist_isin(sl, (void*)5)); tt_assert(smartlist_isin(sl, (void*)7)); /* subtract */ smartlist_add_all(sl, primes); smartlist_subtract(sl, odds); tt_int_op(smartlist_len(sl), ==, 1); tt_assert(smartlist_isin(sl, (void*)2)); end: smartlist_free(odds); smartlist_free(evens); smartlist_free(ints); smartlist_free(primes); smartlist_free(sl); }
/** Return true iff some element E of sl2 has smartlist_isin(sl1,E). */ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) { int i; for (i=0; i < sl2->num_used; i++) if (smartlist_isin(sl1, sl2->list[i])) return 1; return 0; }
/** Remove every element E of sl1 such that !smartlist_isin(sl2,E). * Does not preserve the order of sl1. */ void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) { int i; for (i=0; i < sl1->num_used; i++) if (!smartlist_isin(sl2, sl1->list[i])) { sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */ i--; /* so we process the new i'th element */ } }
/** Run unit tests for basic dynamic-sized array functionality. */ static void test_container_smartlist_basic(void *unused) { smartlist_t *sl; /* XXXX test sort_digests, uniq_strings, uniq_digests */ /* Test smartlist add, del_keeporder, insert, get. */ sl = smartlist_create(); smartlist_add(sl, (void*)1); smartlist_add(sl, (void*)2); smartlist_add(sl, (void*)3); smartlist_add(sl, (void*)4); smartlist_del_keeporder(sl, 1); smartlist_insert(sl, 1, (void*)22); smartlist_insert(sl, 0, (void*)0); smartlist_insert(sl, 5, (void*)555); tt_ptr_op(smartlist_get(sl,0), ==, (void*)0); tt_ptr_op(smartlist_get(sl,1), ==, (void*)1); tt_ptr_op(smartlist_get(sl,2), ==, (void*)22); tt_ptr_op(smartlist_get(sl,3), ==, (void*)3); tt_ptr_op(smartlist_get(sl,4), ==, (void*)4); tt_ptr_op(smartlist_get(sl,5), ==, (void*)555); /* Try deleting in the middle. */ smartlist_del(sl, 1); tt_ptr_op(smartlist_get(sl, 1), ==, (void*)555); /* Try deleting at the end. */ smartlist_del(sl, 4); tt_int_op(smartlist_len(sl), ==, 4); /* test isin. */ tt_assert(smartlist_isin(sl, (void*)3)); tt_assert(!smartlist_isin(sl, (void*)99)); end: smartlist_free(sl); }
/** Run unit tests for smartlist-of-strings functionality. */ static void test_container_smartlist_strings(void *unused) { smartlist_t *sl = smartlist_create(); char *cp=NULL, *cp_alloc=NULL; size_t sz; /* Test split and join */ tt_int_op(smartlist_len(sl), ==, 0); smartlist_split_string(sl, "abc", ":", 0, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abc"); smartlist_split_string(sl, "a::bc::", "::", 0, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl, 1), ==, "a"); tt_str_op(smartlist_get(sl, 2), ==, "bc"); tt_str_op(smartlist_get(sl, 3), ==, ""); cp_alloc = smartlist_join_strings(sl, "", 0, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); tt_str_op(cp_alloc, ==, "abc!a!bc!"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXYXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "", 1, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl, 4), ==, ""); tt_str_op(smartlist_get(sl, 5), ==, "def"); tt_str_op(smartlist_get(sl, 6), ==, " "); tt_str_op(smartlist_get(sl, 7), ==, "ghijk"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl,0), ==, "a"); tt_str_op(smartlist_get(sl,1), ==, "bbd"); tt_str_op(smartlist_get(sl,2), ==, "cdef"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl,3), ==, "z"); tt_str_op(smartlist_get(sl,4), ==, "zhasd"); tt_str_op(smartlist_get(sl,5), ==, ""); tt_str_op(smartlist_get(sl,6), ==, "bnud"); tt_str_op(smartlist_get(sl,7), ==, ""); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, " ab\tc \td ef ", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl,0), ==, "ab"); tt_str_op(smartlist_get(sl,1), ==, "c"); tt_str_op(smartlist_get(sl,2), ==, "d"); tt_str_op(smartlist_get(sl,3), ==, "ef"); smartlist_split_string(sl, "ghi\tj", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 6); tt_str_op(smartlist_get(sl,4), ==, "ghi"); tt_str_op(smartlist_get(sl,5), ==, "j"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, ""); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "XY"); free(cp_alloc); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl, 0), ==, "z"); tt_str_op(smartlist_get(sl, 1), ==, "zhasd"); tt_str_op(smartlist_get(sl, 2), ==, "bnud"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); tt_int_op(smartlist_len(sl), ==, 5); tt_str_op(smartlist_get(sl, 3), ==, "z"); tt_str_op(smartlist_get(sl, 4), ==, "zhasd <> <> bnud<>"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "abcd\n", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abcd"); smartlist_split_string(sl, "efgh", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 2); tt_str_op(smartlist_get(sl, 1), ==, "efgh"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test swapping, shuffling, and sorting. */ smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); tt_int_op(smartlist_len(sl), ==, 7); smartlist_sort(sl, _compare_strs); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,arma,by,nickm,onion,router,the"); free(cp_alloc); smartlist_swap(sl, 1, 5); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,router,by,nickm,onion,arma,the"); free(cp_alloc); smartlist_shuffle(sl); tt_int_op(smartlist_len(sl), ==, 7); tt_assert(smartlist_string_isin(sl, "and")); tt_assert(smartlist_string_isin(sl, "router")); tt_assert(smartlist_string_isin(sl, "by")); tt_assert(smartlist_string_isin(sl, "nickm")); tt_assert(smartlist_string_isin(sl, "onion")); tt_assert(smartlist_string_isin(sl, "arma")); tt_assert(smartlist_string_isin(sl, "the")); /* Test bsearch. */ smartlist_sort(sl, _compare_strs); tt_str_op(smartlist_bsearch(sl, "zNicKM", _compare_without_first_ch), ==, "nickm"); tt_str_op(smartlist_bsearch(sl, " AND", _compare_without_first_ch), ==, "and"); tt_ptr_op(smartlist_bsearch(sl, " ANz", _compare_without_first_ch), ==, NULL); /* Test bsearch_idx */ { int f; tt_int_op(smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f), ==, 2); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f), ==, 7); tt_int_op(f, ==, 0); } /* Test reverse() and pop_last() */ smartlist_reverse(sl); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "the,router,onion,nickm,by,arma,and"); free(cp_alloc); cp_alloc = smartlist_pop_last(sl); tt_str_op(cp_alloc, ==, "and"); free(cp_alloc); tt_int_op(smartlist_len(sl), ==, 6); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); tt_ptr_op(cp_alloc, ==, NULL); /* Test uniq() */ smartlist_split_string(sl, "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", ",", 0, 0); smartlist_sort(sl, _compare_strs); smartlist_uniq(sl, _compare_strs, free); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "50,a,canal,man,noon,panama,plan,radar"); free(cp_alloc); /* Test string_isin and isin_case and num_isin */ tt_assert(smartlist_string_isin(sl, "noon")); tt_assert(!smartlist_string_isin(sl, "noonoon")); tt_assert(smartlist_string_isin_case(sl, "nOOn")); tt_assert(!smartlist_string_isin_case(sl, "nooNooN")); tt_assert(smartlist_string_num_isin(sl, 50)); tt_assert(!smartlist_string_num_isin(sl, 60)); /* Test smartlist_choose */ { int i; int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); tt_assert(smartlist_isin(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) allsame = 0; if (!smartlist_isin(sl, second)) allin = 0; } tt_assert(!allsame); tt_assert(allin); } SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test string_remove and remove and join_strings2 */ smartlist_split_string(sl, "Some say the Earth will end in ice and some in fire", " ", 0, 0); cp = smartlist_get(sl, 4); tt_str_op(cp, ==, "will"); smartlist_add(sl, cp); smartlist_remove(sl, cp); free(cp); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); free(cp_alloc); smartlist_string_remove(sl, "in"); cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); tt_str_op(cp_alloc, ==, "Some+say+the+Earth+fire+end+some+ice+and"); tt_int_op((int)sz, ==, 40); end: SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_free(sl); free(cp_alloc); }
/* non-unique, sorted. */ smartlist_split_string(sl2, "Ambush Anchorman Anchorman Anemias Anemias Bacon " "Crossbowmen Inhumane Insurance Knish Know Manners " "Manners Maraschinos Wombats Wombats Work", " ", 0, 0); SMARTLIST_FOREACH_JOIN(sl, char *, cp1, sl2, char *, cp2, strcmp(cp1,cp2), smartlist_add(sl3, cp2)) { tt_str_op(cp1, ==, cp2); smartlist_add(sl4, cp1); } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); SMARTLIST_FOREACH(sl3, const char *, cp, tt_assert(smartlist_isin(sl2, cp) && !smartlist_string_isin(sl, cp))); SMARTLIST_FOREACH(sl4, const char *, cp, tt_assert(smartlist_isin(sl, cp) && smartlist_string_isin(sl2, cp))); joined = smartlist_join_strings(sl3, ",", 0, NULL); tt_str_op(joined, ==, "Anemias,Anemias,Crossbowmen,Work"); free(joined); joined = smartlist_join_strings(sl4, ",", 0, NULL); tt_str_op(joined, ==, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," "Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats"); end: smartlist_free(sl4); smartlist_free(sl3);
/** Verify that circuit <b>c</b> has all of its invariants * correct. Trigger an assert if anything is invalid. */ void assert_circuit_ok(const circuit_t *c) { edge_connection_t *conn; const or_circuit_t *or_circ = NULL; const origin_circuit_t *origin_circ = NULL; tor_assert(c); tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC); tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN && c->purpose <= _CIRCUIT_PURPOSE_MAX); { /* Having a separate variable for this pleases GCC 4.2 in ways I hope I * never understand. -NM. */ circuit_t *nonconst_circ = (circuit_t*) c; if (CIRCUIT_IS_ORIGIN(c)) origin_circ = TO_ORIGIN_CIRCUIT(nonconst_circ); else or_circ = TO_OR_CIRCUIT(nonconst_circ); } if (c->n_conn) { tor_assert(!c->n_hop); if (c->n_circ_id) { /* We use the _impl variant here to make sure we don't fail on marked * circuits, which would not be returned by the regular function. */ circuit_t *c2 = circuit_get_by_circid_orconn_impl(c->n_circ_id, c->n_conn); tor_assert(c == c2); } } if (or_circ && or_circ->p_conn) { if (or_circ->p_circ_id) { /* ibid */ circuit_t *c2 = circuit_get_by_circid_orconn_impl(or_circ->p_circ_id, or_circ->p_conn); tor_assert(c == c2); } } #if 0 /* false now that rendezvous exits are attached to p_streams */ if (origin_circ) for (conn = origin_circ->p_streams; conn; conn = conn->next_stream) tor_assert(conn->_base.type == CONN_TYPE_AP); #endif if (or_circ) for (conn = or_circ->n_streams; conn; conn = conn->next_stream) tor_assert(conn->_base.type == CONN_TYPE_EXIT); tor_assert(c->deliver_window >= 0); tor_assert(c->package_window >= 0); if (c->state == CIRCUIT_STATE_OPEN) { tor_assert(!c->n_conn_onionskin); if (or_circ) { tor_assert(or_circ->n_crypto); tor_assert(or_circ->p_crypto); tor_assert(or_circ->n_digest); tor_assert(or_circ->p_digest); } } if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) { tor_assert(circuits_pending_or_conns && smartlist_isin(circuits_pending_or_conns, c)); } else { tor_assert(!circuits_pending_or_conns || !smartlist_isin(circuits_pending_or_conns, c)); } if (origin_circ && origin_circ->cpath) { assert_cpath_ok(origin_circ->cpath); } if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) { tor_assert(or_circ); if (!c->marked_for_close) { tor_assert(or_circ->rend_splice); tor_assert(or_circ->rend_splice->rend_splice == or_circ); } tor_assert(or_circ->rend_splice != or_circ); } else { tor_assert(!or_circ || !or_circ->rend_splice); } }