test_scheduler.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /* Copyright (c) 2014-2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include <math.h>
  5. #include <event2/event.h>
  6. #define TOR_CHANNEL_INTERNAL_
  7. #define CHANNEL_PRIVATE_
  8. #include "or.h"
  9. #include "config.h"
  10. #include "compat_libevent.h"
  11. #include "channel.h"
  12. #include "channeltls.h"
  13. #include "connection.h"
  14. #include "networkstatus.h"
  15. #define SCHEDULER_PRIVATE_
  16. #include "scheduler.h"
  17. /* Test suite stuff */
  18. #include "test.h"
  19. #include "fakechans.h"
  20. /* Shamelessly stolen from compat_libevent.c */
  21. #define V(major, minor, patch) \
  22. (((major) << 24) | ((minor) << 16) | ((patch) << 8))
  23. /******************************************************************************
  24. * Statistical info
  25. *****************************************************************************/
  26. static int scheduler_compare_channels_mock_ctr = 0;
  27. static int scheduler_run_mock_ctr = 0;
  28. /******************************************************************************
  29. * Utility functions and things we need to mock
  30. *****************************************************************************/
  31. static or_options_t mocked_options;
  32. static const or_options_t *
  33. mock_get_options(void)
  34. {
  35. return &mocked_options;
  36. }
  37. static void
  38. cleanup_scheduler_options(void)
  39. {
  40. if (mocked_options.SchedulerTypes_) {
  41. SMARTLIST_FOREACH(mocked_options.SchedulerTypes_, int *, i, tor_free(i));
  42. smartlist_free(mocked_options.SchedulerTypes_);
  43. mocked_options.SchedulerTypes_ = NULL;
  44. }
  45. }
  46. static void
  47. set_scheduler_options(int val)
  48. {
  49. int *type;
  50. if (mocked_options.SchedulerTypes_ == NULL) {
  51. mocked_options.SchedulerTypes_ = smartlist_new();
  52. }
  53. type = tor_malloc_zero(sizeof(int));
  54. *type = val;
  55. smartlist_add(mocked_options.SchedulerTypes_, type);
  56. }
  57. static void
  58. clear_options(void)
  59. {
  60. cleanup_scheduler_options();
  61. memset(&mocked_options, 0, sizeof(mocked_options));
  62. }
  63. static int32_t
  64. mock_vanilla_networkstatus_get_param(
  65. const networkstatus_t *ns, const char *param_name, int32_t default_val,
  66. int32_t min_val, int32_t max_val)
  67. {
  68. (void)ns;
  69. (void)default_val;
  70. (void)min_val;
  71. (void)max_val;
  72. // only support KISTSchedRunInterval right now
  73. tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0);
  74. return -1;
  75. }
  76. static int32_t
  77. mock_kist_networkstatus_get_param(
  78. const networkstatus_t *ns, const char *param_name, int32_t default_val,
  79. int32_t min_val, int32_t max_val)
  80. {
  81. (void)ns;
  82. (void)default_val;
  83. (void)min_val;
  84. (void)max_val;
  85. // only support KISTSchedRunInterval right now
  86. tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0);
  87. return 12;
  88. }
  89. /* Event base for scheduelr tests */
  90. static struct event_base *mock_event_base = NULL;
  91. /* Setup for mock event stuff */
  92. static void mock_event_free_all(void);
  93. static void mock_event_init(void);
  94. static void
  95. mock_event_free_all(void)
  96. {
  97. tt_ptr_op(mock_event_base, OP_NE, NULL);
  98. if (mock_event_base) {
  99. event_base_free(mock_event_base);
  100. mock_event_base = NULL;
  101. }
  102. tt_ptr_op(mock_event_base, OP_EQ, NULL);
  103. done:
  104. return;
  105. }
  106. static void
  107. mock_event_init(void)
  108. {
  109. struct event_config *cfg = NULL;
  110. tt_ptr_op(mock_event_base, OP_EQ, NULL);
  111. /*
  112. * Really cut down from tor_libevent_initialize of
  113. * src/common/compat_libevent.c to kill config dependencies
  114. */
  115. if (!mock_event_base) {
  116. cfg = event_config_new();
  117. #if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
  118. /* We can enable changelist support with epoll, since we don't give
  119. * Libevent any dup'd fds. This lets us avoid some syscalls. */
  120. event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
  121. #endif
  122. mock_event_base = event_base_new_with_config(cfg);
  123. event_config_free(cfg);
  124. }
  125. tt_ptr_op(mock_event_base, OP_NE, NULL);
  126. done:
  127. return;
  128. }
  129. static struct event_base *
  130. tor_libevent_get_base_mock(void)
  131. {
  132. return mock_event_base;
  133. }
  134. static int
  135. scheduler_compare_channels_mock(const void *c1_v,
  136. const void *c2_v)
  137. {
  138. uintptr_t p1, p2;
  139. p1 = (uintptr_t)(c1_v);
  140. p2 = (uintptr_t)(c2_v);
  141. ++scheduler_compare_channels_mock_ctr;
  142. if (p1 == p2) return 0;
  143. else if (p1 < p2) return 1;
  144. else return -1;
  145. }
  146. static void
  147. scheduler_run_noop_mock(void)
  148. {
  149. ++scheduler_run_mock_ctr;
  150. }
  151. static circuitmux_t *mock_ccm_tgt_1 = NULL;
  152. static circuitmux_t *mock_ccm_tgt_2 = NULL;
  153. static circuitmux_t *mock_cgp_tgt_1 = NULL;
  154. static circuitmux_policy_t *mock_cgp_val_1 = NULL;
  155. static circuitmux_t *mock_cgp_tgt_2 = NULL;
  156. static circuitmux_policy_t *mock_cgp_val_2 = NULL;
  157. static const circuitmux_policy_t *
  158. circuitmux_get_policy_mock(circuitmux_t *cmux)
  159. {
  160. const circuitmux_policy_t *result = NULL;
  161. tt_assert(cmux != NULL);
  162. if (cmux) {
  163. if (cmux == mock_cgp_tgt_1) result = mock_cgp_val_1;
  164. else if (cmux == mock_cgp_tgt_2) result = mock_cgp_val_2;
  165. else result = circuitmux_get_policy__real(cmux);
  166. }
  167. done:
  168. return result;
  169. }
  170. static int
  171. circuitmux_compare_muxes_mock(circuitmux_t *cmux_1,
  172. circuitmux_t *cmux_2)
  173. {
  174. int result = 0;
  175. tt_assert(cmux_1 != NULL);
  176. tt_assert(cmux_2 != NULL);
  177. if (cmux_1 != cmux_2) {
  178. if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1;
  179. else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) {
  180. result = 1;
  181. } else {
  182. if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_2) result = -1;
  183. else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) {
  184. result = 1;
  185. } else {
  186. result = circuitmux_compare_muxes__real(cmux_1, cmux_2);
  187. }
  188. }
  189. }
  190. /* else result = 0 always */
  191. done:
  192. return result;
  193. }
  194. typedef struct {
  195. const channel_t *chan;
  196. ssize_t cells;
  197. } flush_mock_channel_t;
  198. static smartlist_t *chans_for_flush_mock = NULL;
  199. static void
  200. channel_flush_some_cells_mock_free_all(void)
  201. {
  202. if (chans_for_flush_mock) {
  203. SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
  204. flush_mock_channel_t *,
  205. flush_mock_ch) {
  206. SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
  207. tor_free(flush_mock_ch);
  208. } SMARTLIST_FOREACH_END(flush_mock_ch);
  209. smartlist_free(chans_for_flush_mock);
  210. chans_for_flush_mock = NULL;
  211. }
  212. }
  213. static void
  214. channel_flush_some_cells_mock_set(channel_t *chan, ssize_t num_cells)
  215. {
  216. int found = 0;
  217. if (!chan) return;
  218. if (num_cells <= 0) return;
  219. if (!chans_for_flush_mock) {
  220. chans_for_flush_mock = smartlist_new();
  221. }
  222. SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
  223. flush_mock_channel_t *,
  224. flush_mock_ch) {
  225. if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
  226. if (flush_mock_ch->chan == chan) {
  227. /* Found it */
  228. flush_mock_ch->cells = num_cells;
  229. found = 1;
  230. break;
  231. }
  232. } else {
  233. /* That shouldn't be there... */
  234. SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
  235. tor_free(flush_mock_ch);
  236. }
  237. } SMARTLIST_FOREACH_END(flush_mock_ch);
  238. if (! found) {
  239. /* The loop didn't find it */
  240. flush_mock_channel_t *flush_mock_ch;
  241. flush_mock_ch = tor_malloc_zero(sizeof(*flush_mock_ch));
  242. flush_mock_ch->chan = chan;
  243. flush_mock_ch->cells = num_cells;
  244. smartlist_add(chans_for_flush_mock, flush_mock_ch);
  245. }
  246. }
  247. static int
  248. channel_more_to_flush_mock(channel_t *chan)
  249. {
  250. tor_assert(chan);
  251. flush_mock_channel_t *found_mock_ch = NULL;
  252. /* Check if we have any queued */
  253. if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue))
  254. return 1;
  255. SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
  256. flush_mock_channel_t *,
  257. flush_mock_ch) {
  258. if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
  259. if (flush_mock_ch->chan == chan) {
  260. /* Found it */
  261. found_mock_ch = flush_mock_ch;
  262. break;
  263. }
  264. } else {
  265. /* That shouldn't be there... */
  266. SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
  267. tor_free(flush_mock_ch);
  268. }
  269. } SMARTLIST_FOREACH_END(flush_mock_ch);
  270. tor_assert(found_mock_ch);
  271. /* Check if any circuits would like to queue some */
  272. /* special for the mock: return the number of cells (instead of 1), or zero
  273. * if nothing to flush */
  274. return (found_mock_ch->cells > 0 ? (int)found_mock_ch->cells : 0 );
  275. }
  276. static void
  277. channel_write_to_kernel_mock(channel_t *chan)
  278. {
  279. (void)chan;
  280. //log_debug(LD_SCHED, "chan=%d writing to kernel",
  281. // (int)chan->global_identifier);
  282. }
  283. static int
  284. channel_should_write_to_kernel_mock(outbuf_table_t *ot, channel_t *chan)
  285. {
  286. (void)ot;
  287. (void)chan;
  288. return 1;
  289. /* We could make this more complicated if we wanted. But I don't think doing
  290. * so tests much of anything */
  291. //static int called_counter = 0;
  292. //if (++called_counter >= 3) {
  293. // called_counter -= 3;
  294. // log_debug(LD_SCHED, "chan=%d should write to kernel",
  295. // (int)chan->global_identifier);
  296. // return 1;
  297. //}
  298. //return 0;
  299. }
  300. static ssize_t
  301. channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells)
  302. {
  303. ssize_t flushed = 0, max;
  304. char unlimited = 0;
  305. flush_mock_channel_t *found = NULL;
  306. tt_ptr_op(chan, OP_NE, NULL);
  307. if (chan) {
  308. if (num_cells < 0) {
  309. num_cells = 0;
  310. unlimited = 1;
  311. }
  312. /* Check if we have it */
  313. if (chans_for_flush_mock != NULL) {
  314. SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
  315. flush_mock_channel_t *,
  316. flush_mock_ch) {
  317. if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
  318. if (flush_mock_ch->chan == chan) {
  319. /* Found it */
  320. found = flush_mock_ch;
  321. break;
  322. }
  323. } else {
  324. /* That shouldn't be there... */
  325. SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
  326. tor_free(flush_mock_ch);
  327. }
  328. } SMARTLIST_FOREACH_END(flush_mock_ch);
  329. if (found) {
  330. /* We found one */
  331. if (found->cells < 0) found->cells = 0;
  332. if (unlimited) max = found->cells;
  333. else max = MIN(found->cells, num_cells);
  334. flushed += max;
  335. found->cells -= max;
  336. }
  337. }
  338. }
  339. done:
  340. return flushed;
  341. }
  342. static void
  343. update_socket_info_impl_mock(socket_table_ent_t *ent)
  344. {
  345. ent->cwnd = ent->unacked = ent->mss = ent->notsent = 0;
  346. ent->limit = INT_MAX;
  347. }
  348. static void
  349. perform_channel_state_tests(int KISTSchedRunInterval, int sched_type)
  350. {
  351. channel_t *ch1 = NULL, *ch2 = NULL;
  352. int old_count;
  353. /* setup options so we're sure about what sched we are running */
  354. MOCK(get_options, mock_get_options);
  355. clear_options();
  356. mocked_options.KISTSchedRunInterval = KISTSchedRunInterval;
  357. set_scheduler_options(sched_type);
  358. /* Set up libevent and scheduler */
  359. mock_event_init();
  360. MOCK(tor_libevent_get_base, tor_libevent_get_base_mock);
  361. scheduler_init();
  362. /*
  363. * Install the compare channels mock so we can test
  364. * scheduler_touch_channel().
  365. */
  366. MOCK(scheduler_compare_channels, scheduler_compare_channels_mock);
  367. /*
  368. * Disable scheduler_run so we can just check the state transitions
  369. * without having to make everything it might call work too.
  370. */
  371. ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock;
  372. tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
  373. /* Set up a fake channel */
  374. ch1 = new_fake_channel();
  375. tt_assert(ch1);
  376. /* Start it off in OPENING */
  377. ch1->state = CHANNEL_STATE_OPENING;
  378. /* We'll need a cmux */
  379. ch1->cmux = circuitmux_alloc();
  380. /* Try to register it */
  381. channel_register(ch1);
  382. tt_assert(ch1->registered);
  383. /* It should start off in SCHED_CHAN_IDLE */
  384. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
  385. /* Now get another one */
  386. ch2 = new_fake_channel();
  387. tt_assert(ch2);
  388. ch2->state = CHANNEL_STATE_OPENING;
  389. ch2->cmux = circuitmux_alloc();
  390. channel_register(ch2);
  391. tt_assert(ch2->registered);
  392. /* Send ch1 to SCHED_CHAN_WAITING_TO_WRITE */
  393. scheduler_channel_has_waiting_cells(ch1);
  394. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
  395. /* This should send it to SCHED_CHAN_PENDING */
  396. scheduler_channel_wants_writes(ch1);
  397. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  398. tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
  399. /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */
  400. scheduler_channel_wants_writes(ch2);
  401. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  402. /* Drop ch2 back to idle */
  403. scheduler_channel_doesnt_want_writes(ch2);
  404. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
  405. /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */
  406. scheduler_channel_wants_writes(ch2);
  407. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  408. /* ...and this should kick ch2 into SCHED_CHAN_PENDING */
  409. scheduler_channel_has_waiting_cells(ch2);
  410. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  411. tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
  412. /* This should send ch2 to SCHED_CHAN_WAITING_TO_WRITE */
  413. scheduler_channel_doesnt_want_writes(ch2);
  414. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
  415. tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
  416. /* ...and back to SCHED_CHAN_PENDING */
  417. scheduler_channel_wants_writes(ch2);
  418. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  419. tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
  420. /* Now we exercise scheduler_touch_channel */
  421. old_count = scheduler_compare_channels_mock_ctr;
  422. scheduler_touch_channel(ch1);
  423. tt_assert(scheduler_compare_channels_mock_ctr > old_count);
  424. /* Close */
  425. channel_mark_for_close(ch1);
  426. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING);
  427. channel_mark_for_close(ch2);
  428. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING);
  429. channel_closed(ch1);
  430. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED);
  431. ch1 = NULL;
  432. channel_closed(ch2);
  433. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED);
  434. ch2 = NULL;
  435. /* Shut things down */
  436. channel_free_all();
  437. scheduler_free_all();
  438. mock_event_free_all();
  439. done:
  440. tor_free(ch1);
  441. tor_free(ch2);
  442. UNMOCK(scheduler_compare_channels);
  443. UNMOCK(tor_libevent_get_base);
  444. UNMOCK(get_options);
  445. cleanup_scheduler_options();
  446. return;
  447. }
  448. static void
  449. test_scheduler_compare_channels(void *arg)
  450. {
  451. /* We don't actually need whole fake channels... */
  452. channel_t c1, c2;
  453. /* ...and some dummy circuitmuxes too */
  454. circuitmux_t *cm1 = NULL, *cm2 = NULL;
  455. int result;
  456. (void)arg;
  457. /* We can't actually see sizeof(circuitmux_t) from here */
  458. cm1 = tor_malloc_zero(sizeof(void *));
  459. cm2 = tor_malloc_zero(sizeof(void *));
  460. c1.cmux = cm1;
  461. c2.cmux = cm2;
  462. /* Configure circuitmux_get_policy() mock */
  463. mock_cgp_tgt_1 = cm1;
  464. mock_cgp_tgt_2 = cm2;
  465. /*
  466. * This is to test the different-policies case, which uses the policy
  467. * cast to an uintptr_t as an arbitrary but definite thing to compare.
  468. */
  469. mock_cgp_val_1 = tor_malloc_zero(16);
  470. mock_cgp_val_2 = tor_malloc_zero(16);
  471. if ( ((uintptr_t) mock_cgp_val_1) > ((uintptr_t) mock_cgp_val_2) ) {
  472. void *tmp = mock_cgp_val_1;
  473. mock_cgp_val_1 = mock_cgp_val_2;
  474. mock_cgp_val_2 = tmp;
  475. }
  476. MOCK(circuitmux_get_policy, circuitmux_get_policy_mock);
  477. /* Now set up circuitmux_compare_muxes() mock using cm1/cm2 */
  478. mock_ccm_tgt_1 = cm1;
  479. mock_ccm_tgt_2 = cm2;
  480. MOCK(circuitmux_compare_muxes, circuitmux_compare_muxes_mock);
  481. /* Equal-channel case */
  482. result = scheduler_compare_channels(&c1, &c1);
  483. tt_int_op(result, OP_EQ, 0);
  484. /* Distinct channels, distinct policies */
  485. result = scheduler_compare_channels(&c1, &c2);
  486. tt_int_op(result, OP_EQ, -1);
  487. result = scheduler_compare_channels(&c2, &c1);
  488. tt_int_op(result, OP_EQ, 1);
  489. /* Distinct channels, same policy */
  490. tor_free(mock_cgp_val_2);
  491. mock_cgp_val_2 = mock_cgp_val_1;
  492. result = scheduler_compare_channels(&c1, &c2);
  493. tt_int_op(result, OP_EQ, -1);
  494. result = scheduler_compare_channels(&c2, &c1);
  495. tt_int_op(result, OP_EQ, 1);
  496. done:
  497. UNMOCK(circuitmux_compare_muxes);
  498. mock_ccm_tgt_1 = NULL;
  499. mock_ccm_tgt_2 = NULL;
  500. UNMOCK(circuitmux_get_policy);
  501. mock_cgp_tgt_1 = NULL;
  502. mock_cgp_tgt_2 = NULL;
  503. tor_free(cm1);
  504. tor_free(cm2);
  505. if (mock_cgp_val_1 != mock_cgp_val_2)
  506. tor_free(mock_cgp_val_1);
  507. tor_free(mock_cgp_val_2);
  508. mock_cgp_val_1 = NULL;
  509. mock_cgp_val_2 = NULL;
  510. return;
  511. }
  512. /******************************************************************************
  513. * The actual tests!
  514. *****************************************************************************/
  515. static void
  516. test_scheduler_loop_vanilla(void *arg)
  517. {
  518. (void)arg;
  519. channel_t *ch1 = NULL, *ch2 = NULL;
  520. void (*run_func_ptr)(void);
  521. /* setup options so we're sure about what sched we are running */
  522. MOCK(get_options, mock_get_options);
  523. clear_options();
  524. set_scheduler_options(SCHEDULER_VANILLA);
  525. mocked_options.KISTSchedRunInterval = -1;
  526. /* Set up libevent and scheduler */
  527. mock_event_init();
  528. MOCK(tor_libevent_get_base, tor_libevent_get_base_mock);
  529. scheduler_init();
  530. /*
  531. * Install the compare channels mock so we can test
  532. * scheduler_touch_channel().
  533. */
  534. MOCK(scheduler_compare_channels, scheduler_compare_channels_mock);
  535. /*
  536. * Disable scheduler_run so we can just check the state transitions
  537. * without having to make everything it might call work too.
  538. */
  539. run_func_ptr = the_scheduler->run;
  540. ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock;
  541. tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
  542. /* Set up a fake channel */
  543. ch1 = new_fake_channel();
  544. ch1->magic = TLS_CHAN_MAGIC;
  545. tt_assert(ch1);
  546. /* Start it off in OPENING */
  547. ch1->state = CHANNEL_STATE_OPENING;
  548. /* We'll need a cmux */
  549. ch1->cmux = circuitmux_alloc();
  550. /* Try to register it */
  551. channel_register(ch1);
  552. tt_assert(ch1->registered);
  553. /* Finish opening it */
  554. channel_change_state_open(ch1);
  555. /* It should start off in SCHED_CHAN_IDLE */
  556. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
  557. /* Now get another one */
  558. ch2 = new_fake_channel();
  559. ch2->magic = TLS_CHAN_MAGIC;
  560. tt_assert(ch2);
  561. ch2->state = CHANNEL_STATE_OPENING;
  562. ch2->cmux = circuitmux_alloc();
  563. channel_register(ch2);
  564. tt_assert(ch2->registered);
  565. /*
  566. * Don't open ch2; then channel_num_cells_writeable() will return
  567. * zero and we'll get coverage of that exception case in scheduler_run()
  568. */
  569. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
  570. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING);
  571. /* Send it to SCHED_CHAN_WAITING_TO_WRITE */
  572. scheduler_channel_has_waiting_cells(ch1);
  573. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
  574. /* This should send it to SCHED_CHAN_PENDING */
  575. scheduler_channel_wants_writes(ch1);
  576. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  577. tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
  578. /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */
  579. scheduler_channel_wants_writes(ch2);
  580. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  581. /* Drop ch2 back to idle */
  582. scheduler_channel_doesnt_want_writes(ch2);
  583. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
  584. /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */
  585. scheduler_channel_wants_writes(ch2);
  586. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  587. /* ...and this should kick ch2 into SCHED_CHAN_PENDING */
  588. scheduler_channel_has_waiting_cells(ch2);
  589. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  590. tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
  591. /*
  592. * Now we've got two pending channels and need to fire off
  593. * the scheduler run() that we kept.
  594. */
  595. run_func_ptr();
  596. /*
  597. * Assert that they're still in the states we left and aren't still
  598. * pending
  599. */
  600. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
  601. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING);
  602. tt_assert(ch1->scheduler_state != SCHED_CHAN_PENDING);
  603. tt_assert(ch2->scheduler_state != SCHED_CHAN_PENDING);
  604. tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
  605. /* Now, finish opening ch2, and get both back to pending */
  606. channel_change_state_open(ch2);
  607. scheduler_channel_wants_writes(ch1);
  608. scheduler_channel_wants_writes(ch2);
  609. scheduler_channel_has_waiting_cells(ch1);
  610. scheduler_channel_has_waiting_cells(ch2);
  611. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
  612. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPEN);
  613. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  614. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
  615. tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
  616. /* Now, set up the channel_flush_some_cells() mock */
  617. MOCK(channel_flush_some_cells, channel_flush_some_cells_mock);
  618. /*
  619. * 16 cells on ch1 means it'll completely drain into the 32 cells
  620. * fakechan's num_cells_writeable() returns.
  621. */
  622. channel_flush_some_cells_mock_set(ch1, 16);
  623. /*
  624. * This one should get sent back to pending, since num_cells_writeable()
  625. * will still return non-zero.
  626. */
  627. channel_flush_some_cells_mock_set(ch2, 48);
  628. /*
  629. * And re-run the scheduler run() loop with non-zero returns from
  630. * channel_flush_some_cells() this time.
  631. */
  632. run_func_ptr();
  633. /*
  634. * ch1 should have gone to SCHED_CHAN_WAITING_FOR_CELLS, with 16 flushed
  635. * and 32 writeable.
  636. */
  637. tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  638. /*
  639. * ...ch2 should also have gone to SCHED_CHAN_WAITING_FOR_CELLS, with
  640. * channel_more_to_flush() returning false and channel_num_cells_writeable()
  641. * > 0/
  642. */
  643. tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
  644. /* Close */
  645. channel_mark_for_close(ch1);
  646. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING);
  647. channel_mark_for_close(ch2);
  648. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING);
  649. channel_closed(ch1);
  650. tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED);
  651. ch1 = NULL;
  652. channel_closed(ch2);
  653. tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED);
  654. ch2 = NULL;
  655. /* Shut things down */
  656. channel_flush_some_cells_mock_free_all();
  657. channel_free_all();
  658. scheduler_free_all();
  659. mock_event_free_all();
  660. done:
  661. tor_free(ch1);
  662. tor_free(ch2);
  663. cleanup_scheduler_options();
  664. UNMOCK(channel_flush_some_cells);
  665. UNMOCK(scheduler_compare_channels);
  666. UNMOCK(tor_libevent_get_base);
  667. UNMOCK(get_options);
  668. }
  669. static void
  670. test_scheduler_loop_kist(void *arg)
  671. {
  672. (void) arg;
  673. #ifndef HAVE_KIST_SUPPORT
  674. return;
  675. #endif
  676. channel_t *ch1 = new_fake_channel(), *ch2 = new_fake_channel();
  677. /* setup options so we're sure about what sched we are running */
  678. MOCK(get_options, mock_get_options);
  679. MOCK(channel_flush_some_cells, channel_flush_some_cells_mock);
  680. MOCK(channel_more_to_flush, channel_more_to_flush_mock);
  681. MOCK(channel_write_to_kernel, channel_write_to_kernel_mock);
  682. MOCK(channel_should_write_to_kernel, channel_should_write_to_kernel_mock);
  683. MOCK(update_socket_info_impl, update_socket_info_impl_mock);
  684. clear_options();
  685. mocked_options.KISTSchedRunInterval = 11;
  686. set_scheduler_options(SCHEDULER_KIST);
  687. scheduler_init();
  688. tt_assert(ch1);
  689. ch1->magic = TLS_CHAN_MAGIC;
  690. ch1->state = CHANNEL_STATE_OPENING;
  691. ch1->cmux = circuitmux_alloc();
  692. channel_register(ch1);
  693. tt_assert(ch1->registered);
  694. channel_change_state_open(ch1);
  695. scheduler_channel_has_waiting_cells(ch1);
  696. scheduler_channel_wants_writes(ch1);
  697. channel_flush_some_cells_mock_set(ch1, 5);
  698. tt_assert(ch2);
  699. ch2->magic = TLS_CHAN_MAGIC;
  700. ch2->state = CHANNEL_STATE_OPENING;
  701. ch2->cmux = circuitmux_alloc();
  702. channel_register(ch2);
  703. tt_assert(ch2->registered);
  704. channel_change_state_open(ch2);
  705. scheduler_channel_has_waiting_cells(ch2);
  706. scheduler_channel_wants_writes(ch2);
  707. channel_flush_some_cells_mock_set(ch2, 5);
  708. the_scheduler->run();
  709. scheduler_channel_has_waiting_cells(ch1);
  710. channel_flush_some_cells_mock_set(ch1, 5);
  711. the_scheduler->run();
  712. scheduler_channel_has_waiting_cells(ch1);
  713. channel_flush_some_cells_mock_set(ch1, 5);
  714. scheduler_channel_has_waiting_cells(ch2);
  715. channel_flush_some_cells_mock_set(ch2, 5);
  716. the_scheduler->run();
  717. channel_flush_some_cells_mock_free_all();
  718. tt_int_op(1,==,1);
  719. done:
  720. /* Prep the channel so the free() function doesn't explode. */
  721. ch1->state = ch2->state = CHANNEL_STATE_CLOSED;
  722. ch1->registered = ch2->registered = 0;
  723. channel_free(ch1);
  724. channel_free(ch2);
  725. UNMOCK(update_socket_info_impl);
  726. UNMOCK(channel_should_write_to_kernel);
  727. UNMOCK(channel_write_to_kernel);
  728. UNMOCK(channel_more_to_flush);
  729. UNMOCK(channel_flush_some_cells);
  730. UNMOCK(get_options);
  731. scheduler_free_all();
  732. return;
  733. }
  734. static void
  735. test_scheduler_channel_states(void *arg)
  736. {
  737. (void)arg;
  738. perform_channel_state_tests(-1, SCHEDULER_VANILLA);
  739. perform_channel_state_tests(11, SCHEDULER_KIST_LITE);
  740. #ifdef HAVE_KIST_SUPPORT
  741. perform_channel_state_tests(11, SCHEDULER_KIST);
  742. #endif
  743. }
  744. static void
  745. test_scheduler_initfree(void *arg)
  746. {
  747. (void)arg;
  748. tt_ptr_op(channels_pending, ==, NULL);
  749. tt_ptr_op(run_sched_ev, ==, NULL);
  750. mock_event_init();
  751. MOCK(tor_libevent_get_base, tor_libevent_get_base_mock);
  752. MOCK(get_options, mock_get_options);
  753. set_scheduler_options(SCHEDULER_KIST);
  754. set_scheduler_options(SCHEDULER_KIST_LITE);
  755. set_scheduler_options(SCHEDULER_VANILLA);
  756. scheduler_init();
  757. tt_ptr_op(channels_pending, !=, NULL);
  758. tt_ptr_op(run_sched_ev, !=, NULL);
  759. /* We have specified nothing in the torrc and there's no consensus so the
  760. * KIST scheduler is what should be in use */
  761. tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
  762. tt_int_op(sched_run_interval, ==, 10);
  763. scheduler_free_all();
  764. UNMOCK(tor_libevent_get_base);
  765. mock_event_free_all();
  766. tt_ptr_op(channels_pending, ==, NULL);
  767. tt_ptr_op(run_sched_ev, ==, NULL);
  768. done:
  769. UNMOCK(get_options);
  770. cleanup_scheduler_options();
  771. return;
  772. }
  773. static void
  774. test_scheduler_can_use_kist(void *arg)
  775. {
  776. (void)arg;
  777. int res_should, res_freq;
  778. MOCK(get_options, mock_get_options);
  779. /* Test force disabling of KIST */
  780. clear_options();
  781. mocked_options.KISTSchedRunInterval = -1;
  782. res_should = scheduler_can_use_kist();
  783. res_freq = kist_scheduler_run_interval(NULL);
  784. tt_int_op(res_should, ==, 0);
  785. tt_int_op(res_freq, ==, -1);
  786. /* Test force enabling of KIST */
  787. clear_options();
  788. mocked_options.KISTSchedRunInterval = 1234;
  789. res_should = scheduler_can_use_kist();
  790. res_freq = kist_scheduler_run_interval(NULL);
  791. #ifdef HAVE_KIST_SUPPORT
  792. tt_int_op(res_should, ==, 1);
  793. #else /* HAVE_KIST_SUPPORT */
  794. tt_int_op(res_should, ==, 0);
  795. #endif /* HAVE_KIST_SUPPORT */
  796. tt_int_op(res_freq, ==, 1234);
  797. /* Test defer to consensus, but no consensus available */
  798. clear_options();
  799. mocked_options.KISTSchedRunInterval = 0;
  800. res_should = scheduler_can_use_kist();
  801. res_freq = kist_scheduler_run_interval(NULL);
  802. #ifdef HAVE_KIST_SUPPORT
  803. tt_int_op(res_should, ==, 1);
  804. #else /* HAVE_KIST_SUPPORT */
  805. tt_int_op(res_should, ==, 0);
  806. #endif /* HAVE_KIST_SUPPORT */
  807. tt_int_op(res_freq, ==, 10);
  808. /* Test defer to consensus, and kist consensus available */
  809. MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
  810. clear_options();
  811. mocked_options.KISTSchedRunInterval = 0;
  812. res_should = scheduler_can_use_kist();
  813. res_freq = kist_scheduler_run_interval(NULL);
  814. #ifdef HAVE_KIST_SUPPORT
  815. tt_int_op(res_should, ==, 1);
  816. #else /* HAVE_KIST_SUPPORT */
  817. tt_int_op(res_should, ==, 0);
  818. #endif /* HAVE_KIST_SUPPORT */
  819. tt_int_op(res_freq, ==, 12);
  820. UNMOCK(networkstatus_get_param);
  821. /* Test defer to consensus, and vanilla consensus available */
  822. MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
  823. clear_options();
  824. mocked_options.KISTSchedRunInterval = 0;
  825. res_should = scheduler_can_use_kist();
  826. res_freq = kist_scheduler_run_interval(NULL);
  827. tt_int_op(res_should, ==, 0);
  828. tt_int_op(res_freq, ==, -1);
  829. UNMOCK(networkstatus_get_param);
  830. done:
  831. UNMOCK(get_options);
  832. return;
  833. }
  834. static void
  835. test_scheduler_ns_changed(void *arg)
  836. {
  837. (void) arg;
  838. /*
  839. * Currently no scheduler implementations use the old/new consensuses passed
  840. * in scheduler_notify_networkstatus_changed, so it is okay to pass NULL.
  841. *
  842. * "But then what does test actually exercise???" It tests that
  843. * scheduler_notify_networkstatus_changed fetches the correct value from the
  844. * consensus, and then switches the scheduler if necessasry.
  845. */
  846. MOCK(get_options, mock_get_options);
  847. clear_options();
  848. set_scheduler_options(SCHEDULER_KIST);
  849. set_scheduler_options(SCHEDULER_VANILLA);
  850. tt_ptr_op(the_scheduler, ==, NULL);
  851. /* Change from vanilla to kist via consensus */
  852. the_scheduler = get_vanilla_scheduler();
  853. MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
  854. scheduler_notify_networkstatus_changed(NULL, NULL);
  855. UNMOCK(networkstatus_get_param);
  856. #ifdef HAVE_KIST_SUPPORT
  857. tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
  858. #else
  859. tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
  860. #endif
  861. /* Change from kist to vanilla via consensus */
  862. the_scheduler = get_kist_scheduler();
  863. MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
  864. scheduler_notify_networkstatus_changed(NULL, NULL);
  865. UNMOCK(networkstatus_get_param);
  866. tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
  867. /* Doesn't change when using KIST */
  868. the_scheduler = get_kist_scheduler();
  869. MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
  870. scheduler_notify_networkstatus_changed(NULL, NULL);
  871. UNMOCK(networkstatus_get_param);
  872. #ifdef HAVE_KIST_SUPPORT
  873. tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
  874. #else
  875. tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
  876. #endif
  877. /* Doesn't change when using vanilla */
  878. the_scheduler = get_vanilla_scheduler();
  879. MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
  880. scheduler_notify_networkstatus_changed(NULL, NULL);
  881. UNMOCK(networkstatus_get_param);
  882. tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
  883. done:
  884. UNMOCK(get_options);
  885. cleanup_scheduler_options();
  886. return;
  887. }
  888. struct testcase_t scheduler_tests[] = {
  889. { "compare_channels", test_scheduler_compare_channels,
  890. TT_FORK, NULL, NULL },
  891. { "channel_states", test_scheduler_channel_states, TT_FORK, NULL, NULL },
  892. { "initfree", test_scheduler_initfree, TT_FORK, NULL, NULL },
  893. { "loop_vanilla", test_scheduler_loop_vanilla, TT_FORK, NULL, NULL },
  894. { "loop_kist", test_scheduler_loop_kist, TT_FORK, NULL, NULL },
  895. { "ns_changed", test_scheduler_ns_changed, TT_FORK, NULL, NULL},
  896. { "should_use_kist", test_scheduler_can_use_kist, TT_FORK, NULL, NULL },
  897. END_OF_TESTCASES
  898. };