#define CIRCUITBUILD_PRIVATE
#define CIRCUITSTATS_PRIVATE
#define CIRCUITLIST_PRIVATE
#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
#include "app/config/config.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
#include "core/or/channel.h"
#include "core/or/crypt_path_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
static origin_circuit_t *add_opened_threehop(void);
static origin_circuit_t *build_unopened_fourhop(struct timeval);
static origin_circuit_t *subtest_fourhop_circuit(struct timeval, int);
static int marked_for_close;
static void
mock_circuit_mark_for_close(circuit_t *circ, int reason, int line,
const char *file)
{
(void) circ;
(void) reason;
(void) line;
(void) file;
marked_for_close = 1;
return;
}
static origin_circuit_t *
add_opened_threehop(void)
{
struct timeval circ_start_time;
memset(&circ_start_time, 0, sizeof(circ_start_time));
extend_info_t fakehop;
memset(&fakehop, 0, sizeof(fakehop));
extend_info_t *fakehop_list[DEFAULT_ROUTE_LEN] = {&fakehop,
&fakehop,
&fakehop};
return new_test_origin_circuit(true,
circ_start_time,
DEFAULT_ROUTE_LEN,
fakehop_list);
}
static origin_circuit_t *
build_unopened_fourhop(struct timeval circ_start_time)
{
extend_info_t fakehop;
memset(&fakehop, 0, sizeof(fakehop));
extend_info_t *fakehop_list[4] = {&fakehop,
&fakehop,
&fakehop,
&fakehop};
return new_test_origin_circuit(false,
circ_start_time,
4,
fakehop_list);
}
static origin_circuit_t *
subtest_fourhop_circuit(struct timeval circ_start_time, int should_timeout)
{
origin_circuit_t *origin_circ = build_unopened_fourhop(circ_start_time);
origin_circ->cpath->state = CPATH_STATE_OPEN;
circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
origin_circ->cpath->next->state = CPATH_STATE_OPEN;
circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 0);
origin_circ->cpath->next->next->state = CPATH_STATE_OPEN;
circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
!should_timeout);
origin_circ->cpath->next->next->next->state = CPATH_STATE_OPEN;
circuit_build_times_handle_completed_hop(origin_circ);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ,
!should_timeout);
done:
return origin_circ;
}
static void
test_circuitstats_hoplen(void *arg)
{
struct timeval circ_start_time;
origin_circuit_t *threehop = NULL;
origin_circuit_t *fourhop = NULL;
(void)arg;
MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
circuit_build_times_init(get_circuit_build_times_mutable());
get_circuit_build_times_mutable()->close_ms *= 2;
tor_gettimeofday(&circ_start_time);
circ_start_time.tv_sec -= 119;
fourhop = subtest_fourhop_circuit(circ_start_time, 0);
tt_int_op(fourhop->relaxed_timeout, OP_EQ, 0);
tt_int_op(marked_for_close, OP_EQ, 0);
circuit_expire_building();
tt_int_op(marked_for_close, OP_EQ, 0);
tt_int_op(fourhop->relaxed_timeout, OP_EQ, 1);
TO_CIRCUIT(fourhop)->timestamp_began.tv_sec -= 119;
circuit_expire_building();
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
tt_int_op(marked_for_close, OP_EQ, 1);
circuit_free_(TO_CIRCUIT(fourhop));
circuit_build_times_reset(get_circuit_build_times_mutable());
threehop = add_opened_threehop();
tor_gettimeofday(&circ_start_time);
circ_start_time.tv_sec -= 59;
fourhop = subtest_fourhop_circuit(circ_start_time, 0);
circuit_expire_building();
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_NE,
CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT);
circuit_free_((circuit_t *)fourhop);
circuit_build_times_reset(get_circuit_build_times_mutable());
circ_start_time.tv_sec -= 2;
fourhop = subtest_fourhop_circuit(circ_start_time, 0);
tt_int_op(TO_CIRCUIT(fourhop)->purpose, OP_EQ,
CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT);
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
circuit_expire_building();
tt_int_op(get_circuit_build_times()->total_build_times, OP_EQ, 1);
done:
UNMOCK(circuit_mark_for_close_);
circuit_free_(TO_CIRCUIT(threehop));
circuit_free_(TO_CIRCUIT(fourhop));
circuit_build_times_free_timeouts(get_circuit_build_times_mutable());
}
#define TEST_CIRCUITSTATS(name, flags) \
{ #name, test_##name, (flags), &helper_pubsub_setup, NULL }
struct testcase_t circuitstats_tests[] = {
TEST_CIRCUITSTATS(circuitstats_hoplen, TT_FORK),
END_OF_TESTCASES
};