1 /* Copyright (c) 2014-2015, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 #define TOR_CHANNEL_INTERNAL_
11 #include "channeltls.h"
12 #include "connection_or.h"
14 /* For init/free stuff */
15 #include "scheduler.h"
18 /* Test suite stuff */
20 #include "fakechans.h"
22 /* The channeltls unit tests */
23 static void test_channeltls_create(void *arg
);
24 static void test_channeltls_num_bytes_queued(void *arg
);
25 static void test_channeltls_overhead_estimate(void *arg
);
27 /* Mocks used by channeltls unit tests */
28 static size_t tlschan_buf_datalen_mock(const buf_t
*buf
);
29 static or_connection_t
* tlschan_connection_or_connect_mock(
30 const tor_addr_t
*addr
,
33 channel_tls_t
*tlschan
);
34 static int tlschan_is_local_addr_mock(const tor_addr_t
*addr
);
36 /* Fake close method */
37 static void tlschan_fake_close_method(channel_t
*chan
);
39 /* Flags controlling behavior of channeltls unit test mocks */
40 static int tlschan_local
= 0;
41 static const buf_t
* tlschan_buf_datalen_mock_target
= NULL
;
42 static size_t tlschan_buf_datalen_mock_size
= 0;
44 /* Thing to cast to fake tor_tls_t * to appease assert_connection_ok() */
45 static int fake_tortls
= 0; /* Bleh... */
48 test_channeltls_create(void *arg
)
52 const char test_digest
[DIGEST_LEN
] = {
53 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
54 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
58 /* Set up a fake address to fake-connect to */
59 test_addr
.family
= AF_INET
;
60 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
62 /* For this test we always want the address to be treated as non-local */
64 /* Install is_local_addr() mock */
65 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
67 /* Install mock for connection_or_connect() */
68 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
71 ch
= channel_tls_connect(&test_addr
, 567, test_digest
);
72 tt_assert(ch
!= NULL
);
76 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
78 * Use fake close method that doesn't try to do too much to fake
81 ch
->close
= tlschan_fake_close_method
;
82 channel_mark_for_close(ch
);
83 free_fake_channel(ch
);
84 UNMOCK(scheduler_release_channel
);
87 UNMOCK(connection_or_connect
);
88 UNMOCK(is_local_addr
);
94 test_channeltls_num_bytes_queued(void *arg
)
98 const char test_digest
[DIGEST_LEN
] = {
99 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
100 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
101 channel_tls_t
*tlschan
= NULL
;
103 int fake_outbuf
= 0, n
;
107 /* Set up a fake address to fake-connect to */
108 test_addr
.family
= AF_INET
;
109 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
111 /* For this test we always want the address to be treated as non-local */
113 /* Install is_local_addr() mock */
114 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
116 /* Install mock for connection_or_connect() */
117 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
120 ch
= channel_tls_connect(&test_addr
, 567, test_digest
);
121 tt_assert(ch
!= NULL
);
124 * Next, we have to test ch->num_bytes_queued, which is
125 * channel_tls_num_bytes_queued_method. We can't mock
126 * connection_get_outbuf_len() directly because it's static INLINE
127 * in connection.h, but we can mock buf_datalen(). Note that
128 * if bufferevents ever work, this will break with them enabled.
131 tt_assert(ch
->num_bytes_queued
!= NULL
);
132 tlschan
= BASE_CHAN_TO_TLS(ch
);
133 tt_assert(tlschan
!= NULL
);
134 if (TO_CONN(tlschan
->conn
)->outbuf
== NULL
) {
135 /* We need an outbuf to make sure buf_datalen() gets called */
137 TO_CONN(tlschan
->conn
)->outbuf
= buf_new();
139 tlschan_buf_datalen_mock_target
= TO_CONN(tlschan
->conn
)->outbuf
;
140 tlschan_buf_datalen_mock_size
= 1024;
141 MOCK(buf_datalen
, tlschan_buf_datalen_mock
);
142 len
= ch
->num_bytes_queued(ch
);
143 tt_int_op(len
, ==, tlschan_buf_datalen_mock_size
);
145 * We also cover num_cells_writeable here; since wide_circ_ids = 0 on
146 * the fake tlschans, cell_network_size returns 512, and so with
147 * tlschan_buf_datalen_mock_size == 1024, we should be able to write
148 * ceil((OR_CONN_HIGHWATER - 1024) / 512) = ceil(OR_CONN_HIGHWATER / 512)
151 n
= ch
->num_cells_writeable(ch
);
152 tt_int_op(n
, ==, CEIL_DIV(OR_CONN_HIGHWATER
, 512) - 2);
154 tlschan_buf_datalen_mock_target
= NULL
;
155 tlschan_buf_datalen_mock_size
= 0;
157 buf_free(TO_CONN(tlschan
->conn
)->outbuf
);
158 TO_CONN(tlschan
->conn
)->outbuf
= NULL
;
163 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
165 * Use fake close method that doesn't try to do too much to fake
168 ch
->close
= tlschan_fake_close_method
;
169 channel_mark_for_close(ch
);
170 free_fake_channel(ch
);
171 UNMOCK(scheduler_release_channel
);
174 UNMOCK(connection_or_connect
);
175 UNMOCK(is_local_addr
);
181 test_channeltls_overhead_estimate(void *arg
)
183 tor_addr_t test_addr
;
184 channel_t
*ch
= NULL
;
185 const char test_digest
[DIGEST_LEN
] = {
186 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
187 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
189 channel_tls_t
*tlschan
= NULL
;
193 /* Set up a fake address to fake-connect to */
194 test_addr
.family
= AF_INET
;
195 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
197 /* For this test we always want the address to be treated as non-local */
199 /* Install is_local_addr() mock */
200 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
202 /* Install mock for connection_or_connect() */
203 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
206 ch
= channel_tls_connect(&test_addr
, 567, test_digest
);
207 tt_assert(ch
!= NULL
);
209 /* First case: silly low ratios should get clamped to 1.0f */
210 tlschan
= BASE_CHAN_TO_TLS(ch
);
211 tt_assert(tlschan
!= NULL
);
212 tlschan
->conn
->bytes_xmitted
= 128;
213 tlschan
->conn
->bytes_xmitted_by_tls
= 64;
214 r
= ch
->get_overhead_estimate(ch
);
215 tt_assert(fabsf(r
- 1.0f
) < 1E-12);
217 tlschan
->conn
->bytes_xmitted_by_tls
= 127;
218 r
= ch
->get_overhead_estimate(ch
);
219 tt_assert(fabsf(r
- 1.0f
) < 1E-12);
221 /* Now middle of the range */
222 tlschan
->conn
->bytes_xmitted_by_tls
= 192;
223 r
= ch
->get_overhead_estimate(ch
);
224 tt_assert(fabsf(r
- 1.5f
) < 1E-12);
226 /* Now above the 2.0f clamp */
227 tlschan
->conn
->bytes_xmitted_by_tls
= 257;
228 r
= ch
->get_overhead_estimate(ch
);
229 tt_assert(fabsf(r
- 2.0f
) < 1E-12);
231 tlschan
->conn
->bytes_xmitted_by_tls
= 512;
232 r
= ch
->get_overhead_estimate(ch
);
233 tt_assert(fabsf(r
- 2.0f
) < 1E-12);
237 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
239 * Use fake close method that doesn't try to do too much to fake
242 ch
->close
= tlschan_fake_close_method
;
243 channel_mark_for_close(ch
);
244 free_fake_channel(ch
);
245 UNMOCK(scheduler_release_channel
);
248 UNMOCK(connection_or_connect
);
249 UNMOCK(is_local_addr
);
255 tlschan_buf_datalen_mock(const buf_t
*buf
)
257 if (buf
!= NULL
&& buf
== tlschan_buf_datalen_mock_target
) {
258 return tlschan_buf_datalen_mock_size
;
260 return buf_datalen__real(buf
);
264 static or_connection_t
*
265 tlschan_connection_or_connect_mock(const tor_addr_t
*addr
,
268 channel_tls_t
*tlschan
)
270 or_connection_t
*result
= NULL
;
272 tt_assert(addr
!= NULL
);
273 tt_assert(port
!= 0);
274 tt_assert(digest
!= NULL
);
275 tt_assert(tlschan
!= NULL
);
277 /* Make a fake orconn */
278 result
= tor_malloc_zero(sizeof(*result
));
279 result
->base_
.magic
= OR_CONNECTION_MAGIC
;
280 result
->base_
.state
= OR_CONN_STATE_OPEN
;
281 result
->base_
.type
= CONN_TYPE_OR
;
282 result
->base_
.socket_family
= addr
->family
;
283 result
->base_
.address
= tor_strdup("<fake>");
284 memcpy(&(result
->base_
.addr
), addr
, sizeof(tor_addr_t
));
285 result
->base_
.port
= port
;
286 memcpy(result
->identity_digest
, digest
, DIGEST_LEN
);
287 result
->chan
= tlschan
;
288 memcpy(&(result
->real_addr
), addr
, sizeof(tor_addr_t
));
289 result
->tls
= (tor_tls_t
*)((void *)(&fake_tortls
));
296 tlschan_fake_close_method(channel_t
*chan
)
298 channel_tls_t
*tlschan
= NULL
;
300 tt_assert(chan
!= NULL
);
301 tt_int_op(chan
->magic
, ==, TLS_CHAN_MAGIC
);
303 tlschan
= BASE_CHAN_TO_TLS(chan
);
304 tt_assert(tlschan
!= NULL
);
306 /* Just free the fake orconn */
307 tor_free(tlschan
->conn
->base_
.address
);
308 tor_free(tlschan
->conn
);
310 channel_closed(chan
);
317 tlschan_is_local_addr_mock(const tor_addr_t
*addr
)
319 tt_assert(addr
!= NULL
);
322 return tlschan_local
;
325 struct testcase_t channeltls_tests
[] = {
326 { "create", test_channeltls_create
, TT_FORK
, NULL
, NULL
},
327 { "num_bytes_queued", test_channeltls_num_bytes_queued
,
328 TT_FORK
, NULL
, NULL
},
329 { "overhead_estimate", test_channeltls_overhead_estimate
,
330 TT_FORK
, NULL
, NULL
},