static void test_virtaddrmap(void *data) { /* Let's start with a bunch of random addresses. */ int ipv6, bits, iter, b; virtual_addr_conf_t cfg[2]; uint8_t bytes[16]; (void)data; tor_addr_parse(&cfg[0].addr, "64.65.0.0"); tor_addr_parse(&cfg[1].addr, "3491:c0c0::"); for (ipv6 = 0; ipv6 <= 1; ++ipv6) { for (bits = 0; bits < 18; ++bits) { tor_addr_t last_a; cfg[ipv6].bits = bits; memset(bytes, 0, sizeof(bytes)); tor_addr_copy(&last_a, &cfg[ipv6].addr); /* Generate 128 addresses with each addr/bits combination. */ for (iter = 0; iter < 128; ++iter) { tor_addr_t a; get_random_virtual_addr(&cfg[ipv6], &a); //printf("%s\n", fmt_addr(&a)); /* Make sure that the first b bits match the configured network */ tt_int_op(0, OP_EQ, tor_addr_compare_masked(&a, &cfg[ipv6].addr, bits, CMP_EXACT)); /* And track which bits have been different between pairs of * addresses */ update_difference(ipv6, bytes, &last_a, &a); } /* Now make sure all but the first 'bits' bits of bytes are true */ for (b = bits+1; b < (ipv6?128:32); ++b) { tt_assert(1 & (bytes[b/8] >> (7-(b&7)))); } } } done: ; }
static void test_pubsub_basic(void *arg) { (void)arg; foobar_subscriber_data_t subdata1 = { "hi", 0 }; foobar_subscriber_data_t subdata2 = { "wow", 0 }; const foobar_subscriber_t *sub1; const foobar_subscriber_t *sub2; foobar_event_data_t ed = { 0, "x" }; foobar_event_data_t ed2 = { 0, "y" }; sub1 = foobar_subscribe(foobar_sub1, &subdata1, SUBSCRIBE_ATSTART, 100); tt_assert(sub1); foobar_notify(&ed, 0); tt_int_op(subdata1.l, OP_EQ, 100); tt_int_op(subdata2.l, OP_EQ, 0); tt_int_op(ed.u, OP_EQ, 10); sub2 = foobar_subscribe(foobar_sub2, &subdata2, 0, 5); tt_assert(sub2); foobar_notify(&ed2, 0); tt_int_op(subdata1.l, OP_EQ, 200); tt_int_op(subdata2.l, OP_EQ, 50); tt_int_op(ed2.u, OP_EQ, 15); foobar_unsubscribe(sub1); foobar_notify(&ed, 0); tt_int_op(subdata1.l, OP_EQ, 200); tt_int_op(subdata2.l, OP_EQ, 100); tt_int_op(ed.u, OP_EQ, 15); done: foobar_clear(); }
static void NS(test_main)(void *arg) { routerset_t *set = NULL; routerset_t **setp = &set; int r; (void)arg; NS_MOCK(geoip_get_country); r = routerset_add_unknown_ccs(setp, 0); tt_ptr_op(*setp, OP_NE, NULL); tt_int_op(r, OP_EQ, 0); done: if (set != NULL) routerset_free(set); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); routerinfo_t ri; country_t country = 1; int r; const char *nickname = "foo"; (void)arg; memset(&ri, 0, sizeof(ri)); strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; r = routerset_contains_router(set, &ri, country); tt_int_op(r, OP_EQ, 4); done: routerset_free(set); }
static void test_address_tor_addr_to_ipv4n(void *ignored) { (void)ignored; tor_addr_t *a = tor_malloc_zero(sizeof(tor_addr_t)); uint32_t res; a->family = AF_INET6; res = tor_addr_to_ipv4n(a); tt_assert(!res); a->family = AF_INET; a->addr.in_addr.s_addr = 43; res = tor_addr_to_ipv4n(a); tt_assert(res); tt_int_op(res, OP_EQ, 43); done: tor_free(a); }
static void test_address_tor_addr_to_in(void *ignored) { (void)ignored; tor_addr_t *a = tor_malloc_zero(sizeof(tor_addr_t)); const struct in_addr *res; a->family = AF_INET6; res = tor_addr_to_in(a); tt_assert(!res); a->family = AF_INET; a->addr.in_addr.s_addr = 44; res = tor_addr_to_in(a); tt_assert(res); tt_int_op(res->s_addr, OP_EQ, 44); done: tor_free(a); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); extend_info_t ei; int r; const char *nickname = "foo"; (void)arg; memset(&ei, 0, sizeof(ei)); strmap_set_lc(set->names, nickname, (void *)1); strncpy(ei.nickname, nickname, sizeof(ei.nickname) - 1); ei.nickname[sizeof(ei.nickname) - 1] = '\0'; r = routerset_contains_extendinfo(set, &ei); tt_int_op(r, OP_EQ, 4); done: routerset_free(set); }
static void test_util_format_base64_decode(void *ignored) { (void)ignored; int res; int i; char *src; char *dst, *real_dst; uint8_t expected[] = {0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65}; char real_src[] = "ZXhhbXBsZQ=="; src = tor_malloc_zero(256); dst = tor_malloc_zero(1000); real_dst = tor_malloc_zero(10); for (i=0;i<256;i++) { src[i] = (char)i; } res = base64_decode(dst, 1, src, SIZE_T_CEILING); tt_int_op(res, OP_EQ, -1); res = base64_decode(dst, SIZE_T_CEILING+1, src, 10); tt_int_op(res, OP_EQ, -1); const char *s = "T3BhIG11bmRv"; res = base64_decode(dst, 9, s, strlen(s)); tt_int_op(res, OP_EQ, 9); tt_mem_op(dst, OP_EQ, "Opa mundo", 9); memset(dst, 0, 1000); res = base64_decode(dst, 100, s, strlen(s)); tt_int_op(res, OP_EQ, 9); tt_mem_op(dst, OP_EQ, "Opa mundo", 9); s = "SGVsbG8gd29ybGQ="; res = base64_decode(dst, 100, s, strlen(s)); tt_int_op(res, OP_EQ, 11); tt_mem_op(dst, OP_EQ, "Hello world", 11); res = base64_decode(real_dst, 10, real_src, 10); tt_int_op(res, OP_EQ, 7); tt_mem_op(real_dst, OP_EQ, expected, 7); done: tor_free(src); tor_free(dst); tor_free(real_dst); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); routerstatus_t rs; country_t country = 1; int r; const char *nickname = "foo"; (void)arg; memset(&rs, 0, sizeof(rs)); strmap_set_lc(set->names, nickname, (void *)1); strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; r = routerset_contains_routerstatus(set, &rs, country); tt_int_op(r, OP_EQ, 4); done: routerset_free(set); }
static void test_rend_cache_lookup_entry(void *data) { int ret; rend_data_t *mock_rend_query = NULL; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; rend_cache_entry_t *entry = NULL; rend_encoded_v2_service_descriptor_t *desc_holder = NULL; char *service_id = NULL; (void)data; rend_cache_init(); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); ret = rend_cache_lookup_entry("abababababababab", 0, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("invalid query", 2, NULL); tt_int_op(ret, OP_EQ, -EINVAL); ret = rend_cache_lookup_entry("abababababababab", 2, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("abababababababab", 4224, NULL); tt_int_op(ret, OP_EQ, -ENOENT); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_lookup_entry(service_id, 2, NULL); tt_int_op(ret, OP_EQ, 0); ret = rend_cache_lookup_entry(service_id, 2, &entry); tt_assert(entry); tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); done: rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_cache_free_all(); rend_data_free(mock_rend_query); }
/** Helper to conduct tests for populate_live_entry_guards(). This test adds some entry guards to our list, and then tests populate_live_entry_guards() to mke sure it filters them correctly. <b>num_needed</b> is the number of guard nodes we support. It's configurable to make sure we function properly with 1 or 3 guard nodes configured. */ static void populate_live_entry_guards_test_helper(int num_needed) { smartlist_t *our_nodelist = NULL; smartlist_t *live_entry_guards = smartlist_new(); const smartlist_t *all_entry_guards = get_entry_guards(); or_options_t *options = get_options_mutable(); int retval; /* Set NumEntryGuards to the provided number. */ options->NumEntryGuards = num_needed; tt_int_op(num_needed, OP_EQ, decide_num_guards(options, 0)); /* The global entry guards smartlist should be empty now. */ tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 0); /* Walk the nodelist and add all nodes as entry guards. */ our_nodelist = nodelist_get_list(); tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); tt_assert(node_tmp); } SMARTLIST_FOREACH_END(node); /* Make sure the nodes were added as entry guards. */ tt_int_op(smartlist_len(all_entry_guards), OP_EQ, NUMBER_OF_DESCRIPTORS); /* Ensure that all the possible entry guards are enough to satisfy us. */ tt_int_op(smartlist_len(all_entry_guards), OP_GE, num_needed); /* Walk the entry guard list for some sanity checking */ SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { /* Since we called add_an_entry_guard() with 'for_discovery' being False, all guards should have made_contact enabled. */ tt_int_op(entry->made_contact, OP_EQ, 1); /* Since we don't have a routerstatus, all of the entry guards are not directory servers. */ tt_int_op(entry->is_dir_cache, OP_EQ, 0); } SMARTLIST_FOREACH_END(entry);
static void test_cntev_bucket_millis_empty(void *arg) { struct timeval tvnow; (void)arg; /* 1970-01-02 00:00:42.200000 */ tvnow.tv_sec = 86400 + 42; tvnow.tv_usec = 200000; /* Bucket has not been refilled. */ tt_int_op(0, OP_EQ, bucket_millis_empty(0, 42120, 0, 100, &tvnow)); tt_int_op(0, OP_EQ, bucket_millis_empty(-10, 42120, -10, 100, &tvnow)); /* Bucket was not empty. */ tt_int_op(0, OP_EQ, bucket_millis_empty(10, 42120, 20, 100, &tvnow)); /* Bucket has been emptied 80 msec ago and has just been refilled. */ tt_int_op(80, OP_EQ, bucket_millis_empty(-20, 42120, -10, 100, &tvnow)); tt_int_op(80, OP_EQ, bucket_millis_empty(-10, 42120, 0, 100, &tvnow)); tt_int_op(80, OP_EQ, bucket_millis_empty(0, 42120, 10, 100, &tvnow)); /* Bucket has been emptied 180 msec ago, last refill was 100 msec ago * which was insufficient to make it positive, so cap msec at 100. */ tt_int_op(100, OP_EQ, bucket_millis_empty(0, 42020, 1, 100, &tvnow)); /* 1970-01-02 00:00:00:050000 */ tvnow.tv_sec = 86400; tvnow.tv_usec = 50000; /* Last emptied 30 msec before midnight, tvnow is 50 msec after * midnight, that's 80 msec in total. */ tt_int_op(80, OP_EQ, bucket_millis_empty(0, 86400000 - 30, 1, 100, &tvnow)); done: ; }
static void test_util_format_base16_decode(void *ignored) { (void)ignored; int res; int i; char *src; char *dst; src = tor_malloc_zero(256); dst = tor_malloc_zero(1000); for (i=0;i<256;i++) { src[i] = (char)i; } res = base16_decode(dst, 3, src, 3); tt_int_op(res, OP_EQ, -1); res = base16_decode(dst, 1, src, 10); tt_int_op(res, OP_EQ, -1); res = base16_decode(dst, SIZE_T_CEILING+2, src, 10); tt_int_op(res, OP_EQ, -1); res = base16_decode(dst, 1000, "", 0); tt_int_op(res, OP_EQ, 0); res = base16_decode(dst, 1000, "aabc", 4); tt_int_op(res, OP_EQ, 0); tt_mem_op(dst, OP_EQ, "\xaa\xbc", 2); res = base16_decode(dst, 1000, "aabcd", 6); tt_int_op(res, OP_EQ, -1); res = base16_decode(dst, 1000, "axxx", 4); tt_int_op(res, OP_EQ, -1); done: tor_free(src); tor_free(dst); }
static void test_address_tor_addr_to_mapped_ipv4h(void *ignored) { (void)ignored; tor_addr_t *a = tor_malloc_zero(sizeof(tor_addr_t)); uint32_t res; uint8_t toset[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 42}; a->family = AF_INET; res = tor_addr_to_mapped_ipv4h(a); tt_assert(!res); a->family = AF_INET6; memcpy(a->addr.in6_addr.s6_addr, toset, 16); res = tor_addr_to_mapped_ipv4h(a); tt_assert(res); tt_int_op(res, OP_EQ, 42); done: tor_free(a); }
/** Run unit tests for digest set code (implemented as a hashtable or as a * bloom filter) */ static void test_container_digestset(void *arg) { smartlist_t *included = smartlist_new(); char d[DIGEST_LEN]; int i; int ok = 1; int false_positives = 0; digestset_t *set = NULL; (void)arg; for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); smartlist_add(included, tor_memdup(d, DIGEST_LEN)); } set = digestset_new(1000); SMARTLIST_FOREACH(included, const char *, cp, if (digestset_contains(set, cp)) ok = 0); tt_assert(ok); SMARTLIST_FOREACH(included, const char *, cp, digestset_add(set, cp)); SMARTLIST_FOREACH(included, const char *, cp, if (!digestset_contains(set, cp)) ok = 0); tt_assert(ok); for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); if (digestset_contains(set, d)) ++false_positives; } tt_int_op(50, OP_GT, false_positives); /* Should be far lower. */ done: if (set) digestset_free(set); SMARTLIST_FOREACH(included, char *, cp, tor_free(cp)); smartlist_free(included); }
static void test_storagedir_save_labeled(void *arg) { (void)arg; char *dirname = tor_strdup(get_fname_rnd("store_dir")); storage_dir_t *d = NULL; uint8_t *inp = tor_malloc_zero(8192); config_line_t *labels = NULL; char *fname = NULL; uint8_t *saved = NULL; d = storage_dir_new(dirname, 10); tt_assert(d); crypto_rand((char *)inp, 8192); config_line_append(&labels, "Foo", "bar baz"); config_line_append(&labels, "quux", "quuzXxz"); const char expected[] = "Foo bar baz\n" "quux quuzXxz\n"; int r = storage_dir_save_labeled_to_file(d, labels, inp, 8192, &fname); tt_int_op(r, OP_EQ, 0); size_t n = 0; saved = storage_dir_read(d, fname, 1, &n); tt_assert(memchr(saved, '\0', n)); tt_str_op((char*)saved, OP_EQ, expected); /* NUL guarantees strcmp works */ tt_mem_op(saved+strlen(expected)+1, OP_EQ, inp, 8192); done: storage_dir_free(d); tor_free(dirname); tor_free(inp); tor_free(fname); config_free_lines(labels); tor_free(saved); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); int r; const char *nickname = "foo"; routerstatus_t rs; (void)arg; strmap_set_lc(set->names, nickname, (void *)1); strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; NS(mock_node).ri = NULL; NS(mock_node).rs = &rs; r = routerset_contains_node(set, &NS(mock_node)); tt_int_op(r, OP_EQ, 4); done: routerset_free(set); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); int r; const char *nickname = "foo"; routerinfo_t ri; node_t mock_node; (void)arg; strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; mock_node.ri = &ri; mock_node.rs = NULL; r = routerset_contains_node(set, &mock_node); tt_int_op(r, OP_EQ, 4); done: routerset_free(set); }
static void test_rend_cache_increment_allocation(void *data) { (void)data; // Test when the cache is not overflowing rend_cache_total_allocation = 5; rend_cache_increment_allocation(3); tt_int_op(rend_cache_total_allocation, OP_EQ, 8); // Test when there are too many allocations rend_cache_total_allocation = SIZE_MAX-1; rend_cache_increment_allocation(2); tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX); // And again rend_cache_increment_allocation(2); tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX); done: (void)0; }
static void NS(test_main)(void *arg) { int expected, actual; (void)arg; NS_MOCK(tls_get_write_overhead_ratio); NS_MOCK(we_are_hibernating); NS_MOCK(public_server_mode); NS_MOCK(router_get_my_routerinfo); expected = -1; actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); done: NS_UNMOCK(tls_get_write_overhead_ratio); NS_UNMOCK(we_are_hibernating); NS_UNMOCK(public_server_mode); NS_UNMOCK(router_get_my_routerinfo); }
/* Send an empty ESTABLISH_INTRO cell. Should fail. */ static void test_establish_intro_wrong_keytype(void *arg) { int retval; or_circuit_t *intro_circ = or_circuit_new(0,NULL); char circ_nonce[DIGEST_LEN] = {0}; (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, (uint8_t *) "", 0); expect_log_msg_containing("Empty ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
/** * Calling bridge_get_addrport() should give me the address and port * of the bridge. In this case, we sort the smartlist of bridges on * fingerprints and choose the first one. */ static void test_bridges_bridge_get_addrport(void *arg) { smartlist_t *bridgelist; const bridge_info_t *bridge; const tor_addr_port_t *addrport; helper_add_bridges_to_bridgelist(arg); bridgelist = (smartlist_t*)bridge_list_get(); tt_ptr_op(bridgelist, OP_NE, NULL); // This should be the bridge at 6.6.6.6:6666 with fingerprint // 0000000000000000000000000000000000000000 bridge = smartlist_get(bridgelist, 0); tt_ptr_op(bridge, OP_NE, NULL); addrport = bridge_get_addr_port(bridge); tt_int_op(addrport->port, OP_EQ, 6666); done: mark_bridge_list(); sweep_bridge_list(); }
static void test_replaycache_badalloc(void *arg) { replaycache_t *r = NULL; /* Negative horizon should fail */ (void)arg; r = replaycache_new(-600, 300); tt_assert(r == NULL); /* Negative interval should get adjusted to zero */ r = replaycache_new(600, -300); tt_assert(r != NULL); tt_int_op(r->scrub_interval,OP_EQ, 0); replaycache_free(r); /* Negative horizon and negative interval should still fail */ r = replaycache_new(-600, -300); tt_assert(r == NULL); done: if (r) replaycache_free(r); return; }
static void test_replaycache_future(void *arg) { replaycache_t *r = NULL; int result; time_t elapsed = 0; (void)arg; r = replaycache_new(600, 300); tt_assert(r != NULL); /* Set up like in test_replaycache_hit() */ result = replaycache_add_and_test_internal(100, r, test_buffer, strlen(test_buffer), &elapsed); tt_int_op(result,OP_EQ, 0); /* elapsed should still be 0, since it wasn't written */ tt_int_op(elapsed,OP_EQ, 0); result = replaycache_add_and_test_internal(200, r, test_buffer, strlen(test_buffer), &elapsed); tt_int_op(result,OP_EQ, 1); /* elapsed should be the time since the last hit */ tt_int_op(elapsed,OP_EQ, 100); /* * Now let's turn the clock back to get coverage on the cache entry from the * future not-supposed-to-happen case. */ result = replaycache_add_and_test_internal(150, r, test_buffer, strlen(test_buffer), &elapsed); /* We should still get a hit */ tt_int_op(result,OP_EQ, 1); /* ...but it shouldn't let us see a negative elapsed time */ tt_int_op(elapsed,OP_EQ, 0); done: if (r) replaycache_free(r); return; }
static void test_clist_maps(void *arg) { channel_t *ch1 = new_fake_channel(); channel_t *ch2 = new_fake_channel(); channel_t *ch3 = new_fake_channel(); or_circuit_t *or_c1=NULL, *or_c2=NULL; (void) arg; MOCK(circuitmux_attach_circuit, circuitmux_attach_mock); MOCK(circuitmux_detach_circuit, circuitmux_detach_mock); memset(&cam, 0, sizeof(cam)); memset(&cdm, 0, sizeof(cdm)); tt_assert(ch1); tt_assert(ch2); tt_assert(ch3); ch1->cmux = tor_malloc(1); ch2->cmux = tor_malloc(1); ch3->cmux = tor_malloc(1); or_c1 = or_circuit_new(100, ch2); tt_assert(or_c1); GOT_CMUX_ATTACH(ch2->cmux, or_c1, CELL_DIRECTION_IN); tt_int_op(or_c1->p_circ_id, OP_EQ, 100); tt_ptr_op(or_c1->p_chan, OP_EQ, ch2); or_c2 = or_circuit_new(100, ch1); tt_assert(or_c2); GOT_CMUX_ATTACH(ch1->cmux, or_c2, CELL_DIRECTION_IN); tt_int_op(or_c2->p_circ_id, OP_EQ, 100); tt_ptr_op(or_c2->p_chan, OP_EQ, ch1); circuit_set_n_circid_chan(TO_CIRCUIT(or_c1), 200, ch1); GOT_CMUX_ATTACH(ch1->cmux, or_c1, CELL_DIRECTION_OUT); circuit_set_n_circid_chan(TO_CIRCUIT(or_c2), 200, ch2); GOT_CMUX_ATTACH(ch2->cmux, or_c2, CELL_DIRECTION_OUT); tt_ptr_op(circuit_get_by_circid_channel(200, ch1), OP_EQ, TO_CIRCUIT(or_c1)); tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2)); tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1)); /* Try the same thing again, to test the "fast" path. */ tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1)); tt_assert(circuit_id_in_use_on_channel(100, ch2)); tt_assert(! circuit_id_in_use_on_channel(101, ch2)); /* Try changing the circuitid and channel of that circuit. */ circuit_set_p_circid_chan(or_c1, 500, ch3); GOT_CMUX_DETACH(ch2->cmux, TO_CIRCUIT(or_c1)); GOT_CMUX_ATTACH(ch3->cmux, TO_CIRCUIT(or_c1), CELL_DIRECTION_IN); tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, NULL); tt_assert(! circuit_id_in_use_on_channel(100, ch2)); tt_ptr_op(circuit_get_by_circid_channel(500, ch3), OP_EQ, TO_CIRCUIT(or_c1)); /* Now let's see about destroy handling. */ tt_assert(! circuit_id_in_use_on_channel(205, ch2)); tt_assert(circuit_id_in_use_on_channel(200, ch2)); channel_note_destroy_pending(ch2, 200); channel_note_destroy_pending(ch2, 205); channel_note_destroy_pending(ch1, 100); tt_assert(circuit_id_in_use_on_channel(205, ch2)) tt_assert(circuit_id_in_use_on_channel(200, ch2)); tt_assert(circuit_id_in_use_on_channel(100, ch1)); tt_assert(TO_CIRCUIT(or_c2)->n_delete_pending != 0); tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2)); tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, TO_CIRCUIT(or_c2)); /* Okay, now free ch2 and make sure that the circuit ID is STILL not * usable, because we haven't declared the destroy to be nonpending */ tt_int_op(cdm.ncalls, OP_EQ, 0); circuit_free(TO_CIRCUIT(or_c2)); or_c2 = NULL; /* prevent free */ tt_int_op(cdm.ncalls, OP_EQ, 2); memset(&cdm, 0, sizeof(cdm)); tt_assert(circuit_id_in_use_on_channel(200, ch2)); tt_assert(circuit_id_in_use_on_channel(100, ch1)); tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL); tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL); /* Now say that the destroy is nonpending */ channel_note_destroy_not_pending(ch2, 200); tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL); channel_note_destroy_not_pending(ch1, 100); tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL); tt_assert(! circuit_id_in_use_on_channel(200, ch2)); tt_assert(! circuit_id_in_use_on_channel(100, ch1)); done: if (or_c1) circuit_free(TO_CIRCUIT(or_c1)); if (or_c2) circuit_free(TO_CIRCUIT(or_c2)); if (ch1) tor_free(ch1->cmux); if (ch2) tor_free(ch2->cmux); if (ch3) tor_free(ch3->cmux); tor_free(ch1); tor_free(ch2); tor_free(ch3); UNMOCK(circuitmux_attach_circuit); UNMOCK(circuitmux_detach_circuit); }
static void test_pick_circid(void *arg) { bitarray_t *ba = NULL; channel_t *chan1, *chan2; circid_t circid; int i; (void) arg; chan1 = tor_malloc_zero(sizeof(channel_t)); chan2 = tor_malloc_zero(sizeof(channel_t)); chan2->wide_circ_ids = 1; chan1->circ_id_type = CIRC_ID_TYPE_NEITHER; tt_int_op(0, OP_EQ, get_unique_circ_id_by_chan(chan1)); /* Basic tests, with no collisions */ chan1->circ_id_type = CIRC_ID_TYPE_LOWER; for (i = 0; i < 50; ++i) { circid = get_unique_circ_id_by_chan(chan1); tt_uint_op(0, OP_LT, circid); tt_uint_op(circid, OP_LT, (1<<15)); } chan1->circ_id_type = CIRC_ID_TYPE_HIGHER; for (i = 0; i < 50; ++i) { circid = get_unique_circ_id_by_chan(chan1); tt_uint_op((1<<15), OP_LT, circid); tt_uint_op(circid, OP_LT, (1<<16)); } chan2->circ_id_type = CIRC_ID_TYPE_LOWER; for (i = 0; i < 50; ++i) { circid = get_unique_circ_id_by_chan(chan2); tt_uint_op(0, OP_LT, circid); tt_uint_op(circid, OP_LT, (1u<<31)); } chan2->circ_id_type = CIRC_ID_TYPE_HIGHER; for (i = 0; i < 50; ++i) { circid = get_unique_circ_id_by_chan(chan2); tt_uint_op((1u<<31), OP_LT, circid); } /* Now make sure that we can behave well when we are full up on circuits */ chan1->circ_id_type = CIRC_ID_TYPE_LOWER; chan2->circ_id_type = CIRC_ID_TYPE_LOWER; chan1->wide_circ_ids = chan2->wide_circ_ids = 0; ba = bitarray_init_zero((1<<15)); for (i = 0; i < (1<<15); ++i) { circid = get_unique_circ_id_by_chan(chan1); if (circid == 0) { tt_int_op(i, OP_GT, (1<<14)); break; } tt_uint_op(circid, OP_LT, (1<<15)); tt_assert(! bitarray_is_set(ba, circid)); bitarray_set(ba, circid); channel_mark_circid_unusable(chan1, circid); } tt_int_op(i, OP_LT, (1<<15)); /* Make sure that being full on chan1 does not interfere with chan2 */ for (i = 0; i < 100; ++i) { circid = get_unique_circ_id_by_chan(chan2); tt_uint_op(circid, OP_GT, 0); tt_uint_op(circid, OP_LT, (1<<15)); channel_mark_circid_unusable(chan2, circid); } done: tor_free(chan1); tor_free(chan2); bitarray_free(ba); circuit_free_all(); }
static void test_rend_token_maps(void *arg) { or_circuit_t *c1, *c2, *c3, *c4; const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y"; const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it "; const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care."; /* -- Adapted from a quote by Fredrik Lundh. */ (void)arg; (void)tok1; //xxxx c1 = or_circuit_new(0, NULL); c2 = or_circuit_new(0, NULL); c3 = or_circuit_new(0, NULL); c4 = or_circuit_new(0, NULL); /* Make sure we really filled up the tok* variables */ tt_int_op(tok1[REND_TOKEN_LEN-1], OP_EQ, 'y'); tt_int_op(tok2[REND_TOKEN_LEN-1], OP_EQ, ' '); tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.'); /* No maps; nothing there. */ tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok1)); tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok1)); circuit_set_rendezvous_cookie(c1, tok1); circuit_set_intro_point_digest(c2, tok2); tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok3)); tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok3)); tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok2)); tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok1)); /* Without purpose set, we don't get the circuits */ tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok1)); tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok2)); c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING; c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT; /* Okay, make sure they show up now. */ tt_ptr_op(c1, OP_EQ, circuit_get_rendezvous(tok1)); tt_ptr_op(c2, OP_EQ, circuit_get_intro_point(tok2)); /* Two items at the same place with the same token. */ c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING; circuit_set_rendezvous_cookie(c3, tok2); tt_ptr_op(c2, OP_EQ, circuit_get_intro_point(tok2)); tt_ptr_op(c3, OP_EQ, circuit_get_rendezvous(tok2)); /* Marking a circuit makes it not get returned any more */ circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED); tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok1)); circuit_free(TO_CIRCUIT(c1)); c1 = NULL; /* Freeing a circuit makes it not get returned any more. */ circuit_free(TO_CIRCUIT(c2)); c2 = NULL; tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok2)); /* c3 -- are you still there? */ tt_ptr_op(c3, OP_EQ, circuit_get_rendezvous(tok2)); /* Change its cookie. This never happens in Tor per se, but hey. */ c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT; circuit_set_intro_point_digest(c3, tok3); tt_ptr_op(NULL, OP_EQ, circuit_get_rendezvous(tok2)); tt_ptr_op(c3, OP_EQ, circuit_get_intro_point(tok3)); /* Now replace c3 with c4. */ c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT; circuit_set_intro_point_digest(c4, tok3); tt_ptr_op(c4, OP_EQ, circuit_get_intro_point(tok3)); tt_ptr_op(c3->rendinfo, OP_EQ, NULL); tt_ptr_op(c4->rendinfo, OP_NE, NULL); tt_mem_op(c4->rendinfo, OP_EQ, tok3, REND_TOKEN_LEN); /* Now clear c4's cookie. */ circuit_set_intro_point_digest(c4, NULL); tt_ptr_op(c4->rendinfo, OP_EQ, NULL); tt_ptr_op(NULL, OP_EQ, circuit_get_intro_point(tok3)); done: if (c1) circuit_free(TO_CIRCUIT(c1)); if (c2) circuit_free(TO_CIRCUIT(c2)); if (c3) circuit_free(TO_CIRCUIT(c3)); if (c4) circuit_free(TO_CIRCUIT(c4)); }
/** Run unit tests for buffers.c */ static void test_oom_streambuf(void *arg) { or_options_t *options = get_options_mutable(); circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL; struct timeval tv = { 1389641159, 0 }; uint32_t tvms; int i; smartlist_t *edgeconns = smartlist_new(); (void) arg; MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); /* Far too low for real life. */ options->MaxMemInQueues = 81*packed_cell_mem_cost() + 4096 * 34; options->CellStatistics = 0; tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We don't start out OOM. */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* Start all circuits with a bit of data queued in cells */ tv.tv_usec = 500*1000; /* go halfway into the second. */ tor_gettimeofday_cache_set(&tv); c1 = dummy_or_circuit_new(10,10); tv.tv_usec = 510*1000; tor_gettimeofday_cache_set(&tv); c2 = dummy_origin_circuit_new(20); tv.tv_usec = 520*1000; tor_gettimeofday_cache_set(&tv); c3 = dummy_or_circuit_new(20,20); tv.tv_usec = 530*1000; tor_gettimeofday_cache_set(&tv); c4 = dummy_or_circuit_new(0,0); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 80); tv.tv_usec = 600*1000; tor_gettimeofday_cache_set(&tv); /* Add some connections to c1...c4. */ for (i = 0; i < 4; ++i) { edge_connection_t *ec; /* link it to a circuit */ tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c1, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c2, CONN_TYPE_AP, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); /* Yes, 4 twice*/ tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); smartlist_add(edgeconns, ec); tt_assert(ec); } tv.tv_sec += 1; tv.tv_usec = 0; tvms = (uint32_t) tv_to_msec(&tv); tt_int_op(circuit_max_queued_cell_age(c1, tvms), OP_EQ, 500); tt_int_op(circuit_max_queued_cell_age(c2, tvms), OP_EQ, 490); tt_int_op(circuit_max_queued_cell_age(c3, tvms), OP_EQ, 480); tt_int_op(circuit_max_queued_cell_age(c4, tvms), OP_EQ, 0); tt_int_op(circuit_max_queued_data_age(c1, tvms), OP_EQ, 390); tt_int_op(circuit_max_queued_data_age(c2, tvms), OP_EQ, 380); tt_int_op(circuit_max_queued_data_age(c3, tvms), OP_EQ, 0); tt_int_op(circuit_max_queued_data_age(c4, tvms), OP_EQ, 370); tt_int_op(circuit_max_queued_item_age(c1, tvms), OP_EQ, 500); tt_int_op(circuit_max_queued_item_age(c2, tvms), OP_EQ, 490); tt_int_op(circuit_max_queued_item_age(c3, tvms), OP_EQ, 480); tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 370); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 80); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*16*2); /* Now give c4 a very old buffer of modest size */ { edge_connection_t *ec; tv.tv_sec -= 1; tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); } tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2); tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 1000); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* And run over the limit. */ tv.tv_usec = 800*1000; tor_gettimeofday_cache_set(&tv); c5 = dummy_or_circuit_new(0,5); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 85); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ /* C4 should have died. */ tt_assert(! c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(c4->marked_for_close); tt_assert(! c5->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 85); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*8*2); done: circuit_free(c1); circuit_free(c2); circuit_free(c3); circuit_free(c4); circuit_free(c5); SMARTLIST_FOREACH(edgeconns, edge_connection_t *, ec, connection_free_(TO_CONN(ec))); smartlist_free(edgeconns); UNMOCK(circuit_mark_for_close_); }
/** Run unit tests for buffers.c */ static void test_oom_circbuf(void *arg) { or_options_t *options = get_options_mutable(); circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL; struct timeval tv = { 1389631048, 0 }; (void) arg; MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); /* Far too low for real life. */ options->MaxMemInQueues = 256*packed_cell_mem_cost(); options->CellStatistics = 0; tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We don't start out OOM. */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* Now we're going to fake up some circuits and get them added to the global circuit list. */ tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); c1 = dummy_origin_circuit_new(30); tv.tv_usec = 10*1000; tor_gettimeofday_cache_set(&tv); c2 = dummy_or_circuit_new(20, 20); tt_int_op(packed_cell_mem_cost(), OP_EQ, sizeof(packed_cell_t)); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 70); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We are still not OOM */ tv.tv_usec = 20*1000; tor_gettimeofday_cache_set(&tv); c3 = dummy_or_circuit_new(100, 85); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We are still not OOM */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 255); tv.tv_usec = 30*1000; tor_gettimeofday_cache_set(&tv); /* Adding this cell will trigger our OOM handler. */ c4 = dummy_or_circuit_new(2, 0); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 257); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ tt_assert(c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(! c4->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * (257 - 30)); circuit_free(c1); tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); /* go back in time */ c1 = dummy_or_circuit_new(90, 0); tv.tv_usec = 40*1000; /* go back to the future */ tor_gettimeofday_cache_set(&tv); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ tt_assert(c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(! c4->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * (257 - 30)); done: circuit_free(c1); circuit_free(c2); circuit_free(c3); circuit_free(c4); UNMOCK(circuit_mark_for_close_); }
static void test_util_format_base64_encode(void *ignored) { (void)ignored; int res; int i; char *src; char *dst; src = tor_malloc_zero(256); dst = tor_malloc_zero(1000); for (i=0;i<256;i++) { src[i] = (char)i; } res = base64_encode(NULL, 1, src, 1, 0); tt_int_op(res, OP_EQ, -1); res = base64_encode(dst, 1, NULL, 1, 0); tt_int_op(res, OP_EQ, -1); res = base64_encode(dst, 1, src, 10, 0); tt_int_op(res, OP_EQ, -1); res = base64_encode(dst, SSIZE_MAX-1, src, 1, 0); tt_int_op(res, OP_EQ, -1); res = base64_encode(dst, SSIZE_MAX-1, src, 10, 0); tt_int_op(res, OP_EQ, -1); res = base64_encode(dst, 1000, src, 256, 0); tt_int_op(res, OP_EQ, 344); tt_str_op(dst, OP_EQ, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh" "8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH" "SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3" "BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeY" "mZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wM" "HCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp" "6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="); res = base64_encode(dst, 1000, src, 256, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 350); tt_str_op(dst, OP_EQ, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v\n" "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f\n" "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P\n" "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/\n" "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v\n" "8PHy8/T19vf4+fr7/P3+/w==\n"); res = base64_encode(dst, 1000, src+1, 255, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 346); for (i = 0;i<50;i++) { src[i] = 0; } src[50] = 255; src[51] = 255; src[52] = 255; src[53] = 255; res = base64_encode(dst, 1000, src, 54, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 74); res = base64_encode(dst, 1000, src+1, 53, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 74); res = base64_encode(dst, 1000, src+2, 52, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 74); res = base64_encode(dst, 1000, src+3, 51, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 70); res = base64_encode(dst, 1000, src+4, 50, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 70); res = base64_encode(dst, 1000, src+5, 49, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 70); res = base64_encode(dst, 1000, src+6, 48, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 65); res = base64_encode(dst, 1000, src+7, 47, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 65); res = base64_encode(dst, 1000, src+8, 46, BASE64_ENCODE_MULTILINE); tt_int_op(res, OP_EQ, 65); done: tor_free(src); tor_free(dst); }