test_circuitmux_ewma.c (7106B)
1 /* Copyright (c) 2013-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 #define CIRCUITMUX_PRIVATE 5 #define CIRCUITMUX_EWMA_PRIVATE 6 7 #include "core/or/or.h" 8 #include "core/or/circuitmux.h" 9 #include "core/or/circuitmux_ewma.h" 10 11 #include "test/fakechans.h" 12 #include "test/fakecircs.h" 13 #include "test/test.h" 14 15 static void 16 test_cmux_ewma_active_circuit(void *arg) 17 { 18 circuitmux_t cmux; /* garbage */ 19 circuitmux_policy_data_t *pol_data = NULL; 20 circuit_t circ; /* garbage */ 21 circuitmux_policy_circ_data_t *circ_data = NULL; 22 23 (void) arg; 24 25 pol_data = ewma_policy.alloc_cmux_data(&cmux); 26 tt_assert(pol_data); 27 circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, 28 CELL_DIRECTION_OUT, 42); 29 tt_assert(circ_data); 30 31 /* Get EWMA specific objects. */ 32 33 /* Make circuit active. */ 34 ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); 35 36 circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data); 37 tt_mem_op(entry, OP_EQ, &circ, sizeof(circ)); 38 39 done: 40 ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); 41 ewma_policy.free_cmux_data(&cmux, pol_data); 42 } 43 44 static void 45 test_cmux_ewma_xmit_cell(void *arg) 46 { 47 circuitmux_t cmux; /* garbage */ 48 circuitmux_policy_data_t *pol_data = NULL; 49 circuit_t circ; /* garbage */ 50 circuitmux_policy_circ_data_t *circ_data = NULL; 51 ewma_policy_data_t *ewma_pol_data; 52 ewma_policy_circ_data_t *ewma_data; 53 double old_cell_count; 54 55 (void) arg; 56 57 pol_data = ewma_policy.alloc_cmux_data(&cmux); 58 tt_assert(pol_data); 59 circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, 60 CELL_DIRECTION_OUT, 42); 61 tt_assert(circ_data); 62 ewma_pol_data = TO_EWMA_POL_DATA(pol_data); 63 ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); 64 65 /* Make circuit active. */ 66 ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); 67 68 /* Move back in time the last time we calibrated so we scale the active 69 * circuit when emitting a cell. */ 70 ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100; 71 ewma_data->cell_ewma.last_adjusted_tick = 72 ewma_pol_data->active_circuit_pqueue_last_recalibrated; 73 74 /* Grab old cell count. */ 75 old_cell_count = ewma_data->cell_ewma.cell_count; 76 77 ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1); 78 79 /* Our old cell count should be lower to what we have since we just emitted 80 * a cell and thus we scale. */ 81 tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count); 82 83 done: 84 ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); 85 ewma_policy.free_cmux_data(&cmux, pol_data); 86 } 87 88 static void 89 test_cmux_ewma_notify_circ(void *arg) 90 { 91 circuitmux_t cmux; /* garbage */ 92 circuitmux_policy_data_t *pol_data = NULL; 93 circuit_t circ; /* garbage */ 94 circuitmux_policy_circ_data_t *circ_data = NULL; 95 const ewma_policy_data_t *ewma_pol_data; 96 97 (void) arg; 98 99 pol_data = ewma_policy.alloc_cmux_data(&cmux); 100 tt_assert(pol_data); 101 circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, 102 CELL_DIRECTION_OUT, 42); 103 tt_assert(circ_data); 104 105 /* Currently, notify_circ_active() ignores cmux and circ. They can not be 106 * NULL so it is fine to pass garbage. */ 107 ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); 108 109 /* We should have an active circuit in the queue so its EWMA value can be 110 * tracked. */ 111 ewma_pol_data = TO_EWMA_POL_DATA(pol_data); 112 tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1); 113 tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); 114 115 ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data); 116 /* Should be removed from the active queue. */ 117 ewma_pol_data = TO_EWMA_POL_DATA(pol_data); 118 tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0); 119 tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); 120 121 done: 122 ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); 123 ewma_policy.free_cmux_data(&cmux, pol_data); 124 } 125 126 static void 127 test_cmux_ewma_policy_circ_data(void *arg) 128 { 129 circuitmux_t cmux; /* garbage */ 130 circuitmux_policy_data_t pol_data; /* garbage */ 131 circuit_t circ; /* garbage */ 132 circuitmux_policy_circ_data_t *circ_data = NULL; 133 const ewma_policy_circ_data_t *ewma_data; 134 135 (void) arg; 136 137 /* Currently, alloc_circ_data() ignores every parameter _except_ the cell 138 * direction so it is OK to pass garbage. They can not be NULL. */ 139 circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, 140 CELL_DIRECTION_OUT, 42); 141 tt_assert(circ_data); 142 tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); 143 144 ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); 145 tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); 146 tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); 147 tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); 148 tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0); 149 ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); 150 151 circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, 152 CELL_DIRECTION_IN, 42); 153 tt_assert(circ_data); 154 tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); 155 156 ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); 157 tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); 158 tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); 159 tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); 160 tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1); 161 162 done: 163 ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); 164 } 165 166 static void 167 test_cmux_ewma_policy_data(void *arg) 168 { 169 circuitmux_t cmux; /* garbage. */ 170 circuitmux_policy_data_t *pol_data = NULL; 171 const ewma_policy_data_t *ewma_pol_data; 172 173 (void) arg; 174 175 pol_data = ewma_policy.alloc_cmux_data(&cmux); 176 tt_assert(pol_data); 177 tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC); 178 179 /* Test EWMA object. */ 180 ewma_pol_data = TO_EWMA_POL_DATA(pol_data); 181 tt_assert(ewma_pol_data->active_circuit_pqueue); 182 tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); 183 184 done: 185 ewma_policy.free_cmux_data(&cmux, pol_data); 186 } 187 188 static void * 189 cmux_ewma_setup_test(const struct testcase_t *tc) 190 { 191 static int whatever; 192 193 (void) tc; 194 195 cell_ewma_initialize_ticks(); 196 cmux_ewma_set_options(NULL, NULL); 197 198 return &whatever; 199 } 200 201 static int 202 cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr) 203 { 204 (void) tc; 205 (void) ptr; 206 207 circuitmux_ewma_free_all(); 208 209 return 1; 210 } 211 212 static struct testcase_setup_t cmux_ewma_test_setup = { 213 .setup_fn = cmux_ewma_setup_test, 214 .cleanup_fn = cmux_ewma_cleanup_test, 215 }; 216 217 #define TEST_CMUX_EWMA(name) \ 218 { #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL } 219 220 struct testcase_t circuitmux_ewma_tests[] = { 221 TEST_CMUX_EWMA(active_circuit), 222 TEST_CMUX_EWMA(policy_data), 223 TEST_CMUX_EWMA(policy_circ_data), 224 TEST_CMUX_EWMA(notify_circ), 225 TEST_CMUX_EWMA(xmit_cell), 226 227 END_OF_TESTCASES 228 };