summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/include.am1
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test.h1
-rw-r--r--src/test/test_bwmgt.c205
-rw-r--r--src/test/test_controller_events.c75
-rw-r--r--src/test/test_options.c10
-rw-r--r--src/test/test_util.c7
7 files changed, 215 insertions, 85 deletions
diff --git a/src/test/include.am b/src/test/include.am
index a663fa5524..474da3f880 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -90,6 +90,7 @@ src_test_test_SOURCES = \
src/test/test_address_set.c \
src/test/test_bridges.c \
src/test/test_buffers.c \
+ src/test/test_bwmgt.c \
src/test/test_cell_formats.c \
src/test/test_cell_queue.c \
src/test/test_channel.c \
diff --git a/src/test/test.c b/src/test/test.c
index f90669b5dd..422e181b94 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -813,6 +813,7 @@ struct testgroup_t testgroups[] = {
{ "address_set/", address_set_tests },
{ "bridges/", bridges_tests },
{ "buffer/", buffer_tests },
+ { "bwmgt/", bwmgt_tests },
{ "cellfmt/", cell_format_tests },
{ "cellqueue/", cell_queue_tests },
{ "channel/", channel_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 34c6e46427..1728831ed0 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -187,6 +187,7 @@ extern struct testcase_t addr_tests[];
extern struct testcase_t address_tests[];
extern struct testcase_t address_set_tests[];
extern struct testcase_t bridges_tests[];
+extern struct testcase_t bwmgt_tests[];
extern struct testcase_t buffer_tests[];
extern struct testcase_t cell_format_tests[];
extern struct testcase_t cell_queue_tests[];
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
new file mode 100644
index 0000000000..1a54f44fc4
--- /dev/null
+++ b/src/test/test_bwmgt.c
@@ -0,0 +1,205 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_bwmgt.c
+ * \brief tests for bandwidth management / token bucket functions
+ */
+
+#define TOKEN_BUCKET_PRIVATE
+
+#include "or.h"
+#include "test.h"
+
+#include "token_bucket.h"
+
+// an imaginary time, in timestamp units. Chosen so it will roll over.
+static const uint32_t START_TS = UINT32_MAX-10;
+static const int32_t KB = 1024;
+
+static void
+test_bwmgt_token_buf_init(void *arg)
+{
+ (void)arg;
+ token_bucket_t b;
+
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+ // Burst is correct
+ tt_uint_op(b.burst, OP_EQ, 64*KB);
+ // Rate is correct, within 1 percent.
+ {
+ uint32_t ticks_per_sec =
+ (uint32_t) monotime_msec_to_approx_coarse_stamp_units(1000);
+ uint32_t rate_per_sec = (b.rate * ticks_per_sec / TICKS_PER_STEP);
+
+ tt_uint_op(rate_per_sec, OP_GT, 16*KB-160);
+ tt_uint_op(rate_per_sec, OP_LT, 16*KB+160);
+ }
+ // Bucket starts out full:
+ tt_uint_op(b.last_refilled_at_ts, OP_EQ, START_TS);
+ tt_int_op(b.read_bucket, OP_EQ, 64*KB);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_adjust(void *arg)
+{
+ (void)arg;
+ token_bucket_t b;
+
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+
+ uint32_t rate_orig = b.rate;
+ // Increasing burst
+ token_bucket_adjust(&b, 16*KB, 128*KB);
+ tt_uint_op(b.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket, OP_EQ, 64*KB);
+ tt_uint_op(b.burst, OP_EQ, 128*KB);
+
+ // Decreasing burst but staying above bucket
+ token_bucket_adjust(&b, 16*KB, 96*KB);
+ tt_uint_op(b.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket, OP_EQ, 64*KB);
+ tt_uint_op(b.burst, OP_EQ, 96*KB);
+
+ // Decreasing burst below bucket,
+ token_bucket_adjust(&b, 16*KB, 48*KB);
+ tt_uint_op(b.rate, OP_EQ, rate_orig);
+ tt_uint_op(b.read_bucket, OP_EQ, 48*KB);
+ tt_uint_op(b.burst, OP_EQ, 48*KB);
+
+ // Changing rate.
+ token_bucket_adjust(&b, 32*KB, 48*KB);
+ tt_uint_op(b.rate, OP_GE, rate_orig*2 - 10);
+ tt_uint_op(b.rate, OP_LE, rate_orig*2 + 10);
+ tt_uint_op(b.read_bucket, OP_EQ, 48*KB);
+ tt_uint_op(b.burst, OP_EQ, 48*KB);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_dec(void *arg)
+{
+ (void)arg;
+ token_bucket_t b;
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+
+ // full-to-not-full.
+ tt_int_op(0, OP_EQ, token_bucket_dec_read(&b, KB));
+ tt_int_op(b.read_bucket, OP_EQ, 63*KB);
+
+ // Full to almost-not-full
+ tt_int_op(0, OP_EQ, token_bucket_dec_read(&b, 63*KB - 1));
+ tt_int_op(b.read_bucket, OP_EQ, 1);
+
+ // almost-not-full to empty.
+ tt_int_op(1, OP_EQ, token_bucket_dec_read(&b, 1));
+ tt_int_op(b.read_bucket, OP_EQ, 0);
+
+ // reset bucket, try full-to-empty
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+ tt_int_op(1, OP_EQ, token_bucket_dec_read(&b, 64*KB));
+ tt_int_op(b.read_bucket, OP_EQ, 0);
+
+ // reset bucket, try underflow.
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+ tt_int_op(1, OP_EQ, token_bucket_dec_read(&b, 64*KB + 1));
+ tt_int_op(b.read_bucket, OP_EQ, -1);
+
+ // A second underflow does not make the bucket empty.
+ tt_int_op(0, OP_EQ, token_bucket_dec_read(&b, 1000));
+ tt_int_op(b.read_bucket, OP_EQ, -1001);
+
+ done:
+ ;
+}
+
+static void
+test_bwmgt_token_buf_refill(void *arg)
+{
+ (void)arg;
+ token_bucket_t b;
+ const uint32_t SEC =
+ (uint32_t)monotime_msec_to_approx_coarse_stamp_units(1000);
+ printf("%d\n", (int)SEC);
+ token_bucket_init(&b, 16*KB, 64*KB, START_TS);
+
+ /* Make the buffer much emptier, then let one second elapse. */
+ token_bucket_dec_read(&b, 48*KB);
+ tt_int_op(b.read_bucket, OP_EQ, 16*KB);
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC));
+ tt_int_op(b.read_bucket, OP_GT, 32*KB - 300);
+ tt_int_op(b.read_bucket, OP_LT, 32*KB + 300);
+
+ /* Another half second. */
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2));
+ tt_int_op(b.read_bucket, OP_GT, 40*KB - 400);
+ tt_int_op(b.read_bucket, OP_LT, 40*KB + 400);
+ tt_uint_op(b.last_refilled_at_ts, OP_EQ, START_TS + SEC*3/2);
+
+ /* No time: nothing happens. */
+ {
+ const uint32_t bucket_orig = b.read_bucket;
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2));
+ tt_int_op(b.read_bucket, OP_EQ, bucket_orig);
+ }
+
+ /* Another 30 seconds: fill the bucket. */
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2 + SEC*30));
+ tt_int_op(b.read_bucket, OP_EQ, b.burst);
+ tt_uint_op(b.last_refilled_at_ts, OP_EQ, START_TS + SEC*3/2 + SEC*30);
+
+ /* Another 30 seconds: nothing happens. */
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2 + SEC*60));
+ tt_int_op(b.read_bucket, OP_EQ, b.burst);
+ tt_uint_op(b.last_refilled_at_ts, OP_EQ, START_TS + SEC*3/2 + SEC*60);
+
+ /* Empty the bucket, let two seconds pass, and make sure that a refill is
+ * noticed. */
+ tt_int_op(1, OP_EQ, token_bucket_dec_read(&b, b.burst));
+ tt_int_op(0, OP_EQ, b.read_bucket);
+ tt_int_op(1, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2 + SEC*61));
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*3/2 + SEC*62));
+ tt_int_op(b.read_bucket, OP_GT, 32*KB-400);
+ tt_int_op(b.read_bucket, OP_LT, 32*KB+400);
+
+ /* Underflow the bucket, make sure we detect when it has tokens again. */
+ tt_int_op(1, OP_EQ, token_bucket_dec_read(&b, b.read_bucket+16*KB));
+ tt_int_op(-16*KB, OP_EQ, b.read_bucket);
+ // half a second passes...
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*64));
+ tt_int_op(b.read_bucket, OP_GT, -8*KB-300);
+ tt_int_op(b.read_bucket, OP_LT, -8*KB+300);
+ // a second passes
+ tt_int_op(1, OP_EQ, token_bucket_refill(&b, START_TS + SEC*65));
+ tt_int_op(b.read_bucket, OP_GT, 8*KB-400);
+ tt_int_op(b.read_bucket, OP_LT, 8*KB+400);
+
+ // We step a second backwards, and nothing happens.
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, START_TS + SEC*64));
+ tt_int_op(b.read_bucket, OP_GT, 8*KB-400);
+ tt_int_op(b.read_bucket, OP_LT, 8*KB+400);
+
+ // A ridiculous amount of time passes.
+ tt_int_op(0, OP_EQ, token_bucket_refill(&b, INT32_MAX));
+ tt_int_op(b.read_bucket, OP_EQ, b.burst);
+
+ done:
+ ;
+}
+
+#define BWMGT(name) \
+ { #name, test_bwmgt_ ## name , 0, NULL, NULL }
+
+struct testcase_t bwmgt_tests[] = {
+ BWMGT(token_buf_init),
+ BWMGT(token_buf_adjust),
+ BWMGT(token_buf_dec),
+ BWMGT(token_buf_refill),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 901ad7ab3d..e81aea8d66 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -12,79 +12,6 @@
#include "test.h"
static void
-help_test_bucket_note_empty(uint32_t expected_msec_since_midnight,
- int tokens_before, size_t tokens_removed,
- uint32_t msec_since_epoch)
-{
- uint32_t timestamp_var = 0;
- struct timeval tvnow;
- tvnow.tv_sec = msec_since_epoch / 1000;
- tvnow.tv_usec = (msec_since_epoch % 1000) * 1000;
- connection_buckets_note_empty_ts(&timestamp_var, tokens_before,
- tokens_removed, &tvnow);
- tt_int_op(expected_msec_since_midnight, OP_EQ, timestamp_var);
-
- done:
- ;
-}
-
-static void
-test_cntev_bucket_note_empty(void *arg)
-{
- (void)arg;
-
- /* Two cases with nothing to note, because bucket was empty before;
- * 86442200 == 1970-01-02 00:00:42.200000 */
- help_test_bucket_note_empty(0, 0, 0, 86442200);
- help_test_bucket_note_empty(0, -100, 100, 86442200);
-
- /* Nothing to note, because bucket has not been emptied. */
- help_test_bucket_note_empty(0, 101, 100, 86442200);
-
- /* Bucket was emptied, note 42200 msec since midnight. */
- help_test_bucket_note_empty(42200, 101, 101, 86442200);
- help_test_bucket_note_empty(42200, 101, 102, 86442200);
-}
-
-static void
-test_cntev_bucket_millis_empty(void *arg)
-{
- struct timeval tvnow;
- (void)arg;
-
- /* 1970-01-02 00:00:42.200000 */
- tvnow.tv_sec = 86400 + 42;
- tvnow.tv_usec = 200000;
-
- /* Bucket has not been refilled. */
- tt_int_op(0, OP_EQ, bucket_millis_empty(0, 42120, 0, 100, &tvnow));
- tt_int_op(0, OP_EQ, bucket_millis_empty(-10, 42120, -10, 100, &tvnow));
-
- /* Bucket was not empty. */
- tt_int_op(0, OP_EQ, bucket_millis_empty(10, 42120, 20, 100, &tvnow));
-
- /* Bucket has been emptied 80 msec ago and has just been refilled. */
- tt_int_op(80, OP_EQ, bucket_millis_empty(-20, 42120, -10, 100, &tvnow));
- tt_int_op(80, OP_EQ, bucket_millis_empty(-10, 42120, 0, 100, &tvnow));
- tt_int_op(80, OP_EQ, bucket_millis_empty(0, 42120, 10, 100, &tvnow));
-
- /* Bucket has been emptied 180 msec ago, last refill was 100 msec ago
- * which was insufficient to make it positive, so cap msec at 100. */
- tt_int_op(100, OP_EQ, bucket_millis_empty(0, 42020, 1, 100, &tvnow));
-
- /* 1970-01-02 00:00:00:050000 */
- tvnow.tv_sec = 86400;
- tvnow.tv_usec = 50000;
-
- /* Last emptied 30 msec before midnight, tvnow is 50 msec after
- * midnight, that's 80 msec in total. */
- tt_int_op(80, OP_EQ, bucket_millis_empty(0, 86400000 - 30, 1, 100, &tvnow));
-
- done:
- ;
-}
-
-static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
unsigned int waiting_time,
unsigned int removed, unsigned int exitward)
@@ -395,8 +322,6 @@ test_cntev_event_mask(void *arg)
{ #name, test_cntev_ ## name, flags, 0, NULL }
struct testcase_t controller_event_tests[] = {
- TEST(bucket_note_empty, TT_FORK),
- TEST(bucket_millis_empty, TT_FORK),
TEST(sum_up_cell_stats, TT_FORK),
TEST(append_cell_stats, TT_FORK),
TEST(format_cell_stats, TT_FORK),
diff --git a/src/test/test_options.c b/src/test/test_options.c
index af349ed015..9974ed2575 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -4104,16 +4104,6 @@ test_options_validate__testing_options(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
"TestingEnableTbEmptyEvent 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "TestingEnableTbEmptyEvent may only be changed "
- "in testing Tor networks!");
- tor_free(msg);
-
- free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
diff --git a/src/test/test_util.c b/src/test/test_util.c
index ce8567d9af..3dd2b51a3a 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -5907,6 +5907,13 @@ test_util_monotonic_time(void *arg)
tt_u64_op(coarse_stamp_diff, OP_GE, 120);
tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
+ {
+ uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
+ uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
+ tt_int_op(ms, OP_GE, 4950);
+ tt_int_op(ms, OP_LT, 5050);
+ }
+
done:
;
}