LCOV - code coverage report
Current view: top level - test - test_helpers.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 235 262 89.7 %
Date: 2021-11-24 03:28:48 Functions: 19 20 95.0 %

          Line data    Source code
       1             : /* Copyright (c) 2014-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_helpers.c
       6             :  * \brief Some helper functions to avoid code duplication in unit tests.
       7             :  */
       8             : 
       9             : #define ROUTERLIST_PRIVATE
      10             : #define CONFIG_PRIVATE
      11             : #define CONNECTION_PRIVATE
      12             : #define CONNECTION_OR_PRIVATE
      13             : #define MAINLOOP_PRIVATE
      14             : 
      15             : #include "orconfig.h"
      16             : #include "core/or/or.h"
      17             : 
      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"
      27             : 
      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"
      33             : 
      34             : #include "feature/nodelist/nodelist.h"
      35             : #include "feature/nodelist/routerlist.h"
      36             : 
      37             : #include "app/config/config.h"
      38             : #include "app/main/subsysmgr.h"
      39             : 
      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"
      46             : 
      47             : #include "feature/nodelist/node_st.h"
      48             : #include "feature/nodelist/routerlist_st.h"
      49             : 
      50             : #ifdef HAVE_SYS_STAT_H
      51             : #include <sys/stat.h>
      52             : #endif
      53             : 
      54             : #ifdef _WIN32
      55             : /* For mkdir() */
      56             : #include <direct.h>
      57             : #else
      58             : #include <dirent.h>
      59             : #endif /* defined(_WIN32) */
      60             : 
      61             : #include "test/test.h"
      62             : #include "test/test_helpers.h"
      63             : #include "test/test_connection.h"
      64             : 
      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
      75             : 
      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           2 : get_yesterday_date_str(void)
      81             : {
      82           2 :   static char buf[ISO_TIME_LEN+1];
      83             : 
      84           2 :   time_t yesterday = time(NULL) - 24*60*60;
      85           2 :   format_iso_time(buf, yesterday);
      86           2 :   return buf;
      87             : }
      88             : 
      89             : /* NOP replacement for router_descriptor_is_older_than() */
      90             : static int
      91          24 : router_descriptor_is_older_than_replacement(const routerinfo_t *router,
      92             :                                             int seconds)
      93             : {
      94          24 :   (void) router;
      95          24 :   (void) seconds;
      96          24 :   return 0;
      97             : }
      98             : 
      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           3 : helper_setup_fake_routerlist(void)
     104             : {
     105           3 :   int retval;
     106           3 :   routerlist_t *our_routerlist = NULL;
     107           3 :   const smartlist_t *our_nodelist = NULL;
     108             : 
     109             :   /* Read the file that contains our test descriptors. */
     110             : 
     111             :   /* We need to mock this function otherwise the descriptors will not
     112             :      accepted as they are too old. */
     113           3 :   MOCK(router_descriptor_is_older_than,
     114             :        router_descriptor_is_older_than_replacement);
     115             : 
     116             :   // Pick a time when these descriptors' certificates were valid.
     117           3 :   update_approx_time(1603981036);
     118             : 
     119             :   /* Load all the test descriptors to the routerlist. */
     120           3 :   retval = router_load_routers_from_string(TEST_DESCRIPTORS,
     121             :                                            NULL, SAVED_IN_JOURNAL,
     122             :                                            NULL, 0, NULL);
     123           3 :   tt_int_op(retval, OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS);
     124             : 
     125           3 :   update_approx_time(0); // this restores the regular approx_time behavior
     126             : 
     127             :   /* Sanity checking of routerlist and nodelist. */
     128           3 :   our_routerlist = router_get_routerlist();
     129           3 :   tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ,
     130             :               HELPER_NUMBER_OF_DESCRIPTORS);
     131           3 :   routerlist_assert_ok(our_routerlist);
     132             : 
     133           3 :   our_nodelist = nodelist_get_list();
     134           3 :   tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS);
     135             : 
     136             :   /* Mark all routers as non-guards but up and running! */
     137          27 :   SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) {
     138          24 :     node->is_running = 1;
     139          24 :     node->is_valid = 1;
     140          24 :     node->is_possible_guard = 0;
     141          24 :   } SMARTLIST_FOREACH_END(node);
     142             : 
     143           3 :  done:
     144           3 :   UNMOCK(router_descriptor_is_older_than);
     145           3 : }
     146             : 
     147             : void
     148          94 : connection_write_to_buf_mock(const char *string, size_t len,
     149             :                              connection_t *conn, int compressed)
     150             : {
     151          94 :   (void) compressed;
     152             : 
     153          94 :   tor_assert(string);
     154          94 :   tor_assert(conn);
     155             : 
     156          94 :   buf_add(conn->outbuf, string, len);
     157          94 : }
     158             : 
     159             : char *
     160          33 : buf_get_contents(buf_t *buf, size_t *sz_out)
     161             : {
     162          33 :   tor_assert(buf);
     163          33 :   tor_assert(sz_out);
     164             : 
     165          33 :   char *out;
     166          33 :   *sz_out = buf_datalen(buf);
     167          33 :   if (*sz_out >= ULONG_MAX)
     168             :     return NULL; /* C'mon, really? */
     169          33 :   out = tor_malloc(*sz_out + 1);
     170          33 :   if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) {
     171           0 :     tor_free(out);
     172           0 :     return NULL;
     173             :   }
     174          33 :   out[*sz_out] = '\0'; /* Hopefully gratuitous. */
     175          33 :   return out;
     176             : }
     177             : 
     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          19 : dummy_origin_circuit_new(int n_cells)
     182             : {
     183          19 :   origin_circuit_t *circ = origin_circuit_new();
     184          19 :   int i;
     185          19 :   cell_t cell;
     186             : 
     187         358 :   for (i=0; i < n_cells; ++i) {
     188         320 :     crypto_rand((void*)&cell, sizeof(cell));
     189         320 :     cell_queue_append_packed_copy(TO_CIRCUIT(circ),
     190             :                                   &TO_CIRCUIT(circ)->n_chan_cells,
     191             :                                   1, &cell, 1, 0);
     192             :   }
     193             : 
     194          19 :   TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
     195          19 :   return TO_CIRCUIT(circ);
     196             : }
     197             : 
     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!!"
     202             :  */
     203             : int
     204           8 : mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
     205             :                                         uint16_t family, tor_addr_t *out)
     206             : {
     207           8 :   if (name && strchr(name, '!')) {
     208             :     return -1;
     209             :   }
     210           0 :   return tor_addr_lookup__real(name, family, out);
     211             : }
     212             : 
     213             : static char *
     214          24 : create_directory(const char *parent_dir, const char *name)
     215             : {
     216          24 :   char *dir = NULL;
     217          24 :   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          24 :   tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
     222             : #endif
     223          24 :   return dir;
     224             : 
     225           0 :  done:
     226           0 :   tor_free(dir);
     227           0 :   return NULL;
     228             : }
     229             : 
     230             : static char *
     231          32 : create_file(const char *parent_dir, const char *name, const char *contents)
     232             : {
     233          32 :   char *path = NULL;
     234          32 :   tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", parent_dir, name);
     235          32 :   contents = contents == NULL ? "" : contents;
     236          32 :   tt_int_op(write_str_to_file(path, contents, 0), OP_EQ, 0);
     237          32 :   return path;
     238             : 
     239           0 :  done:
     240           0 :   tor_free(path);
     241           0 :   return NULL;
     242             : }
     243             : 
     244             : int
     245           8 : create_test_directory_structure(const char *parent_dir)
     246             : {
     247           8 :   int ret = -1;
     248           8 :   char *dir1 = NULL;
     249           8 :   char *dir2 = NULL;
     250           8 :   char *file1 = NULL;
     251           8 :   char *file2 = NULL;
     252           8 :   char *dot = NULL;
     253           8 :   char *empty = NULL;
     254           8 :   char *forbidden = NULL;
     255             : 
     256           8 :   dir1 = create_directory(parent_dir, "dir1");
     257           8 :   tt_assert(dir1);
     258           8 :   dir2 = create_directory(parent_dir, "dir2");
     259           8 :   tt_assert(dir2);
     260           8 :   file1 = create_file(parent_dir, "file1", "Test 1");
     261           8 :   tt_assert(file1);
     262           8 :   file2 = create_file(parent_dir, "file2", "Test 2");
     263           8 :   tt_assert(file2);
     264           8 :   dot = create_file(parent_dir, ".test-hidden", "Test .");
     265           8 :   tt_assert(dot);
     266           8 :   empty = create_file(parent_dir, "empty", NULL);
     267           8 :   tt_assert(empty);
     268           8 :   forbidden = create_directory(parent_dir, "forbidden");
     269           8 :   tt_assert(forbidden);
     270             : #ifndef _WIN32
     271           8 :   tt_int_op(chmod(forbidden, 0), OP_EQ, 0);
     272             : #endif
     273             :   ret = 0;
     274           8 :  done:
     275           8 :   tor_free(dir1);
     276           8 :   tor_free(dir2);
     277           8 :   tor_free(file1);
     278           8 :   tor_free(file2);
     279           8 :   tor_free(dot);
     280           8 :   tor_free(empty);
     281           8 :   tor_free(forbidden);
     282           8 :   return ret;
     283             : }
     284             : 
     285             : /*********** Helper funcs for making new connections/streams *****************/
     286             : 
     287             : /* Helper for test_conn_get_connection() */
     288             : static int
     289           0 : fake_close_socket(tor_socket_t sock)
     290             : {
     291           0 :   (void)sock;
     292           0 :   return 0;
     293             : }
     294             : 
     295             : /* Helper for test_conn_get_proxy_or_connection() */
     296             : void
     297           2 : mock_connection_or_change_state(or_connection_t *conn, uint8_t state)
     298             : {
     299           2 :   tor_assert(conn);
     300           2 :   conn->base_.state = state;
     301           2 : }
     302             : 
     303             : static int mock_connection_connect_sockaddr_called = 0;
     304             : static int fake_socket_number = TEST_CONN_FD_INIT;
     305             : 
     306             : /* Helper for test_conn_get_connection() */
     307             : static int
     308          21 : 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)
     314             : {
     315          21 :   (void)sa_len;
     316          21 :   (void)bindaddr;
     317          21 :   (void)bindaddr_len;
     318             : 
     319          21 :   tor_assert(conn);
     320          21 :   tor_assert(sa);
     321          21 :   tor_assert(socket_error);
     322             : 
     323          21 :   mock_connection_connect_sockaddr_called++;
     324             : 
     325          21 :   conn->s = fake_socket_number++;
     326          21 :   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          21 :   tt_int_op(connection_add_connecting(conn), OP_EQ, 0);
     331             : 
     332          21 :  done:
     333             :   /* Fake "connected" status */
     334          21 :   return 1;
     335             : }
     336             : 
     337             : or_connection_t *
     338           2 : test_conn_get_proxy_or_connection(unsigned int proxy_type)
     339             : {
     340           2 :   or_connection_t *conn = NULL;
     341           2 :   tor_addr_t dst_addr;
     342           2 :   tor_addr_t proxy_addr;
     343           2 :   int socket_err = 0;
     344           2 :   int in_progress = 0;
     345             : 
     346           2 :   MOCK(connection_connect_sockaddr,
     347             :        mock_connection_connect_sockaddr);
     348           2 :   MOCK(connection_write_to_buf_impl_,
     349             :        connection_write_to_buf_mock);
     350           2 :   MOCK(connection_or_change_state,
     351             :        mock_connection_or_change_state);
     352           2 :   MOCK(tor_close_socket, fake_close_socket);
     353             : 
     354           2 :   tor_init_connection_lists();
     355             : 
     356           2 :   conn = or_connection_new(CONN_TYPE_OR, TEST_CONN_FAMILY);
     357           2 :   tt_assert(conn);
     358             : 
     359             :   /* Set up a destination address. */
     360           2 :   test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY,
     361             :                                &dst_addr);
     362           2 :   tt_assert(!tor_addr_is_null(&dst_addr));
     363             : 
     364           2 :   conn->proxy_type = proxy_type;
     365           2 :   conn->base_.proxy_state = PROXY_INFANT;
     366             : 
     367           2 :   tor_addr_copy_tight(&conn->base_.addr, &dst_addr);
     368           2 :   conn->base_.address = tor_addr_to_str_dup(&dst_addr);
     369           2 :   conn->base_.port = TEST_CONN_PORT;
     370             : 
     371             :   /* Set up a proxy address. */
     372           2 :   test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY,
     373             :                                &proxy_addr);
     374           2 :   tt_assert(!tor_addr_is_null(&proxy_addr));
     375             : 
     376           2 :   conn->base_.state = OR_CONN_STATE_CONNECTING;
     377             : 
     378           2 :   mock_connection_connect_sockaddr_called = 0;
     379           2 :   in_progress = connection_connect(TO_CONN(conn), TEST_CONN_ADDRESS_PORT,
     380             :                                    &proxy_addr, TEST_CONN_PORT, &socket_err);
     381           2 :   tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
     382           2 :   tt_assert(!socket_err);
     383           2 :   tt_assert(in_progress == 0 || in_progress == 1);
     384             : 
     385           2 :   assert_connection_ok(TO_CONN(conn), time(NULL));
     386             : 
     387           2 :   in_progress = connection_or_finished_connecting(conn);
     388           2 :   tt_int_op(in_progress, OP_EQ, 0);
     389             : 
     390           2 :   assert_connection_ok(TO_CONN(conn), time(NULL));
     391             : 
     392           2 :   UNMOCK(connection_connect_sockaddr);
     393           2 :   UNMOCK(connection_write_to_buf_impl_);
     394           2 :   UNMOCK(connection_or_change_state);
     395           2 :   UNMOCK(tor_close_socket);
     396           2 :   return conn;
     397             : 
     398             :   /* On failure */
     399           0 :  done:
     400           0 :   UNMOCK(connection_connect_sockaddr);
     401           0 :   UNMOCK(connection_write_to_buf_impl_);
     402           0 :   UNMOCK(connection_or_change_state);
     403           0 :   UNMOCK(tor_close_socket);
     404           0 :   connection_free_(TO_CONN(conn));
     405           0 :   return NULL;
     406             : }
     407             : 
     408             : /** Create and return a new connection/stream */
     409             : connection_t *
     410          19 : test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
     411             : {
     412          19 :   connection_t *conn = NULL;
     413          19 :   tor_addr_t addr;
     414          19 :   int socket_err = 0;
     415          19 :   int in_progress = 0;
     416             : 
     417          19 :   MOCK(connection_connect_sockaddr,
     418             :        mock_connection_connect_sockaddr);
     419          19 :   MOCK(tor_close_socket, fake_close_socket);
     420             : 
     421          19 :   tor_init_connection_lists();
     422             : 
     423          19 :   conn = connection_new(type, TEST_CONN_FAMILY);
     424          19 :   tt_assert(conn);
     425             : 
     426          19 :   test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
     427          19 :   tt_assert(!tor_addr_is_null(&addr));
     428             : 
     429          19 :   tor_addr_copy_tight(&conn->addr, &addr);
     430          19 :   conn->port = TEST_CONN_PORT;
     431          19 :   mock_connection_connect_sockaddr_called = 0;
     432          19 :   in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
     433             :                                    TEST_CONN_PORT, &socket_err);
     434          19 :   tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
     435          19 :   tt_assert(!socket_err);
     436          19 :   tt_assert(in_progress == 0 || in_progress == 1);
     437             : 
     438             :   /* fake some of the attributes so the connection looks OK */
     439          19 :   conn->state = state;
     440          19 :   conn->purpose = purpose;
     441          19 :   assert_connection_ok(conn, time(NULL));
     442             : 
     443          19 :   UNMOCK(connection_connect_sockaddr);
     444          19 :   UNMOCK(tor_close_socket);
     445          19 :   return conn;
     446             : 
     447             :   /* On failure */
     448           0 :  done:
     449           0 :   UNMOCK(connection_connect_sockaddr);
     450           0 :   UNMOCK(tor_close_socket);
     451           0 :   return NULL;
     452             : }
     453             : 
     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          28 : helper_parse_options(const char *conf)
     460             : {
     461          28 :   int ret = 0;
     462          28 :   char *msg = NULL;
     463          28 :   or_options_t *opt = NULL;
     464          28 :   config_line_t *line = NULL;
     465             : 
     466             :   /* Kind of pointless to call this with a NULL value. */
     467          28 :   tt_assert(conf);
     468             : 
     469          28 :   opt = options_new();
     470          28 :   tt_assert(opt);
     471          28 :   ret = config_get_lines(conf, &line, 1);
     472          28 :   if (ret != 0) {
     473           0 :     goto done;
     474             :   }
     475          28 :   ret = config_assign(get_options_mgr(), opt, line, 0, &msg);
     476          28 :   if (ret != 0) {
     477           0 :     goto done;
     478             :   }
     479             : 
     480          28 :  done:
     481          28 :   config_free_lines(line);
     482          28 :   if (ret != 0) {
     483           0 :     or_options_free(opt);
     484           0 :     opt = NULL;
     485             :   }
     486          28 :   return opt;
     487             : }
     488             : 
     489             : /**
     490             :  * Dispatch alertfn callback: flush all messages right now. Implements
     491             :  * DELIV_IMMEDIATE.
     492             :  **/
     493             : static void
     494          41 : alertfn_immediate(dispatch_t *d, channel_id_t chan, void *arg)
     495             : {
     496          41 :   (void) arg;
     497          41 :   dispatch_flush(d, chan, INT_MAX);
     498          41 : }
     499             : 
     500             : /**
     501             :  * Setup helper for tests that need pubsub active
     502             :  *
     503             :  * Does not hook up mainloop events.  Does set immediate delivery for
     504             :  * all channels.
     505             :  */
     506             : void *
     507          10 : helper_setup_pubsub(const struct testcase_t *testcase)
     508             : {
     509          10 :   dispatch_t *dispatcher = NULL;
     510          10 :   pubsub_builder_t *builder = pubsub_builder_new();
     511          10 :   channel_id_t chan = get_channel_id("orconn");
     512             : 
     513          10 :   (void)testcase;
     514          10 :   (void)subsystems_add_pubsub(builder);
     515          10 :   dispatcher = pubsub_builder_finalize(builder, NULL);
     516          10 :   tor_assert(dispatcher);
     517          10 :   dispatch_set_alert_fn(dispatcher, chan, alertfn_immediate, NULL);
     518          10 :   chan = get_channel_id("ocirc");
     519          10 :   dispatch_set_alert_fn(dispatcher, chan, alertfn_immediate, NULL);
     520          10 :   return dispatcher;
     521             : }
     522             : 
     523             : /**
     524             :  * Cleanup helper for tests that need pubsub active
     525             :  */
     526             : int
     527          10 : helper_cleanup_pubsub(const struct testcase_t *testcase, void *dispatcher_)
     528             : {
     529          10 :   dispatch_t *dispatcher = dispatcher_;
     530             : 
     531          10 :   (void)testcase;
     532          10 :   dispatch_free(dispatcher);
     533          10 :   return 1;
     534             : }
     535             : 
     536             : const struct testcase_setup_t helper_pubsub_setup = {
     537             :   helper_setup_pubsub, helper_cleanup_pubsub
     538             : };
     539             : 
     540             : origin_circuit_t *
     541          12 : new_test_origin_circuit(bool has_opened,
     542             :                         struct timeval circ_start_time,
     543             :                         int path_len,
     544             :                         extend_info_t **ei_list)
     545             : {
     546          12 :   origin_circuit_t *origin_circ = origin_circuit_new();
     547             : 
     548          12 :   TO_CIRCUIT(origin_circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
     549             : 
     550          12 :   origin_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
     551          12 :   origin_circ->build_state->desired_path_len = path_len;
     552             : 
     553          12 :   if (ei_list) {
     554          47 :     for (int i = 0; i < path_len; i++) {
     555          35 :       extend_info_t *ei = ei_list[i];
     556          35 :       cpath_append_hop(&origin_circ->cpath, ei);
     557             :     }
     558             :   }
     559             : 
     560          12 :   if (has_opened) {
     561           7 :     origin_circ->has_opened = 1;
     562           7 :     TO_CIRCUIT(origin_circ)->state = CIRCUIT_STATE_OPEN;
     563           7 :     origin_circ->cpath->state = CPATH_STATE_OPEN;
     564             :   } else {
     565           5 :     TO_CIRCUIT(origin_circ)->timestamp_began = circ_start_time;
     566           5 :     TO_CIRCUIT(origin_circ)->timestamp_created = circ_start_time;
     567           5 :     origin_circ->cpath->state = CPATH_STATE_CLOSED;
     568             :   }
     569             : 
     570          12 :   return origin_circ;
     571             : }

Generated by: LCOV version 1.14