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

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       3             : /* See LICENSE for licensing information */
       4             : 
       5             : /**
       6             :  * \file test.c
       7             :  * \brief Unit tests for many pieces of the lower level Tor modules.
       8             :  **/
       9             : 
      10             : #include "orconfig.h"
      11             : #include "lib/crypt_ops/crypto_dh.h"
      12             : #include "lib/crypt_ops/crypto_rand.h"
      13             : #include "app/config/or_state_st.h"
      14             : #include "test/rng_test_helpers.h"
      15             : 
      16             : #include <stdio.h>
      17             : #ifdef HAVE_FCNTL_H
      18             : #include <fcntl.h>
      19             : #endif
      20             : 
      21             : #ifdef _WIN32
      22             : /* For mkdir() */
      23             : #include <direct.h>
      24             : #else
      25             : #include <dirent.h>
      26             : #endif /* defined(_WIN32) */
      27             : 
      28             : #include <math.h>
      29             : 
      30             : /* These macros pull in declarations for some functions and structures that
      31             :  * are typically file-private. */
      32             : #define ROUTER_PRIVATE
      33             : #define CIRCUITSTATS_PRIVATE
      34             : #define CIRCUITLIST_PRIVATE
      35             : #define MAINLOOP_PRIVATE
      36             : #define STATEFILE_PRIVATE
      37             : 
      38             : #include "core/or/or.h"
      39             : #include "lib/err/backtrace.h"
      40             : #include "lib/buf/buffers.h"
      41             : #include "core/or/circuitlist.h"
      42             : #include "core/or/circuitstats.h"
      43             : #include "lib/compress/compress.h"
      44             : #include "app/config/config.h"
      45             : #include "core/or/connection_edge.h"
      46             : #include "core/or/extendinfo.h"
      47             : #include "test/test.h"
      48             : #include "core/mainloop/mainloop.h"
      49             : #include "lib/memarea/memarea.h"
      50             : #include "core/or/onion.h"
      51             : #include "core/crypto/onion_ntor.h"
      52             : #include "core/crypto/onion_fast.h"
      53             : #include "core/crypto/onion_tap.h"
      54             : #include "core/or/policies.h"
      55             : #include "app/config/statefile.h"
      56             : #include "lib/crypt_ops/crypto_curve25519.h"
      57             : #include "feature/nodelist/networkstatus.h"
      58             : 
      59             : #include "core/or/extend_info_st.h"
      60             : #include "core/or/or_circuit_st.h"
      61             : #include "feature/relay/onion_queue.h"
      62             : 
      63             : /** Run unit tests for the onion handshake code. */
      64             : static void
      65           1 : test_onion_handshake(void *arg)
      66             : {
      67             :   /* client-side */
      68           1 :   crypto_dh_t *c_dh = NULL;
      69           1 :   char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
      70           1 :   char c_keys[40];
      71             :   /* server-side */
      72           1 :   char s_buf[TAP_ONIONSKIN_REPLY_LEN];
      73           1 :   char s_keys[40];
      74           1 :   int i;
      75             :   /* shared */
      76           1 :   crypto_pk_t *pk = NULL, *pk2 = NULL;
      77             : 
      78           1 :   (void)arg;
      79           1 :   pk = pk_generate(0);
      80           1 :   pk2 = pk_generate(1);
      81             : 
      82             :   /* client handshake 1. */
      83           1 :   memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
      84           1 :   tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
      85             : 
      86           4 :   for (i = 1; i <= 3; ++i) {
      87           3 :     crypto_pk_t *k1, *k2;
      88           3 :     if (i==1) {
      89             :       /* server handshake: only one key known. */
      90             :       k1 = pk;  k2 = NULL;
      91           2 :     } else if (i==2) {
      92             :       /* server handshake: try the right key first. */
      93             :       k1 = pk;  k2 = pk2;
      94             :     } else {
      95             :       /* server handshake: try the right key second. */
      96           1 :       k1 = pk2; k2 = pk;
      97             :     }
      98             : 
      99           3 :     memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
     100           3 :     memset(s_keys, 0, 40);
     101           3 :     tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
     102             :                                                   s_buf, s_keys, 40));
     103             : 
     104             :     /* client handshake 2 */
     105           3 :     memset(c_keys, 0, 40);
     106           3 :     tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys,
     107             :                                                 40, NULL));
     108             : 
     109           3 :     tt_mem_op(c_keys,OP_EQ, s_keys, 40);
     110           3 :     memset(s_buf, 0, 40);
     111           3 :     tt_mem_op(c_keys,OP_NE, s_buf, 40);
     112             :   }
     113           1 :  done:
     114           1 :   crypto_dh_free(c_dh);
     115           1 :   crypto_pk_free(pk);
     116           1 :   crypto_pk_free(pk2);
     117           1 : }
     118             : 
     119             : static void
     120           1 : test_bad_onion_handshake(void *arg)
     121             : {
     122           1 :   char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
     123           1 :   char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN];
     124             :   /* client-side */
     125           1 :   crypto_dh_t *c_dh = NULL;
     126           1 :   char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
     127           1 :   char c_keys[40];
     128             :   /* server-side */
     129           1 :   char s_buf[TAP_ONIONSKIN_REPLY_LEN];
     130           1 :   char s_keys[40];
     131             :   /* shared */
     132           1 :   crypto_pk_t *pk = NULL, *pk2 = NULL;
     133             : 
     134           1 :   (void)arg;
     135             : 
     136           1 :   pk = pk_generate(0);
     137           1 :   pk2 = pk_generate(1);
     138             : 
     139             :   /* Server: Case 1: the encrypted data is degenerate. */
     140           1 :   memset(junk_buf, 0, sizeof(junk_buf));
     141           1 :   crypto_pk_obsolete_public_hybrid_encrypt(pk,
     142             :                                junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN,
     143             :                                junk_buf, DH1024_KEY_LEN,
     144             :                                PK_PKCS1_OAEP_PADDING, 1);
     145           1 :   tt_int_op(-1, OP_EQ,
     146             :             onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
     147             :                                             s_buf, s_keys, 40));
     148             : 
     149             :   /* Server: Case 2: the encrypted data is not long enough. */
     150           1 :   memset(junk_buf, 0, sizeof(junk_buf));
     151           1 :   memset(junk_buf2, 0, sizeof(junk_buf2));
     152           1 :   crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2),
     153             :                                junk_buf, 48, PK_PKCS1_OAEP_PADDING);
     154           1 :   tt_int_op(-1, OP_EQ,
     155             :             onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
     156             :                                             s_buf, s_keys, 40));
     157             : 
     158             :   /* client handshake 1: do it straight. */
     159           1 :   memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
     160           1 :   tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
     161             : 
     162             :   /* Server: Case 3: we just don't have the right key. */
     163           1 :   tt_int_op(-1, OP_EQ,
     164             :             onion_skin_TAP_server_handshake(c_buf, pk2, NULL,
     165             :                                             s_buf, s_keys, 40));
     166             : 
     167             :   /* Server: Case 4: The RSA-encrypted portion is corrupt. */
     168           1 :   c_buf[64] ^= 33;
     169           1 :   tt_int_op(-1, OP_EQ,
     170             :             onion_skin_TAP_server_handshake(c_buf, pk, NULL,
     171             :                                             s_buf, s_keys, 40));
     172           1 :   c_buf[64] ^= 33;
     173             : 
     174             :   /* (Let the server proceed) */
     175           1 :   tt_int_op(0, OP_EQ,
     176             :             onion_skin_TAP_server_handshake(c_buf, pk, NULL,
     177             :                                             s_buf, s_keys, 40));
     178             : 
     179             :   /* Client: Case 1: The server sent back junk. */
     180           1 :   const char *msg = NULL;
     181           1 :   s_buf[64] ^= 33;
     182           1 :   tt_int_op(-1, OP_EQ,
     183             :             onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
     184           1 :   s_buf[64] ^= 33;
     185           1 :   tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. "
     186             :             "Bug or attack.");
     187             : 
     188             :   /* Let the client finish; make sure it can. */
     189           1 :   msg = NULL;
     190           1 :   tt_int_op(0, OP_EQ,
     191             :             onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
     192           1 :   tt_mem_op(s_keys,OP_EQ, c_keys, 40);
     193           1 :   tt_ptr_op(msg, OP_EQ, NULL);
     194             : 
     195             :   /* Client: Case 2: The server sent back a degenerate DH. */
     196           1 :   memset(s_buf, 0, sizeof(s_buf));
     197           1 :   tt_int_op(-1, OP_EQ,
     198             :             onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
     199           1 :   tt_str_op(msg, OP_EQ, "DH computation failed.");
     200             : 
     201           1 :  done:
     202           1 :   crypto_dh_free(c_dh);
     203           1 :   crypto_pk_free(pk);
     204           1 :   crypto_pk_free(pk2);
     205           1 : }
     206             : 
     207             : static void
     208           1 : test_ntor_handshake(void *arg)
     209             : {
     210             :   /* client-side */
     211           1 :   ntor_handshake_state_t *c_state = NULL;
     212           1 :   uint8_t c_buf[NTOR_ONIONSKIN_LEN];
     213           1 :   uint8_t c_keys[400];
     214             : 
     215             :   /* server-side */
     216           1 :   di_digest256_map_t *s_keymap=NULL;
     217           1 :   curve25519_keypair_t s_keypair;
     218           1 :   uint8_t s_buf[NTOR_REPLY_LEN];
     219           1 :   uint8_t s_keys[400];
     220             : 
     221             :   /* shared */
     222           1 :   const curve25519_public_key_t *server_pubkey;
     223           1 :   uint8_t node_id[20] = "abcdefghijklmnopqrst";
     224             : 
     225           1 :   (void) arg;
     226             : 
     227             :   /* Make the server some keys */
     228           1 :   curve25519_secret_key_generate(&s_keypair.seckey, 0);
     229           1 :   curve25519_public_key_generate(&s_keypair.pubkey, &s_keypair.seckey);
     230           1 :   dimap_add_entry(&s_keymap, s_keypair.pubkey.public_key, &s_keypair);
     231           1 :   server_pubkey = &s_keypair.pubkey;
     232             : 
     233             :   /* client handshake 1. */
     234           1 :   memset(c_buf, 0, NTOR_ONIONSKIN_LEN);
     235           1 :   tt_int_op(0, OP_EQ, onion_skin_ntor_create(node_id, server_pubkey,
     236             :                                           &c_state, c_buf));
     237             : 
     238             :   /* server handshake */
     239           1 :   memset(s_buf, 0, NTOR_REPLY_LEN);
     240           1 :   memset(s_keys, 0, 40);
     241           1 :   tt_int_op(0, OP_EQ, onion_skin_ntor_server_handshake(c_buf, s_keymap, NULL,
     242             :                                                     node_id,
     243             :                                                     s_buf, s_keys, 400));
     244             : 
     245             :   /* client handshake 2 */
     246           1 :   memset(c_keys, 0, 40);
     247           1 :   tt_int_op(0, OP_EQ, onion_skin_ntor_client_handshake(c_state, s_buf,
     248             :                                                        c_keys, 400, NULL));
     249             : 
     250           1 :   tt_mem_op(c_keys,OP_EQ, s_keys, 400);
     251           1 :   memset(s_buf, 0, 40);
     252           1 :   tt_mem_op(c_keys,OP_NE, s_buf, 40);
     253             : 
     254             :   /* Now try with a bogus server response. Zero input should trigger
     255             :    * All The Problems. */
     256           1 :   memset(c_keys, 0, 400);
     257           1 :   memset(s_buf, 0, NTOR_REPLY_LEN);
     258           1 :   const char *msg = NULL;
     259           1 :   tt_int_op(-1, OP_EQ, onion_skin_ntor_client_handshake(c_state, s_buf,
     260             :                                                         c_keys, 400, &msg));
     261           1 :   tt_str_op(msg, OP_EQ, "Zero output from curve25519 handshake");
     262             : 
     263           1 :  done:
     264           1 :   ntor_handshake_state_free(c_state);
     265           1 :   dimap_free(s_keymap, NULL);
     266           1 : }
     267             : 
     268             : static void
     269           1 : test_fast_handshake(void *arg)
     270             : {
     271             :   /* tests for the obsolete "CREATE_FAST" handshake. */
     272           1 :   (void) arg;
     273           1 :   fast_handshake_state_t *state = NULL;
     274           1 :   uint8_t client_handshake[CREATE_FAST_LEN];
     275           1 :   uint8_t server_handshake[CREATED_FAST_LEN];
     276           1 :   uint8_t s_keys[100], c_keys[100];
     277             : 
     278             :   /* First, test an entire handshake. */
     279           1 :   memset(client_handshake, 0, sizeof(client_handshake));
     280           1 :   tt_int_op(0, OP_EQ, fast_onionskin_create(&state, client_handshake));
     281           1 :   tt_assert(! fast_mem_is_zero((char*)client_handshake,
     282             :                               sizeof(client_handshake)));
     283             : 
     284           1 :   tt_int_op(0, OP_EQ,
     285             :             fast_server_handshake(client_handshake, server_handshake,
     286             :                                   s_keys, 100));
     287           1 :   const char *msg = NULL;
     288           1 :   tt_int_op(0, OP_EQ,
     289             :             fast_client_handshake(state, server_handshake, c_keys, 100, &msg));
     290           1 :   tt_ptr_op(msg, OP_EQ, NULL);
     291           1 :   tt_mem_op(s_keys, OP_EQ, c_keys, 100);
     292             : 
     293             :   /* Now test a failing handshake. */
     294           1 :   server_handshake[0] ^= 3;
     295           1 :   tt_int_op(-1, OP_EQ,
     296             :             fast_client_handshake(state, server_handshake, c_keys, 100, &msg));
     297           1 :   tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on fast handshake. "
     298             :             "Bug or attack.");
     299             : 
     300           1 :  done:
     301           1 :   fast_handshake_state_free(state);
     302           1 : }
     303             : 
     304             : /** Run unit tests for the onion queues. */
     305             : static void
     306           1 : test_onion_queues(void *arg)
     307             : {
     308           1 :   uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
     309           1 :   uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0};
     310             : 
     311           1 :   or_circuit_t *circ1 = or_circuit_new(0, NULL);
     312           1 :   or_circuit_t *circ2 = or_circuit_new(0, NULL);
     313             : 
     314           1 :   create_cell_t *onionskin = NULL, *create2_ptr;
     315           1 :   create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t));
     316           1 :   create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t));
     317           1 :   (void)arg;
     318           1 :   create2_ptr = create2; /* remember, but do not free */
     319             : 
     320           1 :   create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
     321             :                    TAP_ONIONSKIN_CHALLENGE_LEN, buf1);
     322           1 :   create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
     323             :                    NTOR_ONIONSKIN_LEN, buf2);
     324             : 
     325           1 :   tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
     326           1 :   tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1));
     327           1 :   create1 = NULL;
     328           1 :   tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
     329             : 
     330           1 :   tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
     331           1 :   tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2));
     332           1 :   create2 = NULL;
     333           1 :   tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
     334             : 
     335           1 :   tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin));
     336           1 :   tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
     337           1 :   tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
     338           1 :   tt_ptr_op(onionskin, OP_EQ, create2_ptr);
     339             : 
     340           1 :   clear_pending_onions();
     341           1 :   tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
     342           1 :   tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
     343             : 
     344           1 :  done:
     345           1 :   circuit_free_(TO_CIRCUIT(circ1));
     346           1 :   circuit_free_(TO_CIRCUIT(circ2));
     347           1 :   tor_free(create1);
     348           1 :   tor_free(create2);
     349           1 :   tor_free(onionskin);
     350           1 : }
     351             : 
     352             : static int32_t cbtnummodes = 10;
     353             : 
     354             : static int32_t
     355          12 : mock_xm_networkstatus_get_param(
     356             :     const networkstatus_t *ns, const char *param_name, int32_t default_val,
     357             :     int32_t min_val, int32_t max_val)
     358             : {
     359          12 :   (void)ns;
     360          12 :   (void)default_val;
     361          12 :   (void)min_val;
     362          12 :   (void)max_val;
     363             :   // only support cbtnummodes right now
     364          12 :   tor_assert(strcmp(param_name, "cbtnummodes")==0);
     365          12 :   return cbtnummodes;
     366             : }
     367             : 
     368             : static void
     369           1 : test_circuit_timeout_xm_alpha(void *arg)
     370             : {
     371           1 :   circuit_build_times_t cbt;
     372           1 :   build_time_t Xm;
     373           1 :   int alpha_ret;
     374           1 :   circuit_build_times_init(&cbt);
     375           1 :   (void)arg;
     376             : 
     377             :   /* Plan:
     378             :    * 1. Create array of build times with 10 modes.
     379             :    * 2. Make sure Xm calc is sane for 1,3,5,10,15,20 modes.
     380             :    * 3. Make sure alpha calc is sane for 1,3,5,10,15,20 modes.
     381             :    */
     382             : 
     383             :   /* 110 build times, 9 modes, 8 mode ties, 10 abandoned */
     384           1 :   build_time_t circuit_build_times[] = {
     385             :     100, 20, 1000, 500, 200, 5000, 30, 600, 200, 300, CBT_BUILD_ABANDONED,
     386             :     101, 21, 1001, 501, 201, 5001, 31, 601, 201, 301, CBT_BUILD_ABANDONED,
     387             :     102, 22, 1002, 502, 202, 5002, 32, 602, 202, 302, CBT_BUILD_ABANDONED,
     388             :     103, 23, 1003, 503, 203, 5003, 33, 603, 203, 303, CBT_BUILD_ABANDONED,
     389             :     104, 24, 1004, 504, 204, 5004, 34, 604, 204, 304, CBT_BUILD_ABANDONED,
     390             :     105, 25, 1005, 505, 205, 5005, 35, 605, 205, 305, CBT_BUILD_ABANDONED,
     391             :     106, 26, 1006, 506, 206, 5006, 36, 606, 206, 306, CBT_BUILD_ABANDONED,
     392             :     107, 27, 1007, 507, 207, 5007, 37, 607, 207, 307, CBT_BUILD_ABANDONED,
     393             :     108, 28, 1008, 508, 208, 5008, 38, 608, 208, 308, CBT_BUILD_ABANDONED,
     394             :     109, 29, 1009, 509, 209, 5009, 39, 609, 209, 309, CBT_BUILD_ABANDONED
     395             :   };
     396             : 
     397           1 :   memcpy(cbt.circuit_build_times, circuit_build_times,
     398             :          sizeof(circuit_build_times));
     399           1 :   cbt.total_build_times = 110;
     400             : 
     401           1 :   MOCK(networkstatus_get_param, mock_xm_networkstatus_get_param);
     402             : 
     403             : #define CBT_ALPHA_PRECISION 0.00001
     404           1 :   cbtnummodes = 1;
     405           1 :   Xm = circuit_build_times_get_xm(&cbt);
     406           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     407           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     408           1 :   tt_int_op(Xm, OP_EQ, 205);
     409           1 :   tt_assert(fabs(cbt.alpha - 1.394401) < CBT_ALPHA_PRECISION);
     410             : 
     411           1 :   cbtnummodes = 3;
     412           1 :   Xm = circuit_build_times_get_xm(&cbt);
     413           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     414           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     415           1 :   tt_int_op(Xm, OP_EQ, 117);
     416           1 :   tt_assert(fabs(cbt.alpha - 0.902313) < CBT_ALPHA_PRECISION);
     417             : 
     418           1 :   cbtnummodes = 5;
     419           1 :   Xm = circuit_build_times_get_xm(&cbt);
     420           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     421           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     422           1 :   tt_int_op(Xm, OP_EQ, 146);
     423           1 :   tt_assert(fabs(cbt.alpha - 1.049032) < CBT_ALPHA_PRECISION);
     424             : 
     425           1 :   cbtnummodes = 10;
     426           1 :   Xm = circuit_build_times_get_xm(&cbt);
     427           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     428           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     429           1 :   tt_int_op(Xm, OP_EQ, 800);
     430           1 :   tt_assert(fabs(cbt.alpha - 4.851754) < CBT_ALPHA_PRECISION);
     431             : 
     432           1 :   cbtnummodes = 15;
     433           1 :   Xm = circuit_build_times_get_xm(&cbt);
     434           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     435           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     436           1 :   tt_int_op(Xm, OP_EQ, 800);
     437           1 :   tt_assert(fabs(cbt.alpha - 4.851754) < CBT_ALPHA_PRECISION);
     438             : 
     439           1 :   cbtnummodes = 20;
     440           1 :   Xm = circuit_build_times_get_xm(&cbt);
     441           1 :   alpha_ret = circuit_build_times_update_alpha(&cbt);
     442           1 :   tt_int_op(alpha_ret, OP_EQ, 1);
     443           1 :   tt_int_op(Xm, OP_EQ, 800);
     444           1 :   tt_assert(fabs(cbt.alpha - 4.851754) < CBT_ALPHA_PRECISION);
     445             : 
     446           1 :  done:
     447             : #undef CBT_ALPHA_PRECISION
     448           1 :   UNMOCK(networkstatus_get_param);
     449           1 :   circuit_build_times_free_timeouts(&cbt);
     450           1 : }
     451             : 
     452             : static void
     453           1 : test_circuit_timeout(void *arg)
     454             : {
     455             :   /* Plan:
     456             :    *  1. Generate 1000 samples
     457             :    *  2. Estimate parameters
     458             :    *  3. If difference, repeat
     459             :    *  4. Save state
     460             :    *  5. load state
     461             :    *  6. Estimate parameters
     462             :    *  7. compare differences
     463             :    */
     464           1 :   circuit_build_times_t initial;
     465           1 :   circuit_build_times_t estimate;
     466           1 :   circuit_build_times_t final;
     467           1 :   double timeout1, timeout2;
     468           1 :   or_state_t *state=NULL;
     469           1 :   int i, runs;
     470           1 :   (void)arg;
     471             : 
     472           1 :   initialize_periodic_events();
     473             : 
     474           1 :   circuit_build_times_init(&initial);
     475           1 :   circuit_build_times_init(&estimate);
     476           1 :   circuit_build_times_init(&final);
     477             : 
     478           1 :   state = or_state_new();
     479             : 
     480             :   // Use a deterministic RNG here, or else we'll get nondeterministic
     481             :   // coverage in some of the circuitstats functions.
     482           1 :   testing_enable_deterministic_rng();
     483             : 
     484           1 :   circuitbuild_running_unit_tests();
     485             : #define timeout0 (build_time_t)(30*1000.0)
     486           1 :   initial.Xm = 3000;
     487           1 :   circuit_build_times_initial_alpha(&initial,
     488             :                                     CBT_DEFAULT_QUANTILE_CUTOFF/100.0,
     489             :                                     timeout0);
     490           1 :   do {
     491         101 :     for (i=0; i < CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE; i++) {
     492         100 :       build_time_t sample = circuit_build_times_generate_sample(&initial,0,1);
     493             : 
     494         100 :       circuit_build_times_add_time(&estimate, sample);
     495             :     }
     496           1 :     circuit_build_times_update_alpha(&estimate);
     497           1 :     timeout1 = circuit_build_times_calculate_timeout(&estimate,
     498             :                                   CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
     499           1 :     circuit_build_times_set_timeout(&estimate);
     500           1 :     log_notice(LD_CIRC, "Timeout1 is %f, Xm is %d", timeout1, estimate.Xm);
     501             :            /* 2% error */
     502           2 :   } while (fabs(circuit_build_times_cdf(&initial, timeout0) -
     503           1 :                 circuit_build_times_cdf(&initial, timeout1)) > 0.02);
     504             : 
     505           1 :   tt_int_op(estimate.total_build_times, OP_LE, CBT_NCIRCUITS_TO_OBSERVE);
     506             : 
     507           1 :   circuit_build_times_update_state(&estimate, state);
     508           1 :   circuit_build_times_free_timeouts(&final);
     509           1 :   tt_int_op(circuit_build_times_parse_state(&final, state), OP_EQ, 0);
     510             : 
     511           1 :   circuit_build_times_update_alpha(&final);
     512           1 :   timeout2 = circuit_build_times_calculate_timeout(&final,
     513             :                                  CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
     514             : 
     515           1 :   circuit_build_times_set_timeout(&final);
     516           1 :   log_notice(LD_CIRC, "Timeout2 is %f, Xm is %d", timeout2, final.Xm);
     517             : 
     518             :   /* 5% here because some accuracy is lost due to histogram conversion */
     519           1 :   tt_assert(fabs(circuit_build_times_cdf(&initial, timeout0) -
     520             :                    circuit_build_times_cdf(&initial, timeout2)) < 0.05);
     521             : 
     522          51 :   for (runs = 0; runs < 50; runs++) {
     523          50 :     int build_times_idx = 0;
     524          50 :     int total_build_times = 0;
     525             : 
     526          50 :     final.close_ms = final.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
     527          50 :     estimate.close_ms = estimate.timeout_ms
     528          50 :                       = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
     529             : 
     530        2050 :     for (i = 0; i < CBT_DEFAULT_RECENT_CIRCUITS*2; i++) {
     531        2000 :       circuit_build_times_network_circ_success(&estimate);
     532        2000 :       circuit_build_times_add_time(&estimate,
     533             :             circuit_build_times_generate_sample(&estimate, 0,
     534             :                 CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
     535             : 
     536        2000 :       circuit_build_times_network_circ_success(&estimate);
     537        2000 :       circuit_build_times_add_time(&final,
     538             :             circuit_build_times_generate_sample(&final, 0,
     539             :                 CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
     540             :     }
     541             : 
     542          50 :     tt_assert(!circuit_build_times_network_check_changed(&estimate));
     543          50 :     tt_assert(!circuit_build_times_network_check_changed(&final));
     544             : 
     545             :     /* Reset liveness to be non-live */
     546          50 :     final.liveness.network_last_live = 0;
     547          50 :     estimate.liveness.network_last_live = 0;
     548             : 
     549          50 :     build_times_idx = estimate.build_times_idx;
     550          50 :     total_build_times = estimate.total_build_times;
     551             : 
     552          50 :     tt_assert(circuit_build_times_network_check_live(&estimate));
     553          50 :     tt_assert(circuit_build_times_network_check_live(&final));
     554             : 
     555         100 :     circuit_build_times_count_close(&estimate, 0,
     556          50 :             (time_t)(approx_time()-estimate.close_ms/1000.0-1));
     557         100 :     circuit_build_times_count_close(&final, 0,
     558          50 :             (time_t)(approx_time()-final.close_ms/1000.0-1));
     559             : 
     560          50 :     tt_assert(!circuit_build_times_network_check_live(&estimate));
     561          50 :     tt_assert(!circuit_build_times_network_check_live(&final));
     562             : 
     563          50 :     log_info(LD_CIRC, "idx: %d %d, tot: %d %d",
     564             :              build_times_idx, estimate.build_times_idx,
     565             :              total_build_times, estimate.total_build_times);
     566             : 
     567             :     /* Check rollback index. Should match top of loop. */
     568          50 :     tt_assert(build_times_idx == estimate.build_times_idx);
     569             :     // This can fail if estimate.total_build_times == 1000, because
     570             :     // in that case, rewind actually causes us to lose timeouts
     571          50 :     if (total_build_times != CBT_NCIRCUITS_TO_OBSERVE)
     572          50 :       tt_assert(total_build_times == estimate.total_build_times);
     573             : 
     574             :     /* Now simulate that the network has become live and we need
     575             :      * a change */
     576          50 :     circuit_build_times_network_is_live(&estimate);
     577          50 :     circuit_build_times_network_is_live(&final);
     578             : 
     579        1000 :     for (i = 0; i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT; i++) {
     580         900 :       circuit_build_times_count_timeout(&estimate, 1);
     581             : 
     582         900 :       if (i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1) {
     583         850 :         circuit_build_times_count_timeout(&final, 1);
     584             :       }
     585             :     }
     586             : 
     587          50 :     tt_int_op(estimate.liveness.after_firsthop_idx, OP_EQ, 0);
     588          50 :     tt_assert(final.liveness.after_firsthop_idx ==
     589             :                 CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1);
     590             : 
     591          50 :     tt_assert(circuit_build_times_network_check_live(&estimate));
     592          50 :     tt_assert(circuit_build_times_network_check_live(&final));
     593             : 
     594          50 :     circuit_build_times_count_timeout(&final, 1);
     595             : 
     596             :     /* Ensure return value for degenerate cases are clamped correctly */
     597          50 :     initial.alpha = INT32_MAX;
     598          50 :     tt_assert(circuit_build_times_calculate_timeout(&initial, .99999999) <=
     599             :               INT32_MAX);
     600          50 :     initial.alpha = 0;
     601          50 :     tt_assert(circuit_build_times_calculate_timeout(&initial, .5) <=
     602             :               INT32_MAX);
     603             :   }
     604             : 
     605           1 :  done:
     606           1 :   circuit_build_times_free_timeouts(&initial);
     607           1 :   circuit_build_times_free_timeouts(&estimate);
     608           1 :   circuit_build_times_free_timeouts(&final);
     609           1 :   or_state_free(state);
     610           1 :   teardown_periodic_events();
     611             : 
     612           1 :   testing_disable_deterministic_rng();
     613           1 : }
     614             : 
     615             : #define ENT(name)                                                       \
     616             :   { #name, test_ ## name , 0, NULL, NULL }
     617             : #define FORK(name)                                                      \
     618             :   { #name, test_ ## name , TT_FORK, NULL, NULL }
     619             : 
     620             : static struct testcase_t test_array[] = {
     621             :   ENT(onion_handshake),
     622             :   { "bad_onion_handshake", test_bad_onion_handshake, 0, NULL, NULL },
     623             :   ENT(onion_queues),
     624             :   { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
     625             :   { "fast_handshake", test_fast_handshake, 0, NULL, NULL },
     626             :   FORK(circuit_timeout),
     627             :   FORK(circuit_timeout_xm_alpha),
     628             : 
     629             :   END_OF_TESTCASES
     630             : };
     631             : 
     632             : struct testgroup_t testgroups[] = {
     633             :   { "", test_array },
     634             :   { "accounting/", accounting_tests },
     635             :   { "addr/", addr_tests },
     636             :   { "address/", address_tests },
     637             :   { "address_set/", address_set_tests },
     638             :   { "bridges/", bridges_tests },
     639             :   { "buffer/", buffer_tests },
     640             :   { "bwmgt/", bwmgt_tests },
     641             :   { "cellfmt/", cell_format_tests },
     642             :   { "cellqueue/", cell_queue_tests },
     643             :   { "channel/", channel_tests },
     644             :   { "channelpadding/", channelpadding_tests },
     645             :   { "channeltls/", channeltls_tests },
     646             :   { "checkdir/", checkdir_tests },
     647             :   { "circuitbuild/", circuitbuild_tests },
     648             :   { "circuitpadding/", circuitpadding_tests },
     649             :   { "circuitlist/", circuitlist_tests },
     650             :   { "circuitmux/", circuitmux_tests },
     651             :   { "circuitmux_ewma/", circuitmux_ewma_tests },
     652             :   { "circuitstats/", circuitstats_tests },
     653             :   { "circuituse/", circuituse_tests },
     654             :   { "compat/libevent/", compat_libevent_tests },
     655             :   { "config/", config_tests },
     656             :   { "config/mgr/", confmgr_tests },
     657             :   { "config/parse/", confparse_tests },
     658             :   { "connection/", connection_tests },
     659             :   { "conscache/", conscache_tests },
     660             :   { "consdiff/", consdiff_tests },
     661             :   { "consdiffmgr/", consdiffmgr_tests },
     662             :   { "container/", container_tests },
     663             :   { "container/namemap/", namemap_tests },
     664             :   { "control/", controller_tests },
     665             :   { "control/btrack/", btrack_tests },
     666             :   { "control/event/", controller_event_tests },
     667             :   { "crypto/", crypto_tests },
     668             :   { "crypto/ope/", crypto_ope_tests },
     669             : #ifdef ENABLE_OPENSSL
     670             :   { "crypto/openssl/", crypto_openssl_tests },
     671             : #endif
     672             :   { "crypto/pem/", pem_tests },
     673             :   { "crypto/rng/", crypto_rng_tests },
     674             :   { "dir/", dir_tests },
     675             :   { "dir/auth/ports/", dirauth_port_tests },
     676             :   { "dir/auth/process_descs/", process_descs_tests },
     677             :   { "dir/md/", microdesc_tests },
     678             :   { "dirauth/dirvote/", dirvote_tests},
     679             :   { "dir/voting/flags/", voting_flags_tests },
     680             :   { "dir/voting/schedule/", voting_schedule_tests },
     681             :   { "dir_handle_get/", dir_handle_get_tests },
     682             :   { "dispatch/", dispatch_tests, },
     683             :   { "dns/", dns_tests },
     684             :   { "dos/", dos_tests },
     685             :   { "entryconn/", entryconn_tests },
     686             :   { "entrynodes/", entrynodes_tests },
     687             :   { "extorport/", extorport_tests },
     688             :   { "geoip/", geoip_tests },
     689             :   { "guardfraction/", guardfraction_tests },
     690             :   { "hs_cache/", hs_cache },
     691             :   { "hs_cell/", hs_cell_tests },
     692             :   { "hs_client/", hs_client_tests },
     693             :   { "hs_common/", hs_common_tests },
     694             :   { "hs_config/", hs_config_tests },
     695             :   { "hs_control/", hs_control_tests },
     696             :   { "hs_descriptor/", hs_descriptor },
     697             :   { "hs_dos/", hs_dos_tests },
     698             :   { "hs_intropoint/", hs_intropoint_tests },
     699             :   { "hs_metrics/", hs_metrics_tests },
     700             :   { "hs_ntor/", hs_ntor_tests },
     701             :   { "hs_ob/", hs_ob_tests },
     702             :   { "hs_service/", hs_service_tests },
     703             :   { "keypin/", keypin_tests },
     704             :   { "link-handshake/", link_handshake_tests },
     705             :   { "mainloop/", mainloop_tests },
     706             :   { "metrics/", metrics_tests },
     707             :   { "netinfo/", netinfo_tests },
     708             :   { "nodelist/", nodelist_tests },
     709             :   { "oom/", oom_tests },
     710             :   { "oos/", oos_tests },
     711             :   { "options/", options_tests },
     712             :   { "options/act/", options_act_tests },
     713             :   { "parsecommon/", parsecommon_tests },
     714             :   { "periodic-event/" , periodic_event_tests },
     715             :   { "policy/" , policy_tests },
     716             :   { "prob_distr/", prob_distr_tests },
     717             :   { "procmon/", procmon_tests },
     718             :   { "process/", process_tests },
     719             :   { "proto/haproxy/", proto_haproxy_tests },
     720             :   { "proto/http/", proto_http_tests },
     721             :   { "proto/misc/", proto_misc_tests },
     722             :   { "protover/", protover_tests },
     723             :   { "pt/", pt_tests },
     724             :   { "pubsub/build/", pubsub_build_tests },
     725             :   { "pubsub/msg/", pubsub_msg_tests },
     726             :   { "relay/" , relay_tests },
     727             :   { "relaycell/", relaycell_tests },
     728             :   { "relaycrypt/", relaycrypt_tests },
     729             :   { "replaycache/", replaycache_tests },
     730             :   { "router/", router_tests },
     731             :   { "routerkeys/", routerkeys_tests },
     732             :   { "routerlist/", routerlist_tests },
     733             :   { "routerset/" , routerset_tests },
     734             :   { "scheduler/", scheduler_tests },
     735             :   { "sendme/", sendme_tests },
     736             :   { "shared-random/", sr_tests },
     737             :   { "socks/", socks_tests },
     738             :   { "statefile/", statefile_tests },
     739             :   { "stats/", stats_tests },
     740             :   { "status/" , status_tests },
     741             :   { "storagedir/", storagedir_tests },
     742             :   { "token_bucket/", token_bucket_tests },
     743             :   { "tortls/", tortls_tests },
     744             : #ifndef ENABLE_NSS
     745             :   { "tortls/openssl/", tortls_openssl_tests },
     746             : #endif
     747             :   { "tortls/x509/", x509_tests },
     748             :   { "util/", util_tests },
     749             :   { "util/format/", util_format_tests },
     750             :   { "util/handle/", handle_tests },
     751             :   { "util/logging/", logging_tests },
     752             :   { "util/process/", util_process_tests },
     753             :   { "util/thread/", thread_tests },
     754             :   END_OF_GROUPS
     755             : };

Generated by: LCOV version 1.14