test_periodic_event.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /* Copyright (c) 2018-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file test_periodic_event.c
  5. * \brief Test the periodic events that Tor uses for different roles. They are
  6. * part of the libevent mainloop
  7. */
  8. #define CONFIG_PRIVATE
  9. #define HS_SERVICE_PRIVATE
  10. #define MAINLOOP_PRIVATE
  11. #include "test/test.h"
  12. #include "test/test_helpers.h"
  13. #include "core/or/or.h"
  14. #include "app/config/config.h"
  15. #include "feature/hibernate/hibernate.h"
  16. #include "feature/hs/hs_service.h"
  17. #include "core/mainloop/mainloop.h"
  18. #include "core/mainloop/netstatus.h"
  19. #include "core/mainloop/periodic.h"
  20. /** Helper function: This is replaced in some tests for the event callbacks so
  21. * we don't actually go into the code path of those callbacks. */
  22. static int
  23. dumb_event_fn(time_t now, const or_options_t *options)
  24. {
  25. (void) now;
  26. (void) options;
  27. /* Will get rescheduled in 300 seconds. It just can't be 0. */
  28. return 300;
  29. }
  30. static void
  31. register_dummy_hidden_service(hs_service_t *service)
  32. {
  33. memset(service, 0, sizeof(hs_service_t));
  34. memset(&service->keys.identity_pk, 'A', sizeof(service->keys.identity_pk));
  35. (void) register_service(get_hs_service_map(), service);
  36. }
  37. static void
  38. test_pe_initialize(void *arg)
  39. {
  40. (void) arg;
  41. /* Initialize the events but the callback won't get called since we would
  42. * need to run the main loop and then wait for a second delaying the unit
  43. * tests. Instead, we'll test the callback work indepedently elsewhere. */
  44. initialize_periodic_events();
  45. periodic_events_connect_all();
  46. set_network_participation(false);
  47. rescan_periodic_events(get_options());
  48. /* Validate that all events have been set up. */
  49. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  50. periodic_event_item_t *item = &mainloop_periodic_events[i];
  51. tt_assert(item->ev);
  52. tt_assert(item->fn);
  53. tt_u64_op(item->last_action_time, OP_EQ, 0);
  54. /* Every event must have role(s) assign to it. This is done statically. */
  55. tt_u64_op(item->roles, OP_NE, 0);
  56. int should_be_enabled = (item->roles & PERIODIC_EVENT_ROLE_ALL) &&
  57. !(item->flags & PERIODIC_EVENT_FLAG_NEED_NET);
  58. tt_uint_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
  59. }
  60. done:
  61. teardown_periodic_events();
  62. }
  63. static void
  64. test_pe_launch(void *arg)
  65. {
  66. hs_service_t service, *to_remove = NULL;
  67. or_options_t *options;
  68. (void) arg;
  69. hs_init();
  70. /* We need to put tor in hibernation live state so the events requiring
  71. * network gets enabled. */
  72. consider_hibernation(time(NULL));
  73. set_network_participation(true);
  74. /* Hack: We'll set a dumb fn() of each events so they don't get called when
  75. * dispatching them. We just want to test the state of the callbacks, not
  76. * the whole code path. */
  77. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  78. periodic_event_item_t *item = &mainloop_periodic_events[i];
  79. item->fn = dumb_event_fn;
  80. }
  81. options = get_options_mutable();
  82. options->SocksPort_set = 1;
  83. periodic_events_on_new_options(options);
  84. #if 0
  85. /* Lets make sure that before intialization, we can't scan the periodic
  86. * events list and launch them. Lets try by being a Client. */
  87. /* XXXX We make sure these events are initialized now way earlier than we
  88. * did before. */
  89. for (int i = 0; periodic_events[i].name; ++i) {
  90. periodic_event_item_t *item = &periodic_events[i];
  91. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
  92. }
  93. #endif /* 0 */
  94. initialize_periodic_events();
  95. periodic_events_connect_all();
  96. /* Now that we've initialized, rescan the list to launch. */
  97. periodic_events_on_new_options(options);
  98. int mask = PERIODIC_EVENT_ROLE_CLIENT|PERIODIC_EVENT_ROLE_ALL|
  99. PERIODIC_EVENT_ROLE_NET_PARTICIPANT;
  100. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  101. periodic_event_item_t *item = &mainloop_periodic_events[i];
  102. int should_be_enabled = !!(item->roles & mask);
  103. tt_int_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
  104. // enabled or not, the event has not yet been run.
  105. tt_u64_op(item->last_action_time, OP_EQ, 0);
  106. }
  107. /* Remove Client but become a Relay. */
  108. options->SocksPort_set = 0;
  109. options->ORPort_set = 1;
  110. periodic_events_on_new_options(options);
  111. unsigned roles = get_my_roles(options);
  112. tt_uint_op(roles, OP_EQ,
  113. PERIODIC_EVENT_ROLE_RELAY|PERIODIC_EVENT_ROLE_DIRSERVER|
  114. PERIODIC_EVENT_ROLE_ALL|PERIODIC_EVENT_ROLE_NET_PARTICIPANT);
  115. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  116. periodic_event_item_t *item = &mainloop_periodic_events[i];
  117. /* Only Client role should be disabled. */
  118. if (item->roles == PERIODIC_EVENT_ROLE_CLIENT) {
  119. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
  120. }
  121. if (item->roles & PERIODIC_EVENT_ROLE_RELAY) {
  122. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
  123. }
  124. /* Non Relay role should be disabled, except for Dirserver. */
  125. if (!(item->roles & roles)) {
  126. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
  127. }
  128. }
  129. /* Disable everything and we'll enable them ALL. */
  130. options->SocksPort_set = 0;
  131. options->ORPort_set = 0;
  132. options->DisableNetwork = 1;
  133. set_network_participation(false);
  134. periodic_events_on_new_options(options);
  135. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  136. periodic_event_item_t *item = &mainloop_periodic_events[i];
  137. int should_be_enabled = (item->roles & PERIODIC_EVENT_ROLE_ALL) &&
  138. !(item->flags & PERIODIC_EVENT_FLAG_NEED_NET);
  139. tt_int_op(periodic_event_is_enabled(item), OP_EQ, should_be_enabled);
  140. }
  141. /* Enable everything. */
  142. options->SocksPort_set = 1; options->ORPort_set = 1;
  143. options->BridgeRelay = 1; options->AuthoritativeDir = 1;
  144. options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
  145. options->DisableNetwork = 0;
  146. set_network_participation(true);
  147. register_dummy_hidden_service(&service);
  148. periodic_events_on_new_options(options);
  149. /* Note down the reference because we need to remove this service from the
  150. * global list before the hs_free_all() call so it doesn't try to free
  151. * memory on the stack. Furthermore, we can't remove it now else it will
  152. * trigger a rescan of the event disabling the HS service event. */
  153. to_remove = &service;
  154. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  155. periodic_event_item_t *item = &mainloop_periodic_events[i];
  156. tt_int_op(periodic_event_is_enabled(item), OP_EQ,
  157. (item->roles != PERIODIC_EVENT_ROLE_CONTROLEV));
  158. }
  159. done:
  160. if (to_remove) {
  161. remove_service(get_hs_service_map(), to_remove);
  162. }
  163. hs_free_all();
  164. }
  165. static void
  166. test_pe_get_roles(void *arg)
  167. {
  168. int roles;
  169. (void) arg;
  170. /* Just so the HS global map exists. */
  171. hs_init();
  172. or_options_t *options = get_options_mutable();
  173. tt_assert(options);
  174. set_network_participation(true);
  175. const int ALL = PERIODIC_EVENT_ROLE_ALL |
  176. PERIODIC_EVENT_ROLE_NET_PARTICIPANT;
  177. /* Nothing configured, should be no roles. */
  178. tt_assert(net_is_disabled());
  179. roles = get_my_roles(options);
  180. tt_int_op(roles, OP_EQ, ALL);
  181. /* Indicate we have a SocksPort, roles should be come Client. */
  182. options->SocksPort_set = 1;
  183. roles = get_my_roles(options);
  184. tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_CLIENT|ALL);
  185. /* Now, we'll add a ORPort so should now be a Relay + Client. */
  186. options->ORPort_set = 1;
  187. roles = get_my_roles(options);
  188. tt_int_op(roles, OP_EQ,
  189. (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
  190. PERIODIC_EVENT_ROLE_DIRSERVER | ALL));
  191. /* Now add a Bridge. */
  192. options->BridgeRelay = 1;
  193. roles = get_my_roles(options);
  194. tt_int_op(roles, OP_EQ,
  195. (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY |
  196. PERIODIC_EVENT_ROLE_BRIDGE | PERIODIC_EVENT_ROLE_DIRSERVER |
  197. ALL));
  198. tt_assert(roles & PERIODIC_EVENT_ROLE_ROUTER);
  199. /* Unset client so we can solely test Router role. */
  200. options->SocksPort_set = 0;
  201. roles = get_my_roles(options);
  202. tt_int_op(roles, OP_EQ,
  203. PERIODIC_EVENT_ROLE_ROUTER | PERIODIC_EVENT_ROLE_DIRSERVER |
  204. ALL);
  205. /* Reset options so we can test authorities. */
  206. options->SocksPort_set = 0;
  207. options->ORPort_set = 0;
  208. options->BridgeRelay = 0;
  209. roles = get_my_roles(options);
  210. tt_int_op(roles, OP_EQ, ALL);
  211. /* Now upgrade to Dirauth. */
  212. options->DirPort_set = 1;
  213. options->AuthoritativeDir = 1;
  214. options->V3AuthoritativeDir = 1;
  215. roles = get_my_roles(options);
  216. tt_int_op(roles, OP_EQ,
  217. PERIODIC_EVENT_ROLE_DIRAUTH|PERIODIC_EVENT_ROLE_DIRSERVER|ALL);
  218. tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
  219. /* Now Bridge Authority. */
  220. options->V3AuthoritativeDir = 0;
  221. options->BridgeAuthoritativeDir = 1;
  222. roles = get_my_roles(options);
  223. tt_int_op(roles, OP_EQ,
  224. PERIODIC_EVENT_ROLE_BRIDGEAUTH|PERIODIC_EVENT_ROLE_DIRSERVER|ALL);
  225. tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
  226. /* Move that bridge auth to become a relay. */
  227. options->ORPort_set = 1;
  228. roles = get_my_roles(options);
  229. tt_int_op(roles, OP_EQ,
  230. (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY
  231. | PERIODIC_EVENT_ROLE_DIRSERVER|ALL));
  232. tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
  233. /* And now an Hidden service. */
  234. hs_service_t service;
  235. register_dummy_hidden_service(&service);
  236. roles = get_my_roles(options);
  237. /* Remove it now so the hs_free_all() doesn't try to free stack memory. */
  238. remove_service(get_hs_service_map(), &service);
  239. tt_int_op(roles, OP_EQ,
  240. (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY |
  241. PERIODIC_EVENT_ROLE_HS_SERVICE | PERIODIC_EVENT_ROLE_DIRSERVER |
  242. ALL));
  243. tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES);
  244. done:
  245. hs_free_all();
  246. }
  247. static void
  248. test_pe_hs_service(void *arg)
  249. {
  250. hs_service_t service, *to_remove = NULL;
  251. (void) arg;
  252. hs_init();
  253. /* We need to put tor in hibernation live state so the events requiring
  254. * network gets enabled. */
  255. consider_hibernation(time(NULL));
  256. /* Initialize the events so we can enable them */
  257. initialize_periodic_events();
  258. periodic_events_connect_all();
  259. /* Hack: We'll set a dumb fn() of each events so they don't get called when
  260. * dispatching them. We just want to test the state of the callbacks, not
  261. * the whole code path. */
  262. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  263. periodic_event_item_t *item = &mainloop_periodic_events[i];
  264. item->fn = dumb_event_fn;
  265. }
  266. /* This should trigger a rescan of the list and enable the HS service
  267. * events. */
  268. register_dummy_hidden_service(&service);
  269. /* Note down the reference because we need to remove this service from the
  270. * global list before the hs_free_all() call so it doesn't try to free
  271. * memory on the stack. Furthermore, we can't remove it now else it will
  272. * trigger a rescan of the event disabling the HS service event. */
  273. to_remove = &service;
  274. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  275. periodic_event_item_t *item = &mainloop_periodic_events[i];
  276. if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
  277. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
  278. }
  279. }
  280. to_remove = NULL;
  281. /* Remove the service from the global map, it should trigger a rescan and
  282. * disable the HS service events. */
  283. remove_service(get_hs_service_map(), &service);
  284. for (int i = 0; mainloop_periodic_events[i].name; ++i) {
  285. periodic_event_item_t *item = &mainloop_periodic_events[i];
  286. if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
  287. tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
  288. }
  289. }
  290. done:
  291. if (to_remove) {
  292. remove_service(get_hs_service_map(), to_remove);
  293. }
  294. hs_free_all();
  295. }
  296. #define PE_TEST(name) \
  297. { #name, test_pe_## name , TT_FORK, NULL, NULL }
  298. struct testcase_t periodic_event_tests[] = {
  299. PE_TEST(initialize),
  300. PE_TEST(launch),
  301. PE_TEST(get_roles),
  302. PE_TEST(hs_service),
  303. END_OF_TESTCASES
  304. };