mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Refactor the core of choosing by weights into a function
This eliminates duplicated code, and lets us test a hairy piece of functionality.
This commit is contained in:
@@ -65,6 +65,10 @@
|
||||
|
||||
#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex)
|
||||
|
||||
#define tt_double_op(a,op,b) \
|
||||
tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%f", \
|
||||
TT_EXIT_TEST_FUNCTION)
|
||||
|
||||
const char *get_fname(const char *name);
|
||||
crypto_pk_t *pk_generate(int idx);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define DIRSERV_PRIVATE
|
||||
#define DIRVOTE_PRIVATE
|
||||
#define ROUTER_PRIVATE
|
||||
#define ROUTERLIST_PRIVATE
|
||||
#define HIBERNATE_PRIVATE
|
||||
#include "or.h"
|
||||
#include "directory.h"
|
||||
@@ -1381,6 +1382,85 @@ test_dir_v3_networkstatus(void)
|
||||
ns_detached_signatures_free(dsig2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dir_random_weighted(void *testdata)
|
||||
{
|
||||
int histogram[10];
|
||||
uint64_t vals[10] = {3,1,2,4,6,0,7,5,8,9}, total=0;
|
||||
uint64_t zeros[5] = {0,0,0,0,0};
|
||||
int i, choice;
|
||||
const int n = 50000;
|
||||
double max_sq_error;
|
||||
(void) testdata;
|
||||
|
||||
/* Try a ten-element array with values from 0 through 10. The values are
|
||||
* in a scrambled order to make sure we don't depend on order. */
|
||||
memset(histogram,0,sizeof(histogram));
|
||||
for (i=0; i<10; ++i)
|
||||
total += vals[i];
|
||||
tt_int_op(total, ==, 45);
|
||||
for (i=0; i<n; ++i) {
|
||||
uint64_t t;
|
||||
choice = choose_array_element_by_weight(vals, 10, &t);
|
||||
tt_int_op(t, ==, total);
|
||||
tt_int_op(choice, >=, 0);
|
||||
tt_int_op(choice, <, 10);
|
||||
histogram[choice]++;
|
||||
}
|
||||
|
||||
/* Now see if we chose things about frequently enough. */
|
||||
max_sq_error = 0;
|
||||
for (i=0; i<10; ++i) {
|
||||
int expected = (int)(n*vals[i]/total);
|
||||
double frac_diff = 0, sq;
|
||||
TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected));
|
||||
if (expected)
|
||||
frac_diff = (histogram[i] - expected) / ((double)expected);
|
||||
else
|
||||
tt_int_op(histogram[i], ==, 0);
|
||||
|
||||
sq = frac_diff * frac_diff;
|
||||
if (sq > max_sq_error)
|
||||
max_sq_error = sq;
|
||||
}
|
||||
/* It should almost always be much much less than this. If you want to
|
||||
* figure out the odds, please feel free. */
|
||||
tt_double_op(max_sq_error, <, .05);
|
||||
|
||||
/* Now try a singleton; do we choose it? */
|
||||
for (i = 0; i < 100; ++i) {
|
||||
choice = choose_array_element_by_weight(vals, 1, NULL);
|
||||
tt_int_op(choice, ==, 0);
|
||||
}
|
||||
|
||||
/* Now try an array of zeros. We should choose randomly. */
|
||||
memset(histogram,0,sizeof(histogram));
|
||||
for (i = 0; i < n; ++i) {
|
||||
uint64_t t;
|
||||
choice = choose_array_element_by_weight(zeros, 5, &t);
|
||||
tt_int_op(t, ==, 0);
|
||||
tt_int_op(choice, >=, 0);
|
||||
tt_int_op(choice, <, 5);
|
||||
histogram[choice]++;
|
||||
}
|
||||
/* Now see if we chose things about frequently enough. */
|
||||
max_sq_error = 0;
|
||||
for (i=0; i<5; ++i) {
|
||||
int expected = n/5;
|
||||
double frac_diff = 0, sq;
|
||||
TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected));
|
||||
frac_diff = (histogram[i] - expected) / ((double)expected);
|
||||
sq = frac_diff * frac_diff;
|
||||
if (sq > max_sq_error)
|
||||
max_sq_error = sq;
|
||||
}
|
||||
/* It should almost always be much much less than this. If you want to
|
||||
* figure out the odds, please feel free. */
|
||||
tt_double_op(max_sq_error, <, .05);
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
#define DIR_LEGACY(name) \
|
||||
{ #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name }
|
||||
|
||||
@@ -1396,6 +1476,7 @@ struct testcase_t dir_tests[] = {
|
||||
DIR_LEGACY(measured_bw),
|
||||
DIR_LEGACY(param_voting),
|
||||
DIR_LEGACY(v3_networkstatus),
|
||||
DIR(random_weighted),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user