mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
Add scheduler channel states unit test
This commit is contained in:
parent
dc3af04ba8
commit
684bcd886a
@ -41,6 +41,8 @@ static circuitmux_t *mock_cgp_tgt_1 = NULL;
|
|||||||
static const circuitmux_policy_t *mock_cgp_val_1 = NULL;
|
static const circuitmux_policy_t *mock_cgp_val_1 = NULL;
|
||||||
static circuitmux_t *mock_cgp_tgt_2 = NULL;
|
static circuitmux_t *mock_cgp_tgt_2 = NULL;
|
||||||
static const circuitmux_policy_t *mock_cgp_val_2 = NULL;
|
static const circuitmux_policy_t *mock_cgp_val_2 = NULL;
|
||||||
|
static int scheduler_compare_channels_mock_ctr = 0;
|
||||||
|
static int scheduler_run_mock_ctr = 0;
|
||||||
|
|
||||||
/* Setup for mock event stuff */
|
/* Setup for mock event stuff */
|
||||||
static void mock_event_free_all(void);
|
static void mock_event_free_all(void);
|
||||||
@ -51,9 +53,13 @@ static int circuitmux_compare_muxes_mock(circuitmux_t *cmux_1,
|
|||||||
circuitmux_t *cmux_2);
|
circuitmux_t *cmux_2);
|
||||||
static const circuitmux_policy_t * circuitmux_get_policy_mock(
|
static const circuitmux_policy_t * circuitmux_get_policy_mock(
|
||||||
circuitmux_t *cmux);
|
circuitmux_t *cmux);
|
||||||
|
static int scheduler_compare_channels_mock(const void *c1_v,
|
||||||
|
const void *c2_v);
|
||||||
|
static void scheduler_run_noop_mock(void);
|
||||||
static struct event_base * tor_libevent_get_base_mock(void);
|
static struct event_base * tor_libevent_get_base_mock(void);
|
||||||
|
|
||||||
/* Scheduler test cases */
|
/* Scheduler test cases */
|
||||||
|
static void test_scheduler_channel_states(void *arg);
|
||||||
static void test_scheduler_compare_channels(void *arg);
|
static void test_scheduler_compare_channels(void *arg);
|
||||||
static void test_scheduler_initfree(void *arg);
|
static void test_scheduler_initfree(void *arg);
|
||||||
static void test_scheduler_queue_heuristic(void *arg);
|
static void test_scheduler_queue_heuristic(void *arg);
|
||||||
@ -130,8 +136,7 @@ circuitmux_compare_muxes_mock(circuitmux_t *cmux_1,
|
|||||||
if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1;
|
if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1;
|
||||||
else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) {
|
else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) {
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_1) result = -1;
|
if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_1) result = -1;
|
||||||
else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) {
|
else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) {
|
||||||
result = 1;
|
result = 1;
|
||||||
@ -162,6 +167,28 @@ circuitmux_get_policy_mock(circuitmux_t *cmux)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
scheduler_compare_channels_mock(const void *c1_v,
|
||||||
|
const void *c2_v)
|
||||||
|
{
|
||||||
|
uintptr_t p1, p2;
|
||||||
|
|
||||||
|
p1 = (uintptr_t)(c1_v);
|
||||||
|
p2 = (uintptr_t)(c2_v);
|
||||||
|
|
||||||
|
++scheduler_compare_channels_mock_ctr;
|
||||||
|
|
||||||
|
if (p1 == p2) return 0;
|
||||||
|
else if (p1 < p2) return 1;
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scheduler_run_noop_mock(void)
|
||||||
|
{
|
||||||
|
++scheduler_run_mock_ctr;
|
||||||
|
}
|
||||||
|
|
||||||
static struct event_base *
|
static struct event_base *
|
||||||
tor_libevent_get_base_mock(void)
|
tor_libevent_get_base_mock(void)
|
||||||
{
|
{
|
||||||
@ -170,6 +197,125 @@ tor_libevent_get_base_mock(void)
|
|||||||
|
|
||||||
/* Test cases */
|
/* Test cases */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_scheduler_channel_states(void *arg)
|
||||||
|
{
|
||||||
|
channel_t *ch1 = NULL, *ch2 = NULL;
|
||||||
|
int old_count;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
/* Set up libevent and scheduler */
|
||||||
|
|
||||||
|
mock_event_init();
|
||||||
|
MOCK(tor_libevent_get_base, tor_libevent_get_base_mock);
|
||||||
|
scheduler_init();
|
||||||
|
/*
|
||||||
|
* Install the compare channels mock so we can test
|
||||||
|
* scheduler_touch_channel().
|
||||||
|
*/
|
||||||
|
MOCK(scheduler_compare_channels, scheduler_compare_channels_mock);
|
||||||
|
/*
|
||||||
|
* Disable scheduler_run so we can just check the state transitions
|
||||||
|
* without having to make everything it might call work too.
|
||||||
|
*/
|
||||||
|
MOCK(scheduler_run, scheduler_run_noop_mock);
|
||||||
|
|
||||||
|
test_eq(smartlist_len(channels_pending), 0);
|
||||||
|
|
||||||
|
/* Set up a fake channel */
|
||||||
|
ch1 = new_fake_channel();
|
||||||
|
test_assert(ch1);
|
||||||
|
|
||||||
|
/* Start it off in OPENING */
|
||||||
|
ch1->state = CHANNEL_STATE_OPENING;
|
||||||
|
/* We'll need a cmux */
|
||||||
|
ch1->cmux = circuitmux_alloc();
|
||||||
|
/* Try to register it */
|
||||||
|
channel_register(ch1);
|
||||||
|
test_assert(ch1->registered);
|
||||||
|
|
||||||
|
/* It should start off in SCHED_CHAN_IDLE */
|
||||||
|
test_eq(ch1->scheduler_state, SCHED_CHAN_IDLE);
|
||||||
|
|
||||||
|
/* Now get another one */
|
||||||
|
ch2 = new_fake_channel();
|
||||||
|
test_assert(ch2);
|
||||||
|
ch2->state = CHANNEL_STATE_OPENING;
|
||||||
|
ch2->cmux = circuitmux_alloc();
|
||||||
|
channel_register(ch2);
|
||||||
|
test_assert(ch2->registered);
|
||||||
|
|
||||||
|
/* Send it to SCHED_CHAN_WAITING_TO_WRITE */
|
||||||
|
scheduler_channel_has_waiting_cells(ch1);
|
||||||
|
test_eq(ch1->scheduler_state, SCHED_CHAN_WAITING_TO_WRITE);
|
||||||
|
|
||||||
|
/* This should send it to SCHED_CHAN_PENDING */
|
||||||
|
scheduler_channel_wants_writes(ch1);
|
||||||
|
test_eq(ch1->scheduler_state, SCHED_CHAN_PENDING);
|
||||||
|
test_eq(smartlist_len(channels_pending), 1);
|
||||||
|
|
||||||
|
/* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */
|
||||||
|
scheduler_channel_wants_writes(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_WAITING_FOR_CELLS);
|
||||||
|
|
||||||
|
/* Drop ch2 back to idle */
|
||||||
|
scheduler_channel_doesnt_want_writes(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_IDLE);
|
||||||
|
|
||||||
|
/* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */
|
||||||
|
scheduler_channel_wants_writes(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_WAITING_FOR_CELLS);
|
||||||
|
|
||||||
|
/* ...and this should kick ch2 into SCHED_CHAN_PENDING */
|
||||||
|
scheduler_channel_has_waiting_cells(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_PENDING);
|
||||||
|
test_eq(smartlist_len(channels_pending), 2);
|
||||||
|
|
||||||
|
/* This should send ch2 to SCHED_CHAN_WAITING_TO_WRITE */
|
||||||
|
scheduler_channel_doesnt_want_writes(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_WAITING_TO_WRITE);
|
||||||
|
test_eq(smartlist_len(channels_pending), 1);
|
||||||
|
|
||||||
|
/* ...and back to SCHED_CHAN_PENDING */
|
||||||
|
scheduler_channel_wants_writes(ch2);
|
||||||
|
test_eq(ch2->scheduler_state, SCHED_CHAN_PENDING);
|
||||||
|
test_eq(smartlist_len(channels_pending), 2);
|
||||||
|
|
||||||
|
/* Now we exercise scheduler_touch_channel */
|
||||||
|
old_count = scheduler_compare_channels_mock_ctr;
|
||||||
|
scheduler_touch_channel(ch1);
|
||||||
|
test_assert(scheduler_compare_channels_mock_ctr > old_count);
|
||||||
|
|
||||||
|
/* Close */
|
||||||
|
channel_mark_for_close(ch1);
|
||||||
|
test_eq(ch1->state, CHANNEL_STATE_CLOSING);
|
||||||
|
channel_mark_for_close(ch2);
|
||||||
|
test_eq(ch2->state, CHANNEL_STATE_CLOSING);
|
||||||
|
channel_closed(ch1);
|
||||||
|
test_eq(ch1->state, CHANNEL_STATE_CLOSED);
|
||||||
|
ch1 = NULL;
|
||||||
|
channel_closed(ch2);
|
||||||
|
test_eq(ch2->state, CHANNEL_STATE_CLOSED);
|
||||||
|
ch2 = NULL;
|
||||||
|
|
||||||
|
/* Shut things down */
|
||||||
|
|
||||||
|
channel_free_all();
|
||||||
|
scheduler_free_all();
|
||||||
|
mock_event_free_all();
|
||||||
|
|
||||||
|
done:
|
||||||
|
tor_free(ch1);
|
||||||
|
tor_free(ch2);
|
||||||
|
|
||||||
|
UNMOCK(scheduler_compare_channels);
|
||||||
|
UNMOCK(scheduler_run);
|
||||||
|
UNMOCK(tor_libevent_get_base);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_scheduler_compare_channels(void *arg)
|
test_scheduler_compare_channels(void *arg)
|
||||||
{
|
{
|
||||||
@ -208,7 +354,7 @@ test_scheduler_compare_channels(void *arg)
|
|||||||
/* Equal-channel case */
|
/* Equal-channel case */
|
||||||
result = scheduler_compare_channels(&c1, &c1);
|
result = scheduler_compare_channels(&c1, &c1);
|
||||||
test_eq(result, 0);
|
test_eq(result, 0);
|
||||||
|
|
||||||
/* Distinct channels, distinct policies */
|
/* Distinct channels, distinct policies */
|
||||||
result = scheduler_compare_channels(&c1, &c2);
|
result = scheduler_compare_channels(&c1, &c2);
|
||||||
test_eq(result, -1);
|
test_eq(result, -1);
|
||||||
@ -303,6 +449,7 @@ test_scheduler_queue_heuristic(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct testcase_t scheduler_tests[] = {
|
struct testcase_t scheduler_tests[] = {
|
||||||
|
{ "channel_states", test_scheduler_channel_states, TT_FORK, NULL, NULL },
|
||||||
{ "compare_channels", test_scheduler_compare_channels,
|
{ "compare_channels", test_scheduler_compare_channels,
|
||||||
TT_FORK, NULL, NULL },
|
TT_FORK, NULL, NULL },
|
||||||
{ "initfree", test_scheduler_initfree, TT_FORK, NULL, NULL },
|
{ "initfree", test_scheduler_initfree, TT_FORK, NULL, NULL },
|
||||||
|
Loading…
Reference in New Issue
Block a user