Line data Source code
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 1 : test_cmux_ewma_active_circuit(void *arg)
17 : {
18 1 : circuitmux_t cmux; /* garbage */
19 1 : circuitmux_policy_data_t *pol_data = NULL;
20 1 : circuit_t circ; /* garbage */
21 1 : circuitmux_policy_circ_data_t *circ_data = NULL;
22 :
23 1 : (void) arg;
24 :
25 1 : pol_data = ewma_policy.alloc_cmux_data(&cmux);
26 1 : tt_assert(pol_data);
27 1 : circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
28 : CELL_DIRECTION_OUT, 42);
29 1 : tt_assert(circ_data);
30 :
31 : /* Get EWMA specific objects. */
32 :
33 : /* Make circuit active. */
34 1 : ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
35 :
36 1 : circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data);
37 1 : tt_mem_op(entry, OP_EQ, &circ, sizeof(circ));
38 :
39 1 : done:
40 1 : ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
41 1 : ewma_policy.free_cmux_data(&cmux, pol_data);
42 1 : }
43 :
44 : static void
45 1 : test_cmux_ewma_xmit_cell(void *arg)
46 : {
47 1 : circuitmux_t cmux; /* garbage */
48 1 : circuitmux_policy_data_t *pol_data = NULL;
49 1 : circuit_t circ; /* garbage */
50 1 : circuitmux_policy_circ_data_t *circ_data = NULL;
51 1 : ewma_policy_data_t *ewma_pol_data;
52 1 : ewma_policy_circ_data_t *ewma_data;
53 1 : double old_cell_count;
54 :
55 1 : (void) arg;
56 :
57 1 : pol_data = ewma_policy.alloc_cmux_data(&cmux);
58 1 : tt_assert(pol_data);
59 1 : circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
60 : CELL_DIRECTION_OUT, 42);
61 1 : tt_assert(circ_data);
62 1 : ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
63 1 : ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
64 :
65 : /* Make circuit active. */
66 1 : 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 1 : ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100;
71 1 : ewma_data->cell_ewma.last_adjusted_tick =
72 : ewma_pol_data->active_circuit_pqueue_last_recalibrated;
73 :
74 : /* Grab old cell count. */
75 1 : old_cell_count = ewma_data->cell_ewma.cell_count;
76 :
77 1 : 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 1 : tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count);
82 :
83 1 : done:
84 1 : ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
85 1 : ewma_policy.free_cmux_data(&cmux, pol_data);
86 1 : }
87 :
88 : static void
89 1 : test_cmux_ewma_notify_circ(void *arg)
90 : {
91 1 : circuitmux_t cmux; /* garbage */
92 1 : circuitmux_policy_data_t *pol_data = NULL;
93 1 : circuit_t circ; /* garbage */
94 1 : circuitmux_policy_circ_data_t *circ_data = NULL;
95 1 : const ewma_policy_data_t *ewma_pol_data;
96 :
97 1 : (void) arg;
98 :
99 1 : pol_data = ewma_policy.alloc_cmux_data(&cmux);
100 1 : tt_assert(pol_data);
101 1 : circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
102 : CELL_DIRECTION_OUT, 42);
103 1 : 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 1 : 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 1 : ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
112 1 : tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1);
113 1 : tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
114 :
115 1 : ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data);
116 : /* Should be removed from the active queue. */
117 1 : ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
118 1 : tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0);
119 1 : tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
120 :
121 1 : done:
122 1 : ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
123 1 : ewma_policy.free_cmux_data(&cmux, pol_data);
124 1 : }
125 :
126 : static void
127 1 : test_cmux_ewma_policy_circ_data(void *arg)
128 : {
129 1 : circuitmux_t cmux; /* garbage */
130 1 : circuitmux_policy_data_t pol_data; /* garbage */
131 1 : circuit_t circ; /* garbage */
132 1 : circuitmux_policy_circ_data_t *circ_data = NULL;
133 1 : const ewma_policy_circ_data_t *ewma_data;
134 :
135 1 : (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 1 : circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
140 : CELL_DIRECTION_OUT, 42);
141 1 : tt_assert(circ_data);
142 1 : tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
143 :
144 1 : ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
145 1 : tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
146 1 : tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
147 1 : tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
148 1 : tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0);
149 1 : ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
150 :
151 1 : circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
152 : CELL_DIRECTION_IN, 42);
153 1 : tt_assert(circ_data);
154 1 : tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
155 :
156 1 : ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
157 1 : tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
158 1 : tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
159 1 : tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
160 1 : tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1);
161 :
162 1 : done:
163 1 : ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
164 1 : }
165 :
166 : static void
167 1 : test_cmux_ewma_policy_data(void *arg)
168 : {
169 1 : circuitmux_t cmux; /* garbage. */
170 1 : circuitmux_policy_data_t *pol_data = NULL;
171 1 : const ewma_policy_data_t *ewma_pol_data;
172 :
173 1 : (void) arg;
174 :
175 1 : pol_data = ewma_policy.alloc_cmux_data(&cmux);
176 1 : tt_assert(pol_data);
177 1 : tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC);
178 :
179 : /* Test EWMA object. */
180 1 : ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
181 1 : tt_assert(ewma_pol_data->active_circuit_pqueue);
182 1 : tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
183 :
184 1 : done:
185 1 : ewma_policy.free_cmux_data(&cmux, pol_data);
186 1 : }
187 :
188 : static void *
189 5 : cmux_ewma_setup_test(const struct testcase_t *tc)
190 : {
191 5 : static int whatever;
192 :
193 5 : (void) tc;
194 :
195 5 : cell_ewma_initialize_ticks();
196 5 : cmux_ewma_set_options(NULL, NULL);
197 :
198 5 : return &whatever;
199 : }
200 :
201 : static int
202 5 : cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr)
203 : {
204 5 : (void) tc;
205 5 : (void) ptr;
206 :
207 5 : circuitmux_ewma_free_all();
208 :
209 5 : 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 : };
|