#define CONFIG_PRIVATE
#define HS_SERVICE_PRIVATE
#define MAINLOOP_PRIVATE
#include "test/test.h"
#include "test/test_helpers.h"
#include "core/or/or.h"
#include "app/config/config.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_service.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/periodic.h"
static int
dumb_event_fn(time_t now, const or_options_t *options)
{
(void) now;
(void) options;
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_periodic_events();
periodic_events_connect_all();
set_network_participation(false);
rescan_periodic_events(get_options());
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
tt_assert(item->ev);
tt_assert(item->fn);
tt_u64_op(item->last_action_time, OP_EQ, 0);
tt_u64_op(item->roles, OP_NE, 0);
int should_be_enabled = (item->roles & PERIODIC_EVENT_ROLE_ALL) &&
!(item->flags & PERIODIC_EVENT_FLAG_NEED_NET);
tt_uint_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
}
done:
teardown_periodic_events();
}
static void
test_pe_launch(void *arg)
{
hs_service_t service, *to_remove = NULL;
or_options_t *options;
(void) arg;
hs_init();
consider_hibernation(time(NULL));
set_network_participation(true);
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
item->fn = dumb_event_fn;
}
options = get_options_mutable();
options->SocksPort_set = 1;
periodic_events_on_new_options(options);
#if 0#endif
initialize_periodic_events();
periodic_events_connect_all();
periodic_events_on_new_options(options);
int mask = PERIODIC_EVENT_ROLE_CLIENT|PERIODIC_EVENT_ROLE_ALL|
PERIODIC_EVENT_ROLE_NET_PARTICIPANT;
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
int should_be_enabled = !!(item->roles & mask);
tt_int_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
tt_u64_op(item->last_action_time, OP_EQ, 0);
}
options->SocksPort_set = 0;
options->ORPort_set = 1;
periodic_events_on_new_options(options);
unsigned roles = get_my_roles(options);
tt_uint_op(roles, OP_EQ,
PERIODIC_EVENT_ROLE_RELAY|PERIODIC_EVENT_ROLE_DIRSERVER|
PERIODIC_EVENT_ROLE_ALL|PERIODIC_EVENT_ROLE_NET_PARTICIPANT);
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
if (item->roles == PERIODIC_EVENT_ROLE_CLIENT) {
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
}
if (item->roles & PERIODIC_EVENT_ROLE_RELAY) {
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
}
if (!(item->roles & roles)) {
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
}
}
options->SocksPort_set = 0;
options->ORPort_set = 0;
options->DisableNetwork = 1;
set_network_participation(false);
periodic_events_on_new_options(options);
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
int should_be_enabled = (item->roles & PERIODIC_EVENT_ROLE_ALL) &&
!(item->flags & PERIODIC_EVENT_FLAG_NEED_NET);
tt_int_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
}
options->SocksPort_set = 1; options->ORPort_set = 1;
options->BridgeRelay = 1; options->AuthoritativeDir = 1;
options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
options->DisableNetwork = 0;
set_network_participation(true);
register_dummy_hidden_service(&service);
periodic_events_on_new_options(options);
to_remove = &service;
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
tt_int_op(periodic_event_is_enabled(item), OP_EQ,
(item->roles != PERIODIC_EVENT_ROLE_CONTROLEV));
}
done:
if (to_remove) {
remove_service(get_hs_service_map(), to_remove);
}
hs_free_all();
}
static void
test_pe_get_roles(void *arg)
{
int roles;
(void) arg;
hs_init();
or_options_t *options = get_options_mutable();
tt_assert(options);
set_network_participation(true);
const int ALL = PERIODIC_EVENT_ROLE_ALL |
PERIODIC_EVENT_ROLE_NET_PARTICIPANT;
tt_assert(net_is_disabled());
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ, ALL);
options->SocksPort_set = 1;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_CLIENT|ALL);
options->ORPort_set = 1;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ,
(PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
PERIODIC_EVENT_ROLE_DIRSERVER | ALL));
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 | PERIODIC_EVENT_ROLE_DIRSERVER |
ALL));
tt_assert(roles & PERIODIC_EVENT_ROLE_ROUTER);
options->SocksPort_set = 0;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ,
PERIODIC_EVENT_ROLE_ROUTER | PERIODIC_EVENT_ROLE_DIRSERVER |
ALL);
options->SocksPort_set = 0;
options->ORPort_set = 0;
options->BridgeRelay = 0;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ, ALL);
options->DirPort_set = 1;
options->AuthoritativeDir = 1;
options->V3AuthoritativeDir = 1;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ,
PERIODIC_EVENT_ROLE_DIRAUTH|PERIODIC_EVENT_ROLE_DIRSERVER|ALL);
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
options->V3AuthoritativeDir = 0;
options->BridgeAuthoritativeDir = 1;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ,
PERIODIC_EVENT_ROLE_BRIDGEAUTH|PERIODIC_EVENT_ROLE_DIRSERVER|ALL);
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
options->ORPort_set = 1;
roles = get_my_roles(options);
tt_int_op(roles, OP_EQ,
(PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY
| PERIODIC_EVENT_ROLE_DIRSERVER|ALL));
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
hs_service_t service;
register_dummy_hidden_service(&service);
roles = get_my_roles(options);
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 | PERIODIC_EVENT_ROLE_DIRSERVER |
ALL));
tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
done:
hs_free_all();
}
static void
test_pe_hs_service(void *arg)
{
hs_service_t service, *to_remove = NULL;
(void) arg;
hs_init();
consider_hibernation(time(NULL));
initialize_periodic_events();
periodic_events_connect_all();
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
item->fn = dumb_event_fn;
}
register_dummy_hidden_service(&service);
to_remove = &service;
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
}
}
to_remove = NULL;
remove_service(get_hs_service_map(), &service);
for (int i = 0; mainloop_periodic_events[i].name; ++i) {
periodic_event_item_t *item = &mainloop_periodic_events[i];
if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
}
}
done:
if (to_remove) {
remove_service(get_hs_service_map(), to_remove);
}
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),
PE_TEST(hs_service),
END_OF_TESTCASES
};