LCOV - code coverage report
Current view: top level - test - test_circuitlist.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 281 285 98.6 %
Date: 2021-11-24 03:28:48 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2013-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : #define CHANNEL_OBJECT_PRIVATE
       5             : #define CIRCUITBUILD_PRIVATE
       6             : #define CIRCUITLIST_PRIVATE
       7             : #define HS_CIRCUITMAP_PRIVATE
       8             : #include "core/or/or.h"
       9             : #include "core/or/channel.h"
      10             : #include "core/or/circuitbuild.h"
      11             : #include "core/or/circuitlist.h"
      12             : #include "core/or/circuitmux_ewma.h"
      13             : #include "feature/hs/hs_circuitmap.h"
      14             : #include "test/test.h"
      15             : #include "test/log_test_helpers.h"
      16             : 
      17             : #include "core/or/or_circuit_st.h"
      18             : #include "core/or/origin_circuit_st.h"
      19             : 
      20             : #include "lib/container/bitarray.h"
      21             : 
      22             : static channel_t *
      23           3 : new_fake_channel(void)
      24             : {
      25           3 :   channel_t *chan = tor_malloc_zero(sizeof(channel_t));
      26           3 :   channel_init(chan);
      27           3 :   return chan;
      28             : }
      29             : 
      30             : static struct {
      31             :   int ncalls;
      32             :   void *cmux;
      33             :   void *circ;
      34             :   cell_direction_t dir;
      35             : } cam;
      36             : 
      37             : static void
      38           5 : circuitmux_attach_mock(circuitmux_t *cmux, circuit_t *circ,
      39             :                          cell_direction_t dir)
      40             : {
      41           5 :   ++cam.ncalls;
      42           5 :   cam.cmux = cmux;
      43           5 :   cam.circ = circ;
      44           5 :   cam.dir = dir;
      45           5 : }
      46             : 
      47             : static struct {
      48             :   int ncalls;
      49             :   void *cmux;
      50             :   void *circ;
      51             : } cdm;
      52             : 
      53             : static void
      54           5 : circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ)
      55             : {
      56           5 :   ++cdm.ncalls;
      57           5 :   cdm.cmux = cmux;
      58           5 :   cdm.circ = circ;
      59           5 : }
      60             : 
      61             : #define GOT_CMUX_ATTACH(mux_, circ_, dir_) do {  \
      62             :     tt_int_op(cam.ncalls, OP_EQ, 1);                \
      63             :     tt_ptr_op(cam.cmux, OP_EQ, (mux_));             \
      64             :     tt_ptr_op(cam.circ, OP_EQ, (circ_));            \
      65             :     tt_int_op(cam.dir, OP_EQ, (dir_));              \
      66             :     memset(&cam, 0, sizeof(cam));                \
      67             :   } while (0)
      68             : 
      69             : #define GOT_CMUX_DETACH(mux_, circ_) do {        \
      70             :     tt_int_op(cdm.ncalls, OP_EQ, 1);                \
      71             :     tt_ptr_op(cdm.cmux, OP_EQ, (mux_));             \
      72             :     tt_ptr_op(cdm.circ, OP_EQ, (circ_));            \
      73             :     memset(&cdm, 0, sizeof(cdm));                \
      74             :   } while (0)
      75             : 
      76             : static void
      77           1 : test_clist_maps(void *arg)
      78             : {
      79           1 :   channel_t *ch1 = new_fake_channel();
      80           1 :   channel_t *ch2 = new_fake_channel();
      81           1 :   channel_t *ch3 = new_fake_channel();
      82           1 :   or_circuit_t *or_c1=NULL, *or_c2=NULL;
      83             : 
      84           1 :   (void) arg;
      85             : 
      86           1 :   MOCK(circuitmux_attach_circuit, circuitmux_attach_mock);
      87           1 :   MOCK(circuitmux_detach_circuit, circuitmux_detach_mock);
      88           1 :   memset(&cam, 0, sizeof(cam));
      89           1 :   memset(&cdm, 0, sizeof(cdm));
      90             : 
      91           1 :   tt_assert(ch1);
      92           1 :   tt_assert(ch2);
      93           1 :   tt_assert(ch3);
      94             : 
      95           1 :   ch1->cmux = tor_malloc(1);
      96           1 :   ch2->cmux = tor_malloc(1);
      97           1 :   ch3->cmux = tor_malloc(1);
      98             : 
      99           1 :   or_c1 = or_circuit_new(100, ch2);
     100           1 :   tt_assert(or_c1);
     101           1 :   GOT_CMUX_ATTACH(ch2->cmux, or_c1, CELL_DIRECTION_IN);
     102           1 :   tt_int_op(or_c1->p_circ_id, OP_EQ, 100);
     103           1 :   tt_ptr_op(or_c1->p_chan, OP_EQ, ch2);
     104             : 
     105           1 :   or_c2 = or_circuit_new(100, ch1);
     106           1 :   tt_assert(or_c2);
     107           1 :   GOT_CMUX_ATTACH(ch1->cmux, or_c2, CELL_DIRECTION_IN);
     108           1 :   tt_int_op(or_c2->p_circ_id, OP_EQ, 100);
     109           1 :   tt_ptr_op(or_c2->p_chan, OP_EQ, ch1);
     110             : 
     111           1 :   circuit_set_n_circid_chan(TO_CIRCUIT(or_c1), 200, ch1);
     112           1 :   GOT_CMUX_ATTACH(ch1->cmux, or_c1, CELL_DIRECTION_OUT);
     113             : 
     114           1 :   circuit_set_n_circid_chan(TO_CIRCUIT(or_c2), 200, ch2);
     115           1 :   GOT_CMUX_ATTACH(ch2->cmux, or_c2, CELL_DIRECTION_OUT);
     116             : 
     117           1 :   tt_ptr_op(circuit_get_by_circid_channel(200, ch1), OP_EQ, TO_CIRCUIT(or_c1));
     118           1 :   tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2));
     119           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1));
     120             :   /* Try the same thing again, to test the "fast" path. */
     121           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, TO_CIRCUIT(or_c1));
     122           1 :   tt_assert(circuit_id_in_use_on_channel(100, ch2));
     123           1 :   tt_assert(! circuit_id_in_use_on_channel(101, ch2));
     124             : 
     125             :   /* Try changing the circuitid and channel of that circuit. */
     126           1 :   circuit_set_p_circid_chan(or_c1, 500, ch3);
     127           1 :   GOT_CMUX_DETACH(ch2->cmux, TO_CIRCUIT(or_c1));
     128           1 :   GOT_CMUX_ATTACH(ch3->cmux, TO_CIRCUIT(or_c1), CELL_DIRECTION_IN);
     129           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch2), OP_EQ, NULL);
     130           1 :   tt_assert(! circuit_id_in_use_on_channel(100, ch2));
     131           1 :   tt_ptr_op(circuit_get_by_circid_channel(500, ch3), OP_EQ, TO_CIRCUIT(or_c1));
     132             : 
     133             :   /* Now let's see about destroy handling. */
     134           1 :   tt_assert(! circuit_id_in_use_on_channel(205, ch2));
     135           1 :   tt_assert(circuit_id_in_use_on_channel(200, ch2));
     136           1 :   channel_note_destroy_pending(ch2, 200);
     137           1 :   channel_note_destroy_pending(ch2, 205);
     138           1 :   channel_note_destroy_pending(ch1, 100);
     139           1 :   tt_assert(circuit_id_in_use_on_channel(205, ch2));
     140           1 :   tt_assert(circuit_id_in_use_on_channel(200, ch2));
     141           1 :   tt_assert(circuit_id_in_use_on_channel(100, ch1));
     142             : 
     143           1 :   tt_assert(TO_CIRCUIT(or_c2)->n_delete_pending != 0);
     144           1 :   tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, TO_CIRCUIT(or_c2));
     145           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, TO_CIRCUIT(or_c2));
     146             : 
     147             :   /* Okay, now free ch2 and make sure that the circuit ID is STILL not
     148             :    * usable, because we haven't declared the destroy to be nonpending */
     149           1 :   tt_int_op(cdm.ncalls, OP_EQ, 0);
     150           1 :   circuit_free_(TO_CIRCUIT(or_c2));
     151           1 :   or_c2 = NULL; /* prevent free */
     152           1 :   tt_int_op(cdm.ncalls, OP_EQ, 2);
     153           1 :   memset(&cdm, 0, sizeof(cdm));
     154           1 :   tt_assert(circuit_id_in_use_on_channel(200, ch2));
     155           1 :   tt_assert(circuit_id_in_use_on_channel(100, ch1));
     156           1 :   tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL);
     157           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL);
     158             : 
     159             :   /* Now say that the destroy is nonpending */
     160           1 :   channel_note_destroy_not_pending(ch2, 200);
     161           1 :   tt_ptr_op(circuit_get_by_circid_channel(200, ch2), OP_EQ, NULL);
     162           1 :   channel_note_destroy_not_pending(ch1, 100);
     163           1 :   tt_ptr_op(circuit_get_by_circid_channel(100, ch1), OP_EQ, NULL);
     164           1 :   tt_assert(! circuit_id_in_use_on_channel(200, ch2));
     165           1 :   tt_assert(! circuit_id_in_use_on_channel(100, ch1));
     166             : 
     167           1 :  done:
     168           1 :   if (or_c1)
     169           1 :     circuit_free_(TO_CIRCUIT(or_c1));
     170           1 :   if (or_c2)
     171           0 :     circuit_free_(TO_CIRCUIT(or_c2));
     172           1 :   if (ch1)
     173           1 :     tor_free(ch1->cmux);
     174           1 :   if (ch2)
     175           1 :     tor_free(ch2->cmux);
     176           1 :   if (ch3)
     177           1 :     tor_free(ch3->cmux);
     178           1 :   tor_free(ch1);
     179           1 :   tor_free(ch2);
     180           1 :   tor_free(ch3);
     181           1 :   UNMOCK(circuitmux_attach_circuit);
     182           1 :   UNMOCK(circuitmux_detach_circuit);
     183           1 : }
     184             : 
     185             : static void
     186           1 : test_rend_token_maps(void *arg)
     187             : {
     188           1 :   or_circuit_t *c1, *c2, *c3, *c4;
     189           1 :   origin_circuit_t *c5;
     190           1 :   const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y";
     191           1 :   const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it ";
     192           1 :   const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care.";
     193             :   /* -- Adapted from a quote by Fredrik Lundh. */
     194             : 
     195           1 :   (void)arg;
     196           1 :   (void)tok1; //xxxx
     197             : 
     198           1 :   hs_circuitmap_init();
     199             : 
     200           1 :   c1 = or_circuit_new(0, NULL);
     201           1 :   c2 = or_circuit_new(0, NULL);
     202           1 :   c3 = or_circuit_new(0, NULL);
     203           1 :   c4 = or_circuit_new(0, NULL);
     204           1 :   c5 = origin_circuit_new();
     205             : 
     206           1 :   ed25519_public_key_t intro_pk1 = { {1} }; /* Junk, not important. */
     207           1 :   ed25519_public_key_t intro_pk2 = { {2} }; /* Junk, not important. */
     208           1 :   ed25519_public_key_t intro_pk3 = { {3} }; /* Junk, not important. */
     209             : 
     210             :   /* Make sure we really filled up the tok* variables */
     211           1 :   tt_int_op(tok1[REND_TOKEN_LEN-1], OP_EQ, 'y');
     212           1 :   tt_int_op(tok2[REND_TOKEN_LEN-1], OP_EQ, ' ');
     213           1 :   tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.');
     214             : 
     215             :   /* No maps; nothing there. */
     216           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     217           1 :   tt_ptr_op(NULL, OP_EQ,
     218             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk1));
     219             : 
     220           1 :   hs_circuitmap_register_rend_circ_relay_side(c1, tok1);
     221           1 :   hs_circuitmap_register_intro_circ_v3_relay_side(c2, &intro_pk2);
     222             : 
     223           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok3));
     224           1 :   tt_ptr_op(NULL, OP_EQ,
     225             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk3));
     226           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
     227           1 :   tt_ptr_op(NULL, OP_EQ,
     228             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     229             : 
     230             :   /* Without purpose set, we don't get the circuits */
     231           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     232           1 :   tt_ptr_op(NULL, OP_EQ,
     233             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     234             : 
     235           1 :   c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
     236           1 :   c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
     237             : 
     238             :   /* Okay, make sure they show up now. */
     239           1 :   tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     240           1 :   tt_ptr_op(c2, OP_EQ,
     241             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     242             : 
     243             :   /* Two items at the same place with the same token. */
     244           1 :   c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
     245           1 :   hs_circuitmap_register_rend_circ_relay_side(c3, tok2);
     246           1 :   tt_ptr_op(c2, OP_EQ,
     247             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     248           1 :   tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
     249             : 
     250             :   /* Marking a circuit makes it not get returned any more */
     251           1 :   circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED);
     252           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     253           1 :   circuit_free_(TO_CIRCUIT(c1));
     254           1 :   c1 = NULL;
     255             : 
     256             :   /* Freeing a circuit makes it not get returned any more. */
     257           1 :   circuit_free_(TO_CIRCUIT(c2));
     258           1 :   c2 = NULL;
     259           1 :   tt_ptr_op(NULL, OP_EQ,
     260             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     261             : 
     262             :   /* c3 -- are you still there? */
     263           1 :   tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
     264             :   /* Change its cookie.  This never happens in Tor per se, but hey. */
     265           1 :   c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
     266           1 :   hs_circuitmap_register_intro_circ_v3_relay_side(c3, &intro_pk3);
     267             : 
     268           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
     269           1 :   tt_ptr_op(c3, OP_EQ,
     270             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk3));
     271             : 
     272             :   /* Now replace c3 with c4. */
     273           1 :   c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
     274           1 :   hs_circuitmap_register_intro_circ_v3_relay_side(c4, &intro_pk3);
     275             : 
     276           1 :   tt_ptr_op(c4, OP_EQ,
     277             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk3));
     278             : 
     279           1 :   tt_ptr_op(TO_CIRCUIT(c3)->hs_token, OP_EQ, NULL);
     280           1 :   tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_NE, NULL);
     281           1 :   tt_mem_op(TO_CIRCUIT(c4)->hs_token->token, OP_EQ, &intro_pk3,
     282           1 :             REND_TOKEN_LEN);
     283             : 
     284             :   /* Now clear c4's cookie. */
     285           1 :   hs_circuitmap_remove_circuit(TO_CIRCUIT(c4));
     286           1 :   tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_EQ, NULL);
     287           1 :   tt_ptr_op(NULL, OP_EQ,
     288             :             hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk3));
     289             : 
     290             :   /* Now let's do a check for the client-side rend circuitmap */
     291           1 :   c5->base_.purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
     292           1 :   hs_circuitmap_register_rend_circ_client_side(c5, tok1);
     293             : 
     294           1 :   tt_ptr_op(c5, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok1));
     295           1 :   tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_client_side(tok2));
     296             : 
     297           1 :  done:
     298           0 :   if (c1)
     299           0 :     circuit_free_(TO_CIRCUIT(c1));
     300           1 :   if (c2)
     301           0 :     circuit_free_(TO_CIRCUIT(c2));
     302           1 :   if (c3)
     303           1 :     circuit_free_(TO_CIRCUIT(c3));
     304           1 :   if (c4)
     305           1 :     circuit_free_(TO_CIRCUIT(c4));
     306           1 :   if (c5)
     307           1 :     circuit_free_(TO_CIRCUIT(c5));
     308           1 : }
     309             : 
     310             : static void
     311           1 : mock_channel_dump_statistics(channel_t *chan, int severity)
     312             : {
     313           1 :   (void)chan;
     314           1 :   (void)severity;
     315           1 : }
     316             : 
     317             : static void
     318           1 : test_pick_circid(void *arg)
     319             : {
     320           1 :   bitarray_t *ba = NULL;
     321           1 :   channel_t *chan1, *chan2;
     322           1 :   circid_t circid;
     323           1 :   int i;
     324           1 :   (void) arg;
     325             : 
     326           1 :   MOCK(channel_dump_statistics, mock_channel_dump_statistics);
     327             : 
     328           1 :   chan1 = tor_malloc_zero(sizeof(channel_t));
     329           1 :   chan2 = tor_malloc_zero(sizeof(channel_t));
     330           1 :   chan2->wide_circ_ids = 1;
     331             : 
     332           1 :   chan1->cmux = circuitmux_alloc();
     333           1 :   chan2->cmux = circuitmux_alloc();
     334             : 
     335             :   /* CIRC_ID_TYPE_NEITHER is supposed to create a warning. */
     336           1 :   chan1->circ_id_type = CIRC_ID_TYPE_NEITHER;
     337           1 :   setup_full_capture_of_logs(LOG_WARN);
     338           1 :   tt_int_op(0, OP_EQ, get_unique_circ_id_by_chan(chan1));
     339           1 :   expect_single_log_msg_containing("Trying to pick a circuit ID for a "
     340             :                            "connection from a client with no identity.");
     341           1 :   teardown_capture_of_logs();
     342             : 
     343             :   /* Basic tests, with no collisions */
     344           1 :   chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
     345          51 :   for (i = 0; i < 50; ++i) {
     346          50 :     circid = get_unique_circ_id_by_chan(chan1);
     347          50 :     tt_uint_op(0, OP_LT, circid);
     348          50 :     tt_uint_op(circid, OP_LT, (1<<15));
     349             :   }
     350           1 :   chan1->circ_id_type = CIRC_ID_TYPE_HIGHER;
     351          51 :   for (i = 0; i < 50; ++i) {
     352          50 :     circid = get_unique_circ_id_by_chan(chan1);
     353          50 :     tt_uint_op((1<<15), OP_LT, circid);
     354          50 :     tt_uint_op(circid, OP_LT, (1<<16));
     355             :   }
     356             : 
     357           1 :   chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
     358          51 :   for (i = 0; i < 50; ++i) {
     359          50 :     circid = get_unique_circ_id_by_chan(chan2);
     360          50 :     tt_uint_op(0, OP_LT, circid);
     361          50 :     tt_uint_op(circid, OP_LT, (1u<<31));
     362             :   }
     363           1 :   chan2->circ_id_type = CIRC_ID_TYPE_HIGHER;
     364          51 :   for (i = 0; i < 50; ++i) {
     365          50 :     circid = get_unique_circ_id_by_chan(chan2);
     366          50 :     tt_uint_op((1u<<31), OP_LT, circid);
     367             :   }
     368             : 
     369             :   /* Now make sure that we can behave well when we are full up on circuits */
     370           1 :   chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
     371           1 :   chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
     372           1 :   chan1->wide_circ_ids = chan2->wide_circ_ids = 0;
     373           1 :   ba = bitarray_init_zero((1<<15));
     374       29234 :   for (i = 0; i < (1<<15); ++i) {
     375       29233 :     circid = get_unique_circ_id_by_chan(chan1);
     376       29233 :     if (circid == 0) {
     377           1 :       tt_int_op(i, OP_GT, (1<<14));
     378             :       break;
     379             :     }
     380       29232 :     tt_uint_op(circid, OP_LT, (1<<15));
     381       29232 :     tt_assert(! bitarray_is_set(ba, circid));
     382       29232 :     bitarray_set(ba, circid);
     383       29232 :     channel_mark_circid_unusable(chan1, circid);
     384             :   }
     385           1 :   tt_int_op(i, OP_LT, (1<<15));
     386             :   /* Make sure that being full on chan1 does not interfere with chan2 */
     387         101 :   for (i = 0; i < 100; ++i) {
     388         100 :     circid = get_unique_circ_id_by_chan(chan2);
     389         100 :     tt_uint_op(circid, OP_GT, 0);
     390         100 :     tt_uint_op(circid, OP_LT, (1<<15));
     391         100 :     channel_mark_circid_unusable(chan2, circid);
     392             :   }
     393             : 
     394           1 :  done:
     395           1 :   circuitmux_free(chan1->cmux);
     396           1 :   circuitmux_free(chan2->cmux);
     397           1 :   tor_free(chan1);
     398           1 :   tor_free(chan2);
     399           1 :   bitarray_free(ba);
     400           1 :   circuit_free_all();
     401           1 :   teardown_capture_of_logs();
     402           1 :   UNMOCK(channel_dump_statistics);
     403           1 : }
     404             : 
     405             : /** Test that the circuit pools of our HS circuitmap are isolated based on
     406             :  *  their token type. */
     407             : static void
     408           1 : test_hs_circuitmap_isolation(void *arg)
     409             : {
     410           1 :   or_circuit_t *circ1 = NULL;
     411           1 :   origin_circuit_t *circ2 = NULL;
     412           1 :   or_circuit_t *circ3 = NULL;
     413           1 :   origin_circuit_t *circ4 = NULL;
     414             : 
     415           1 :   (void)arg;
     416             : 
     417           1 :   hs_circuitmap_init();
     418             : 
     419           1 :   ed25519_public_key_t intro_pk1 = { {1} }; /* Junk, not important. */
     420           1 :   ed25519_public_key_t intro_pk2 = { {2} }; /* Junk, not important. */
     421             : 
     422             :   {
     423           1 :     const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th";
     424             : 
     425           1 :     circ1 = or_circuit_new(0, NULL);
     426           1 :     tt_assert(circ1);
     427           1 :     circ1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
     428             : 
     429             :     /* check that circuitmap is empty right? */
     430           1 :     tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     431             : 
     432             :     /* Register circ1 with tok1 as relay-side rend circ */
     433           1 :     hs_circuitmap_register_rend_circ_relay_side(circ1, tok1);
     434             : 
     435             :     /* check that service-side getters don't work */
     436           1 :     tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_service_side(tok1));
     437           1 :     tt_ptr_op(NULL, OP_EQ,
     438             :               hs_circuitmap_get_intro_circ_v3_service_side(&intro_pk1));
     439             : 
     440             :     /* Check that the right getter works. */
     441           1 :     tt_ptr_op(circ1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
     442             :   }
     443             : 
     444             :   {
     445           1 :     const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi";
     446             : 
     447           1 :     circ2 = origin_circuit_new();
     448           1 :     tt_assert(circ2);
     449           1 :     circ2->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
     450           1 :     circ3 = or_circuit_new(0, NULL);
     451           1 :     tt_assert(circ3);
     452           1 :     circ3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
     453           1 :     circ4 = origin_circuit_new();
     454           1 :     tt_assert(circ4);
     455           1 :     circ4->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
     456             : 
     457             :     /* Register circ2 with tok2 as service-side intro v2 circ */
     458           1 :     hs_circuitmap_register_intro_circ_v3_service_side(circ2, &intro_pk2);
     459             :     /* Register circ3 with tok2 again but for different purpose */
     460           1 :     hs_circuitmap_register_intro_circ_v3_relay_side(circ3, &intro_pk2);
     461             : 
     462             :     /* Check that the getters work */
     463           1 :     tt_ptr_op(circ2, OP_EQ,
     464             :               hs_circuitmap_get_intro_circ_v3_service_side(&intro_pk2));
     465           1 :     tt_ptr_op(circ3, OP_EQ,
     466             :               hs_circuitmap_get_intro_circ_v3_relay_side(&intro_pk2));
     467             : 
     468             :     /* Register circ4 with tok2: it should override circ2 */
     469           1 :     hs_circuitmap_register_intro_circ_v3_service_side(circ4, &intro_pk2);
     470             : 
     471             :     /* check that relay-side getters don't work */
     472           1 :     tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
     473             : 
     474             :     /* Check that the getter returns circ4; the last circuit registered with
     475             :      * that token. */
     476           1 :     tt_ptr_op(circ4, OP_EQ,
     477             :               hs_circuitmap_get_intro_circ_v3_service_side(&intro_pk2));
     478             :   }
     479             : 
     480           1 :  done:
     481           1 :   circuit_free_(TO_CIRCUIT(circ1));
     482           1 :   circuit_free_(TO_CIRCUIT(circ2));
     483           1 :   circuit_free_(TO_CIRCUIT(circ3));
     484           1 :   circuit_free_(TO_CIRCUIT(circ4));
     485           1 : }
     486             : 
     487             : struct testcase_t circuitlist_tests[] = {
     488             :   { "maps", test_clist_maps, TT_FORK, NULL, NULL },
     489             :   { "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
     490             :   { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
     491             :   { "hs_circuitmap_isolation", test_hs_circuitmap_isolation,
     492             :     TT_FORK, NULL, NULL },
     493             :   END_OF_TESTCASES
     494             : };

Generated by: LCOV version 1.14