1 /* Copyright (c) 2014-2018, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define CIRCUITBUILD_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
);
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
));
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
));
61 assert_circuit_ok_mock(const circuit_t
*c
)
68 test_relay_close_circuit(void *arg
)
70 channel_t
*nchan
= NULL
, *pchan
= NULL
;
71 or_circuit_t
*orcirc
= NULL
;
73 int old_count
, new_count
;
77 /* Make fake channels to be nchan and pchan for the circuit */
78 nchan
= new_fake_channel();
81 pchan
= new_fake_channel();
84 /* Make a fake orcirc */
85 orcirc
= new_fake_orcirc(nchan
, pchan
);
87 circuitmux_attach_circuit(nchan
->cmux
, TO_CIRCUIT(orcirc
),
89 circuitmux_attach_circuit(pchan
->cmux
, TO_CIRCUIT(orcirc
),
93 cell
= tor_malloc_zero(sizeof(cell_t
));
96 MOCK(scheduler_channel_has_waiting_cells
,
97 scheduler_channel_has_waiting_cells_mock
);
98 MOCK(assert_circuit_ok
,
99 assert_circuit_ok_mock
);
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 */
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
);
149 free_fake_channel(nchan
);
150 free_fake_channel(pchan
);
151 UNMOCK(assert_circuit_ok
);
157 test_relay_append_cell_to_circuit_queue(void *arg
)
159 channel_t
*nchan
= NULL
, *pchan
= NULL
;
160 or_circuit_t
*orcirc
= NULL
;
162 int old_count
, new_count
;
166 /* Make fake channels to be nchan and pchan for the circuit */
167 nchan
= new_fake_channel();
170 pchan
= new_fake_channel();
173 /* Make a fake orcirc */
174 orcirc
= new_fake_orcirc(nchan
, pchan
);
176 circuitmux_attach_circuit(nchan
->cmux
, TO_CIRCUIT(orcirc
),
178 circuitmux_attach_circuit(pchan
->cmux
, TO_CIRCUIT(orcirc
),
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
);
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 */
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
);
222 free_fake_channel(nchan
);
223 free_fake_channel(pchan
);
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
},