aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2019-05-23 09:50:28 -0400
committerDavid Goulet <dgoulet@torproject.org>2019-05-23 09:50:28 -0400
commit29955f13e5bc8e61724759ec7245aae602672111 (patch)
tree5e432fe63b8b94593ac0114b0b389cc439809e27
parente13e2012b9d1bbde73bea22d9fd13fb0b88c04de (diff)
parent9e5c27bd2c278238d003b2fc1891d5de48b766d7 (diff)
downloadtor-29955f13e5bc8e61724759ec7245aae602672111.tar.gz
tor-29955f13e5bc8e61724759ec7245aae602672111.zip
Merge branch 'tor-github/pr/1022'
-rw-r--r--.travis.yml2
-rw-r--r--changes/ticket2887811
-rw-r--r--src/ext/tinytest.c6
-rw-r--r--src/ext/tinytest.h3
-rw-r--r--src/test/rng_test_helpers.c36
-rw-r--r--src/test/rng_test_helpers.h3
-rw-r--r--src/test/test_circuitpadding.c29
-rw-r--r--src/test/test_prob_distr.c29
8 files changed, 93 insertions, 26 deletions
diff --git a/.travis.yml b/.travis.yml
index f78333611f..330388aa47 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,7 +42,7 @@ matrix:
## include creates builds with gcc, linux
include:
## We include a single coverage build with the best options for coverage
- - env: COVERAGE_OPTIONS="--enable-coverage" HARDENING_OPTIONS=""
+ - env: COVERAGE_OPTIONS="--enable-coverage" HARDENING_OPTIONS="" TOR_TEST_RNG_SEED="636f766572616765"
## We only want to check these build option combinations once
## (they shouldn't vary by compiler or OS)
## We run rust and coverage with hardening off, which seems like enough
diff --git a/changes/ticket28878 b/changes/ticket28878
new file mode 100644
index 0000000000..73ca47c72f
--- /dev/null
+++ b/changes/ticket28878
@@ -0,0 +1,11 @@
+ o Minor features (testing):
+ - The circuitpadding tests now use a reproducible RNG implementation,
+ so that if a test fails, we can learn why. Part of ticket 28878.
+ - Tor's tests now support an environment variable, TOR_TEST_RNG_SEED,
+ to set the RNG seed for tests that use a reproducible RNG.
+ Part of ticket 28878.
+
+ o Minor features (continuous integration):
+ - When running coverage builds on Travis, we now set TOR_TEST_RNG_SEED,
+ to avoid RNG-based coverage differences.
+ Part of ticket 28878.
diff --git a/src/ext/tinytest.c b/src/ext/tinytest.c
index 16f11e4639..239fdd0a38 100644
--- a/src/ext/tinytest.c
+++ b/src/ext/tinytest.c
@@ -492,6 +492,12 @@ tinytest_set_test_skipped_(void)
cur_test_outcome = SKIP;
}
+int
+tinytest_cur_test_has_failed(void)
+{
+ return (cur_test_outcome == FAIL);
+}
+
char *
tinytest_format_hex_(const void *val_, unsigned long len)
{
diff --git a/src/ext/tinytest.h b/src/ext/tinytest.h
index ed07b26bc0..05c2fda052 100644
--- a/src/ext/tinytest.h
+++ b/src/ext/tinytest.h
@@ -72,6 +72,9 @@ struct testlist_alias_t {
};
#define END_OF_ALIASES { NULL, NULL }
+/** Return true iff the current test has failed. */
+int tinytest_cur_test_has_failed(void);
+
/** Implementation: called from a test to indicate failure, before logging. */
void tinytest_set_test_failed_(void);
/** Implementation: called from a test to indicate that we're skipping. */
diff --git a/src/test/rng_test_helpers.c b/src/test/rng_test_helpers.c
index d268cb64b7..f4e8df7e7b 100644
--- a/src/test/rng_test_helpers.c
+++ b/src/test/rng_test_helpers.c
@@ -17,6 +17,7 @@
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
+#include "ext/tinytest.h"
#include "test/rng_test_helpers.h"
@@ -54,7 +55,8 @@ static uint8_t rng_seed[16];
static crypto_xof_t *rng_xof = NULL;
/**
- * Print the seed for our PRNG to stdout. We use this when we're
+ * Print the seed for our PRNG to stdout. We use this when we're failed
+ * test that had a reproducible RNG set.
**/
void
testing_dump_reproducible_rng_seed(void)
@@ -122,9 +124,22 @@ enable_deterministic_rng_impl(const uint8_t *seed, size_t seed_len)
void
testing_enable_reproducible_rng(void)
{
- uint8_t seed[16];
- crypto_rand((char*)seed, sizeof(seed));
- enable_deterministic_rng_impl(seed, sizeof(seed));
+ const char *provided_seed = getenv("TOR_TEST_RNG_SEED");
+ if (provided_seed) {
+ size_t hexlen = strlen(provided_seed);
+ size_t seedlen = hexlen / 2;
+ uint8_t *seed = tor_malloc(hexlen / 2);
+ if (base16_decode((char*)seed, seedlen, provided_seed, hexlen) < 0) {
+ puts("Cannot decode value in TOR_TEST_RNG_SEED");
+ exit(1);
+ }
+ enable_deterministic_rng_impl(seed, seedlen);
+ tor_free(seed);
+ } else {
+ uint8_t seed[16];
+ crypto_rand((char*)seed, sizeof(seed));
+ enable_deterministic_rng_impl(seed, sizeof(seed));
+ }
}
/**
@@ -228,3 +243,16 @@ testing_disable_rng_override(void)
rng_is_replaced = false;
}
+
+/**
+ * As testing_disable_rng_override(), but dump the seed if the current
+ * test has failed.
+ */
+void
+testing_disable_reproducible_rng(void)
+{
+ if (tinytest_cur_test_has_failed()) {
+ testing_dump_reproducible_rng_seed();
+ }
+ testing_disable_rng_override();
+}
diff --git a/src/test/rng_test_helpers.h b/src/test/rng_test_helpers.h
index 907099450d..d7925148ae 100644
--- a/src/test/rng_test_helpers.h
+++ b/src/test/rng_test_helpers.h
@@ -14,8 +14,7 @@ void testing_prefilled_rng_reset(void);
void testing_disable_rng_override(void);
-#define testing_disable_reproducible_rng() \
- testing_disable_rng_override()
+void testing_disable_reproducible_rng(void);
#define testing_disable_deterministic_rng() \
testing_disable_rng_override()
#define testing_disable_prefilled_rng() \
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index 1ac2bd676e..a2d192203e 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -36,6 +36,8 @@
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
+#include "test/rng_test_helpers.h"
+
/* Start our monotime mocking at 1 second past whatever monotime_init()
* thought the actual wall clock time was, for platforms with bad resolution
* and weird timevalues during monotime_init() before mocking. */
@@ -313,6 +315,7 @@ test_circuitpadding_rtt(void *arg)
MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock);
+ testing_enable_reproducible_rng();
dummy_channel.cmux = circuitmux_alloc();
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
@@ -416,6 +419,7 @@ test_circuitpadding_rtt(void *arg)
UNMOCK(circuit_package_relay_cell);
UNMOCK(circuitmux_attach_circuit);
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
return;
}
@@ -540,6 +544,7 @@ test_circuitpadding_token_removal_higher(void *arg)
/* Mock it up */
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Setup test environment (time etc.) */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -633,6 +638,7 @@ test_circuitpadding_token_removal_higher(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
/** Test lower token removal strategy by bin */
@@ -645,6 +651,7 @@ test_circuitpadding_token_removal_lower(void *arg)
/* Mock it up */
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Setup test environment (time etc.) */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -731,6 +738,7 @@ test_circuitpadding_token_removal_lower(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
/** Test closest token removal strategy by bin */
@@ -743,6 +751,7 @@ test_circuitpadding_closest_token_removal(void *arg)
/* Mock it up */
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Setup test environment (time etc.) */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -837,6 +846,7 @@ test_circuitpadding_closest_token_removal(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
/** Test closest token removal strategy with usec */
@@ -849,6 +859,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg)
/* Mock it up */
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Setup test environment (time etc.) */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -948,6 +959,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
/** Test closest token removal strategy with usec */
@@ -960,6 +972,7 @@ test_circuitpadding_token_removal_exact(void *arg)
/* Mock it up */
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Setup test environment (time etc.) */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -1007,6 +1020,7 @@ test_circuitpadding_token_removal_exact(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
#undef BIG_HISTOGRAM_LEN
@@ -1019,6 +1033,8 @@ test_circuitpadding_tokens(void *arg)
int64_t actual_mocked_monotime_start;
(void)arg;
+ testing_enable_reproducible_rng();
+
/** Test plan:
*
* 1. Test symmetry between bin_to_usec and usec_to_bin
@@ -1272,6 +1288,7 @@ test_circuitpadding_tokens(void *arg)
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
monotime_disable_test_mocking();
tor_free(circ_client_machine.states);
+ testing_disable_reproducible_rng();
}
void
@@ -1299,6 +1316,7 @@ test_circuitpadding_wronghop(void *arg)
/* Mock this function so that our cell counting tests don't get confused by
* padding that gets sent by scheduled timers. */
MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
client_side = TO_CIRCUIT(origin_circuit_new());
dummy_channel.cmux = circuitmux_alloc();
@@ -1472,6 +1490,7 @@ test_circuitpadding_wronghop(void *arg)
UNMOCK(circuit_package_relay_cell);
UNMOCK(circuitmux_attach_circuit);
nodes_free();
+ testing_disable_reproducible_rng();
}
void
@@ -1952,6 +1971,7 @@ test_circuitpadding_conditions(void *arg)
int64_t actual_mocked_monotime_start;
(void)arg;
MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
+ testing_enable_reproducible_rng();
nodes_init();
dummy_channel.cmux = circuitmux_alloc();
@@ -2056,6 +2076,7 @@ test_circuitpadding_conditions(void *arg)
done:
/* XXX: Free everything */
+ testing_disable_reproducible_rng();
return;
}
@@ -2385,6 +2406,7 @@ test_circuitpadding_sample_distribution(void *arg)
/* mock this function so that we dont actually schedule any padding */
MOCK(circpad_machine_schedule_padding,
circpad_machine_schedule_padding_mock);
+ testing_enable_reproducible_rng();
/* Initialize a machine with multiple probability distributions */
circpad_machines_init();
@@ -2417,6 +2439,7 @@ test_circuitpadding_sample_distribution(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
UNMOCK(circpad_machine_schedule_padding);
+ testing_disable_reproducible_rng();
}
static circpad_decision_t
@@ -2442,6 +2465,7 @@ test_circuitpadding_machine_rate_limiting(void *arg)
* really care about padding counts */
MOCK(circpad_machine_spec_transition, circpad_machine_spec_transition_mock);
MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock);
+ testing_enable_reproducible_rng();
/* Setup machine and circuits */
client_side = TO_CIRCUIT(origin_circuit_new());
@@ -2495,6 +2519,7 @@ test_circuitpadding_machine_rate_limiting(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
+ testing_disable_reproducible_rng();
}
/* Test global padding rate limits */
@@ -2514,6 +2539,7 @@ test_circuitpadding_global_rate_limiting(void *arg)
MOCK(circuit_package_relay_cell,
circuit_package_relay_cell_mock);
MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
+ testing_enable_reproducible_rng();
monotime_init();
monotime_enable_test_mocking();
@@ -2593,6 +2619,7 @@ test_circuitpadding_global_rate_limiting(void *arg)
circuitmux_free(dummy_channel.cmux);
SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
smartlist_free(vote1.net_params);
+ testing_disable_reproducible_rng();
}
/* Test reduced and disabled padding */
@@ -2603,6 +2630,7 @@ test_circuitpadding_reduce_disable(void *arg)
int64_t actual_mocked_monotime_start;
MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
+ testing_enable_reproducible_rng();
nodes_init();
dummy_channel.cmux = circuitmux_alloc();
@@ -2742,6 +2770,7 @@ test_circuitpadding_reduce_disable(void *arg)
free_fake_orcirc(relay_side);
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
+ testing_disable_reproducible_rng();
}
/** Just a basic machine whose whole purpose is to reach the END state */
diff --git a/src/test/test_prob_distr.c b/src/test/test_prob_distr.c
index 747c3d98e6..0ecbf65f41 100644
--- a/src/test/test_prob_distr.c
+++ b/src/test/test_prob_distr.c
@@ -1119,13 +1119,14 @@ test_psi_dist_sample(const struct dist *dist)
}
static void
-dump_seed(void)
+write_stochastic_warning(void)
{
- printf("\n"
+ if (tinytest_cur_test_has_failed()) {
+ printf("\n"
"NOTE: This is a stochastic test, and we expect it to fail from\n"
"time to time, with some low probability. If you see it fail more\n"
"than one trial in 100, though, please tell us.\n\n");
- testing_dump_reproducible_rng_seed();
+ }
}
static void
@@ -1180,7 +1181,7 @@ test_stochastic_uniform(void *arg)
done:
if (tests_failed) {
- dump_seed();
+ write_stochastic_warning();
}
testing_disable_reproducible_rng();
}
@@ -1273,7 +1274,7 @@ test_stochastic_genpareto(void *arg)
done:
if (tests_failed) {
- dump_seed();
+ write_stochastic_warning();
}
testing_disable_reproducible_rng();
}
@@ -1301,7 +1302,7 @@ test_stochastic_geometric(void *arg)
done:
if (tests_failed) {
- dump_seed();
+ write_stochastic_warning();
}
testing_disable_reproducible_rng();
}
@@ -1328,7 +1329,7 @@ test_stochastic_logistic(void *arg)
done:
if (tests_failed) {
- dump_seed();
+ write_stochastic_warning();
}
testing_disable_reproducible_rng();
}
@@ -1337,7 +1338,6 @@ static void
test_stochastic_log_logistic(void *arg)
{
bool ok = 0;
- bool tests_failed = true;
(void) arg;
testing_enable_reproducible_rng();
@@ -1351,12 +1351,8 @@ test_stochastic_log_logistic(void *arg)
ok = test_stochastic_log_logistic_impl(exp(-10), 1e-2);
tt_assert(ok);
- tests_failed = false;
-
done:
- if (tests_failed) {
- dump_seed();
- }
+ write_stochastic_warning();
testing_disable_reproducible_rng();
}
@@ -1364,7 +1360,6 @@ static void
test_stochastic_weibull(void *arg)
{
bool ok = 0;
- bool tests_failed = true;
(void) arg;
testing_enable_reproducible_rng();
@@ -1380,12 +1375,8 @@ test_stochastic_weibull(void *arg)
ok = test_stochastic_weibull_impl(10, 1);
tt_assert(ok);
- tests_failed = false;
-
done:
- if (tests_failed) {
- dump_seed();
- }
+ write_stochastic_warning();
testing_disable_reproducible_rng();
UNMOCK(crypto_rand);
}