TOR_VEGAS: Implement Prop#324 TOR_VEGAS.
[tor.git] / src / test / test_helpers.c
blob2edaa746f13c724b5fe1b4e7d8d63230fc1623c2
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file test_helpers.c
6 * \brief Some helper functions to avoid code duplication in unit tests.
7 */
9 #define ROUTERLIST_PRIVATE
10 #define CONFIG_PRIVATE
11 #define CONNECTION_PRIVATE
12 #define CONNECTION_OR_PRIVATE
13 #define MAINLOOP_PRIVATE
15 #include "orconfig.h"
16 #include "core/or/or.h"
18 #include "lib/buf/buffers.h"
19 #include "lib/confmgt/confmgt.h"
20 #include "lib/crypt_ops/crypto_rand.h"
21 #include "lib/dispatch/dispatch.h"
22 #include "lib/dispatch/dispatch_naming.h"
23 #include "lib/encoding/confline.h"
24 #include "lib/net/resolve.h"
25 #include "lib/pubsub/pubsub_build.h"
26 #include "lib/pubsub/pubsub_connect.h"
28 #include "core/mainloop/connection.h"
29 #include "core/mainloop/mainloop.h"
30 #include "core/or/connection_or.h"
31 #include "core/or/crypt_path.h"
32 #include "core/or/relay.h"
34 #include "feature/nodelist/nodelist.h"
35 #include "feature/nodelist/routerlist.h"
37 #include "app/config/config.h"
38 #include "app/main/subsysmgr.h"
40 #include "core/or/cell_st.h"
41 #include "core/or/connection_st.h"
42 #include "core/or/cpath_build_state_st.h"
43 #include "core/or/crypt_path_st.h"
44 #include "core/or/origin_circuit_st.h"
45 #include "core/or/or_connection_st.h"
47 #include "feature/nodelist/node_st.h"
48 #include "feature/nodelist/routerlist_st.h"
50 #ifdef HAVE_SYS_STAT_H
51 #include <sys/stat.h>
52 #endif
54 #ifdef _WIN32
55 /* For mkdir() */
56 #include <direct.h>
57 #else
58 #include <dirent.h>
59 #endif /* defined(_WIN32) */
61 #include "test/test.h"
62 #include "test/test_helpers.h"
63 #include "test/test_connection.h"
65 #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
66 DISABLE_GCC_WARNING("-Woverlength-strings")
67 /* We allow huge string constants in the unit tests, but not in the code
68 * at large. */
69 #endif
70 #include "test_descriptors.inc"
71 #include "core/or/circuitlist.h"
72 #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
73 ENABLE_GCC_WARNING("-Woverlength-strings")
74 #endif
76 /* Return a statically allocated string representing yesterday's date
77 * in ISO format. We use it so that state file items are not found to
78 * be outdated. */
79 const char *
80 get_yesterday_date_str(void)
82 static char buf[ISO_TIME_LEN+1];
84 time_t yesterday = time(NULL) - 24*60*60;
85 format_iso_time(buf, yesterday);
86 return buf;
89 /* NOP replacement for router_descriptor_is_older_than() */
90 static int
91 router_descriptor_is_older_than_replacement(const routerinfo_t *router,
92 int seconds)
94 (void) router;
95 (void) seconds;
96 return 0;
99 /** Parse a file containing router descriptors and load them to our
100 routerlist. This function is used to setup an artificial network
101 so that we can conduct tests on it. */
102 void
103 helper_setup_fake_routerlist(void)
105 int retval;
106 routerlist_t *our_routerlist = NULL;
107 const smartlist_t *our_nodelist = NULL;
109 /* Read the file that contains our test descriptors. */
111 /* We need to mock this function otherwise the descriptors will not
112 accepted as they are too old. */
113 MOCK(router_descriptor_is_older_than,
114 router_descriptor_is_older_than_replacement);
116 // Pick a time when these descriptors' certificates were valid.
117 update_approx_time(1603981036);
119 /* Load all the test descriptors to the routerlist. */
120 retval = router_load_routers_from_string(TEST_DESCRIPTORS,
121 NULL, SAVED_IN_JOURNAL,
122 NULL, 0, NULL);
123 tt_int_op(retval, OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS);
125 update_approx_time(0); // this restores the regular approx_time behavior
127 /* Sanity checking of routerlist and nodelist. */
128 our_routerlist = router_get_routerlist();
129 tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ,
130 HELPER_NUMBER_OF_DESCRIPTORS);
131 routerlist_assert_ok(our_routerlist);
133 our_nodelist = nodelist_get_list();
134 tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS);
136 /* Mark all routers as non-guards but up and running! */
137 SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) {
138 node->is_running = 1;
139 node->is_valid = 1;
140 node->is_possible_guard = 0;
141 } SMARTLIST_FOREACH_END(node);
143 done:
144 UNMOCK(router_descriptor_is_older_than);
147 void
148 connection_write_to_buf_mock(const char *string, size_t len,
149 connection_t *conn, int compressed)
151 (void) compressed;
153 tor_assert(string);
154 tor_assert(conn);
156 buf_add(conn->outbuf, string, len);
159 char *
160 buf_get_contents(buf_t *buf, size_t *sz_out)
162 tor_assert(buf);
163 tor_assert(sz_out);
165 char *out;
166 *sz_out = buf_datalen(buf);
167 if (*sz_out >= ULONG_MAX)
168 return NULL; /* C'mon, really? */
169 out = tor_malloc(*sz_out + 1);
170 if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) {
171 tor_free(out);
172 return NULL;
174 out[*sz_out] = '\0'; /* Hopefully gratuitous. */
175 return out;
178 /* Set up a fake origin circuit with the specified number of cells,
179 * Return a pointer to the newly-created dummy circuit */
180 circuit_t *
181 dummy_origin_circuit_new(int n_cells)
183 origin_circuit_t *circ = origin_circuit_new();
184 int i;
185 cell_t cell;
187 for (i=0; i < n_cells; ++i) {
188 crypto_rand((void*)&cell, sizeof(cell));
189 cell_queue_append_packed_copy(TO_CIRCUIT(circ),
190 &TO_CIRCUIT(circ)->n_chan_cells,
191 1, &cell, 1, 0);
194 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
195 return TO_CIRCUIT(circ);
198 /** Mock-replacement. As tor_addr_lookup, but always fails on any
199 * address containing a !. This is necessary for running the unit tests
200 * on networks where DNS hijackers think it's helpful to give answers
201 * for things like 1.2.3.4.5 or "invalidstuff!!"
204 mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
205 uint16_t family, tor_addr_t *out)
207 if (name && strchr(name, '!')) {
208 return -1;
210 return tor_addr_lookup__real(name, family, out);
213 static char *
214 create_directory(const char *parent_dir, const char *name)
216 char *dir = NULL;
217 tor_asprintf(&dir, "%s"PATH_SEPARATOR"%s", parent_dir, name);
218 #ifdef _WIN32
219 tt_int_op(mkdir(dir), OP_EQ, 0);
220 #else
221 tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
222 #endif
223 return dir;
225 done:
226 tor_free(dir);
227 return NULL;
230 static char *
231 create_file(const char *parent_dir, const char *name, const char *contents)
233 char *path = NULL;
234 tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", parent_dir, name);
235 contents = contents == NULL ? "" : contents;
236 tt_int_op(write_str_to_file(path, contents, 0), OP_EQ, 0);
237 return path;
239 done:
240 tor_free(path);
241 return NULL;
245 create_test_directory_structure(const char *parent_dir)
247 int ret = -1;
248 char *dir1 = NULL;
249 char *dir2 = NULL;
250 char *file1 = NULL;
251 char *file2 = NULL;
252 char *dot = NULL;
253 char *empty = NULL;
254 char *forbidden = NULL;
256 dir1 = create_directory(parent_dir, "dir1");
257 tt_assert(dir1);
258 dir2 = create_directory(parent_dir, "dir2");
259 tt_assert(dir2);
260 file1 = create_file(parent_dir, "file1", "Test 1");
261 tt_assert(file1);
262 file2 = create_file(parent_dir, "file2", "Test 2");
263 tt_assert(file2);
264 dot = create_file(parent_dir, ".test-hidden", "Test .");
265 tt_assert(dot);
266 empty = create_file(parent_dir, "empty", NULL);
267 tt_assert(empty);
268 forbidden = create_directory(parent_dir, "forbidden");
269 tt_assert(forbidden);
270 #ifndef _WIN32
271 tt_int_op(chmod(forbidden, 0), OP_EQ, 0);
272 #endif
273 ret = 0;
274 done:
275 tor_free(dir1);
276 tor_free(dir2);
277 tor_free(file1);
278 tor_free(file2);
279 tor_free(dot);
280 tor_free(empty);
281 tor_free(forbidden);
282 return ret;
285 /*********** Helper funcs for making new connections/streams *****************/
287 /* Helper for test_conn_get_connection() */
288 static int
289 fake_close_socket(tor_socket_t sock)
291 (void)sock;
292 return 0;
295 /* Helper for test_conn_get_proxy_or_connection() */
296 void
297 mock_connection_or_change_state(or_connection_t *conn, uint8_t state)
299 tor_assert(conn);
300 conn->base_.state = state;
303 static int mock_connection_connect_sockaddr_called = 0;
304 static int fake_socket_number = TEST_CONN_FD_INIT;
306 /* Helper for test_conn_get_connection() */
307 static int
308 mock_connection_connect_sockaddr(connection_t *conn,
309 const struct sockaddr *sa,
310 socklen_t sa_len,
311 const struct sockaddr *bindaddr,
312 socklen_t bindaddr_len,
313 int *socket_error)
315 (void)sa_len;
316 (void)bindaddr;
317 (void)bindaddr_len;
319 tor_assert(conn);
320 tor_assert(sa);
321 tor_assert(socket_error);
323 mock_connection_connect_sockaddr_called++;
325 conn->s = fake_socket_number++;
326 tt_assert(SOCKET_OK(conn->s));
327 /* We really should call tor_libevent_initialize() here. Because we don't,
328 * we are relying on other parts of the code not checking if the_event_base
329 * (and therefore event->ev_base) is NULL. */
330 tt_int_op(connection_add_connecting(conn), OP_EQ, 0);
332 done:
333 /* Fake "connected" status */
334 return 1;
337 or_connection_t *
338 test_conn_get_proxy_or_connection(unsigned int proxy_type)
340 or_connection_t *conn = NULL;
341 tor_addr_t dst_addr;
342 tor_addr_t proxy_addr;
343 int socket_err = 0;
344 int in_progress = 0;
346 MOCK(connection_connect_sockaddr,
347 mock_connection_connect_sockaddr);
348 MOCK(connection_write_to_buf_impl_,
349 connection_write_to_buf_mock);
350 MOCK(connection_or_change_state,
351 mock_connection_or_change_state);
352 MOCK(tor_close_socket, fake_close_socket);
354 tor_init_connection_lists();
356 conn = or_connection_new(CONN_TYPE_OR, TEST_CONN_FAMILY);
357 tt_assert(conn);
359 /* Set up a destination address. */
360 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY,
361 &dst_addr);
362 tt_assert(!tor_addr_is_null(&dst_addr));
364 conn->proxy_type = proxy_type;
365 conn->base_.proxy_state = PROXY_INFANT;
367 tor_addr_copy_tight(&conn->base_.addr, &dst_addr);
368 conn->base_.address = tor_addr_to_str_dup(&dst_addr);
369 conn->base_.port = TEST_CONN_PORT;
371 /* Set up a proxy address. */
372 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY,
373 &proxy_addr);
374 tt_assert(!tor_addr_is_null(&proxy_addr));
376 conn->base_.state = OR_CONN_STATE_CONNECTING;
378 mock_connection_connect_sockaddr_called = 0;
379 in_progress = connection_connect(TO_CONN(conn), TEST_CONN_ADDRESS_PORT,
380 &proxy_addr, TEST_CONN_PORT, &socket_err);
381 tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
382 tt_assert(!socket_err);
383 tt_assert(in_progress == 0 || in_progress == 1);
385 assert_connection_ok(TO_CONN(conn), time(NULL));
387 in_progress = connection_or_finished_connecting(conn);
388 tt_int_op(in_progress, OP_EQ, 0);
390 assert_connection_ok(TO_CONN(conn), time(NULL));
392 UNMOCK(connection_connect_sockaddr);
393 UNMOCK(connection_write_to_buf_impl_);
394 UNMOCK(connection_or_change_state);
395 UNMOCK(tor_close_socket);
396 return conn;
398 /* On failure */
399 done:
400 UNMOCK(connection_connect_sockaddr);
401 UNMOCK(connection_write_to_buf_impl_);
402 UNMOCK(connection_or_change_state);
403 UNMOCK(tor_close_socket);
404 connection_free_(TO_CONN(conn));
405 return NULL;
408 /** Create and return a new connection/stream */
409 connection_t *
410 test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
412 connection_t *conn = NULL;
413 tor_addr_t addr;
414 int socket_err = 0;
415 int in_progress = 0;
417 MOCK(connection_connect_sockaddr,
418 mock_connection_connect_sockaddr);
419 MOCK(tor_close_socket, fake_close_socket);
421 tor_init_connection_lists();
423 conn = connection_new(type, TEST_CONN_FAMILY);
424 tt_assert(conn);
426 test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
427 tt_assert(!tor_addr_is_null(&addr));
429 tor_addr_copy_tight(&conn->addr, &addr);
430 conn->port = TEST_CONN_PORT;
431 mock_connection_connect_sockaddr_called = 0;
432 in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
433 TEST_CONN_PORT, &socket_err);
434 tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
435 tt_assert(!socket_err);
436 tt_assert(in_progress == 0 || in_progress == 1);
438 /* fake some of the attributes so the connection looks OK */
439 conn->state = state;
440 conn->purpose = purpose;
441 assert_connection_ok(conn, time(NULL));
443 UNMOCK(connection_connect_sockaddr);
444 UNMOCK(tor_close_socket);
445 return conn;
447 /* On failure */
448 done:
449 UNMOCK(connection_connect_sockaddr);
450 UNMOCK(tor_close_socket);
451 return NULL;
454 /* Helper function to parse a set of torrc options in a text format and return
455 * a newly allocated or_options_t object containing the configuration. On
456 * error, NULL is returned indicating that the conf couldn't be parsed
457 * properly. */
458 or_options_t *
459 helper_parse_options(const char *conf)
461 int ret = 0;
462 char *msg = NULL;
463 or_options_t *opt = NULL;
464 config_line_t *line = NULL;
466 /* Kind of pointless to call this with a NULL value. */
467 tt_assert(conf);
469 opt = options_new();
470 tt_assert(opt);
471 ret = config_get_lines(conf, &line, 1);
472 if (ret != 0) {
473 goto done;
475 ret = config_assign(get_options_mgr(), opt, line, 0, &msg);
476 if (ret != 0) {
477 goto done;
480 done:
481 config_free_lines(line);
482 if (ret != 0) {
483 or_options_free(opt);
484 opt = NULL;
486 return opt;
490 * Dispatch alertfn callback: flush all messages right now. Implements
491 * DELIV_IMMEDIATE.
493 static void
494 alertfn_immediate(dispatch_t *d, channel_id_t chan, void *arg)
496 (void) arg;
497 dispatch_flush(d, chan, INT_MAX);
501 * Setup helper for tests that need pubsub active
503 * Does not hook up mainloop events. Does set immediate delivery for
504 * all channels.
506 void *
507 helper_setup_pubsub(const struct testcase_t *testcase)
509 dispatch_t *dispatcher = NULL;
510 pubsub_builder_t *builder = pubsub_builder_new();
511 channel_id_t chan = get_channel_id("orconn");
513 (void)testcase;
514 (void)subsystems_add_pubsub(builder);
515 dispatcher = pubsub_builder_finalize(builder, NULL);
516 tor_assert(dispatcher);
517 dispatch_set_alert_fn(dispatcher, chan, alertfn_immediate, NULL);
518 chan = get_channel_id("ocirc");
519 dispatch_set_alert_fn(dispatcher, chan, alertfn_immediate, NULL);
520 return dispatcher;
524 * Cleanup helper for tests that need pubsub active
527 helper_cleanup_pubsub(const struct testcase_t *testcase, void *dispatcher_)
529 dispatch_t *dispatcher = dispatcher_;
531 (void)testcase;
532 dispatch_free(dispatcher);
533 return 1;
536 const struct testcase_setup_t helper_pubsub_setup = {
537 helper_setup_pubsub, helper_cleanup_pubsub
540 origin_circuit_t *
541 new_test_origin_circuit(bool has_opened,
542 struct timeval circ_start_time,
543 int path_len,
544 extend_info_t **ei_list)
546 origin_circuit_t *origin_circ = origin_circuit_new();
548 TO_CIRCUIT(origin_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
550 origin_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
551 origin_circ->build_state->desired_path_len = path_len;
553 if (ei_list) {
554 for (int i = 0; i < path_len; i++) {
555 extend_info_t *ei = ei_list[i];
556 cpath_append_hop(&origin_circ->cpath, ei);
560 if (has_opened) {
561 origin_circ->has_opened = 1;
562 TO_CIRCUIT(origin_circ)->state = CIRCUIT_STATE_OPEN;
563 origin_circ->cpath->state = CPATH_STATE_OPEN;
564 } else {
565 TO_CIRCUIT(origin_circ)->timestamp_began = circ_start_time;
566 TO_CIRCUIT(origin_circ)->timestamp_created = circ_start_time;
567 origin_circ->cpath->state = CPATH_STATE_CLOSED;
570 return origin_circ;