mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge remote-tracking branch 'chelseakomlo/circuituse'
This commit is contained in:
commit
f96f4c0e42
7
changes/ticket18873
Normal file
7
changes/ticket18873
Normal file
@ -0,0 +1,7 @@
|
||||
o Code simplification and refactoring:
|
||||
- Extracted dummy_origin_circuit_new so it can be used by other test
|
||||
functions.
|
||||
- Refactor circuit_predict_and_launch_new for readability and testability.
|
||||
- Added unit tests for extracted functions.
|
||||
- Extracted magic numbers in circuituse.c into defined variables.
|
||||
- Refactor circuit_is_available_for_use to remove unnecessary check
|
@ -1508,9 +1508,9 @@ circuit_get_unhandled_ports(time_t now)
|
||||
* If we're returning 0, set need_uptime and need_capacity to
|
||||
* indicate any requirements that the unhandled ports have.
|
||||
*/
|
||||
int
|
||||
circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
|
||||
int *need_capacity)
|
||||
MOCK_IMPL(int,
|
||||
circuit_all_predicted_ports_handled, (time_t now, int *need_uptime,
|
||||
int *need_capacity))
|
||||
{
|
||||
int i, enough;
|
||||
uint16_t *port;
|
||||
|
@ -40,8 +40,9 @@ int onionskin_answer(or_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell,
|
||||
const char *keys,
|
||||
const uint8_t *rend_circ_nonce);
|
||||
int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
|
||||
int *need_capacity);
|
||||
MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
|
||||
int *need_uptime,
|
||||
int *need_capacity));
|
||||
|
||||
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
|
@ -1022,8 +1022,117 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
|
||||
/** Don't keep more than this many unused open circuits around. */
|
||||
#define MAX_UNUSED_OPEN_CIRCUITS 14
|
||||
|
||||
/** Figure out how many circuits we have open that are clean. Make
|
||||
* sure it's enough for all the upcoming behaviors we predict we'll have.
|
||||
/* Return true if a circuit is available for use, meaning that it is open,
|
||||
* clean, usable for new multi-hop connections, and a general purpose origin
|
||||
* circuit.
|
||||
* Accept any kind of circuit, return false if the above conditions are not
|
||||
* met. */
|
||||
STATIC int
|
||||
circuit_is_available_for_use(const circuit_t *circ)
|
||||
{
|
||||
const origin_circuit_t *origin_circ;
|
||||
cpath_build_state_t *build_state;
|
||||
|
||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||
return 0; /* We first filter out only origin circuits before doing the
|
||||
following checks. */
|
||||
if (circ->marked_for_close)
|
||||
return 0; /* Don't mess with marked circs */
|
||||
if (circ->timestamp_dirty)
|
||||
return 0; /* Only count clean circs */
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
|
||||
return 0; /* We only pay attention to general purpose circuits.
|
||||
General purpose circuits are always origin circuits. */
|
||||
|
||||
origin_circ = CONST_TO_ORIGIN_CIRCUIT(circ);
|
||||
if (origin_circ->unusable_for_new_conns)
|
||||
return 0;
|
||||
|
||||
build_state = origin_circ->build_state;
|
||||
if (build_state->onehop_tunnel)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return true if we need any more exit circuits.
|
||||
* needs_uptime and needs_capacity are set only if we need more exit circuits.
|
||||
* Check if we know of a port that's been requested recently and no circuit
|
||||
* is currently available that can handle it. */
|
||||
STATIC int
|
||||
needs_exit_circuits(time_t now, int *needs_uptime, int *needs_capacity)
|
||||
{
|
||||
return (!circuit_all_predicted_ports_handled(now, needs_uptime,
|
||||
needs_capacity) &&
|
||||
router_have_consensus_path() == CONSENSUS_PATH_EXIT);
|
||||
}
|
||||
|
||||
/* Hidden services need at least this many internal circuits */
|
||||
#define SUFFICIENT_UPTIME_INTERNAL_HS_SERVERS 3
|
||||
|
||||
/* Return true if we need any more hidden service server circuits.
|
||||
* HS servers only need an internal circuit. */
|
||||
STATIC int
|
||||
needs_hs_server_circuits(int num_uptime_internal)
|
||||
{
|
||||
return (num_rend_services() &&
|
||||
num_uptime_internal < SUFFICIENT_UPTIME_INTERNAL_HS_SERVERS &&
|
||||
router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN);
|
||||
}
|
||||
|
||||
/* We need at least this many internal circuits for hidden service clients */
|
||||
#define SUFFICIENT_INTERNAL_HS_CLIENTS 3
|
||||
|
||||
/* We need at least this much uptime for internal circuits for hidden service
|
||||
* clients */
|
||||
#define SUFFICIENT_UPTIME_INTERNAL_HS_CLIENTS 2
|
||||
|
||||
/* Return true if we need any more hidden service client circuits.
|
||||
* HS clients only need an internal circuit. */
|
||||
STATIC int
|
||||
needs_hs_client_circuits(time_t now, int *needs_uptime, int *needs_capacity,
|
||||
int num_internal, int num_uptime_internal)
|
||||
{
|
||||
int used_internal_recently = rep_hist_get_predicted_internal(now,
|
||||
needs_uptime,
|
||||
needs_capacity);
|
||||
int requires_uptime = num_uptime_internal <
|
||||
SUFFICIENT_UPTIME_INTERNAL_HS_CLIENTS &&
|
||||
needs_uptime;
|
||||
|
||||
return (used_internal_recently &&
|
||||
(requires_uptime || num_internal < SUFFICIENT_INTERNAL_HS_CLIENTS) &&
|
||||
router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN);
|
||||
}
|
||||
|
||||
/* The minimum number of open slots we should keep in order to preemptively
|
||||
* build circuits. */
|
||||
#define CBT_MIN_REMAINING_PREEMPTIVE_CIRCUITS 2
|
||||
|
||||
/* Check to see if we need more circuits to have a good build timeout. However,
|
||||
* leave a couple slots open so that we can still build circuits preemptively
|
||||
* as needed. */
|
||||
#define CBT_MAX_UNUSED_OPEN_CIRCUITS (MAX_UNUSED_OPEN_CIRCUITS - \
|
||||
CBT_MIN_REMAINING_PREEMPTIVE_CIRCUITS)
|
||||
|
||||
/* Return true if we need more circuits for a good build timeout.
|
||||
* XXXX make the assumption that build timeout streams should be
|
||||
* created whenever we can build internal circuits. */
|
||||
STATIC int
|
||||
needs_circuits_for_build(int num)
|
||||
{
|
||||
if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN) {
|
||||
if (num < CBT_MAX_UNUSED_OPEN_CIRCUITS &&
|
||||
!circuit_build_times_disabled() &&
|
||||
circuit_build_times_needs_circuits_now(get_circuit_build_times())) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Determine how many circuits we have open that are clean,
|
||||
* Make sure it's enough for all the upcoming behaviors we predict we'll have.
|
||||
* But put an upper bound on the total number of circuits.
|
||||
*/
|
||||
static void
|
||||
@ -1035,25 +1144,14 @@ circuit_predict_and_launch_new(void)
|
||||
time_t now = time(NULL);
|
||||
int flags = 0;
|
||||
|
||||
/* First, count how many of each type of circuit we have already. */
|
||||
/* Count how many of each type of circuit we currently have. */
|
||||
SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
|
||||
cpath_build_state_t *build_state;
|
||||
origin_circuit_t *origin_circ;
|
||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||
continue;
|
||||
if (circ->marked_for_close)
|
||||
continue; /* don't mess with marked circs */
|
||||
if (circ->timestamp_dirty)
|
||||
continue; /* only count clean circs */
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
|
||||
continue; /* only pay attention to general-purpose circs */
|
||||
origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||
if (origin_circ->unusable_for_new_conns)
|
||||
continue;
|
||||
build_state = origin_circ->build_state;
|
||||
if (build_state->onehop_tunnel)
|
||||
if (!circuit_is_available_for_use(circ))
|
||||
continue;
|
||||
|
||||
num++;
|
||||
|
||||
cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
if (build_state->is_internal)
|
||||
num_internal++;
|
||||
if (build_state->need_uptime && build_state->is_internal)
|
||||
@ -1063,19 +1161,14 @@ circuit_predict_and_launch_new(void)
|
||||
|
||||
/* If that's enough, then stop now. */
|
||||
if (num >= MAX_UNUSED_OPEN_CIRCUITS)
|
||||
return; /* we already have many, making more probably will hurt */
|
||||
return;
|
||||
|
||||
/* Second, see if we need any more exit circuits. */
|
||||
/* check if we know of a port that's been requested recently
|
||||
* and no circuit is currently available that can handle it.
|
||||
* Exits (obviously) require an exit circuit. */
|
||||
if (!circuit_all_predicted_ports_handled(now, &port_needs_uptime,
|
||||
&port_needs_capacity)
|
||||
&& router_have_consensus_path() == CONSENSUS_PATH_EXIT) {
|
||||
if (needs_exit_circuits(now, &port_needs_uptime, &port_needs_capacity)) {
|
||||
if (port_needs_uptime)
|
||||
flags |= CIRCLAUNCH_NEED_UPTIME;
|
||||
if (port_needs_capacity)
|
||||
flags |= CIRCLAUNCH_NEED_CAPACITY;
|
||||
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs (%d internal), need another exit circ.",
|
||||
num, num_internal);
|
||||
@ -1083,12 +1176,10 @@ circuit_predict_and_launch_new(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Third, see if we need any more hidden service (server) circuits.
|
||||
* HS servers only need an internal circuit. */
|
||||
if (num_rend_services() && num_uptime_internal < 3
|
||||
&& router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN) {
|
||||
if (needs_hs_server_circuits(num_uptime_internal)) {
|
||||
flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME |
|
||||
CIRCLAUNCH_IS_INTERNAL);
|
||||
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs (%d internal), need another internal "
|
||||
"circ for my hidden service.",
|
||||
@ -1097,18 +1188,16 @@ circuit_predict_and_launch_new(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fourth, see if we need any more hidden service (client) circuits.
|
||||
* HS clients only need an internal circuit. */
|
||||
if (rep_hist_get_predicted_internal(now, &hidserv_needs_uptime,
|
||||
&hidserv_needs_capacity) &&
|
||||
((num_uptime_internal<2 && hidserv_needs_uptime) ||
|
||||
num_internal<3)
|
||||
&& router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN) {
|
||||
if (needs_hs_client_circuits(now, &hidserv_needs_uptime,
|
||||
&hidserv_needs_capacity,
|
||||
num_internal, num_uptime_internal))
|
||||
{
|
||||
if (hidserv_needs_uptime)
|
||||
flags |= CIRCLAUNCH_NEED_UPTIME;
|
||||
if (hidserv_needs_capacity)
|
||||
flags |= CIRCLAUNCH_NEED_CAPACITY;
|
||||
flags |= CIRCLAUNCH_IS_INTERNAL;
|
||||
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs (%d uptime-internal, %d internal), need"
|
||||
" another hidden service circ.",
|
||||
@ -1117,28 +1206,19 @@ circuit_predict_and_launch_new(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finally, check to see if we still need more circuits to learn
|
||||
* a good build timeout. But if we're close to our max number we
|
||||
* want, don't do another -- we want to leave a few slots open so
|
||||
* we can still build circuits preemptively as needed.
|
||||
* XXXX make the assumption that build timeout streams should be
|
||||
* created whenever we can build internal circuits. */
|
||||
if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN) {
|
||||
if (num < MAX_UNUSED_OPEN_CIRCUITS-2 &&
|
||||
! circuit_build_times_disabled() &&
|
||||
circuit_build_times_needs_circuits_now(get_circuit_build_times())) {
|
||||
if (needs_circuits_for_build(num)) {
|
||||
flags = CIRCLAUNCH_NEED_CAPACITY;
|
||||
/* if there are no exits in the consensus, make timeout
|
||||
* circuits internal */
|
||||
if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL)
|
||||
flags |= CIRCLAUNCH_IS_INTERNAL;
|
||||
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs need another buildtime test circ.", num);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Build a new test circuit every 5 minutes */
|
||||
#define TESTING_CIRCUIT_INTERVAL 300
|
||||
|
@ -59,5 +59,25 @@ int hostname_in_track_host_exits(const or_options_t *options,
|
||||
const char *address);
|
||||
void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
/* Used only by circuituse.c and test_circuituse.c */
|
||||
|
||||
STATIC int circuit_is_available_for_use(const circuit_t *circ);
|
||||
|
||||
STATIC int needs_exit_circuits(time_t now,
|
||||
int *port_needs_uptime,
|
||||
int *port_needs_capacity);
|
||||
STATIC int needs_hs_server_circuits(int num_uptime_internal);
|
||||
|
||||
STATIC int needs_hs_client_circuits(time_t now,
|
||||
int *needs_uptime,
|
||||
int *needs_capacity,
|
||||
int num_internal,
|
||||
int num_uptime_internal);
|
||||
|
||||
STATIC int needs_circuits_for_build(int num);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1569,8 +1569,8 @@ router_have_minimum_dir_info(void)
|
||||
* this can cause router_have_consensus_path() to be set to
|
||||
* CONSENSUS_PATH_EXIT, even if there are no nodes with accept exit policies.
|
||||
*/
|
||||
consensus_path_type_t
|
||||
router_have_consensus_path(void)
|
||||
MOCK_IMPL(consensus_path_type_t,
|
||||
router_have_consensus_path, (void))
|
||||
{
|
||||
return have_consensus_path;
|
||||
}
|
||||
|
@ -118,7 +118,8 @@ typedef enum {
|
||||
* create exit and internal paths, circuits, streams, ... */
|
||||
CONSENSUS_PATH_EXIT = 1
|
||||
} consensus_path_type_t;
|
||||
consensus_path_type_t router_have_consensus_path(void);
|
||||
|
||||
MOCK_DECL(consensus_path_type_t, router_have_consensus_path, (void));
|
||||
|
||||
void router_dir_info_changed(void);
|
||||
const char *get_dir_info_status_string(void);
|
||||
|
@ -80,6 +80,7 @@ src_test_test_SOURCES = \
|
||||
src/test/test_checkdir.c \
|
||||
src/test/test_circuitlist.c \
|
||||
src/test/test_circuitmux.c \
|
||||
src/test/test_circuituse.c \
|
||||
src/test/test_compat_libevent.c \
|
||||
src/test/test_config.c \
|
||||
src/test/test_connection.c \
|
||||
|
@ -1190,6 +1190,7 @@ struct testgroup_t testgroups[] = {
|
||||
{ "checkdir/", checkdir_tests },
|
||||
{ "circuitlist/", circuitlist_tests },
|
||||
{ "circuitmux/", circuitmux_tests },
|
||||
{ "circuituse/", circuituse_tests },
|
||||
{ "compat/libevent/", compat_libevent_tests },
|
||||
{ "config/", config_tests },
|
||||
{ "connection/", connection_tests },
|
||||
|
@ -185,6 +185,7 @@ extern struct testcase_t channeltls_tests[];
|
||||
extern struct testcase_t checkdir_tests[];
|
||||
extern struct testcase_t circuitlist_tests[];
|
||||
extern struct testcase_t circuitmux_tests[];
|
||||
extern struct testcase_t circuituse_tests[];
|
||||
extern struct testcase_t compat_libevent_tests[];
|
||||
extern struct testcase_t config_tests[];
|
||||
extern struct testcase_t connection_tests[];
|
||||
|
302
src/test/test_circuituse.c
Normal file
302
src/test/test_circuituse.c
Normal file
@ -0,0 +1,302 @@
|
||||
/* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2016, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#include "or.h"
|
||||
#include "test.h"
|
||||
#include "test_helpers.h"
|
||||
#include "config.h"
|
||||
#include "circuitlist.h"
|
||||
#include "circuituse.h"
|
||||
#include "circuitbuild.h"
|
||||
#include "nodelist.h"
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_when_marked_for_close(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = tor_malloc(sizeof(circuit_t));
|
||||
circ->marked_for_close = 1;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_when_timestamp_dirty(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = tor_malloc(sizeof(circuit_t));
|
||||
circ->timestamp_dirty = 1;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_for_non_general_purpose(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = tor_malloc(sizeof(circuit_t));
|
||||
circ->purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_for_non_general_origin(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = tor_malloc(sizeof(circuit_t));
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_for_non_origin_purpose(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = tor_malloc(sizeof(circuit_t));
|
||||
circ->purpose = CIRCUIT_PURPOSE_OR;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_ret_false_unusable_for_new_conns(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = dummy_origin_circuit_new(30);
|
||||
mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_returns_false_for_onehop_tunnel(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = dummy_origin_circuit_new(30);
|
||||
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
|
||||
oc->build_state = tor_malloc(sizeof(cpath_build_state_t));
|
||||
oc->build_state->onehop_tunnel = 1;
|
||||
|
||||
tt_int_op(0, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_circuit_is_available_for_use_returns_true_for_clean_circuit(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
circuit_t *circ = dummy_origin_circuit_new(30);
|
||||
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
|
||||
oc->build_state = tor_malloc(sizeof(cpath_build_state_t));
|
||||
oc->build_state->onehop_tunnel = 0;
|
||||
|
||||
tt_int_op(1, ==, circuit_is_available_for_use(circ));
|
||||
|
||||
done:
|
||||
tor_free(circ);
|
||||
}
|
||||
|
||||
static int
|
||||
mock_circuit_all_predicted_ports_handled(time_t now,
|
||||
int *need_uptime,
|
||||
int *need_capacity)
|
||||
{
|
||||
(void)now;
|
||||
|
||||
if (need_uptime && need_capacity)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static consensus_path_type_t
|
||||
mock_router_have_unknown_consensus_path(void)
|
||||
{
|
||||
return CONSENSUS_PATH_UNKNOWN;
|
||||
}
|
||||
|
||||
static consensus_path_type_t
|
||||
mock_router_have_exit_consensus_path(void)
|
||||
{
|
||||
return CONSENSUS_PATH_EXIT;
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_exit_circuits_ret_false_for_predicted_ports_and_path(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
MOCK(circuit_all_predicted_ports_handled,
|
||||
mock_circuit_all_predicted_ports_handled);
|
||||
int needs_uptime = 1;
|
||||
int needs_capacity = 0;
|
||||
|
||||
time_t now = time(NULL);
|
||||
tt_int_op(0, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity));
|
||||
|
||||
done:
|
||||
UNMOCK(circuit_all_predicted_ports_handled);
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_exit_circuits_ret_false_for_non_exit_consensus_path(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
MOCK(circuit_all_predicted_ports_handled,
|
||||
mock_circuit_all_predicted_ports_handled);
|
||||
int needs_uptime = 1;
|
||||
int needs_capacity = 1;
|
||||
MOCK(router_have_consensus_path, mock_router_have_unknown_consensus_path);
|
||||
|
||||
time_t now = time(NULL);
|
||||
tt_int_op(0, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity));
|
||||
|
||||
done:
|
||||
UNMOCK(circuit_all_predicted_ports_handled);
|
||||
UNMOCK(router_have_consensus_path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_exit_circuits_ret_true_for_predicted_ports_and_path(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
MOCK(circuit_all_predicted_ports_handled,
|
||||
mock_circuit_all_predicted_ports_handled);
|
||||
int needs_uptime = 1;
|
||||
int needs_capacity = 1;
|
||||
MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path);
|
||||
|
||||
time_t now = time(NULL);
|
||||
tt_int_op(1, ==, needs_exit_circuits(now, &needs_uptime, &needs_capacity));
|
||||
|
||||
done:
|
||||
UNMOCK(circuit_all_predicted_ports_handled);
|
||||
UNMOCK(router_have_consensus_path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_circuits_for_build_ret_false_consensus_path_unknown(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
MOCK(router_have_consensus_path, mock_router_have_unknown_consensus_path);
|
||||
tt_int_op(0, ==, needs_circuits_for_build(0));
|
||||
done: ;
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_circuits_for_build_ret_false_if_num_less_than_max(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path);
|
||||
tt_int_op(0, ==, needs_circuits_for_build(13));
|
||||
done:
|
||||
UNMOCK(router_have_consensus_path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_needs_circuits_for_build_returns_true_when_more_are_needed(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
MOCK(router_have_consensus_path, mock_router_have_exit_consensus_path);
|
||||
tt_int_op(1, ==, needs_circuits_for_build(0));
|
||||
done:
|
||||
UNMOCK(router_have_consensus_path);
|
||||
}
|
||||
|
||||
struct testcase_t circuituse_tests[] = {
|
||||
{ "marked",
|
||||
test_circuit_is_available_for_use_ret_false_when_marked_for_close,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "timestamp",
|
||||
test_circuit_is_available_for_use_ret_false_when_timestamp_dirty,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "non_general",
|
||||
test_circuit_is_available_for_use_ret_false_for_non_general_purpose,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "non_general",
|
||||
test_circuit_is_available_for_use_ret_false_for_non_general_origin,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "origin",
|
||||
test_circuit_is_available_for_use_ret_false_for_non_origin_purpose,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "clean",
|
||||
test_circuit_is_available_for_use_ret_false_unusable_for_new_conns,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "onehop",
|
||||
test_circuit_is_available_for_use_returns_false_for_onehop_tunnel,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "clean_circ",
|
||||
test_circuit_is_available_for_use_returns_true_for_clean_circuit,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "exit_f",
|
||||
test_needs_exit_circuits_ret_false_for_predicted_ports_and_path,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "exit_t",
|
||||
test_needs_exit_circuits_ret_true_for_predicted_ports_and_path,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "non_exit",
|
||||
test_needs_exit_circuits_ret_false_for_non_exit_consensus_path,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "true",
|
||||
test_needs_exit_circuits_ret_true_for_predicted_ports_and_path,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "consensus_path_unknown",
|
||||
test_needs_circuits_for_build_ret_false_consensus_path_unknown,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "less_than_max",
|
||||
test_needs_circuits_for_build_ret_false_if_num_less_than_max,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
{ "more_needed",
|
||||
test_needs_circuits_for_build_returns_true_when_more_are_needed,
|
||||
TT_FORK, NULL, NULL
|
||||
},
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "orconfig.h"
|
||||
#include "or.h"
|
||||
|
||||
#include "relay.h"
|
||||
#include "routerlist.h"
|
||||
#include "nodelist.h"
|
||||
#include "buffers.h"
|
||||
@ -23,6 +24,8 @@ DISABLE_GCC_WARNING(overlength-strings)
|
||||
* at large. */
|
||||
#endif
|
||||
#include "test_descriptors.inc"
|
||||
#include "or.h"
|
||||
#include "circuitlist.h"
|
||||
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
|
||||
ENABLE_GCC_WARNING(overlength-strings)
|
||||
#endif
|
||||
@ -105,3 +108,23 @@ connection_write_to_buf_mock(const char *string, size_t len,
|
||||
write_to_buf(string, len, conn->outbuf);
|
||||
}
|
||||
|
||||
/* Set up a fake origin circuit with the specified number of cells,
|
||||
* Return a pointer to the newly-created dummy circuit */
|
||||
circuit_t *
|
||||
dummy_origin_circuit_new(int n_cells)
|
||||
{
|
||||
origin_circuit_t *circ = origin_circuit_new();
|
||||
int i;
|
||||
cell_t cell;
|
||||
|
||||
for (i=0; i < n_cells; ++i) {
|
||||
crypto_rand((void*)&cell, sizeof(cell));
|
||||
cell_queue_append_packed_copy(TO_CIRCUIT(circ),
|
||||
&TO_CIRCUIT(circ)->n_chan_cells,
|
||||
1, &cell, 1, 0);
|
||||
}
|
||||
|
||||
TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
|
||||
return TO_CIRCUIT(circ);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
const char *get_yesterday_date_str(void);
|
||||
|
||||
circuit_t * dummy_origin_circuit_new(int num_cells);
|
||||
|
||||
/* Number of descriptors contained in test_descriptors.txt. */
|
||||
#define HELPER_NUMBER_OF_DESCRIPTORS 8
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "config.h"
|
||||
#include "relay.h"
|
||||
#include "test.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
/* small replacement mock for circuit_mark_for_close_ to avoid doing all
|
||||
* the other bookkeeping that comes with marking circuits. */
|
||||
@ -58,24 +59,6 @@ dummy_or_circuit_new(int n_p_cells, int n_n_cells)
|
||||
return TO_CIRCUIT(circ);
|
||||
}
|
||||
|
||||
static circuit_t *
|
||||
dummy_origin_circuit_new(int n_cells)
|
||||
{
|
||||
origin_circuit_t *circ = origin_circuit_new();
|
||||
int i;
|
||||
cell_t cell;
|
||||
|
||||
for (i=0; i < n_cells; ++i) {
|
||||
crypto_rand((void*)&cell, sizeof(cell));
|
||||
cell_queue_append_packed_copy(TO_CIRCUIT(circ),
|
||||
&TO_CIRCUIT(circ)->n_chan_cells,
|
||||
1, &cell, 1, 0);
|
||||
}
|
||||
|
||||
TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
|
||||
return TO_CIRCUIT(circ);
|
||||
}
|
||||
|
||||
static void
|
||||
add_bytes_to_buf(buf_t *buf, size_t n_bytes)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user