1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Unit tests for the statistics (reputation history) module.
12 #include "lib/crypt_ops/crypto_rand.h"
13 #include "app/config/or_state_st.h"
14 #include "test/rng_test_helpers.h"
15 #include "feature/hs/hs_cache.h"
16 #include "test/hs_test_helpers.h"
25 #endif /* defined(_WIN32) */
29 /* These macros pull in declarations for some functions and structures that
30 * are typically file-private. */
31 #define CIRCUITSTATS_PRIVATE
32 #define CIRCUITLIST_PRIVATE
33 #define MAINLOOP_PRIVATE
34 #define STATEFILE_PRIVATE
35 #define BWHIST_PRIVATE
36 #define REPHIST_PRIVATE
37 #define ROUTER_PRIVATE
39 #include "core/or/or.h"
40 #include "lib/err/backtrace.h"
41 #include "lib/buf/buffers.h"
42 #include "core/or/circuitstats.h"
43 #include "app/config/config.h"
44 #include "test/test.h"
45 #include "core/mainloop/mainloop.h"
46 #include "lib/memarea/memarea.h"
47 #include "feature/stats/connstats.h"
48 #include "feature/stats/rephist.h"
49 #include "app/config/statefile.h"
50 #include "feature/stats/bwhist.h"
51 #include "feature/stats/bw_array_st.h"
52 #include "feature/relay/router.h"
54 /** Run unit tests for some stats code. */
58 time_t now
= 1281533250; /* 2010-08-11 13:27:30 UTC */
62 /* Start with testing exit port statistics; we shouldn't collect exit
63 * stats without initializing them. */
65 rep_hist_note_exit_stream_opened(80);
66 rep_hist_note_exit_bytes(80, 100, 10000);
67 s
= rep_hist_format_exit_stats(now
+ 86400);
68 tt_ptr_op(s
, OP_EQ
, NULL
);
70 /* Initialize stats, note some streams and bytes, and generate history
72 rep_hist_exit_stats_init(now
);
73 rep_hist_note_exit_stream_opened(80);
74 rep_hist_note_exit_bytes(80, 100, 10000);
75 rep_hist_note_exit_stream_opened(443);
76 rep_hist_note_exit_bytes(443, 100, 10000);
77 rep_hist_note_exit_bytes(443, 100, 10000);
78 s
= rep_hist_format_exit_stats(now
+ 86400);
79 tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
80 "exit-kibibytes-written 80=1,443=1,other=0\n"
81 "exit-kibibytes-read 80=10,443=20,other=0\n"
82 "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ
, s
);
85 /* Add a few bytes on 10 more ports and ensure that only the top 10
86 * ports are contained in the history string. */
87 for (i
= 50; i
< 60; i
++) {
88 rep_hist_note_exit_bytes(i
, i
, i
);
89 rep_hist_note_exit_stream_opened(i
);
91 s
= rep_hist_format_exit_stats(now
+ 86400);
92 tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
93 "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
94 "59=1,80=1,443=1,other=1\n"
95 "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
96 "59=1,80=10,443=20,other=1\n"
97 "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
98 "59=4,80=4,443=4,other=4\n",OP_EQ
, s
);
101 /* Stop collecting stats, add some bytes, and ensure we don't generate
102 * a history string. */
103 rep_hist_exit_stats_term();
104 rep_hist_note_exit_bytes(80, 100, 10000);
105 s
= rep_hist_format_exit_stats(now
+ 86400);
106 tt_ptr_op(s
, OP_EQ
, NULL
);
108 /* Re-start stats, add some bytes, reset stats, and see what history we
109 * get when observing no streams or bytes at all. */
110 rep_hist_exit_stats_init(now
);
111 rep_hist_note_exit_stream_opened(80);
112 rep_hist_note_exit_bytes(80, 100, 10000);
113 rep_hist_reset_exit_stats(now
);
114 s
= rep_hist_format_exit_stats(now
+ 86400);
115 tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
116 "exit-kibibytes-written other=0\n"
117 "exit-kibibytes-read other=0\n"
118 "exit-streams-opened other=0\n",OP_EQ
, s
);
121 /* Continue with testing connection statistics; we shouldn't collect
122 * conn stats without initializing them. */
123 conn_stats_note_or_conn_bytes(1, 20, 400, now
, false);
124 s
= conn_stats_format(now
+ 86400);
125 tt_ptr_op(s
, OP_EQ
, NULL
);
127 /* Initialize stats, note bytes, and generate history string. */
128 conn_stats_init(now
);
129 conn_stats_note_or_conn_bytes(1, 30000, 400000, now
, false);
130 conn_stats_note_or_conn_bytes(1, 30000, 400000, now
+ 5, false);
131 conn_stats_note_or_conn_bytes(2, 400000, 30000, now
+ 10, true);
132 conn_stats_note_or_conn_bytes(2, 400000, 30000, now
+ 15, true);
133 s
= conn_stats_format(now
+ 86400);
134 tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n"
135 "ipv6-conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",
139 /* Stop collecting stats, add some bytes, and ensure we don't generate
140 * a history string. */
141 conn_stats_terminate();
142 conn_stats_note_or_conn_bytes(2, 400000, 30000, now
+ 15, true);
143 s
= conn_stats_format(now
+ 86400);
144 tt_ptr_op(s
, OP_EQ
, NULL
);
146 /* Re-start stats, add some bytes, reset stats, and see what history we
147 * get when observing no bytes at all. */
148 conn_stats_init(now
);
149 conn_stats_note_or_conn_bytes(1, 30000, 400000, now
, false);
150 conn_stats_note_or_conn_bytes(1, 30000, 400000, now
+ 5, false);
151 conn_stats_note_or_conn_bytes(2, 400000, 30000, now
+ 10, true);
152 conn_stats_note_or_conn_bytes(2, 400000, 30000, now
+ 15, true);
153 conn_stats_reset(now
);
154 s
= conn_stats_format(now
+ 86400);
155 tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n"
156 "ipv6-conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",
160 /* Continue with testing buffer statistics; we shouldn't collect buffer
161 * stats without initializing them. */
162 rep_hist_add_buffer_stats(2.0, 2.0, 20);
163 s
= rep_hist_format_buffer_stats(now
+ 86400);
164 tt_ptr_op(s
, OP_EQ
, NULL
);
166 /* Initialize stats, add statistics for a single circuit, and generate
167 * the history string. */
168 rep_hist_buffer_stats_init(now
);
169 rep_hist_add_buffer_stats(2.0, 2.0, 20);
170 s
= rep_hist_format_buffer_stats(now
+ 86400);
171 tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
172 "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
173 "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
175 "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
176 "cell-circuits-per-decile 1\n",OP_EQ
, s
);
179 /* Add nineteen more circuit statistics to the one that's already in the
180 * history to see that the math works correctly. */
181 for (i
= 21; i
< 30; i
++)
182 rep_hist_add_buffer_stats(2.0, 2.0, i
);
183 for (i
= 20; i
< 30; i
++)
184 rep_hist_add_buffer_stats(3.5, 3.5, i
);
185 s
= rep_hist_format_buffer_stats(now
+ 86400);
186 tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
187 "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
188 "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
190 "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
191 "cell-circuits-per-decile 2\n",OP_EQ
, s
);
194 /* Stop collecting stats, add statistics for one circuit, and ensure we
195 * don't generate a history string. */
196 rep_hist_buffer_stats_term();
197 rep_hist_add_buffer_stats(2.0, 2.0, 20);
198 s
= rep_hist_format_buffer_stats(now
+ 86400);
199 tt_ptr_op(s
, OP_EQ
, NULL
);
201 /* Re-start stats, add statistics for one circuit, reset stats, and make
202 * sure that the history has all zeros. */
203 rep_hist_buffer_stats_init(now
);
204 rep_hist_add_buffer_stats(2.0, 2.0, 20);
205 rep_hist_reset_buffer_stats(now
);
206 s
= rep_hist_format_buffer_stats(now
+ 86400);
207 tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
208 "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
209 "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
211 "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
212 "cell-circuits-per-decile 0\n",OP_EQ
, s
);
218 /** Run unit tests the mtbf stats code. */
220 test_rephist_mtbf(void *arg
)
224 time_t now
= 1572500000; /* 2010-10-31 05:33:20 UTC */
225 time_t far_future
= MAX(now
, time(NULL
)) + 365*24*60*60;
228 /* Make a temporary datadir for these tests */
229 char *ddir_fname
= tor_strdup(get_fname_rnd("datadir_mtbf"));
230 tor_free(get_options_mutable()->DataDirectory
);
231 get_options_mutable()->DataDirectory
= tor_strdup(ddir_fname
);
232 check_private_dir(ddir_fname
, CPD_CREATE
, NULL
);
234 rep_history_clean(far_future
);
238 r
= rep_hist_load_mtbf_data(now
);
239 tt_int_op(r
, OP_EQ
, -1);
240 rep_history_clean(far_future
);
244 r
= rep_hist_record_mtbf_data(now
, 0);
245 tt_int_op(r
, OP_EQ
, 0);
246 r
= rep_hist_load_mtbf_data(now
);
247 tt_int_op(r
, OP_EQ
, 0);
248 rep_history_clean(far_future
);
250 r
= rep_hist_record_mtbf_data(now
, 1);
251 tt_int_op(r
, OP_EQ
, 0);
252 r
= rep_hist_load_mtbf_data(now
);
253 tt_int_op(r
, OP_EQ
, 0);
254 rep_history_clean(far_future
);
257 rep_history_clean(far_future
);
258 tor_free(ddir_fname
);
262 test_commit_max(void *arg
)
265 bw_array_t
*b
= bw_array_new();
266 time_t now
= b
->cur_obs_time
;
269 tt_int_op(b
->next_period
, OP_EQ
, now
+ 2*86400);
271 b
->total_in_period
= 100;
274 tor_assert(b
->total_in_period
== 0);
275 tor_assert(b
->max_total
== 0);
276 tt_int_op(b
->totals
[1], OP_EQ
, 100);
277 tt_int_op(b
->maxima
[1], OP_EQ
, 10);
278 tt_int_op(b
->next_period
, OP_EQ
, now
+ 3*86400);
281 tt_int_op(b
->next_period
, OP_EQ
, now
+ 4*86400);
284 tt_int_op(b
->next_period
, OP_EQ
, now
+ 5*86400);
286 b
->total_in_period
= 100;
289 tor_assert(!b
->next_max_idx
);
290 tt_int_op(b
->cur_obs_idx
, OP_EQ
, 0);
291 tt_int_op(b
->totals
[4], OP_EQ
, 100);
292 tt_int_op(b
->maxima
[4], OP_EQ
, 10);
293 tt_int_op(b
->next_period
, OP_EQ
, now
+ 6*86400);
298 #define test_obs(b, idx, time, tot, max) STMT_BEGIN \
299 tt_int_op(b->cur_obs_idx, OP_EQ, idx); \
300 tt_int_op(b->cur_obs_time, OP_EQ, time); \
301 tt_int_op(b->total_obs, OP_EQ, tot); \
302 tt_int_op(b->max_total, OP_EQ, max); \
306 test_advance_obs(void *arg
)
310 bw_array_t
*b
= bw_array_new();
311 time_t now
= b
->cur_obs_time
;
313 for (iter
= 0; iter
< 10; ++iter
) {
314 b
->obs
[b
->cur_obs_idx
] += 10;
318 /* The current value under cur_obs_idx was zeroed in last iterN. */
319 test_obs(b
, 0, now
+iter
+1, tot
- 10, tot
);
322 test_obs(b
, iter
+1, now
+iter
+1, tot
, tot
);
325 b
->total_in_period
= 100;
326 b
->cur_obs_time
= now
+ NUM_SECS_BW_SUM_INTERVAL
- 1;
328 test_obs(b
, 1, now
+NUM_SECS_BW_SUM_INTERVAL
, 80, 0);
329 tt_int_op(b
->maxima
[0], OP_EQ
, 100);
330 tt_int_op(b
->totals
[0], OP_EQ
, 100);
331 tt_int_op(b
->num_maxes_set
, OP_EQ
, 1);
336 #define test_add_obs_(b, now, checknow, bw, tot) STMT_BEGIN \
338 add_obs(b, now, bw); \
339 tt_int_op(b->cur_obs_time, OP_EQ, checknow); \
340 tt_int_op(b->obs[b->cur_obs_idx], OP_EQ, bw); \
341 tt_int_op(b->total_in_period, OP_EQ, tot); \
345 test_add_obs(void *arg
)
348 bw_array_t
*b
= bw_array_new();
349 time_t now
= b
->cur_obs_time
;
350 uint64_t bw
= 0, tot
= 0;
351 /* Requests for the past should not be entertained. */
352 test_add_obs_(b
, now
-1, now
, bw
, tot
);
353 /* Test the expected functionalities for random values. */
356 test_add_obs_(b
, now
, now
, bw
, tot
);
360 test_add_obs_(b
, now
, now
, bw
, tot
);
365 test_add_obs_(b
, now
, now
, bw
, tot
);
370 static or_options_t mock_options
;
372 static const or_options_t
*
373 mock_get_options(void)
375 return &mock_options
;
378 #define MAX_HIST_VALUE_LEN 21*NUM_TOTALS
380 #define set_test_case(b, max, idx, a1, a2, a3, a4, a5) STMT_BEGIN \
381 b->num_maxes_set = max; \
382 b->next_max_idx = idx; \
390 #define test_fill_bw(b, buf, rv, str, checkrv) STMT_BEGIN \
391 buf = tor_malloc_zero(MAX_HIST_VALUE_LEN); \
392 rv = bwhist_fill_bandwidth_history(buf, MAX_HIST_VALUE_LEN, b); \
393 tt_str_op(buf, OP_EQ, str); \
394 tt_int_op(rv, OP_EQ, checkrv); \
399 test_fill_bandwidth_history(void *arg
)
402 bw_array_t
*b
= bw_array_new();
405 /* Remember bandwidth is rounded down to the nearest 1K. */
407 set_test_case(b
, 0, 0, 0, 0, 0, 0, 0);
408 buf
= tor_malloc_zero(MAX_HIST_VALUE_LEN
);
409 rv
= bwhist_fill_bandwidth_history(buf
, MAX_HIST_VALUE_LEN
, b
);
410 tt_int_op(rv
, OP_EQ
, 0);
413 set_test_case(b
, 1, 1, 1000, 0, 0, 0, 0);
414 test_fill_bw(b
, buf
, rv
, "0", 1);
416 set_test_case(b
, 2, 2, 1000, 1500, 0, 0, 0);
417 test_fill_bw(b
, buf
, rv
, "0,1024", 6);
419 set_test_case(b
, 3, 3, 1000, 1500, 3500, 0, 0);
420 test_fill_bw(b
, buf
, rv
, "0,1024,3072", 11);
422 set_test_case(b
, 4, 4, 1000, 1500, 3500, 8000, 0);
423 test_fill_bw(b
, buf
, rv
, "0,1024,3072,7168", 16);
425 set_test_case(b
, 5, 0, 1000, 1500, 3500, 8000, 6000);
426 test_fill_bw(b
, buf
, rv
, "0,1024,3072,7168,5120", 21);
428 /* Remember oldest entry first. */
429 set_test_case(b
, 5, 1, 10000, 1500, 3500, 8000, 6000);
430 test_fill_bw(b
, buf
, rv
, "1024,3072,7168,5120,9216", 24);
431 /* Mocking get_options to manipulate RelayBandwidthRate. */
432 MOCK(get_options
, mock_get_options
);
433 /* Limits bandwidth to 1 KBps. */
434 /* Cutoff is set to 88473600. */
435 mock_options
.RelayBandwidthRate
= 1024;
436 set_test_case(b
, 5, 2, 88573600, 88473600, 10000, 8000, 6000);
437 test_fill_bw(b
, buf
, rv
, "9216,7168,5120,88473600,88473600", 32);
443 #define set_test_bw_lines(r, w, dr, dw, when) STMT_BEGIN \
444 bwhist_note_bytes_read(r, when, false); \
445 bwhist_note_bytes_written(w, when, false); \
446 bwhist_note_dir_bytes_read(dr, when); \
447 bwhist_note_dir_bytes_written(dw, when); \
450 #define test_get_bw_lines(str, checkstr) STMT_BEGIN \
451 str = bwhist_get_bandwidth_lines(); \
452 tt_str_op(str, OP_EQ, checkstr); \
457 test_get_bandwidth_lines(void *arg
)
460 char *str
= NULL
, *checkstr
= NULL
;
461 char t
[ISO_TIME_LEN
+1];
462 int len
= (67+MAX_HIST_VALUE_LEN
)*4;
463 checkstr
= tor_malloc_zero(len
);
464 time_t now
= time(NULL
);
469 set_test_bw_lines(5000, 5500, 3000, 3500, now
- 6*60*60);
472 set_test_bw_lines(50000, 55000, 30000, 35000, now
- 6*60*60);
475 set_test_bw_lines(25000, 27500, 15000, 17500, now
- 6*60*60);
478 set_test_bw_lines(90000, 76000, 60000, 45000, now
- 6*60*60);
481 set_test_bw_lines(500, 55000, 30000, 35000, now
- 6*60*60);
482 set_test_bw_lines(0, 0, 0, 0, now
);
483 format_iso_time(t
, now
);
484 tor_snprintf(checkstr
, len
, "write-history %s (86400 s) "
485 "5120,54272,26624,75776,54272\n"
486 "read-history %s (86400 s) "
487 "4096,49152,24576,89088,0\n"
488 "dirreq-write-history %s (86400 s) "
489 "3072,34816,17408,44032,34816\n"
490 "dirreq-read-history %s (86400 s) "
491 "2048,29696,14336,59392,29696\n",
493 test_get_bw_lines(str
, checkstr
);
502 mock_should_collect_v3_stats(void)
507 /* Test v3 metrics */
509 test_rephist_v3_onions(void *arg
)
513 char *stats_string
= NULL
;
514 char *desc1_str
= NULL
;
515 ed25519_keypair_t signing_kp1
;
516 hs_descriptor_t
*desc1
= NULL
;
518 const hs_v3_stats_t
*hs_v3_stats
= NULL
;
522 MOCK(should_collect_v3_stats
, mock_should_collect_v3_stats
);
524 get_options_mutable()->HiddenServiceStatistics
= 1;
526 /* Initialize the subsystems */
528 rep_hist_hs_stats_init(0);
530 /* Change time to 03-01-2002 23:36 UTC */
531 update_approx_time(1010101010);
533 /* HS stats should be zero here */
534 hs_v3_stats
= rep_hist_get_hs_v3_stats();
535 tt_int_op(digest256map_size(hs_v3_stats
->v3_onions_seen_this_period
),
538 /* Generate a valid descriptor */
539 ret
= ed25519_keypair_generate(&signing_kp1
, 0);
540 tt_int_op(ret
, OP_EQ
, 0);
541 desc1
= hs_helper_build_hs_desc_with_rev_counter(&signing_kp1
, 42);
543 ret
= hs_desc_encode_descriptor(desc1
, &signing_kp1
, NULL
, &desc1_str
);
544 tt_int_op(ret
, OP_EQ
, 0);
546 /* Store descriptor and check that stats got updated */
547 ret
= hs_cache_store_as_dir(desc1_str
);
548 tt_int_op(ret
, OP_EQ
, 0);
549 hs_v3_stats
= rep_hist_get_hs_v3_stats();
550 tt_int_op(digest256map_size(hs_v3_stats
->v3_onions_seen_this_period
),
554 hs_descriptor_free(desc1
);
557 /* Generate another valid descriptor */
558 ret
= ed25519_keypair_generate(&signing_kp1
, 0);
559 tt_int_op(ret
, OP_EQ
, 0);
560 desc1
= hs_helper_build_hs_desc_with_rev_counter(&signing_kp1
, 42);
562 ret
= hs_desc_encode_descriptor(desc1
, &signing_kp1
, NULL
, &desc1_str
);
563 tt_int_op(ret
, OP_EQ
, 0);
565 /* Store descriptor and check that stats are updated */
566 ret
= hs_cache_store_as_dir(desc1_str
);
567 tt_int_op(ret
, OP_EQ
, 0);
568 hs_v3_stats
= rep_hist_get_hs_v3_stats();
569 tt_int_op(digest256map_size(hs_v3_stats
->v3_onions_seen_this_period
),
572 /* Check that storing the same descriptor twice does not work */
573 ret
= hs_cache_store_as_dir(desc1_str
);
574 tt_int_op(ret
, OP_EQ
, -1);
577 hs_descriptor_free(desc1
);
580 /* Create a descriptor with the same identity key but diff rev counter and
582 desc1
= hs_helper_build_hs_desc_with_rev_counter(&signing_kp1
, 43);
584 ret
= hs_desc_encode_descriptor(desc1
, &signing_kp1
, NULL
, &desc1_str
);
585 tt_int_op(ret
, OP_EQ
, 0);
587 /* Store descriptor and check that stats are updated */
588 ret
= hs_cache_store_as_dir(desc1_str
);
589 tt_int_op(ret
, OP_EQ
, 0);
590 tt_int_op(digest256map_size(hs_v3_stats
->v3_onions_seen_this_period
),
594 hs_descriptor_free(desc1
);
597 /* Now let's skip to four days forward so that the blinded key rolls
599 update_approx_time(approx_time() + 345600);
601 /* Now create a descriptor with the same identity key but diff rev counter
602 and different blinded key */
603 desc1
= hs_helper_build_hs_desc_with_rev_counter(&signing_kp1
, 44);
605 ret
= hs_desc_encode_descriptor(desc1
, &signing_kp1
, NULL
, &desc1_str
);
606 tt_int_op(ret
, OP_EQ
, 0);
608 /* Store descriptor and check that stats are updated */
609 ret
= hs_cache_store_as_dir(desc1_str
);
610 tt_int_op(ret
, OP_EQ
, 0);
611 tt_int_op(digest256map_size(hs_v3_stats
->v3_onions_seen_this_period
),
615 hs_descriptor_free(desc1
);
618 /* Because of differential privacy we can't actually check the stat value,
619 but let's just check that it's formatted correctly. */
620 stats_string
= rep_hist_format_hs_stats(approx_time(), true);
621 tt_assert(strstr(stats_string
, "hidserv-dir-v3-onions-seen"));
624 UNMOCK(should_collect_v3_stats
);
625 tor_free(stats_string
);
629 test_load_stats_file(void *arg
)
632 char *content
= NULL
, *read_file_content
= NULL
, *fname
= NULL
;
636 /* Load conn-stats. */
637 fname
= get_datadir_fname("conn-stats");
639 read_file_content
= tor_strdup(
640 "conn-bi-direct 2020-12-13 15:48:53 (86400 s) 12,34,56,78\n"
641 "ipv6-conn-bi-direct 2020-12-14 15:48:53 (86400 s) 21,43,65,87\n");
642 write_str_to_file(fname
, read_file_content
, 0);
643 ret
= load_stats_file("conn-stats", "conn-bi-direct", 1607874000, &content
);
644 tt_int_op(ret
, OP_EQ
, 1);
645 tt_str_op(read_file_content
, OP_EQ
, content
);
647 /* Load hidserv-stats. */
649 fname
= get_datadir_fname("hidserv-stats");
651 tor_free(read_file_content
);
652 read_file_content
= tor_strdup(
653 "hidserv-stats-end 2020-12-13 15:48:53 (86400 s)\n"
654 "hidserv-rend-relayed-cells 48754891 delta_f=2048 epsilon=0.30 "
656 "hidserv-dir-onions-seen 53 delta_f=8 epsilon=0.30 bin_size=8\n");
657 write_str_to_file(fname
, read_file_content
, 0);
659 ret
= load_stats_file("hidserv-stats", "hidserv-stats-end", 1607874000,
661 tt_int_op(ret
, OP_EQ
, 1);
662 tt_str_op(read_file_content
, OP_EQ
, content
);
664 /* Load dirreq-stats. */
666 fname
= get_datadir_fname("dirreq-stats");
668 tor_free(read_file_content
);
669 read_file_content
= tor_strdup(
670 "dirreq-stats-end 2020-12-13 15:48:53 (86400 s)\n"
671 "dirreq-v3-ips ru=1728,us=1144,de=696,ir=432,gb=328,fr=304,in=296,ua=232\n"
672 "dirreq-v3-reqs ru=3616,us=3576,de=1896,fr=800,gb=632,ir=616\n"
673 "dirreq-v3-resp ok=18472,not-enough-sigs=0,unavailable=0,not-found=0,"
674 "not-modified=3136,busy=0\n"
675 "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
676 "dirreq-v3-tunneled-dl complete=18124,timeout=348,running=4,min=257,"
677 "d1=133653,d2=221050,q1=261242,d3=300622,d4=399758,md=539051,d6=721322,"
678 "d7=959866,q3=1103363,d8=1302035,d9=2046125,max=113404000\n");
679 write_str_to_file(fname
, read_file_content
, 0);
681 ret
= load_stats_file("dirreq-stats", "dirreq-stats-end", 1607874000,
683 tt_int_op(ret
, OP_EQ
, 1);
684 tt_str_op(read_file_content
, OP_EQ
, content
);
686 /* Attempt to load future-stats file not starting with timestamp tag. */
688 fname
= get_datadir_fname("future-stats");
690 tor_free(read_file_content
);
691 read_file_content
= tor_strdup(
692 "future-stuff-at-file-start\n"
693 "future-stats 2020-12-13 15:48:53 (86400 s)\n");
694 write_str_to_file(fname
, read_file_content
, 0);
696 ret
= load_stats_file("future-stats", "future-stats", 1607874000, &content
);
697 tt_int_op(ret
, OP_EQ
, 1);
698 tt_str_op(read_file_content
, OP_EQ
, content
);
702 tor_free(read_file_content
);
706 /** Test the overload stats logic. */
708 test_overload_stats(void *arg
)
710 time_t current_time
= 1010101010;
711 char *stats_str
= NULL
;
714 /* Change time to 03-01-2002 23:36 UTC */
715 /* This should make the extrainfo timestamp be "2002-01-03 23:00:00" */
716 update_approx_time(current_time
);
718 /* With an empty rephist we shouldn't get anything back */
719 stats_str
= rep_hist_get_overload_stats_lines();
720 tt_assert(!stats_str
);
722 /* Note a DNS overload */
723 rep_hist_note_overload(OVERLOAD_GENERAL
);
725 /* Move the time forward one hour */
726 current_time
+= 3600;
727 update_approx_time(current_time
);
729 /* Now check the string */
730 stats_str
= rep_hist_get_overload_stats_lines();
731 tt_str_op("overload-general 1 2002-01-03 23:00:00\n", OP_EQ
, stats_str
);
734 /* Move the time forward 72 hours: see that the line has disappeared. */
735 current_time
+= 3600*72;
736 update_approx_time(current_time
);
738 stats_str
= rep_hist_get_overload_stats_lines();
739 tt_assert(!stats_str
);
741 /* Now the time should be 2002-01-07 00:00:00 */
743 /* Note a DNS overload */
744 rep_hist_note_overload(OVERLOAD_GENERAL
);
746 stats_str
= rep_hist_get_overload_stats_lines();
747 tt_str_op("overload-general 1 2002-01-07 00:00:00\n", OP_EQ
, stats_str
);
750 /* Also note an fd exhaustion event */
751 rep_hist_note_overload(OVERLOAD_FD_EXHAUSTED
);
753 stats_str
= rep_hist_get_overload_stats_lines();
754 tt_str_op("overload-general 1 2002-01-07 00:00:00\n"
755 "overload-fd-exhausted 1 2002-01-07 00:00:00\n", OP_EQ
, stats_str
);
758 /* Move the time forward. Register DNS overload. See that the time changed */
759 current_time
+= 3600*2;
760 update_approx_time(current_time
);
762 rep_hist_note_overload(OVERLOAD_GENERAL
);
764 stats_str
= rep_hist_get_overload_stats_lines();
765 tt_str_op("overload-general 1 2002-01-07 02:00:00\n"
766 "overload-fd-exhausted 1 2002-01-07 00:00:00\n", OP_EQ
, stats_str
);
769 /* Move the time forward. Register a bandwidth ratelimit event. See that the
771 current_time
+= 3600*2;
772 update_approx_time(current_time
);
774 /* Register the rate limit event */
775 rep_hist_note_overload(OVERLOAD_READ
);
776 /* Also set some rate limiting values that should be reflected on the log */
777 get_options_mutable()->BandwidthRate
= 1000;
778 get_options_mutable()->BandwidthBurst
= 2000;
780 stats_str
= rep_hist_get_overload_stats_lines();
781 tt_str_op("overload-general 1 2002-01-07 02:00:00\n"
782 "overload-ratelimits 1 2002-01-07 04:00:00 1000 2000 1 0\n"
783 "overload-fd-exhausted 1 2002-01-07 00:00:00\n", OP_EQ
, stats_str
);
786 /* Move the time forward 24 hours: no rate limit line anymore. */
787 current_time
+= 3600*24;
788 update_approx_time(current_time
);
790 stats_str
= rep_hist_get_overload_stats_lines();
791 tt_str_op("overload-general 1 2002-01-07 02:00:00\n"
792 "overload-fd-exhausted 1 2002-01-07 00:00:00\n", OP_EQ
, stats_str
);
795 /* Move the time forward 44 hours: no fd exhausted line anymore. */
796 current_time
+= 3600*44;
797 update_approx_time(current_time
);
799 stats_str
= rep_hist_get_overload_stats_lines();
800 tt_str_op("overload-general 1 2002-01-07 02:00:00\n", OP_EQ
, stats_str
);
803 /* Move the time forward 2 hours: there is nothing left. */
804 current_time
+= 3600*2;
805 update_approx_time(current_time
);
807 stats_str
= rep_hist_get_overload_stats_lines();
808 tt_assert(!stats_str
);
810 /* Now test the rate-limit rate-limiter ;) */
811 for (int i
= 0; i
< 10; i
++) {
812 rep_hist_note_overload(OVERLOAD_READ
);
814 /* We already have an event registered from the previous tests. We just
815 * registered ten more overload events, but only one should have been counted
816 * because of the rate limiter */
817 stats_str
= rep_hist_get_overload_stats_lines();
818 tt_str_op("overload-ratelimits 1 2002-01-10 02:00:00 1000 2000 2 0\n",
822 /* Increment time by 59 secs and try again. No additional events should
825 update_approx_time(current_time
);
827 for (int i
= 0; i
< 10; i
++) {
828 rep_hist_note_overload(OVERLOAD_READ
);
830 stats_str
= rep_hist_get_overload_stats_lines();
831 tt_str_op("overload-ratelimits 1 2002-01-10 02:00:00 1000 2000 2 0\n",
835 /* Now increment time by 2 secs -- taking it after the minute rate limiting
836 and see that events will register again */
838 update_approx_time(current_time
);
840 for (int i
= 0; i
< 10; i
++) {
841 rep_hist_note_overload(OVERLOAD_READ
);
842 rep_hist_note_overload(OVERLOAD_WRITE
);
844 stats_str
= rep_hist_get_overload_stats_lines();
845 tt_str_op("overload-ratelimits 1 2002-01-10 02:00:00 1000 2000 3 1\n",
854 { #name, test_ ## name , 0, NULL, NULL }
856 { #name, test_ ## name , TT_FORK, NULL, NULL }
858 struct testcase_t stats_tests
[] = {
864 FORK(fill_bandwidth_history
),
865 FORK(get_bandwidth_lines
),
866 FORK(rephist_v3_onions
),
867 FORK(load_stats_file
),
868 FORK(overload_stats
),