1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 #include "orconfig.h"
5 
6 #include <math.h>
7 
8 #define SCHEDULER_KIST_PRIVATE
9 #define CHANNEL_OBJECT_PRIVATE
10 #define CHANNEL_FILE_PRIVATE
11 #include "core/or/or.h"
12 #include "app/config/config.h"
13 #include "lib/evloop/compat_libevent.h"
14 #include "core/or/channel.h"
15 #include "core/or/channeltls.h"
16 #include "core/mainloop/connection.h"
17 #include "feature/nodelist/networkstatus.h"
18 #define SCHEDULER_PRIVATE
19 #include "core/or/scheduler.h"
20 
21 /* Test suite stuff */
22 #include "test/test.h"
23 #include "test/fakechans.h"
24 
25 /* Shamelessly stolen from compat_libevent.c */
26 #define V(major, minor, patch) \
27   (((major) << 24) | ((minor) << 16) | ((patch) << 8))
28 
29 /******************************************************************************
30  * Statistical info
31  *****************************************************************************/
32 static int scheduler_compare_channels_mock_ctr = 0;
33 static int scheduler_run_mock_ctr = 0;
34 
35 /******************************************************************************
36  * Utility functions and things we need to mock
37  *****************************************************************************/
38 static or_options_t mocked_options;
39 static const or_options_t *
mock_get_options(void)40 mock_get_options(void)
41 {
42   return &mocked_options;
43 }
44 
45 static void
cleanup_scheduler_options(void)46 cleanup_scheduler_options(void)
47 {
48   if (mocked_options.SchedulerTypes_) {
49     SMARTLIST_FOREACH(mocked_options.SchedulerTypes_, int *, i, tor_free(i));
50     smartlist_free(mocked_options.SchedulerTypes_);
51     mocked_options.SchedulerTypes_ = NULL;
52   }
53 }
54 
55 static void
set_scheduler_options(int val)56 set_scheduler_options(int val)
57 {
58   int *type;
59 
60   if (mocked_options.SchedulerTypes_ == NULL) {
61     mocked_options.SchedulerTypes_ = smartlist_new();
62   }
63   type = tor_malloc_zero(sizeof(int));
64   *type = val;
65   smartlist_add(mocked_options.SchedulerTypes_, type);
66 }
67 
68 static void
clear_options(void)69 clear_options(void)
70 {
71   cleanup_scheduler_options();
72   memset(&mocked_options, 0, sizeof(mocked_options));
73 }
74 
75 static int32_t
mock_vanilla_networkstatus_get_param(const networkstatus_t * ns,const char * param_name,int32_t default_val,int32_t min_val,int32_t max_val)76 mock_vanilla_networkstatus_get_param(
77     const networkstatus_t *ns, const char *param_name, int32_t default_val,
78     int32_t min_val, int32_t max_val)
79 {
80   (void)ns;
81   (void)default_val;
82   (void)min_val;
83   (void)max_val;
84   // only support KISTSchedRunInterval right now
85   tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0);
86   return 0;
87 }
88 
89 static int32_t
mock_kist_networkstatus_get_param(const networkstatus_t * ns,const char * param_name,int32_t default_val,int32_t min_val,int32_t max_val)90 mock_kist_networkstatus_get_param(
91     const networkstatus_t *ns, const char *param_name, int32_t default_val,
92     int32_t min_val, int32_t max_val)
93 {
94   (void)ns;
95   (void)default_val;
96   (void)min_val;
97   (void)max_val;
98   // only support KISTSchedRunInterval right now
99   tor_assert(strcmp(param_name, "KISTSchedRunInterval")==0);
100   return 12;
101 }
102 
103 static int
scheduler_compare_channels_mock(const void * c1_v,const void * c2_v)104 scheduler_compare_channels_mock(const void *c1_v,
105                                 const void *c2_v)
106 {
107   uintptr_t p1, p2;
108 
109   p1 = (uintptr_t)(c1_v);
110   p2 = (uintptr_t)(c2_v);
111 
112   ++scheduler_compare_channels_mock_ctr;
113 
114   if (p1 == p2) return 0;
115   else if (p1 < p2) return 1;
116   else return -1;
117 }
118 
119 static void
scheduler_run_noop_mock(void)120 scheduler_run_noop_mock(void)
121 {
122   ++scheduler_run_mock_ctr;
123 }
124 
125 static circuitmux_t *mock_ccm_tgt_1 = NULL;
126 static circuitmux_t *mock_ccm_tgt_2 = NULL;
127 static circuitmux_t *mock_cgp_tgt_1 = NULL;
128 static circuitmux_policy_t *mock_cgp_val_1 = NULL;
129 static circuitmux_t *mock_cgp_tgt_2 = NULL;
130 static circuitmux_policy_t *mock_cgp_val_2 = NULL;
131 
132 static const circuitmux_policy_t *
circuitmux_get_policy_mock(circuitmux_t * cmux)133 circuitmux_get_policy_mock(circuitmux_t *cmux)
134 {
135   const circuitmux_policy_t *result = NULL;
136 
137   tt_assert(cmux != NULL);
138   if (cmux) {
139     if (cmux == mock_cgp_tgt_1) result = mock_cgp_val_1;
140     else if (cmux == mock_cgp_tgt_2) result = mock_cgp_val_2;
141     else result = circuitmux_get_policy__real(cmux);
142   }
143 
144  done:
145   return result;
146 }
147 
148 static int
circuitmux_compare_muxes_mock(circuitmux_t * cmux_1,circuitmux_t * cmux_2)149 circuitmux_compare_muxes_mock(circuitmux_t *cmux_1,
150                               circuitmux_t *cmux_2)
151 {
152   int result = 0;
153 
154   tt_assert(cmux_1 != NULL);
155   tt_assert(cmux_2 != NULL);
156 
157   if (cmux_1 != cmux_2) {
158     if (cmux_1 == mock_ccm_tgt_1 && cmux_2 == mock_ccm_tgt_2) result = -1;
159     else if (cmux_1 == mock_ccm_tgt_2 && cmux_2 == mock_ccm_tgt_1) {
160       result = 1;
161     } else {
162       if (cmux_1 == mock_ccm_tgt_1 || cmux_1 == mock_ccm_tgt_2) result = -1;
163       else if (cmux_2 == mock_ccm_tgt_1 || cmux_2 == mock_ccm_tgt_2) {
164         result = 1;
165       } else {
166         result = circuitmux_compare_muxes__real(cmux_1, cmux_2);
167       }
168     }
169   }
170   /* else result = 0 always */
171 
172  done:
173   return result;
174 }
175 
176 typedef struct {
177   const channel_t *chan;
178   ssize_t cells;
179 } flush_mock_channel_t;
180 
181 static smartlist_t *chans_for_flush_mock = NULL;
182 
183 static void
channel_flush_some_cells_mock_free_all(void)184 channel_flush_some_cells_mock_free_all(void)
185 {
186   if (chans_for_flush_mock) {
187     SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
188                             flush_mock_channel_t *,
189                             flush_mock_ch) {
190       SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
191       tor_free(flush_mock_ch);
192     } SMARTLIST_FOREACH_END(flush_mock_ch);
193 
194     smartlist_free(chans_for_flush_mock);
195     chans_for_flush_mock = NULL;
196   }
197 }
198 
199 static void
channel_flush_some_cells_mock_set(channel_t * chan,ssize_t num_cells)200 channel_flush_some_cells_mock_set(channel_t *chan, ssize_t num_cells)
201 {
202   int found = 0;
203 
204   if (!chan) return;
205   if (num_cells <= 0) return;
206 
207   if (!chans_for_flush_mock) {
208     chans_for_flush_mock = smartlist_new();
209   }
210 
211   SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
212                           flush_mock_channel_t *,
213                           flush_mock_ch) {
214     if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
215       if (flush_mock_ch->chan == chan) {
216         /* Found it */
217         flush_mock_ch->cells = num_cells;
218         found = 1;
219         break;
220       }
221     } else {
222       /* That shouldn't be there... */
223       SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
224       tor_free(flush_mock_ch);
225     }
226   } SMARTLIST_FOREACH_END(flush_mock_ch);
227 
228   if (! found) {
229     /* The loop didn't find it */
230     flush_mock_channel_t *flush_mock_ch;
231     flush_mock_ch = tor_malloc_zero(sizeof(*flush_mock_ch));
232     flush_mock_ch->chan = chan;
233     flush_mock_ch->cells = num_cells;
234     smartlist_add(chans_for_flush_mock, flush_mock_ch);
235   }
236 }
237 
238 static int
channel_more_to_flush_mock(channel_t * chan)239 channel_more_to_flush_mock(channel_t *chan)
240 {
241   tor_assert(chan);
242 
243   flush_mock_channel_t *found_mock_ch = NULL;
244 
245   SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
246                           flush_mock_channel_t *,
247                           flush_mock_ch) {
248     if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
249       if (flush_mock_ch->chan == chan) {
250         /* Found it */
251         found_mock_ch = flush_mock_ch;
252         break;
253       }
254     } else {
255       /* That shouldn't be there... */
256       SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
257       tor_free(flush_mock_ch);
258     }
259   } SMARTLIST_FOREACH_END(flush_mock_ch);
260 
261   tor_assert(found_mock_ch);
262 
263   /* Check if any circuits would like to queue some */
264   /* special for the mock: return the number of cells (instead of 1), or zero
265    * if nothing to flush */
266   return (found_mock_ch->cells > 0 ? (int)found_mock_ch->cells : 0 );
267 }
268 
269 static void
channel_write_to_kernel_mock(channel_t * chan)270 channel_write_to_kernel_mock(channel_t *chan)
271 {
272   (void)chan;
273   //log_debug(LD_SCHED, "chan=%d writing to kernel",
274   //    (int)chan->global_identifier);
275 }
276 
277 static int
channel_should_write_to_kernel_mock(outbuf_table_t * ot,channel_t * chan)278 channel_should_write_to_kernel_mock(outbuf_table_t *ot, channel_t *chan)
279 {
280   (void)ot;
281   (void)chan;
282   return 1;
283   /* We could make this more complicated if we wanted. But I don't think doing
284    * so tests much of anything */
285   //static int called_counter = 0;
286   //if (++called_counter >= 3) {
287   //  called_counter -= 3;
288   //  log_debug(LD_SCHED, "chan=%d should write to kernel",
289   //      (int)chan->global_identifier);
290   //  return 1;
291   //}
292   //return 0;
293 }
294 
295 static ssize_t
channel_flush_some_cells_mock(channel_t * chan,ssize_t num_cells)296 channel_flush_some_cells_mock(channel_t *chan, ssize_t num_cells)
297 {
298   ssize_t flushed = 0, max;
299   char unlimited = 0;
300   flush_mock_channel_t *found = NULL;
301 
302   tt_ptr_op(chan, OP_NE, NULL);
303   if (chan) {
304     if (num_cells < 0) {
305       num_cells = 0;
306       unlimited = 1;
307     }
308 
309     /* Check if we have it */
310     if (chans_for_flush_mock != NULL) {
311       SMARTLIST_FOREACH_BEGIN(chans_for_flush_mock,
312                               flush_mock_channel_t *,
313                               flush_mock_ch) {
314         if (flush_mock_ch != NULL && flush_mock_ch->chan != NULL) {
315           if (flush_mock_ch->chan == chan) {
316             /* Found it */
317             found = flush_mock_ch;
318             break;
319           }
320         } else {
321           /* That shouldn't be there... */
322           SMARTLIST_DEL_CURRENT(chans_for_flush_mock, flush_mock_ch);
323           tor_free(flush_mock_ch);
324         }
325       } SMARTLIST_FOREACH_END(flush_mock_ch);
326 
327       if (found) {
328         /* We found one */
329         if (found->cells < 0) found->cells = 0;
330 
331         if (unlimited) max = found->cells;
332         else max = MIN(found->cells, num_cells);
333 
334         flushed += max;
335         found->cells -= max;
336       }
337     }
338   }
339 
340  done:
341   return flushed;
342 }
343 
344 static void
update_socket_info_impl_mock(socket_table_ent_t * ent)345 update_socket_info_impl_mock(socket_table_ent_t *ent)
346 {
347   ent->cwnd = ent->unacked = ent->mss = ent->notsent = 0;
348   ent->limit = INT_MAX;
349 }
350 
351 static void
perform_channel_state_tests(int KISTSchedRunInterval,int sched_type)352 perform_channel_state_tests(int KISTSchedRunInterval, int sched_type)
353 {
354   channel_t *ch1 = NULL, *ch2 = NULL;
355   int old_count;
356 
357   /* setup options so we're sure about what sched we are running */
358   MOCK(get_options, mock_get_options);
359   clear_options();
360   mocked_options.KISTSchedRunInterval = KISTSchedRunInterval;
361   set_scheduler_options(sched_type);
362 
363   /* Set up scheduler */
364   scheduler_init();
365   /*
366    * Install the compare channels mock so we can test
367    * scheduler_touch_channel().
368    */
369   MOCK(scheduler_compare_channels, scheduler_compare_channels_mock);
370   /*
371    * Disable scheduler_run so we can just check the state transitions
372    * without having to make everything it might call work too.
373    */
374   ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock;
375 
376   tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
377 
378   /* Set up a fake channel */
379   ch1 = new_fake_channel();
380   tt_assert(ch1);
381 
382   /* Start it off in OPENING */
383   ch1->state = CHANNEL_STATE_OPENING;
384   /* Try to register it */
385   channel_register(ch1);
386   tt_assert(ch1->registered);
387 
388   /* It should start off in SCHED_CHAN_IDLE */
389   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
390 
391   /* Now get another one */
392   ch2 = new_fake_channel();
393   tt_assert(ch2);
394   ch2->state = CHANNEL_STATE_OPENING;
395   channel_register(ch2);
396   tt_assert(ch2->registered);
397 
398   /* Send ch1 to SCHED_CHAN_WAITING_TO_WRITE */
399   scheduler_channel_has_waiting_cells(ch1);
400   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
401 
402   /* This should send it to SCHED_CHAN_PENDING */
403   scheduler_channel_wants_writes(ch1);
404   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
405   tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
406 
407   /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */
408   scheduler_channel_wants_writes(ch2);
409   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
410 
411   /* Drop ch2 back to idle */
412   scheduler_channel_doesnt_want_writes(ch2);
413   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
414 
415   /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */
416   scheduler_channel_wants_writes(ch2);
417   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
418 
419   /* ...and this should kick ch2 into SCHED_CHAN_PENDING */
420   scheduler_channel_has_waiting_cells(ch2);
421   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
422   tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
423 
424   /* This should send ch2 to SCHED_CHAN_WAITING_TO_WRITE */
425   scheduler_channel_doesnt_want_writes(ch2);
426   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
427   tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
428 
429   /* ...and back to SCHED_CHAN_PENDING */
430   scheduler_channel_wants_writes(ch2);
431   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
432   tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
433 
434   /* Now we exercise scheduler_touch_channel */
435   old_count = scheduler_compare_channels_mock_ctr;
436   scheduler_touch_channel(ch1);
437   tt_assert(scheduler_compare_channels_mock_ctr > old_count);
438 
439   /* Release the ch2 and then do it another time to make sure it doesn't blow
440    * up and we are still in a quiescent state. */
441   scheduler_release_channel(ch2);
442   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
443   tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
444   /* Cheat a bit so make the release more confused but also will tells us if
445    * the release did put the channel in the right state. */
446   ch2->scheduler_state = SCHED_CHAN_PENDING;
447   scheduler_release_channel(ch2);
448   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
449   tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
450 
451   /* Close */
452   channel_mark_for_close(ch1);
453   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING);
454   channel_mark_for_close(ch2);
455   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING);
456   channel_closed(ch1);
457   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED);
458   ch1 = NULL;
459   channel_closed(ch2);
460   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED);
461   ch2 = NULL;
462 
463   /* Shut things down */
464 
465   channel_free_all();
466   scheduler_free_all();
467 
468  done:
469   tor_free(ch1);
470   tor_free(ch2);
471 
472   UNMOCK(scheduler_compare_channels);
473   UNMOCK(get_options);
474   cleanup_scheduler_options();
475 
476   return;
477 }
478 
479 static void
test_scheduler_compare_channels(void * arg)480 test_scheduler_compare_channels(void *arg)
481 {
482   /* We don't actually need whole fake channels... */
483   channel_t c1, c2;
484   /* ...and some dummy circuitmuxes too */
485   circuitmux_t *cm1 = NULL, *cm2 = NULL;
486   int result;
487 
488   (void)arg;
489 
490   /* We can't actually see sizeof(circuitmux_t) from here */
491   cm1 = tor_malloc_zero(sizeof(void *));
492   cm2 = tor_malloc_zero(sizeof(void *));
493 
494   c1.cmux = cm1;
495   c2.cmux = cm2;
496 
497   /* Configure circuitmux_get_policy() mock */
498   mock_cgp_tgt_1 = cm1;
499   mock_cgp_tgt_2 = cm2;
500 
501   /*
502    * This is to test the different-policies case, which uses the policy
503    * cast to an uintptr_t as an arbitrary but definite thing to compare.
504    */
505   mock_cgp_val_1 = tor_malloc_zero(16);
506   mock_cgp_val_2 = tor_malloc_zero(16);
507   if ( ((uintptr_t) mock_cgp_val_1) > ((uintptr_t) mock_cgp_val_2) ) {
508     void *tmp = mock_cgp_val_1;
509     mock_cgp_val_1 = mock_cgp_val_2;
510     mock_cgp_val_2 = tmp;
511   }
512 
513   MOCK(circuitmux_get_policy, circuitmux_get_policy_mock);
514 
515   /* Now set up circuitmux_compare_muxes() mock using cm1/cm2 */
516   mock_ccm_tgt_1 = cm1;
517   mock_ccm_tgt_2 = cm2;
518   MOCK(circuitmux_compare_muxes, circuitmux_compare_muxes_mock);
519 
520   /* Equal-channel case */
521   result = scheduler_compare_channels(&c1, &c1);
522   tt_int_op(result, OP_EQ, 0);
523 
524   /* Distinct channels, distinct policies */
525   result = scheduler_compare_channels(&c1, &c2);
526   tt_int_op(result, OP_EQ, -1);
527   result = scheduler_compare_channels(&c2, &c1);
528   tt_int_op(result, OP_EQ, 1);
529 
530   /* Distinct channels, same policy */
531   tor_free(mock_cgp_val_2);
532   mock_cgp_val_2 = mock_cgp_val_1;
533   result = scheduler_compare_channels(&c1, &c2);
534   tt_int_op(result, OP_EQ, -1);
535   result = scheduler_compare_channels(&c2, &c1);
536   tt_int_op(result, OP_EQ, 1);
537 
538  done:
539 
540   UNMOCK(circuitmux_compare_muxes);
541   mock_ccm_tgt_1 = NULL;
542   mock_ccm_tgt_2 = NULL;
543 
544   UNMOCK(circuitmux_get_policy);
545   mock_cgp_tgt_1 = NULL;
546   mock_cgp_tgt_2 = NULL;
547 
548   tor_free(cm1);
549   tor_free(cm2);
550 
551   if (mock_cgp_val_1 != mock_cgp_val_2)
552     tor_free(mock_cgp_val_1);
553   tor_free(mock_cgp_val_2);
554   mock_cgp_val_1 = NULL;
555   mock_cgp_val_2 = NULL;
556 
557   return;
558 }
559 
560 /******************************************************************************
561  * The actual tests!
562  *****************************************************************************/
563 
564 static void
test_scheduler_loop_vanilla(void * arg)565 test_scheduler_loop_vanilla(void *arg)
566 {
567   (void)arg;
568   channel_t *ch1 = NULL, *ch2 = NULL;
569   void (*run_func_ptr)(void);
570 
571   /* setup options so we're sure about what sched we are running */
572   MOCK(get_options, mock_get_options);
573   clear_options();
574   set_scheduler_options(SCHEDULER_VANILLA);
575   mocked_options.KISTSchedRunInterval = 0;
576 
577   /* Set up scheduler */
578   scheduler_init();
579   /*
580    * Install the compare channels mock so we can test
581    * scheduler_touch_channel().
582    */
583   MOCK(scheduler_compare_channels, scheduler_compare_channels_mock);
584   /*
585    * Disable scheduler_run so we can just check the state transitions
586    * without having to make everything it might call work too.
587    */
588   run_func_ptr = the_scheduler->run;
589   ((scheduler_t *) the_scheduler)->run = scheduler_run_noop_mock;
590 
591   tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
592 
593   /* Set up a fake channel */
594   ch1 = new_fake_channel();
595   ch1->magic = TLS_CHAN_MAGIC;
596   tt_assert(ch1);
597 
598   /* Start it off in OPENING */
599   ch1->state = CHANNEL_STATE_OPENING;
600   /* Try to register it */
601   channel_register(ch1);
602   tt_assert(ch1->registered);
603   /* Finish opening it */
604   channel_change_state_open(ch1);
605 
606   /* It should start off in SCHED_CHAN_IDLE */
607   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
608 
609   /* Now get another one */
610   ch2 = new_fake_channel();
611   ch2->magic = TLS_CHAN_MAGIC;
612   tt_assert(ch2);
613   ch2->state = CHANNEL_STATE_OPENING;
614   channel_register(ch2);
615   tt_assert(ch2->registered);
616   /*
617    * Don't open ch2; then channel_num_cells_writeable() will return
618    * zero and we'll get coverage of that exception case in scheduler_run()
619    */
620 
621   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
622   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING);
623 
624   /* Send it to SCHED_CHAN_WAITING_TO_WRITE */
625   scheduler_channel_has_waiting_cells(ch1);
626   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
627 
628   /* This should send it to SCHED_CHAN_PENDING */
629   scheduler_channel_wants_writes(ch1);
630   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
631   tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
632 
633   /* Now send ch2 to SCHED_CHAN_WAITING_FOR_CELLS */
634   scheduler_channel_wants_writes(ch2);
635   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
636 
637   /* Drop ch2 back to idle */
638   scheduler_channel_doesnt_want_writes(ch2);
639   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
640 
641   /* ...and back to SCHED_CHAN_WAITING_FOR_CELLS */
642   scheduler_channel_wants_writes(ch2);
643   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
644 
645   /* ...and this should kick ch2 into SCHED_CHAN_PENDING */
646   scheduler_channel_has_waiting_cells(ch2);
647   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
648   tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
649 
650   /*
651    * Now we've got two pending channels and need to fire off
652    * the scheduler run() that we kept.
653    */
654   run_func_ptr();
655 
656   /*
657    * Assert that they're still in the states we left and aren't still
658    * pending
659    */
660   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
661   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPENING);
662   tt_assert(ch1->scheduler_state != SCHED_CHAN_PENDING);
663   tt_assert(ch2->scheduler_state != SCHED_CHAN_PENDING);
664   tt_int_op(smartlist_len(channels_pending), OP_EQ, 0);
665 
666   /* Now, finish opening ch2, and get both back to pending */
667   channel_change_state_open(ch2);
668   scheduler_channel_wants_writes(ch1);
669   scheduler_channel_wants_writes(ch2);
670   scheduler_channel_has_waiting_cells(ch1);
671   scheduler_channel_has_waiting_cells(ch2);
672   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_OPEN);
673   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_OPEN);
674   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
675   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
676   tt_int_op(smartlist_len(channels_pending), OP_EQ, 2);
677 
678   /* Now, set up the channel_flush_some_cells() mock */
679   MOCK(channel_flush_some_cells, channel_flush_some_cells_mock);
680   /*
681    * 16 cells on ch1 means it'll completely drain into the 32 cells
682    * fakechan's num_cells_writeable() returns.
683    */
684   channel_flush_some_cells_mock_set(ch1, 16);
685   /*
686    * This one should get sent back to pending, since num_cells_writeable()
687    * will still return non-zero.
688    */
689   channel_flush_some_cells_mock_set(ch2, 48);
690 
691   /*
692    * And re-run the scheduler run() loop with non-zero returns from
693    * channel_flush_some_cells() this time.
694    */
695   run_func_ptr();
696 
697   /*
698    * ch1 should have gone to SCHED_CHAN_WAITING_FOR_CELLS, with 16 flushed
699    * and 32 writeable.
700    */
701   tt_int_op(ch1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
702   /*
703    * ...ch2 should also have gone to SCHED_CHAN_WAITING_FOR_CELLS, with
704    * channel_more_to_flush() returning false and channel_num_cells_writeable()
705    * > 0/
706    */
707   tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
708 
709   /* Close */
710   channel_mark_for_close(ch1);
711   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING);
712   channel_mark_for_close(ch2);
713   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING);
714   channel_closed(ch1);
715   tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSED);
716   ch1 = NULL;
717   channel_closed(ch2);
718   tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSED);
719   ch2 = NULL;
720 
721   /* Shut things down */
722   channel_flush_some_cells_mock_free_all();
723   channel_free_all();
724   scheduler_free_all();
725 
726  done:
727   tor_free(ch1);
728   tor_free(ch2);
729   cleanup_scheduler_options();
730 
731   UNMOCK(channel_flush_some_cells);
732   UNMOCK(scheduler_compare_channels);
733   UNMOCK(get_options);
734 }
735 
736 static void
test_scheduler_loop_kist(void * arg)737 test_scheduler_loop_kist(void *arg)
738 {
739   (void) arg;
740 
741 #ifndef HAVE_KIST_SUPPORT
742   return;
743 #endif
744 
745   channel_t *ch1 = new_fake_channel(), *ch2 = new_fake_channel();
746   channel_t *ch3 = new_fake_channel();
747 
748   /* setup options so we're sure about what sched we are running */
749   MOCK(get_options, mock_get_options);
750   MOCK(channel_flush_some_cells, channel_flush_some_cells_mock);
751   MOCK(channel_more_to_flush, channel_more_to_flush_mock);
752   MOCK(channel_write_to_kernel, channel_write_to_kernel_mock);
753   MOCK(channel_should_write_to_kernel, channel_should_write_to_kernel_mock);
754   MOCK(update_socket_info_impl, update_socket_info_impl_mock);
755   clear_options();
756   mocked_options.KISTSchedRunInterval = 11;
757   set_scheduler_options(SCHEDULER_KIST);
758   scheduler_init();
759 
760   tt_assert(ch1);
761   ch1->magic = TLS_CHAN_MAGIC;
762   ch1->state = CHANNEL_STATE_OPENING;
763   channel_register(ch1);
764   tt_assert(ch1->registered);
765   channel_change_state_open(ch1);
766   scheduler_channel_has_waiting_cells(ch1);
767   scheduler_channel_wants_writes(ch1);
768   channel_flush_some_cells_mock_set(ch1, 5);
769 
770   tt_assert(ch2);
771   ch2->magic = TLS_CHAN_MAGIC;
772   ch2->state = CHANNEL_STATE_OPENING;
773   channel_register(ch2);
774   tt_assert(ch2->registered);
775   channel_change_state_open(ch2);
776   scheduler_channel_has_waiting_cells(ch2);
777   scheduler_channel_wants_writes(ch2);
778   channel_flush_some_cells_mock_set(ch2, 5);
779 
780   the_scheduler->run();
781 
782   scheduler_channel_has_waiting_cells(ch1);
783   channel_flush_some_cells_mock_set(ch1, 5);
784 
785   the_scheduler->run();
786 
787   scheduler_channel_has_waiting_cells(ch1);
788   channel_flush_some_cells_mock_set(ch1, 5);
789   scheduler_channel_has_waiting_cells(ch2);
790   channel_flush_some_cells_mock_set(ch2, 5);
791 
792   the_scheduler->run();
793 
794   channel_flush_some_cells_mock_free_all();
795 
796   /* We'll try to run this closed channel threw the scheduler loop and make
797    * sure it ends up in the right state. */
798   tt_assert(ch3);
799   ch3->magic = TLS_CHAN_MAGIC;
800   ch3->state = CHANNEL_STATE_OPEN;
801   circuitmux_free(ch3->cmux);
802   ch3->cmux = circuitmux_alloc();
803   channel_register(ch3);
804   tt_assert(ch3->registered);
805 
806   ch3->scheduler_state = SCHED_CHAN_WAITING_FOR_CELLS;
807   scheduler_channel_has_waiting_cells(ch3);
808   /* Should be in the pending list now waiting to be handled. */
809   tt_int_op(ch3->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
810   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
811   /* By running the scheduler on a closed channel, it should end up in the
812    * IDLE state and not in the pending channel list. */
813   ch3->state = CHANNEL_STATE_CLOSED;
814   the_scheduler->run();
815   tt_int_op(ch3->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
816   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
817 
818  done:
819   /* Prep the channel so the free() function doesn't explode. */
820   ch1->state = ch2->state = ch3->state = CHANNEL_STATE_CLOSED;
821   ch1->registered = ch2->registered = ch3->registered = 0;
822   channel_free(ch1);
823   channel_free(ch2);
824   channel_free(ch3);
825   UNMOCK(update_socket_info_impl);
826   UNMOCK(channel_should_write_to_kernel);
827   UNMOCK(channel_write_to_kernel);
828   UNMOCK(channel_more_to_flush);
829   UNMOCK(channel_flush_some_cells);
830   UNMOCK(get_options);
831   scheduler_free_all();
832   return;
833 }
834 
835 static void
test_scheduler_channel_states(void * arg)836 test_scheduler_channel_states(void *arg)
837 {
838   (void)arg;
839   perform_channel_state_tests(-1, SCHEDULER_VANILLA);
840   perform_channel_state_tests(11, SCHEDULER_KIST_LITE);
841 #ifdef HAVE_KIST_SUPPORT
842   perform_channel_state_tests(11, SCHEDULER_KIST);
843 #endif
844 }
845 
846 static void
test_scheduler_initfree(void * arg)847 test_scheduler_initfree(void *arg)
848 {
849   (void)arg;
850 
851   tt_ptr_op(channels_pending, OP_EQ, NULL);
852   tt_ptr_op(run_sched_ev, OP_EQ, NULL);
853 
854   MOCK(get_options, mock_get_options);
855   set_scheduler_options(SCHEDULER_KIST);
856   set_scheduler_options(SCHEDULER_KIST_LITE);
857   set_scheduler_options(SCHEDULER_VANILLA);
858 
859   scheduler_init();
860 
861   tt_ptr_op(channels_pending, OP_NE, NULL);
862   tt_ptr_op(run_sched_ev, OP_NE, NULL);
863   /* We have specified nothing in the torrc and there's no consensus so the
864    * KIST scheduler is what should be in use */
865   tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
866   tt_int_op(sched_run_interval, OP_EQ, 10);
867 
868   scheduler_free_all();
869 
870   tt_ptr_op(channels_pending, OP_EQ, NULL);
871   tt_ptr_op(run_sched_ev, OP_EQ, NULL);
872 
873  done:
874   UNMOCK(get_options);
875   cleanup_scheduler_options();
876   return;
877 }
878 
879 static void
test_scheduler_can_use_kist(void * arg)880 test_scheduler_can_use_kist(void *arg)
881 {
882   (void)arg;
883 
884   int res_should, res_freq;
885   MOCK(get_options, mock_get_options);
886 
887   /* Test force enabling of KIST */
888   clear_options();
889   mocked_options.KISTSchedRunInterval = 1234;
890   res_should = scheduler_can_use_kist();
891   res_freq = kist_scheduler_run_interval();
892 #ifdef HAVE_KIST_SUPPORT
893   tt_int_op(res_should, OP_EQ, 1);
894 #else /* HAVE_KIST_SUPPORT */
895   tt_int_op(res_should, OP_EQ, 0);
896 #endif /* HAVE_KIST_SUPPORT */
897   tt_int_op(res_freq, OP_EQ, 1234);
898 
899   /* Test defer to consensus, but no consensus available */
900   clear_options();
901   mocked_options.KISTSchedRunInterval = 0;
902   res_should = scheduler_can_use_kist();
903   res_freq = kist_scheduler_run_interval();
904 #ifdef HAVE_KIST_SUPPORT
905   tt_int_op(res_should, OP_EQ, 1);
906 #else /* HAVE_KIST_SUPPORT */
907   tt_int_op(res_should, OP_EQ, 0);
908 #endif /* HAVE_KIST_SUPPORT */
909   tt_int_op(res_freq, OP_EQ, 10);
910 
911   /* Test defer to consensus, and kist consensus available */
912   MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
913   clear_options();
914   mocked_options.KISTSchedRunInterval = 0;
915   res_should = scheduler_can_use_kist();
916   res_freq = kist_scheduler_run_interval();
917 #ifdef HAVE_KIST_SUPPORT
918   tt_int_op(res_should, OP_EQ, 1);
919 #else /* HAVE_KIST_SUPPORT */
920   tt_int_op(res_should, OP_EQ, 0);
921 #endif /* HAVE_KIST_SUPPORT */
922   tt_int_op(res_freq, OP_EQ, 12);
923   UNMOCK(networkstatus_get_param);
924 
925   /* Test defer to consensus, and vanilla consensus available */
926   MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
927   clear_options();
928   mocked_options.KISTSchedRunInterval = 0;
929   res_should = scheduler_can_use_kist();
930   res_freq = kist_scheduler_run_interval();
931   tt_int_op(res_should, OP_EQ, 0);
932   tt_int_op(res_freq, OP_EQ, 0);
933   UNMOCK(networkstatus_get_param);
934 
935  done:
936   UNMOCK(get_options);
937   return;
938 }
939 
940 static void
test_scheduler_ns_changed(void * arg)941 test_scheduler_ns_changed(void *arg)
942 {
943   (void) arg;
944 
945   /*
946    * Currently no scheduler implementations use the old/new consensuses passed
947    * in scheduler_notify_networkstatus_changed, so it is okay to pass NULL.
948    *
949    * "But then what does test actually exercise???" It tests that
950    * scheduler_notify_networkstatus_changed fetches the correct value from the
951    * consensus, and then switches the scheduler if necessasry.
952    */
953 
954   MOCK(get_options, mock_get_options);
955   clear_options();
956   set_scheduler_options(SCHEDULER_KIST);
957   set_scheduler_options(SCHEDULER_VANILLA);
958 
959   tt_ptr_op(the_scheduler, OP_EQ, NULL);
960 
961   /* Change from vanilla to kist via consensus */
962   the_scheduler = get_vanilla_scheduler();
963   MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
964   scheduler_notify_networkstatus_changed();
965   UNMOCK(networkstatus_get_param);
966 #ifdef HAVE_KIST_SUPPORT
967   tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
968 #else
969   tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
970 #endif
971 
972   /* Change from kist to vanilla via consensus */
973   the_scheduler = get_kist_scheduler();
974   MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
975   scheduler_notify_networkstatus_changed();
976   UNMOCK(networkstatus_get_param);
977   tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
978 
979   /* Doesn't change when using KIST */
980   the_scheduler = get_kist_scheduler();
981   MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
982   scheduler_notify_networkstatus_changed();
983   UNMOCK(networkstatus_get_param);
984 #ifdef HAVE_KIST_SUPPORT
985   tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
986 #else
987   tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
988 #endif
989 
990   /* Doesn't change when using vanilla */
991   the_scheduler = get_vanilla_scheduler();
992   MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
993   scheduler_notify_networkstatus_changed();
994   UNMOCK(networkstatus_get_param);
995   tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
996 
997  done:
998   UNMOCK(get_options);
999   cleanup_scheduler_options();
1000   return;
1001 }
1002 
1003 /*
1004  * Mocked functions for the kist_pending_list test.
1005  */
1006 
1007 static int mock_flush_some_cells_num = 1;
1008 static int mock_more_to_flush = 0;
1009 static int mock_update_socket_info_limit = 0;
1010 
1011 static ssize_t
channel_flush_some_cells_mock_var(channel_t * chan,ssize_t num_cells)1012 channel_flush_some_cells_mock_var(channel_t *chan, ssize_t num_cells)
1013 {
1014   (void) chan;
1015   (void) num_cells;
1016   return mock_flush_some_cells_num;
1017 }
1018 
1019 /* Because when we flush cells, it is possible that the connection outbuf gets
1020  * fully drained, the wants to write scheduler event is fired back while we
1021  * are in the scheduler loop so this mock function does it for us.
1022  * Furthermore, the socket limit is set to 0 so once this is triggered, it
1023  * informs the scheduler that it can't write on the socket anymore. */
1024 static void
channel_write_to_kernel_mock_trigger_24700(channel_t * chan)1025 channel_write_to_kernel_mock_trigger_24700(channel_t *chan)
1026 {
1027   static int chan_id_seen[2] = {0};
1028   if (++chan_id_seen[chan->global_identifier - 1] > 1) {
1029     tt_assert(0);
1030   }
1031 
1032   scheduler_channel_wants_writes(chan);
1033 
1034  done:
1035   return;
1036 }
1037 
1038 static int
channel_more_to_flush_mock_var(channel_t * chan)1039 channel_more_to_flush_mock_var(channel_t *chan)
1040 {
1041   (void) chan;
1042   return mock_more_to_flush;
1043 }
1044 
1045 static void
update_socket_info_impl_mock_var(socket_table_ent_t * ent)1046 update_socket_info_impl_mock_var(socket_table_ent_t *ent)
1047 {
1048   ent->cwnd = ent->unacked = ent->mss = ent->notsent = 0;
1049   ent->limit = mock_update_socket_info_limit;
1050 }
1051 
1052 static void
test_scheduler_kist_pending_list(void * arg)1053 test_scheduler_kist_pending_list(void *arg)
1054 {
1055   (void) arg;
1056 
1057 #ifndef HAVE_KIST_SUPPORT
1058   return;
1059 #endif
1060 
1061   /* This is for testing the channel flow with the pending list that is
1062    * depending on the channel state, what will be the expected behavior of the
1063    * scheduler with that list.
1064    *
1065    * For instance, we want to catch double channel add or removing a channel
1066    * that doesn't exists, or putting a channel in the list in a wrong state.
1067    * Essentially, this will articifically test cases of the KIST main loop and
1068    * entry point in the channel subsystem.
1069    *
1070    * In part, this is to also catch things like #24700 and provide a test bed
1071    * for more testing in the future like so. */
1072 
1073   /* Mocking a series of scheduler function to control the flow of the
1074    * scheduler loop to test every use cases and assess the pending list. */
1075   MOCK(get_options, mock_get_options);
1076   MOCK(channel_flush_some_cells, channel_flush_some_cells_mock_var);
1077   MOCK(channel_more_to_flush, channel_more_to_flush_mock_var);
1078   MOCK(update_socket_info_impl, update_socket_info_impl_mock_var);
1079   MOCK(channel_write_to_kernel, channel_write_to_kernel_mock);
1080   MOCK(channel_should_write_to_kernel, channel_should_write_to_kernel_mock);
1081 
1082   /* Setup options so we're sure about what sched we are running */
1083   mocked_options.KISTSchedRunInterval = 10;
1084   set_scheduler_options(SCHEDULER_KIST);
1085 
1086   /* Init scheduler. */
1087   scheduler_init();
1088 
1089   /* Initialize a channel. We'll need a second channel for the #24700 bug
1090    * test. */
1091   channel_t *chan1 = new_fake_channel();
1092   channel_t *chan2 = new_fake_channel();
1093   tt_assert(chan1);
1094   tt_assert(chan2);
1095   chan1->magic = chan2->magic = TLS_CHAN_MAGIC;
1096   channel_register(chan1);
1097   channel_register(chan2);
1098   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
1099   tt_int_op(chan1->sched_heap_idx, OP_EQ, -1);
1100   tt_int_op(chan2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
1101   tt_int_op(chan2->sched_heap_idx, OP_EQ, -1);
1102 
1103   /* Once a channel becomes OPEN, it always have at least one cell in it so
1104    * the scheduler is notified that the channel wants to write so this is the
1105    * first step. Might not make sense to you but it is the way it is. */
1106   scheduler_channel_wants_writes(chan1);
1107   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
1108   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1109 
1110   /* Signal the scheduler that it has waiting cells which means the channel
1111    * will get scheduled. */
1112   scheduler_channel_has_waiting_cells(chan1);
1113   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1114   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1115   /* Subsequent call should not add it more times. It is possible we add many
1116    * cells in rapid succession before the channel is scheduled. */
1117   scheduler_channel_has_waiting_cells(chan1);
1118   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1119   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1120   scheduler_channel_has_waiting_cells(chan1);
1121   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1122   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1123 
1124   /* We'll flush one cell and make it that the socket can write but no more to
1125    * flush else we end up in an infinite loop. We expect the channel to be put
1126    * in waiting for cells state and the pending list empty. */
1127   mock_update_socket_info_limit = INT_MAX;
1128   mock_more_to_flush = 0;
1129   the_scheduler->run();
1130   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1131   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
1132 
1133   /* Lets make believe that a cell is now in the channel but this time the
1134    * channel can't write so obviously it has more to flush. We expect the
1135    * channel to be back in the pending list. */
1136   scheduler_channel_has_waiting_cells(chan1);
1137   mock_update_socket_info_limit = 0;
1138   mock_more_to_flush = 1;
1139   the_scheduler->run();
1140   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1141   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1142 
1143   /* Channel is in the pending list now, during that time, we'll trigger a
1144    * wants to write event because maybe the channel buffers were emptied in
1145    * the meantime. This is possible because once the connection outbuf is
1146    * flushed down the low watermark, the scheduler is notified.
1147    *
1148    * We expect the channel to NOT be added in the pending list again and stay
1149    * in PENDING state. */
1150   scheduler_channel_wants_writes(chan1);
1151   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1152   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1153 
1154   /* Make it that the channel can write now but has nothing else to flush. We
1155    * expect that it is removed from the pending list and waiting for cells. */
1156   mock_update_socket_info_limit = INT_MAX;
1157   mock_more_to_flush = 0;
1158   the_scheduler->run();
1159   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1160   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
1161 
1162   /* While waiting for cells, lets say we were able to write more things on
1163    * the connection outbuf (unlikely that this can happen but let say it
1164    * does). We expect the channel to stay in waiting for cells. */
1165   scheduler_channel_wants_writes(chan1);
1166   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1167   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
1168 
1169   /* We'll not put it in the pending list and make the flush cell fail with 0
1170    * cell flushed. We expect that it is put back in waiting for cells. */
1171   scheduler_channel_has_waiting_cells(chan1);
1172   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1173   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1174   mock_flush_some_cells_num = 0;
1175   the_scheduler->run();
1176   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1177   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_FOR_CELLS);
1178 
1179   /* Set the channel to a state where it doesn't want to write more. We expect
1180    * that the channel becomes idle. */
1181   scheduler_channel_doesnt_want_writes(chan1);
1182   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1183   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
1184 
1185   /* Some cells arrive on the channel now. We expect it to go back in waiting
1186    * to write. You might wonder why it is not put in the pending list? Because
1187    * once the channel becomes OPEN again (the doesn't want to write event only
1188    * occurs if the channel goes in MAINT mode), if there are cells in the
1189    * channel, the wants to write event is triggered thus putting the channel
1190    * in pending mode.
1191    *
1192    * Else, if no cells, it stays IDLE and then once a cell comes in, it should
1193    * go in waiting to write which is a BUG itself because the channel can't be
1194    * scheduled until a second cell comes in. Hopefully, #24554 will fix that
1195    * for KIST. */
1196   scheduler_channel_has_waiting_cells(chan1);
1197   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1198   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
1199 
1200   /* Second cell comes in, unfortunately, it won't get scheduled until a wants
1201    * to write event occurs like described above. */
1202   scheduler_channel_has_waiting_cells(chan1);
1203   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 0);
1204   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_WAITING_TO_WRITE);
1205 
1206   /* Unblock everything putting the channel in the pending list. */
1207   scheduler_channel_wants_writes(chan1);
1208   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 1);
1209   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1210 
1211   /* Testing bug #24700 which is the situation where we have at least two
1212    * different channels in the pending list. The first one gets flushed and
1213    * bytes are written on the wire which triggers a wants to write event
1214    * because the outbuf is below the low watermark. The bug was that this
1215    * exact channel was added back in the pending list because its state wasn't
1216    * PENDING.
1217    *
1218    * The following does some ninja-tsu to try to make it happen. We need two
1219    * different channels so we create a second one and add it to the pending
1220    * list. Then, we have a custom function when we write to kernel that does
1221    * two important things:
1222    *
1223    *  1) Calls scheduler_channel_wants_writes(chan) on the channel.
1224    *  2) Keeps track of how many times it sees the channel going through. If
1225    *     that limit goes > 1, it means we've added the channel twice in the
1226    *     pending list.
1227    *
1228    * In the end, we expect both channels to be in the pending list after this
1229    * scheduler run. */
1230 
1231   /* Put the second channel in the pending list. */
1232   scheduler_channel_wants_writes(chan2);
1233   scheduler_channel_has_waiting_cells(chan2);
1234   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 2);
1235   tt_int_op(chan2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1236 
1237   /* This makes it that the first pass on socket_can_write() will be true but
1238    * then when a single cell is flushed (514 + 29 bytes), the second call to
1239    * socket_can_write() will be false. If it wasn't sending back false on the
1240    * second run, we end up in an infinite loop of the scheduler. */
1241   mock_update_socket_info_limit = 600;
1242   /* We want to hit "Case 3:" of the scheduler so channel_more_to_flush() is
1243    * true but socket_can_write() has to be false on the second check on the
1244    * channel. */
1245   mock_more_to_flush = 1;
1246   mock_flush_some_cells_num = 1;
1247   MOCK(channel_write_to_kernel, channel_write_to_kernel_mock_trigger_24700);
1248   the_scheduler->run();
1249   tt_int_op(smartlist_len(get_channels_pending()), OP_EQ, 2);
1250   tt_int_op(chan1->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1251   tt_int_op(chan2->scheduler_state, OP_EQ, SCHED_CHAN_PENDING);
1252 
1253  done:
1254   chan1->state = chan2->state = CHANNEL_STATE_CLOSED;
1255   chan1->registered = chan2->registered = 0;
1256   channel_free(chan1);
1257   channel_free(chan2);
1258   scheduler_free_all();
1259 
1260   UNMOCK(get_options);
1261   UNMOCK(channel_flush_some_cells);
1262   UNMOCK(channel_more_to_flush);
1263   UNMOCK(update_socket_info_impl);
1264   UNMOCK(channel_write_to_kernel);
1265   UNMOCK(channel_should_write_to_kernel);
1266 }
1267 
1268 struct testcase_t scheduler_tests[] = {
1269   { "compare_channels", test_scheduler_compare_channels,
1270     TT_FORK, NULL, NULL },
1271   { "channel_states", test_scheduler_channel_states, TT_FORK, NULL, NULL },
1272   { "initfree", test_scheduler_initfree, TT_FORK, NULL, NULL },
1273   { "loop_vanilla", test_scheduler_loop_vanilla, TT_FORK, NULL, NULL },
1274   { "loop_kist", test_scheduler_loop_kist, TT_FORK, NULL, NULL },
1275   { "ns_changed", test_scheduler_ns_changed, TT_FORK, NULL, NULL},
1276   { "should_use_kist", test_scheduler_can_use_kist, TT_FORK, NULL, NULL },
1277   { "kist_pending_list", test_scheduler_kist_pending_list, TT_FORK,
1278     NULL, NULL },
1279   END_OF_TESTCASES
1280 };
1281 
1282