Merge remote-tracking branch 'teor/ticket28318-035' into maint-0.3.5
[tor.git] / src / test / test_relay.c
blob4311392be8af3d75d6b8de6a7b4bfed59898c6a6
1 /* Copyright (c) 2014-2018, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define CIRCUITBUILD_PRIVATE
5 #define RELAY_PRIVATE
6 #define REPHIST_PRIVATE
7 #include "core/or/or.h"
8 #include "core/or/circuitbuild.h"
9 #include "core/or/circuitlist.h"
10 #include "core/or/channeltls.h"
11 #include "feature/stats/rephist.h"
12 #include "core/or/relay.h"
13 #include "feature/stats/rephist.h"
14 #include "lib/container/order.h"
15 /* For init/free stuff */
16 #include "core/or/scheduler.h"
18 #include "core/or/cell_st.h"
19 #include "core/or/or_circuit_st.h"
21 /* Test suite stuff */
22 #include "test/test.h"
23 #include "test/fakechans.h"
25 static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
27 static void test_relay_append_cell_to_circuit_queue(void *arg);
29 static or_circuit_t *
30 new_fake_orcirc(channel_t *nchan, channel_t *pchan)
32 or_circuit_t *orcirc = NULL;
33 circuit_t *circ = NULL;
35 orcirc = tor_malloc_zero(sizeof(*orcirc));
36 circ = &(orcirc->base_);
37 circ->magic = OR_CIRCUIT_MAGIC;
39 circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
40 cell_queue_init(&(circ->n_chan_cells));
42 circ->n_hop = NULL;
43 circ->streams_blocked_on_n_chan = 0;
44 circ->streams_blocked_on_p_chan = 0;
45 circ->n_delete_pending = 0;
46 circ->p_delete_pending = 0;
47 circ->received_destroy = 0;
48 circ->state = CIRCUIT_STATE_OPEN;
49 circ->purpose = CIRCUIT_PURPOSE_OR;
50 circ->package_window = CIRCWINDOW_START_MAX;
51 circ->deliver_window = CIRCWINDOW_START_MAX;
52 circ->n_chan_create_cell = NULL;
54 circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
55 cell_queue_init(&(orcirc->p_chan_cells));
57 return orcirc;
60 static void
61 assert_circuit_ok_mock(const circuit_t *c)
63 (void) c;
64 return;
67 static void
68 test_relay_close_circuit(void *arg)
70 channel_t *nchan = NULL, *pchan = NULL;
71 or_circuit_t *orcirc = NULL;
72 cell_t *cell = NULL;
73 int old_count, new_count;
75 (void)arg;
77 /* Make fake channels to be nchan and pchan for the circuit */
78 nchan = new_fake_channel();
79 tt_assert(nchan);
81 pchan = new_fake_channel();
82 tt_assert(pchan);
84 /* Make a fake orcirc */
85 orcirc = new_fake_orcirc(nchan, pchan);
86 tt_assert(orcirc);
87 circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
88 CELL_DIRECTION_OUT);
89 circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
90 CELL_DIRECTION_IN);
92 /* Make a cell */
93 cell = tor_malloc_zero(sizeof(cell_t));
94 make_fake_cell(cell);
96 MOCK(scheduler_channel_has_waiting_cells,
97 scheduler_channel_has_waiting_cells_mock);
98 MOCK(assert_circuit_ok,
99 assert_circuit_ok_mock);
101 /* Append it */
102 old_count = get_mock_scheduler_has_waiting_cells_count();
103 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
104 CELL_DIRECTION_OUT, 0);
105 new_count = get_mock_scheduler_has_waiting_cells_count();
106 tt_int_op(new_count, OP_EQ, old_count + 1);
108 /* Now try the reverse direction */
109 old_count = get_mock_scheduler_has_waiting_cells_count();
110 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
111 CELL_DIRECTION_IN, 0);
112 new_count = get_mock_scheduler_has_waiting_cells_count();
113 tt_int_op(new_count, OP_EQ, old_count + 1);
115 /* Ensure our write totals are 0 */
116 tt_u64_op(find_largest_max(write_array), OP_EQ, 0);
118 /* Mark the circuit for close */
119 circuit_mark_for_close(TO_CIRCUIT(orcirc), 0);
121 /* Check our write totals. */
122 advance_obs(write_array);
123 commit_max(write_array);
124 /* Check for two cells plus overhead */
125 tt_u64_op(find_largest_max(write_array), OP_EQ,
126 2*(get_cell_network_size(nchan->wide_circ_ids)
127 +TLS_PER_CELL_OVERHEAD));
129 UNMOCK(scheduler_channel_has_waiting_cells);
131 /* Get rid of the fake channels */
132 MOCK(scheduler_release_channel, scheduler_release_channel_mock);
133 channel_mark_for_close(nchan);
134 channel_mark_for_close(pchan);
135 UNMOCK(scheduler_release_channel);
137 /* Shut down channels */
138 channel_free_all();
140 done:
141 tor_free(cell);
142 if (orcirc) {
143 circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
144 circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
145 cell_queue_clear(&orcirc->base_.n_chan_cells);
146 cell_queue_clear(&orcirc->p_chan_cells);
148 tor_free(orcirc);
149 free_fake_channel(nchan);
150 free_fake_channel(pchan);
151 UNMOCK(assert_circuit_ok);
153 return;
156 static void
157 test_relay_append_cell_to_circuit_queue(void *arg)
159 channel_t *nchan = NULL, *pchan = NULL;
160 or_circuit_t *orcirc = NULL;
161 cell_t *cell = NULL;
162 int old_count, new_count;
164 (void)arg;
166 /* Make fake channels to be nchan and pchan for the circuit */
167 nchan = new_fake_channel();
168 tt_assert(nchan);
170 pchan = new_fake_channel();
171 tt_assert(pchan);
173 /* Make a fake orcirc */
174 orcirc = new_fake_orcirc(nchan, pchan);
175 tt_assert(orcirc);
176 circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
177 CELL_DIRECTION_OUT);
178 circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
179 CELL_DIRECTION_IN);
181 /* Make a cell */
182 cell = tor_malloc_zero(sizeof(cell_t));
183 make_fake_cell(cell);
185 MOCK(scheduler_channel_has_waiting_cells,
186 scheduler_channel_has_waiting_cells_mock);
188 /* Append it */
189 old_count = get_mock_scheduler_has_waiting_cells_count();
190 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
191 CELL_DIRECTION_OUT, 0);
192 new_count = get_mock_scheduler_has_waiting_cells_count();
193 tt_int_op(new_count, OP_EQ, old_count + 1);
195 /* Now try the reverse direction */
196 old_count = get_mock_scheduler_has_waiting_cells_count();
197 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
198 CELL_DIRECTION_IN, 0);
199 new_count = get_mock_scheduler_has_waiting_cells_count();
200 tt_int_op(new_count, OP_EQ, old_count + 1);
202 UNMOCK(scheduler_channel_has_waiting_cells);
204 /* Get rid of the fake channels */
205 MOCK(scheduler_release_channel, scheduler_release_channel_mock);
206 channel_mark_for_close(nchan);
207 channel_mark_for_close(pchan);
208 UNMOCK(scheduler_release_channel);
210 /* Shut down channels */
211 channel_free_all();
213 done:
214 tor_free(cell);
215 if (orcirc) {
216 circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
217 circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
218 cell_queue_clear(&orcirc->base_.n_chan_cells);
219 cell_queue_clear(&orcirc->p_chan_cells);
221 tor_free(orcirc);
222 free_fake_channel(nchan);
223 free_fake_channel(pchan);
225 return;
228 struct testcase_t relay_tests[] = {
229 { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
230 TT_FORK, NULL, NULL },
231 { "close_circ_rephist", test_relay_close_circuit,
232 TT_FORK, NULL, NULL },
233 END_OF_TESTCASES