commit 77a5ca901f148d39973343c7916ca7fb27fab2fb Author: rl1987 rl1987@sdf.lonestar.org Date: Wed Jul 22 16:46:44 2015 +0300
Unit test dns_resolve(), dns_clip_ttl(), dns_get_expiry_ttl(). --- src/or/connection.c | 4 +- src/or/connection.h | 2 +- src/or/dns.c | 116 +++---------------- src/or/dns.h | 18 ++- src/or/dns_structs.h | 90 +++++++++++++++ src/test/include.am | 1 + src/test/test.c | 2 + src/test/test_dns.c | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 431 insertions(+), 106 deletions(-)
diff --git a/src/or/connection.c b/src/or/connection.c index ac36578..78176d3 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -654,8 +654,8 @@ connection_free_(connection_t *conn)
/** Make sure <b>conn</b> isn't in any of the global conn lists; then free it. */ -void -connection_free(connection_t *conn) +MOCK_IMPL(void, +connection_free,(connection_t *conn)) { if (!conn) return; diff --git a/src/or/connection.h b/src/or/connection.h index d0a34ec..b6ff3d7 100644 --- a/src/or/connection.h +++ b/src/or/connection.h @@ -28,7 +28,7 @@ listener_connection_t *listener_connection_new(int type, int socket_family); connection_t *connection_new(int type, int socket_family);
void connection_link_connections(connection_t *conn_a, connection_t *conn_b); -void connection_free(connection_t *conn); +MOCK_DECL(void,connection_free,(connection_t *conn)); void connection_free_all(void); void connection_about_to_close_connection(connection_t *conn); void connection_close_immediate(connection_t *conn); diff --git a/src/or/dns.c b/src/or/dns.c index db77d20..d71246d 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -11,6 +11,8 @@ * be nonblocking.) **/
+#define DNS_PRIVATE + #include "or.h" #include "circuitlist.h" #include "circuituse.h" @@ -81,9 +83,6 @@ struct evdns_request;
#endif
-/** Longest hostname we're willing to resolve. */ -#define MAX_ADDRESSLEN 256 - /** How long will we wait for an answer from the resolver before we decide * that the resolver is wedged? */ #define RESOLVE_MAX_TIMEOUT 300 @@ -102,104 +101,16 @@ static char *resolv_conf_fname = NULL; * the nameservers? Used to check whether we need to reconfigure. */ static time_t resolv_conf_mtime = 0;
-/** Linked list of connections waiting for a DNS answer. */ -typedef struct pending_connection_t { - edge_connection_t *conn; - struct pending_connection_t *next; -} pending_connection_t; - -/** Value of 'magic' field for cached_resolve_t. Used to try to catch bad - * pointers and memory stomping. */ -#define CACHED_RESOLVE_MAGIC 0x1234F00D - -/* Possible states for a cached resolve_t */ -/** We are waiting for the resolver system to tell us an answer here. - * When we get one, or when we time out, the state of this cached_resolve_t - * will become "DONE" and we'll possibly add a CACHED - * entry. This cached_resolve_t will be in the hash table so that we will - * know not to launch more requests for this addr, but rather to add more - * connections to the pending list for the addr. */ -#define CACHE_STATE_PENDING 0 -/** This used to be a pending cached_resolve_t, and we got an answer for it. - * Now we're waiting for this cached_resolve_t to expire. This should - * have no pending connections, and should not appear in the hash table. */ -#define CACHE_STATE_DONE 1 -/** We are caching an answer for this address. This should have no pending - * connections, and should appear in the hash table. */ -#define CACHE_STATE_CACHED 2 - -/** @name status values for a single DNS request. - * - * @{ */ -/** The DNS request is in progress. */ -#define RES_STATUS_INFLIGHT 1 -/** The DNS request finished and gave an answer */ -#define RES_STATUS_DONE_OK 2 -/** The DNS request finished and gave an error */ -#define RES_STATUS_DONE_ERR 3 -/**@}*/ - -/** A DNS request: possibly completed, possibly pending; cached_resolve - * structs are stored at the OR side in a hash table, and as a linked - * list from oldest to newest. - */ -typedef struct cached_resolve_t { - HT_ENTRY(cached_resolve_t) node; - uint32_t magic; /**< Must be CACHED_RESOLVE_MAGIC */ - char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */ - - union { - uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful. - * (In host order.) */ - int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */ - } result_ipv4; /**< Outcome of IPv4 lookup */ - union { - struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if - * successful */ - int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */ - } result_ipv6; /**< Outcome of IPv6 lookup, if any */ - union { - char *hostname; /** A hostname, if PTR lookup happened successfully*/ - int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */ - } result_ptr; - /** @name Status fields - * - * These take one of the RES_STATUS_* values, depending on the state - * of the corresponding lookup. - * - * @{ */ - unsigned int res_status_ipv4 : 2; - unsigned int res_status_ipv6 : 2; - unsigned int res_status_hostname : 2; - /**@}*/ - uint8_t state; /**< Is this cached entry pending/done/informative? */ - - time_t expire; /**< Remove items from cache after this time. */ - uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */ - uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */ - uint32_t ttl_hostname; /**< What TTL did the nameserver tell us? */ - /** Connections that want to know when we get an answer for this resolve. */ - pending_connection_t *pending_connections; - /** Position of this element in the heap*/ - int minheap_idx; -} cached_resolve_t; - static void purge_expired_resolves(time_t now); static void dns_found_answer(const char *address, uint8_t query_type, int dns_answer, const tor_addr_t *addr, const char *hostname, uint32_t ttl); -static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type, - const cached_resolve_t *resolve); static int launch_resolve(cached_resolve_t *resolve); static void add_wildcarded_test_address(const char *address); static int configure_nameservers(int force); static int answer_is_wildcarded(const char *ip); -static int dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, - or_circuit_t *oncirc, char **resolved_to_hostname, - int *made_connection_pending_out, - cached_resolve_t **resolve_out); static int set_exitconn_info_from_resolve(edge_connection_t *exitconn, const cached_resolve_t *resolve, char **hostname_out); @@ -367,7 +278,7 @@ dns_clip_ttl(uint32_t ttl)
/** Helper: Given a TTL from a DNS response, determine how long to hold it in * our cache. */ -static uint32_t +STATIC uint32_t dns_get_expiry_ttl(uint32_t ttl) { if (ttl < MIN_DNS_TTL) @@ -605,9 +516,9 @@ purge_expired_resolves(time_t now) * answer back along circ; otherwise, send the answer back along * <b>conn</b>'s attached circuit. */ -static void -send_resolved_cell(edge_connection_t *conn, uint8_t answer_type, - const cached_resolve_t *resolved) +MOCK_IMPL(STATIC void, +send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type, + const cached_resolve_t *resolved)) { char buf[RELAY_PAYLOAD_SIZE], *cp = buf; size_t buflen = 0; @@ -671,8 +582,9 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type, * answer back along circ; otherwise, send the answer back along * <b>conn</b>'s attached circuit. */ -static void -send_resolved_hostname_cell(edge_connection_t *conn, const char *hostname) +MOCK_IMPL(STATIC void, +send_resolved_hostname_cell,(edge_connection_t *conn, + const char *hostname)) { char buf[RELAY_PAYLOAD_SIZE]; size_t buflen; @@ -800,11 +712,11 @@ dns_resolve(edge_connection_t *exitconn) * * Set *<b>resolve_out</b> to a cached resolve, if we found one. */ -static int -dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, +MOCK_IMPL(STATIC int, +dns_resolve_impl,(edge_connection_t *exitconn, int is_resolve, or_circuit_t *oncirc, char **hostname_out, int *made_connection_pending_out, - cached_resolve_t **resolve_out) + cached_resolve_t **resolve_out)) { cached_resolve_t *resolve; cached_resolve_t search; @@ -1145,8 +1057,8 @@ connection_dns_remove(edge_connection_t *conn) * the resolve for <b>address</b> itself, and remove any cached results for * <b>address</b> from the cache. */ -void -dns_cancel_pending_resolve(const char *address) +MOCK_IMPL(void, +dns_cancel_pending_resolve,(const char *address)) { pending_connection_t *pend; cached_resolve_t search; diff --git a/src/or/dns.h b/src/or/dns.h index b13ab0f..6af7796 100644 --- a/src/or/dns.h +++ b/src/or/dns.h @@ -20,7 +20,7 @@ int dns_reset(void); void connection_dns_remove(edge_connection_t *conn); void assert_connection_edge_not_dns_pending(edge_connection_t *conn); void assert_all_pending_dns_resolves_ok(void); -void dns_cancel_pending_resolve(const char *question); +MOCK_DECL(void,dns_cancel_pending_resolve,(const char *question)); int dns_resolve(edge_connection_t *exitconn); void dns_launch_correctness_checks(void); int dns_seems_to_be_broken(void); @@ -28,5 +28,21 @@ int dns_seems_to_be_broken_for_ipv6(void); void dns_reset_correctness_checks(void); void dump_dns_mem_usage(int severity);
+#ifdef DNS_PRIVATE +#include "dns_structs.h" + +STATIC uint32_t dns_get_expiry_ttl(uint32_t ttl); + +MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn, +int is_resolve,or_circuit_t *oncirc, char **hostname_out, +int *made_connection_pending_out, cached_resolve_t **resolve_out)); + +MOCK_DECL(STATIC void,send_resolved_cell,(edge_connection_t *conn, +uint8_t answer_type,const cached_resolve_t *resolved)); + +MOCK_DECL(STATIC void,send_resolved_hostname_cell,(edge_connection_t *conn, +const char *hostname)); +#endif + #endif
diff --git a/src/or/dns_structs.h b/src/or/dns_structs.h new file mode 100644 index 0000000..bb67459 --- /dev/null +++ b/src/or/dns_structs.h @@ -0,0 +1,90 @@ +#ifndef TOR_DNS_STRUCTS_H +#define TOR_DNS_STRUCTS_H + +/** Longest hostname we're willing to resolve. */ +#define MAX_ADDRESSLEN 256 + +/** Linked list of connections waiting for a DNS answer. */ +typedef struct pending_connection_t { + edge_connection_t *conn; + struct pending_connection_t *next; +} pending_connection_t; + +/** Value of 'magic' field for cached_resolve_t. Used to try to catch bad + * pointers and memory stomping. */ +#define CACHED_RESOLVE_MAGIC 0x1234F00D + +/* Possible states for a cached resolve_t */ +/** We are waiting for the resolver system to tell us an answer here. + * When we get one, or when we time out, the state of this cached_resolve_t + * will become "DONE" and we'll possibly add a CACHED + * entry. This cached_resolve_t will be in the hash table so that we will + * know not to launch more requests for this addr, but rather to add more + * connections to the pending list for the addr. */ +#define CACHE_STATE_PENDING 0 +/** This used to be a pending cached_resolve_t, and we got an answer for it. + * Now we're waiting for this cached_resolve_t to expire. This should + * have no pending connections, and should not appear in the hash table. */ +#define CACHE_STATE_DONE 1 +/** We are caching an answer for this address. This should have no pending + * connections, and should appear in the hash table. */ +#define CACHE_STATE_CACHED 2 + +/** @name status values for a single DNS request. + * + * @{ */ +/** The DNS request is in progress. */ +#define RES_STATUS_INFLIGHT 1 +/** The DNS request finished and gave an answer */ +#define RES_STATUS_DONE_OK 2 +/** The DNS request finished and gave an error */ +#define RES_STATUS_DONE_ERR 3 +/**@}*/ + +/** A DNS request: possibly completed, possibly pending; cached_resolve + * structs are stored at the OR side in a hash table, and as a linked + * list from oldest to newest. + */ +typedef struct cached_resolve_t { + HT_ENTRY(cached_resolve_t) node; + uint32_t magic; /**< Must be CACHED_RESOLVE_MAGIC */ + char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */ + + union { + uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful. + * (In host order.) */ + int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */ + } result_ipv4; /**< Outcome of IPv4 lookup */ + union { + struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if + * successful */ + int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */ + } result_ipv6; /**< Outcome of IPv6 lookup, if any */ + union { + char *hostname; /** A hostname, if PTR lookup happened successfully*/ + int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */ + } result_ptr; + /** @name Status fields + * + * These take one of the RES_STATUS_* values, depending on the state + * of the corresponding lookup. + * + * @{ */ + unsigned int res_status_ipv4 : 2; + unsigned int res_status_ipv6 : 2; + unsigned int res_status_hostname : 2; + /**@}*/ + uint8_t state; /**< Is this cached entry pending/done/informative? */ + + time_t expire; /**< Remove items from cache after this time. */ + uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */ + uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */ + uint32_t ttl_hostname; /**< What TTL did the nameserver tell us? */ + /** Connections that want to know when we get an answer for this resolve. */ + pending_connection_t *pending_connections; + /** Position of this element in the heap*/ + int minheap_idx; +} cached_resolve_t; + +#endif + diff --git a/src/test/include.am b/src/test/include.am index 7406c84..8751533 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -90,6 +90,7 @@ src_test_test_SOURCES = \ src/test/test_threads.c \ src/test/test_util.c \ src/test/test_helpers.c \ + src/test/test_dns.c \ src/test/testing_common.c \ src/ext/tinytest.c
diff --git a/src/test/test.c b/src/test/test.c index 7ad849f..e10e260 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1158,6 +1158,7 @@ extern struct testcase_t socks_tests[]; extern struct testcase_t status_tests[]; extern struct testcase_t thread_tests[]; extern struct testcase_t util_tests[]; +extern struct testcase_t dns_tests[];
struct testgroup_t testgroups[] = { { "", test_array }, @@ -1204,6 +1205,7 @@ struct testgroup_t testgroups[] = { { "util/", util_tests }, { "util/logging/", logging_tests }, { "util/thread/", thread_tests }, + { "dns/", dns_tests }, END_OF_GROUPS };
diff --git a/src/test/test_dns.c b/src/test/test_dns.c new file mode 100644 index 0000000..9d1d9c7 --- /dev/null +++ b/src/test/test_dns.c @@ -0,0 +1,304 @@ +#include "or.h" +#include "test.h" + +#define DNS_PRIVATE + +#include "dns.h" +#include "connection.h" + +static void +test_dns_clip_ttl(void *arg) +{ + (void)arg; + + uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_TTL / 2; + + tt_int_op(dns_clip_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL); + tt_int_op(dns_clip_ttl(ttl_mid),==,ttl_mid); + tt_int_op(dns_clip_ttl(MAX_DNS_TTL + 1),==,MAX_DNS_TTL); + + done: + return; +} + +static void +test_dns_expiry_ttl(void *arg) +{ + (void)arg; + + uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_ENTRY_AGE / 2; + + tt_int_op(dns_get_expiry_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL); + tt_int_op(dns_get_expiry_ttl(ttl_mid),==,ttl_mid); + tt_int_op(dns_get_expiry_ttl(MAX_DNS_ENTRY_AGE + 1),==,MAX_DNS_ENTRY_AGE); + + done: + return; +} + +static int resolve_retval = 0; +static int resolve_made_conn_pending = 0; +static char *resolved_name = NULL; +static cached_resolve_t *cache_entry = NULL; + +static int n_fake_impl = 0; + +/** This will be our configurable substitute for <b>dns_resolve_impl</b> in + * dns.c. It will return <b>resolve_retval</b>, + * and set <b>resolve_made_conn_pending</b> to + * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b> + * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b> + * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by + * 1. + */ +STATIC int +dns_resolve_fake_impl(edge_connection_t *exitconn, int is_resolve, + or_circuit_t *oncirc, char **hostname_out, + int *made_connection_pending_out, + cached_resolve_t **resolve_out) +{ + if (made_connection_pending_out) + *made_connection_pending_out = resolve_made_conn_pending; + + if (hostname_out && resolved_name) + *hostname_out = tor_strdup(resolved_name); + + if (resolve_out && cache_entry) + *resolve_out = cache_entry; + + n_fake_impl++; + + return resolve_retval; +} + +static edge_connection_t *conn_for_resolved_cell = NULL; + +static int n_send_resolved_cell_replacement = 0; +static uint8_t last_answer_type = 0; +static cached_resolve_t *last_resolved; + +static void +send_resolved_cell_replacement(edge_connection_t *conn, uint8_t answer_type, + const cached_resolve_t *resolved) +{ + conn_for_resolved_cell = conn; + + last_answer_type = answer_type; + last_resolved = (cached_resolve_t *)resolved; + + n_send_resolved_cell_replacement++; +} + +static int n_send_resolved_hostname_cell_replacement = 0; + +static char *last_resolved_hostname = NULL; + +static void +send_resolved_hostname_cell_replacement(edge_connection_t *conn, + const char *hostname) +{ + conn_for_resolved_cell = conn; + + last_resolved_hostname = (char *)hostname; + + n_send_resolved_hostname_cell_replacement++; +} + +static int n_dns_cancel_pending_resolve_replacement = 0; + +static void +dns_cancel_pending_resolve_replacement(const char *address) +{ + n_dns_cancel_pending_resolve_replacement++; +} + +static int n_connection_free = 0; +static connection_t *last_freed_conn = NULL; + +static void +connection_free_replacement(connection_t *conn) +{ + n_connection_free++; + + last_freed_conn = conn; +} + +static void +test_dns_resolve_outer(void *arg) +{ + int retval; + int prev_n_send_resolved_hostname_cell_replacement; + int prev_n_send_resolved_cell_replacement; + int prev_n_connection_free; + cached_resolve_t *fake_resolved = tor_malloc(sizeof(cached_resolve_t)); + edge_connection_t *exitconn = tor_malloc(sizeof(edge_connection_t)); + edge_connection_t *nextconn = tor_malloc(sizeof(edge_connection_t)); + + or_circuit_t *on_circuit = tor_malloc(sizeof(or_circuit_t)); + memset(on_circuit,0,sizeof(or_circuit_t)); + on_circuit->base_.magic = OR_CIRCUIT_MAGIC; + + memset(fake_resolved,0,sizeof(cached_resolve_t)); + memset(exitconn,0,sizeof(edge_connection_t)); + memset(nextconn,0,sizeof(edge_connection_t)); + + MOCK(dns_resolve_impl,dns_resolve_fake_impl); + MOCK(send_resolved_cell,send_resolved_cell_replacement); + MOCK(send_resolved_hostname_cell,send_resolved_hostname_cell_replacement); + + /* + * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is + * EXIT_PURPOSE_RESOLVE. + * + * We want dns_resolve() to call send_resolved_hostname_cell() for a + * given exit connection (represented by edge_connection_t object) + * with a hostname it received from _impl. + */ + + prev_n_send_resolved_hostname_cell_replacement = + n_send_resolved_hostname_cell_replacement; + + exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE; + exitconn->on_circuit = &(on_circuit->base_); + + resolve_retval = 1; + resolved_name = tor_strdup("www.torproject.org"); + + retval = dns_resolve(exitconn); + + tt_int_op(retval,==,1); + tt_str_op(resolved_name,==,last_resolved_hostname); + tt_assert(conn_for_resolved_cell == exitconn); + tt_int_op(n_send_resolved_hostname_cell_replacement,==, + prev_n_send_resolved_hostname_cell_replacement + 1); + tt_assert(exitconn->on_circuit == NULL); + + last_resolved_hostname = NULL; + + /* CASE 2: dns_resolve_impl returns 1, but does not set hostname. + * Instead, it yields cached_resolve_t object. + * + * We want dns_resolve to call send_resolved_cell on exitconn with + * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl. + */ + + tor_free(resolved_name); + resolved_name = NULL; + + exitconn->on_circuit = &(on_circuit->base_); + + cache_entry = fake_resolved; + + prev_n_send_resolved_cell_replacement = + n_send_resolved_cell_replacement; + + retval = dns_resolve(exitconn); + + tt_int_op(retval,==,1); + tt_assert(conn_for_resolved_cell == exitconn); + tt_int_op(n_send_resolved_cell_replacement,==, + prev_n_send_resolved_cell_replacement + 1); + tt_assert(last_resolved == fake_resolved); + tt_int_op(last_answer_type,==,0xff); + tt_assert(exitconn->on_circuit == NULL); + + /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE + * and _impl returns 1. + * + * We want dns_resolve to prepend exitconn to n_streams linked list. + * We don't want it to send any cells about hostname being resolved. + */ + + exitconn->base_.purpose = EXIT_PURPOSE_CONNECT; + exitconn->on_circuit = &(on_circuit->base_); + + on_circuit->n_streams = nextconn; + + prev_n_send_resolved_cell_replacement = + n_send_resolved_cell_replacement; + + prev_n_send_resolved_hostname_cell_replacement = + n_send_resolved_hostname_cell_replacement; + + retval = dns_resolve(exitconn); + + tt_int_op(retval,==,1); + tt_assert(on_circuit->n_streams == exitconn); + tt_assert(exitconn->next_stream == nextconn); + tt_int_op(prev_n_send_resolved_cell_replacement,==, + n_send_resolved_cell_replacement); + tt_int_op(prev_n_send_resolved_hostname_cell_replacement,==, + n_send_resolved_hostname_cell_replacement); + + /* CASE 4: _impl returns 0. + * + * We want dns_resolve() to set exitconn state to + * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams + * linked list. + */ + + exitconn->on_circuit = &(on_circuit->base_); + + resolve_retval = 0; + + exitconn->next_stream = NULL; + on_circuit->resolving_streams = nextconn; + + retval = dns_resolve(exitconn); + + tt_int_op(retval,==,0); + tt_int_op(exitconn->base_.state,==,EXIT_CONN_STATE_RESOLVING); + tt_assert(on_circuit->resolving_streams == exitconn); + tt_assert(exitconn->next_stream == nextconn); + + /* CASE 5: _impl returns -1 when purpose of exitconn is + * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell + * on exitconn with type being RESOLVED_TYPE_ERROR. + */ + + MOCK(dns_cancel_pending_resolve,dns_cancel_pending_resolve_replacement); + MOCK(connection_free,connection_free_replacement); + + exitconn->on_circuit = &(on_circuit->base_); + exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE; + + resolve_retval = -1; + + prev_n_send_resolved_cell_replacement = + n_send_resolved_cell_replacement; + + prev_n_connection_free = n_connection_free; + + retval = dns_resolve(exitconn); + + tt_int_op(retval,==,-1); + tt_int_op(n_send_resolved_cell_replacement,==, + prev_n_send_resolved_cell_replacement + 1); + tt_int_op(last_answer_type,==,RESOLVED_TYPE_ERROR); + tt_int_op(n_dns_cancel_pending_resolve_replacement,==,1); + tt_int_op(n_connection_free,==,prev_n_connection_free + 1); + tt_assert(last_freed_conn == TO_CONN(exitconn)); + + done: + UNMOCK(dns_resolve_impl); + UNMOCK(send_resolved_cell); + UNMOCK(send_resolved_hostname_cell); + UNMOCK(dns_cancel_pending_resolve); + UNMOCK(connection_free); + tor_free(on_circuit); + tor_free(exitconn); + tor_free(nextconn); + tor_free(resolved_name); + tor_free(fake_resolved); + return; +} + +struct testcase_t dns_tests[] = { + { "clip_ttl", test_dns_clip_ttl, 0, NULL, NULL }, + { "expiry_ttl", test_dns_expiry_ttl, 0, NULL, NULL }, + { "resolve_outer", test_dns_resolve_outer, TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + +#undef DNS_PRIVATE +
tor-commits@lists.torproject.org