test_periodic_event.c 11 KB

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