mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
test: Add periodic events unit tests
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
87cb9ce900
commit
665e23c59a
@ -1351,7 +1351,7 @@ CALLBACK(write_stats_file);
|
|||||||
/* Now we declare an array of periodic_event_item_t for each periodic event */
|
/* Now we declare an array of periodic_event_item_t for each periodic event */
|
||||||
#define CALLBACK(name, r) PERIODIC_EVENT(name, r)
|
#define CALLBACK(name, r) PERIODIC_EVENT(name, r)
|
||||||
|
|
||||||
static periodic_event_item_t periodic_events[] = {
|
STATIC periodic_event_item_t periodic_events[] = {
|
||||||
/* Everyone needs to run those. */
|
/* Everyone needs to run those. */
|
||||||
CALLBACK(add_entropy, PERIODIC_EVENT_ROLE_ALL),
|
CALLBACK(add_entropy, PERIODIC_EVENT_ROLE_ALL),
|
||||||
CALLBACK(check_expired_networkstatus, PERIODIC_EVENT_ROLE_ALL),
|
CALLBACK(check_expired_networkstatus, PERIODIC_EVENT_ROLE_ALL),
|
||||||
@ -1440,7 +1440,7 @@ find_periodic_event(const char *name)
|
|||||||
|
|
||||||
/** Return a bitmask of the roles this tor instance is configured for using
|
/** Return a bitmask of the roles this tor instance is configured for using
|
||||||
* the given options. */
|
* the given options. */
|
||||||
static int
|
STATIC int
|
||||||
get_my_roles(const or_options_t *options)
|
get_my_roles(const or_options_t *options)
|
||||||
{
|
{
|
||||||
tor_assert(options);
|
tor_assert(options);
|
||||||
|
@ -98,8 +98,13 @@ STATIC void init_connection_lists(void);
|
|||||||
STATIC void close_closeable_connections(void);
|
STATIC void close_closeable_connections(void);
|
||||||
STATIC void initialize_periodic_events(void);
|
STATIC void initialize_periodic_events(void);
|
||||||
STATIC void teardown_periodic_events(void);
|
STATIC void teardown_periodic_events(void);
|
||||||
|
STATIC int get_my_roles(const or_options_t *options);
|
||||||
#ifdef TOR_UNIT_TESTS
|
#ifdef TOR_UNIT_TESTS
|
||||||
extern smartlist_t *connection_array;
|
extern smartlist_t *connection_array;
|
||||||
|
|
||||||
|
/* We need the periodic_event_item_t definition. */
|
||||||
|
#include "periodic.h"
|
||||||
|
extern periodic_event_item_t periodic_events[];
|
||||||
#endif
|
#endif
|
||||||
#endif /* defined(MAIN_PRIVATE) */
|
#endif /* defined(MAIN_PRIVATE) */
|
||||||
|
|
||||||
|
@ -144,6 +144,7 @@ src_test_test_SOURCES = \
|
|||||||
src/test/test_oom.c \
|
src/test/test_oom.c \
|
||||||
src/test/test_oos.c \
|
src/test/test_oos.c \
|
||||||
src/test/test_options.c \
|
src/test/test_options.c \
|
||||||
|
src/test/test_periodic_event.c \
|
||||||
src/test/test_policy.c \
|
src/test/test_policy.c \
|
||||||
src/test/test_procmon.c \
|
src/test/test_procmon.c \
|
||||||
src/test/test_proto_http.c \
|
src/test/test_proto_http.c \
|
||||||
|
@ -863,6 +863,7 @@ struct testgroup_t testgroups[] = {
|
|||||||
{ "oom/", oom_tests },
|
{ "oom/", oom_tests },
|
||||||
{ "oos/", oos_tests },
|
{ "oos/", oos_tests },
|
||||||
{ "options/", options_tests },
|
{ "options/", options_tests },
|
||||||
|
{ "periodic-event/" , periodic_event_tests },
|
||||||
{ "policy/" , policy_tests },
|
{ "policy/" , policy_tests },
|
||||||
{ "procmon/", procmon_tests },
|
{ "procmon/", procmon_tests },
|
||||||
{ "proto/http/", proto_http_tests },
|
{ "proto/http/", proto_http_tests },
|
||||||
|
@ -239,6 +239,7 @@ extern struct testcase_t nodelist_tests[];
|
|||||||
extern struct testcase_t oom_tests[];
|
extern struct testcase_t oom_tests[];
|
||||||
extern struct testcase_t oos_tests[];
|
extern struct testcase_t oos_tests[];
|
||||||
extern struct testcase_t options_tests[];
|
extern struct testcase_t options_tests[];
|
||||||
|
extern struct testcase_t periodic_event_tests[];
|
||||||
extern struct testcase_t policy_tests[];
|
extern struct testcase_t policy_tests[];
|
||||||
extern struct testcase_t procmon_tests[];
|
extern struct testcase_t procmon_tests[];
|
||||||
extern struct testcase_t proto_http_tests[];
|
extern struct testcase_t proto_http_tests[];
|
||||||
|
256
src/test/test_periodic_event.c
Normal file
256
src/test/test_periodic_event.c
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/* Copyright (c) 2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file test_periodic_event.c
|
||||||
|
* \brief Test the periodic events that Tor uses for different roles. They are
|
||||||
|
* part of the libevent mainloop
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CONFIG_PRIVATE
|
||||||
|
#define HS_SERVICE_PRIVATE
|
||||||
|
#define MAIN_PRIVATE
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include "test_helpers.h"
|
||||||
|
|
||||||
|
#include "or.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "hs_service.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "periodic.h"
|
||||||
|
|
||||||
|
/** Helper function: This is replaced in some tests for the event callbacks so
|
||||||
|
* we don't actually go into the code path of those callbacks. */
|
||||||
|
static int
|
||||||
|
dumb_event_fn(time_t now, const or_options_t *options)
|
||||||
|
{
|
||||||
|
(void) now;
|
||||||
|
(void) options;
|
||||||
|
|
||||||
|
/* Will get rescheduled in 300 seconds. It just can't be 0. */
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
register_dummy_hidden_service(hs_service_t *service)
|
||||||
|
{
|
||||||
|
memset(service, 0, sizeof(hs_service_t));
|
||||||
|
memset(&service->keys.identity_pk, 'A', sizeof(service->keys.identity_pk));
|
||||||
|
(void) register_service(get_hs_service_map(), service);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_pe_initialize(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Initialize the events but the callback won't get called since we would
|
||||||
|
* need to run the main loop and then wait for a second delaying the unit
|
||||||
|
* tests. Instead, we'll test the callback work indepedently elsewhere. */
|
||||||
|
initialize_periodic_events();
|
||||||
|
|
||||||
|
/* Validate that all events have been set up. */
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
tt_assert(item->ev);
|
||||||
|
tt_assert(item->fn);
|
||||||
|
tt_u64_op(item->last_action_time, OP_EQ, 0);
|
||||||
|
/* Every event must have role(s) assign to it. This is done statically. */
|
||||||
|
tt_u64_op(item->roles, OP_NE, 0);
|
||||||
|
tt_uint_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
teardown_periodic_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_pe_launch(void *arg)
|
||||||
|
{
|
||||||
|
hs_service_t service;
|
||||||
|
or_options_t *options;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
hs_init();
|
||||||
|
|
||||||
|
/* Hack: We'll set a dumb fn() of each events so they don't get called when
|
||||||
|
* dispatching them. We just want to test the state of the callbacks, not
|
||||||
|
* the whole code path. */
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
item->fn = dumb_event_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lets make sure that before intialization, we can't scan the periodic
|
||||||
|
* events list and launch them. Lets try by being a Client. */
|
||||||
|
options = get_options_mutable();
|
||||||
|
options->SocksPort_set = 1;
|
||||||
|
periodic_events_on_new_options(options);
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_periodic_events();
|
||||||
|
|
||||||
|
/* Now that we've initialized, rescan the list to launch. */
|
||||||
|
periodic_events_on_new_options(options);
|
||||||
|
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
if (item->roles & PERIODIC_EVENT_ROLE_CLIENT) {
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
|
||||||
|
tt_u64_op(item->last_action_time, OP_NE, 0);
|
||||||
|
} else {
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
tt_u64_op(item->last_action_time, OP_EQ, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove Client but become a Relay. */
|
||||||
|
options->SocksPort_set = 0;
|
||||||
|
options->ORPort_set = 1;
|
||||||
|
periodic_events_on_new_options(options);
|
||||||
|
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
/* Only Client role should be disabled. */
|
||||||
|
if (item->roles == PERIODIC_EVENT_ROLE_CLIENT) {
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
/* Was previously enabled so they should never be to 0. */
|
||||||
|
tt_u64_op(item->last_action_time, OP_NE, 0);
|
||||||
|
}
|
||||||
|
if (item->roles & PERIODIC_EVENT_ROLE_RELAY) {
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
|
||||||
|
tt_u64_op(item->last_action_time, OP_NE, 0);
|
||||||
|
}
|
||||||
|
/* Non Relay role should be disabled! */
|
||||||
|
if (!(item->roles & PERIODIC_EVENT_ROLE_RELAY)) {
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable everything and we'll enable them ALL. */
|
||||||
|
options->SocksPort_set = 0;
|
||||||
|
options->ORPort_set = 0;
|
||||||
|
periodic_events_on_new_options(options);
|
||||||
|
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable everything. */
|
||||||
|
options->SocksPort_set = 1; options->ORPort_set = 1;
|
||||||
|
options->BridgeRelay = 1; options->AuthoritativeDir = 1;
|
||||||
|
options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
|
||||||
|
register_dummy_hidden_service(&service);
|
||||||
|
periodic_events_on_new_options(options);
|
||||||
|
/* Remove it now so the hs_free_all() doesn't try to free stack memory. */
|
||||||
|
remove_service(get_hs_service_map(), &service);
|
||||||
|
|
||||||
|
for (int i = 0; periodic_events[i].name; ++i) {
|
||||||
|
periodic_event_item_t *item = &periodic_events[i];
|
||||||
|
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
hs_free_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_pe_get_roles(void *arg)
|
||||||
|
{
|
||||||
|
int roles;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Just so the HS global map exists. */
|
||||||
|
hs_init();
|
||||||
|
|
||||||
|
or_options_t *options = get_options_mutable();
|
||||||
|
tt_assert(options);
|
||||||
|
|
||||||
|
/* Nothing configured, should be no roles. */
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Indicate we have a SocksPort, roles should be come Client. */
|
||||||
|
options->SocksPort_set = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_CLIENT);
|
||||||
|
|
||||||
|
/* Now, we'll add a ORPort so should now be a Relay + Client. */
|
||||||
|
options->ORPort_set = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ,
|
||||||
|
(PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY));
|
||||||
|
|
||||||
|
/* Now add a Bridge. */
|
||||||
|
options->BridgeRelay = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ,
|
||||||
|
(PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
|
||||||
|
PERIODIC_EVENT_ROLE_BRIDGE));
|
||||||
|
tt_assert(roles & PERIODIC_EVENT_ROLE_ROUTER);
|
||||||
|
/* Unset client so we can solely test Router role. */
|
||||||
|
options->SocksPort_set = 0;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_ROUTER);
|
||||||
|
|
||||||
|
/* Reset options so we can test authorities. */
|
||||||
|
options->SocksPort_set = 0;
|
||||||
|
options->ORPort_set = 0;
|
||||||
|
options->BridgeRelay = 0;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Now upgrade to Dirauth. */
|
||||||
|
options->AuthoritativeDir = 1;
|
||||||
|
options->V3AuthoritativeDir = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_DIRAUTH);
|
||||||
|
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
|
||||||
|
|
||||||
|
/* Now Bridge Authority. */
|
||||||
|
options->V3AuthoritativeDir = 0;
|
||||||
|
options->BridgeAuthoritativeDir = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_BRIDGEAUTH);
|
||||||
|
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
|
||||||
|
|
||||||
|
/* Move that bridge auth to become a relay. */
|
||||||
|
options->ORPort_set = 1;
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
tt_int_op(roles, OP_EQ,
|
||||||
|
(PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY));
|
||||||
|
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
|
||||||
|
|
||||||
|
/* And now an Hidden service. */
|
||||||
|
hs_service_t service;
|
||||||
|
register_dummy_hidden_service(&service);
|
||||||
|
roles = get_my_roles(options);
|
||||||
|
/* Remove it now so the hs_free_all() doesn't try to free stack memory. */
|
||||||
|
remove_service(get_hs_service_map(), &service);
|
||||||
|
tt_int_op(roles, OP_EQ,
|
||||||
|
(PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY |
|
||||||
|
PERIODIC_EVENT_ROLE_HS_SERVICE));
|
||||||
|
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
|
||||||
|
|
||||||
|
done:
|
||||||
|
hs_free_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PE_TEST(name) \
|
||||||
|
{ #name, test_pe_## name , TT_FORK, NULL, NULL }
|
||||||
|
|
||||||
|
struct testcase_t periodic_event_tests[] = {
|
||||||
|
PE_TEST(initialize),
|
||||||
|
PE_TEST(launch),
|
||||||
|
PE_TEST(get_roles),
|
||||||
|
|
||||||
|
END_OF_TESTCASES
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user