ewma: Implement unit tests

At this commit, 93.9% of line coverage and 95.5% of function coverage.

Closes #32196

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2019-10-28 13:15:56 -04:00
parent 48781c32ca
commit ceca6e7c35
4 changed files with 231 additions and 0 deletions

View File

@ -123,6 +123,7 @@ src_test_test_SOURCES += \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
src/test/test_circuitmux_ewma.c \
src/test/test_circuitbuild.c \
src/test/test_circuituse.c \
src/test/test_circuitstats.c \

View File

@ -836,6 +836,7 @@ struct testgroup_t testgroups[] = {
{ "circuitpadding/", circuitpadding_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
{ "circuitmux_ewma/", circuitmux_ewma_tests },
{ "circuitstats/", circuitstats_tests },
{ "circuituse/", circuituse_tests },
{ "compat/libevent/", compat_libevent_tests },

View File

@ -199,6 +199,7 @@ extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitbuild_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
extern struct testcase_t circuitmux_ewma_tests[];
extern struct testcase_t circuitstats_tests[];
extern struct testcase_t circuituse_tests[];
extern struct testcase_t compat_libevent_tests[];

View File

@ -0,0 +1,228 @@
/* Copyright (c) 2013-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITMUX_PRIVATE
#define CIRCUITMUX_EWMA_PRIVATE
#include "core/or/or.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
#include "test/fakechans.h"
#include "test/fakecircs.h"
#include "test/test.h"
static void
test_cmux_ewma_active_circuit(void *arg)
{
circuitmux_t cmux; /* garbage */
circuitmux_policy_data_t *pol_data = NULL;
circuit_t circ; /* garbage */
circuitmux_policy_circ_data_t *circ_data = NULL;
(void) arg;
pol_data = ewma_policy.alloc_cmux_data(&cmux);
tt_assert(pol_data);
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
CELL_DIRECTION_OUT, 42);
tt_assert(circ_data);
/* Get EWMA specific objects. */
/* Make circuit active. */
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data);
tt_mem_op(entry, OP_EQ, &circ, sizeof(circ));
done:
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
ewma_policy.free_cmux_data(&cmux, pol_data);
}
static void
test_cmux_ewma_xmit_cell(void *arg)
{
circuitmux_t cmux; /* garbage */
circuitmux_policy_data_t *pol_data = NULL;
circuit_t circ; /* garbage */
circuitmux_policy_circ_data_t *circ_data = NULL;
ewma_policy_data_t *ewma_pol_data;
ewma_policy_circ_data_t *ewma_data;
double old_cell_count;
(void) arg;
pol_data = ewma_policy.alloc_cmux_data(&cmux);
tt_assert(pol_data);
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
CELL_DIRECTION_OUT, 42);
tt_assert(circ_data);
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
/* Make circuit active. */
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
/* Move back in time the last time we calibrated so we scale the active
* circuit when emitting a cell. */
ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100;
ewma_data->cell_ewma.last_adjusted_tick =
ewma_pol_data->active_circuit_pqueue_last_recalibrated;
/* Grab old cell count. */
old_cell_count = ewma_data->cell_ewma.cell_count;
ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1);
/* Our old cell count should be lower to what we have since we just emitted
* a cell and thus we scale. */
tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count);
done:
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
ewma_policy.free_cmux_data(&cmux, pol_data);
}
static void
test_cmux_ewma_notify_circ(void *arg)
{
circuitmux_t cmux; /* garbage */
circuitmux_policy_data_t *pol_data = NULL;
circuit_t circ; /* garbage */
circuitmux_policy_circ_data_t *circ_data = NULL;
const ewma_policy_data_t *ewma_pol_data;
(void) arg;
pol_data = ewma_policy.alloc_cmux_data(&cmux);
tt_assert(pol_data);
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
CELL_DIRECTION_OUT, 42);
tt_assert(circ_data);
/* Currently, notify_circ_active() ignores cmux and circ. They can not be
* NULL so it is fine to pass garbage. */
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
/* We should have an active circuit in the queue so its EWMA value can be
* tracked. */
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1);
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data);
/* Should be removed from the active queue. */
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0);
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
done:
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
ewma_policy.free_cmux_data(&cmux, pol_data);
}
static void
test_cmux_ewma_policy_circ_data(void *arg)
{
circuitmux_t cmux; /* garbage */
circuitmux_policy_data_t pol_data; /* garbage */
circuit_t circ; /* garbage */
circuitmux_policy_circ_data_t *circ_data = NULL;
const ewma_policy_circ_data_t *ewma_data;
(void) arg;
/* Currently, alloc_circ_data() ignores every parameter _except_ the cell
* direction so it is OK to pass garbage. They can not be NULL. */
circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
CELL_DIRECTION_OUT, 42);
tt_assert(circ_data);
tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0);
ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
CELL_DIRECTION_IN, 42);
tt_assert(circ_data);
tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1);
done:
ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
}
static void
test_cmux_ewma_policy_data(void *arg)
{
circuitmux_t cmux; /* garbage. */
circuitmux_policy_data_t *pol_data = NULL;
const ewma_policy_data_t *ewma_pol_data;
(void) arg;
pol_data = ewma_policy.alloc_cmux_data(&cmux);
tt_assert(pol_data);
tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC);
/* Test EWMA object. */
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
tt_assert(ewma_pol_data->active_circuit_pqueue);
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
done:
ewma_policy.free_cmux_data(&cmux, pol_data);
}
static void *
cmux_ewma_setup_test(const struct testcase_t *tc)
{
static int whatever;
(void) tc;
cell_ewma_initialize_ticks();
cmux_ewma_set_options(NULL, NULL);
return &whatever;
}
static int
cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr)
{
(void) tc;
(void) ptr;
circuitmux_ewma_free_all();
return 1;
}
static struct testcase_setup_t cmux_ewma_test_setup = {
.setup_fn = cmux_ewma_setup_test,
.cleanup_fn = cmux_ewma_cleanup_test,
};
#define TEST_CMUX_EWMA(name) \
{ #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL }
struct testcase_t circuitmux_ewma_tests[] = {
TEST_CMUX_EWMA(active_circuit),
TEST_CMUX_EWMA(policy_data),
TEST_CMUX_EWMA(policy_circ_data),
TEST_CMUX_EWMA(notify_circ),
TEST_CMUX_EWMA(xmit_cell),
END_OF_TESTCASES
};