aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-08-09 13:47:42 -0400
committerNick Mathewson <nickm@torproject.org>2012-08-09 14:15:58 -0400
commit07df4dd52d3ab2eea2e8a8fc3222a5d297d077de (patch)
treeb11ca0fc673180ab78d37d699f6e1e3790735d7d /src/test
parent9bfb274abb9f9e5d445a75f0b67b433be823a730 (diff)
downloadtor-07df4dd52d3ab2eea2e8a8fc3222a5d297d077de.tar.gz
tor-07df4dd52d3ab2eea2e8a8fc3222a5d297d077de.zip
Refactor the core of choosing by weights into a function
This eliminates duplicated code, and lets us test a hairy piece of functionality.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/test.h4
-rw-r--r--src/test/test_dir.c81
2 files changed, 85 insertions, 0 deletions
diff --git a/src/test/test.h b/src/test/test.h
index 0b6e6c60cb..6dcb9490bd 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -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);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 83c612045b..ed0c5a1afb 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -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
};