commit 708f51637f138a14e5093e442f5ba7b5f8f2479d Author: MrSquanchee usuraj35@gmail.com Date: Sat Apr 4 17:49:50 2020 +0530
Added tests for bandwidth functions
Added tests for 1. commit_max 2. advance_obs 3. add_obs 4. rep_hist_fill_bandwidth_history 5. rep_hist_get_bandwidth_lines
Signed-off-by: Suraj Upadhyay usuraj35@gmail.com --- changes/ticket33812 | 7 ++ src/test/test_stats.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+)
diff --git a/changes/ticket33812 b/changes/ticket33812 new file mode 100644 index 0000000000..bf8dd6e442 --- /dev/null +++ b/changes/ticket33812 @@ -0,0 +1,7 @@ + o Code simplification and refactoring: + - Move the bandwidth structure and function declarations + to new file. Include this module in other files. + Remove REPHIST_PRIVATE. + o Testing: + - Add unit tests for bandwidth statistics manipulation functions. + Closes ticket 33812. Patch by MrSquanchee diff --git a/src/test/test_stats.c b/src/test/test_stats.c index f0715c2e45..01981f602b 100644 --- a/src/test/test_stats.c +++ b/src/test/test_stats.c @@ -30,6 +30,7 @@ #define CIRCUITLIST_PRIVATE #define MAINLOOP_PRIVATE #define STATEFILE_PRIVATE +#define CONFIG_PRIVATE
#include "core/or/or.h" #include "lib/err/backtrace.h" @@ -250,6 +251,244 @@ test_rephist_mtbf(void *arg) tor_free(ddir_fname); }
+static void +test_commit_max(void *arg) +{ + (void) arg; + bw_array_t *b = bw_array_new(); + time_t now = b->cur_obs_time; + + commit_max(b); + tt_int_op(b->next_period, OP_EQ, now + 2*86400); + + b->total_in_period = 100; + b->max_total = 10; + commit_max(b); + tor_assert(b->total_in_period == 0); + tor_assert(b->max_total == 0); + tt_int_op(b->totals[1], OP_EQ, 100); + tt_int_op(b->maxima[1], OP_EQ, 10); + tt_int_op(b->next_period, OP_EQ, now + 3*86400); + + commit_max(b); + tt_int_op(b->next_period, OP_EQ, now + 4*86400); + + commit_max(b); + tt_int_op(b->next_period, OP_EQ, now + 5*86400); + + b->total_in_period = 100; + b->max_total = 10; + commit_max(b); + tor_assert(!b->next_max_idx); + tt_int_op(b->cur_obs_idx, OP_EQ, 0); + tt_int_op(b->totals[4], OP_EQ, 100); + tt_int_op(b->maxima[4], OP_EQ, 10); + tt_int_op(b->next_period, OP_EQ, now + 6*86400); + done: + bw_array_free(b); +} + +#define test_obs(b, idx, time, tot, max) STMT_BEGIN \ + tt_int_op(b->cur_obs_idx, OP_EQ, idx); \ + tt_int_op(b->cur_obs_time, OP_EQ, time); \ + tt_int_op(b->total_obs, OP_EQ, tot); \ + tt_int_op(b->max_total, OP_EQ, max); \ + STMT_END; + +static void +test_advance_obs(void *arg) +{ + (void) arg; + int iter, tot = 0; + bw_array_t *b = bw_array_new(); + time_t now = b->cur_obs_time; + + for (iter = 0; iter < 10; ++iter) { + b->obs[b->cur_obs_idx] += 10; + tot += 10; + advance_obs(b); + if (iter == 9) { + /* The current value under cur_obs_idx was zeroed in last iterN. */ + test_obs(b, 0, now+iter+1, tot - 10, tot); + break; + } + test_obs(b, iter+1, now+iter+1, tot, tot); + } + + b->total_in_period = 100; + b->cur_obs_time = now + NUM_SECS_BW_SUM_INTERVAL - 1; + advance_obs(b); + test_obs(b, 1, now+NUM_SECS_BW_SUM_INTERVAL, 80, 0); + tt_int_op(b->maxima[0], OP_EQ, 100); + tt_int_op(b->totals[0], OP_EQ, 100); + tt_int_op(b->num_maxes_set, OP_EQ, 1); + done: + bw_array_free(b); +} + +#define test_add_obs_(b, now, checknow, bw, tot) STMT_BEGIN \ + tot += bw; \ + add_obs(b, now, bw); \ + tt_int_op(b->cur_obs_time, OP_EQ, checknow); \ + tt_int_op(b->obs[b->cur_obs_idx], OP_EQ, bw); \ + tt_int_op(b->total_in_period, OP_EQ, tot); \ + STMT_END; + +static void +test_add_obs(void *arg) +{ + (void) arg; + bw_array_t *b = bw_array_new(); + time_t now = b->cur_obs_time; + uint64_t bw = 0, tot = 0; + /* Requests for the past should not be entertained. */ + test_add_obs_(b, now-1, now, bw, tot); + /* Test the expected functionalities for random values. */ + now += 53; + bw = 97; + test_add_obs_(b, now, now, bw, tot); + + now += 60*60; + bw = 90; + test_add_obs_(b, now, now, bw, tot); + + now += 24*60*60; + bw = 100; + tot = 0; + test_add_obs_(b, now, now, bw, tot); + done: + bw_array_free(b); +} + +static or_options_t mock_options; + +static const or_options_t * +mock_get_options(void) +{ + return &mock_options; +} + +#define MAX_HIST_VALUE_LEN 21*NUM_TOTALS + +#define set_test_case(b, max, idx, a1, a2, a3, a4, a5) STMT_BEGIN \ + b->num_maxes_set = max; \ + b->next_max_idx = idx; \ + b->totals[0] = a1; \ + b->totals[1] = a2; \ + b->totals[2] = a3; \ + b->totals[3] = a4; \ + b->totals[4] = a5; \ + STMT_END; + +#define test_fill_bw(b, buf, rv, str, checkrv) STMT_BEGIN \ + buf = tor_malloc_zero(MAX_HIST_VALUE_LEN); \ + rv = rep_hist_fill_bandwidth_history(buf, MAX_HIST_VALUE_LEN, b); \ + tt_str_op(buf, OP_EQ, str); \ + tt_int_op(rv, OP_EQ, checkrv); \ + tor_free(buf); \ + STMT_END; + +static void +test_fill_bandwidth_history(void *arg) +{ + (void) arg; + bw_array_t *b = bw_array_new(); + char *buf; + size_t rv; + /* Remember bandwidth is rounded down to the nearest 1K. */ + /* Day 1. */ + set_test_case(b, 0, 0, 0, 0, 0, 0, 0); + buf = tor_malloc_zero(MAX_HIST_VALUE_LEN); + rv = rep_hist_fill_bandwidth_history(buf, MAX_HIST_VALUE_LEN, b); + tt_int_op(rv, OP_EQ, 0); + tor_free(buf); + /* Day 2. */ + set_test_case(b, 1, 1, 1000, 0, 0, 0, 0); + test_fill_bw(b, buf, rv, "0", 1); + /* Day 3. */ + set_test_case(b, 2, 2, 1000, 1500, 0, 0, 0); + test_fill_bw(b, buf, rv, "0,1024", 6); + /* Day 4. */ + set_test_case(b, 3, 3, 1000, 1500, 3500, 0, 0); + test_fill_bw(b, buf, rv, "0,1024,3072", 11); + /* Day 5. */ + set_test_case(b, 4, 4, 1000, 1500, 3500, 8000, 0); + test_fill_bw(b, buf, rv, "0,1024,3072,7168", 16); + /* Day 6. */ + set_test_case(b, 5, 0, 1000, 1500, 3500, 8000, 6000); + test_fill_bw(b, buf, rv, "0,1024,3072,7168,5120", 21); + /* Day 7. */ + /* Remember oldest entry first. */ + set_test_case(b, 5, 1, 10000, 1500, 3500, 8000, 6000); + test_fill_bw(b, buf, rv, "1024,3072,7168,5120,9216", 24); + /* Mocking get_options to manipulate RelayBandwidthRate. */ + MOCK(get_options, mock_get_options); + /* Limits bandwidth to 1 KBps. */ + /* Cutoff is set to 88473600. */ + mock_options.RelayBandwidthRate = 1024; + set_test_case(b, 5, 2, 88573600, 88473600, 10000, 8000, 6000); + test_fill_bw(b, buf, rv, "9216,7168,5120,88473600,88473600", 32); + done: + UNMOCK(get_options); + bw_array_free(b); +} + +#define set_test_bw_lines(r, w, dr, dw, when) STMT_BEGIN \ + rep_hist_note_bytes_read(r, when); \ + rep_hist_note_bytes_written(w, when); \ + rep_hist_note_dir_bytes_read(dr, when); \ + rep_hist_note_dir_bytes_written(dw, when); \ + STMT_END; + +#define test_get_bw_lines(str, checkstr) STMT_BEGIN \ + str = rep_hist_get_bandwidth_lines(); \ + tt_str_op(str, OP_EQ, checkstr); \ + tor_free(str); \ + STMT_END; + +static void +test_get_bandwidth_lines(void *arg) +{ + (void) arg; + char *str, *checkstr; + char t[ISO_TIME_LEN+1]; + int len = (67+MAX_HIST_VALUE_LEN)*4; + checkstr = tor_malloc_zero(len); + time_t now = time(NULL); + bw_arrays_init(); + + /* Day 1. */ + now += 86400; + set_test_bw_lines(5000, 5500, 3000, 3500, now - 6*60*60); + /* Day 2. */ + now += 86400; + set_test_bw_lines(50000, 55000, 30000, 35000, now - 6*60*60); + /* Day 3. */ + now += 86400; + set_test_bw_lines(25000, 27500, 15000, 17500, now - 6*60*60); + /* Day 4. */ + now += 86400; + set_test_bw_lines(90000, 76000, 60000, 45000, now - 6*60*60); + /* Day 5. */ + now += 86400; + set_test_bw_lines(500, 55000, 30000, 35000, now - 6*60*60); + set_test_bw_lines(0, 0, 0, 0, now); + format_iso_time(t, now); + tor_snprintf(checkstr, len, "write-history %s (86400 s) " + "5120,54272,26624,75776,54272\n" + "read-history %s (86400 s) " + "4096,49152,24576,89088,0\n" + "dirreq-write-history %s (86400 s) " + "3072,34816,17408,44032,34816\n" + "dirreq-read-history %s (86400 s) " + "2048,29696,14336,59392,29696\n", + t, t, t, t); + test_get_bw_lines(str, checkstr); + done: + tor_free(checkstr); + bw_arrays_free_all(); +} + #define ENT(name) \ { #name, test_ ## name , 0, NULL, NULL } #define FORK(name) \ @@ -258,6 +497,11 @@ test_rephist_mtbf(void *arg) struct testcase_t stats_tests[] = { FORK(stats), ENT(rephist_mtbf), + FORK(commit_max), + FORK(advance_obs), + FORK(add_obs), + FORK(fill_bandwidth_history), + FORK(get_bandwidth_lines),
END_OF_TESTCASES };