dirvote: Handling adding vote and signature if module is disabled
[tor.git] / src / test / test_bwmgt.c
blob268917005e6f96df0f644d9691183413670c6264
1 /* Copyright (c) 2018, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file test_bwmgt.c
6 * \brief tests for bandwidth management / token bucket functions
7 */
9 #define TOKEN_BUCKET_PRIVATE
11 #include "or.h"
12 #include "test.h"
14 #include "token_bucket.h"
16 // an imaginary time, in timestamp units. Chosen so it will roll over.
17 static const uint32_t START_TS = UINT32_MAX-10;
18 static const int32_t KB = 1024;
19 static const uint32_t GB = (U64_LITERAL(1) << 30);
21 static void
22 test_bwmgt_token_buf_init(void *arg)
24 (void)arg;
25 token_bucket_rw_t b;
27 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
28 // Burst is correct
29 tt_uint_op(b.cfg.burst, OP_EQ, 64*KB);
30 // Rate is correct, within 1 percent.
32 uint32_t ticks_per_sec =
33 (uint32_t) monotime_msec_to_approx_coarse_stamp_units(1000);
34 uint32_t rate_per_sec = (b.cfg.rate * ticks_per_sec / TICKS_PER_STEP);
36 tt_uint_op(rate_per_sec, OP_GT, 16*KB-160);
37 tt_uint_op(rate_per_sec, OP_LT, 16*KB+160);
39 // Bucket starts out full:
40 tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS);
41 tt_int_op(b.read_bucket.bucket, OP_EQ, 64*KB);
43 done:
47 static void
48 test_bwmgt_token_buf_adjust(void *arg)
50 (void)arg;
51 token_bucket_rw_t b;
53 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
55 uint32_t rate_orig = b.cfg.rate;
56 // Increasing burst
57 token_bucket_rw_adjust(&b, 16*KB, 128*KB);
58 tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
59 tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB);
60 tt_uint_op(b.cfg.burst, OP_EQ, 128*KB);
62 // Decreasing burst but staying above bucket
63 token_bucket_rw_adjust(&b, 16*KB, 96*KB);
64 tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
65 tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB);
66 tt_uint_op(b.cfg.burst, OP_EQ, 96*KB);
68 // Decreasing burst below bucket,
69 token_bucket_rw_adjust(&b, 16*KB, 48*KB);
70 tt_uint_op(b.cfg.rate, OP_EQ, rate_orig);
71 tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB);
72 tt_uint_op(b.cfg.burst, OP_EQ, 48*KB);
74 // Changing rate.
75 token_bucket_rw_adjust(&b, 32*KB, 48*KB);
76 tt_uint_op(b.cfg.rate, OP_GE, rate_orig*2 - 10);
77 tt_uint_op(b.cfg.rate, OP_LE, rate_orig*2 + 10);
78 tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB);
79 tt_uint_op(b.cfg.burst, OP_EQ, 48*KB);
81 done:
85 static void
86 test_bwmgt_token_buf_dec(void *arg)
88 (void)arg;
89 token_bucket_rw_t b;
90 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
92 // full-to-not-full.
93 tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, KB));
94 tt_int_op(b.read_bucket.bucket, OP_EQ, 63*KB);
96 // Full to almost-not-full
97 tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 63*KB - 1));
98 tt_int_op(b.read_bucket.bucket, OP_EQ, 1);
100 // almost-not-full to empty.
101 tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 1));
102 tt_int_op(b.read_bucket.bucket, OP_EQ, 0);
104 // reset bucket, try full-to-empty
105 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
106 tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB));
107 tt_int_op(b.read_bucket.bucket, OP_EQ, 0);
109 // reset bucket, try underflow.
110 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
111 tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB + 1));
112 tt_int_op(b.read_bucket.bucket, OP_EQ, -1);
114 // A second underflow does not make the bucket empty.
115 tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 1000));
116 tt_int_op(b.read_bucket.bucket, OP_EQ, -1001);
118 done:
122 static void
123 test_bwmgt_token_buf_refill(void *arg)
125 (void)arg;
126 token_bucket_rw_t b;
127 const uint32_t SEC =
128 (uint32_t)monotime_msec_to_approx_coarse_stamp_units(1000);
129 token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS);
131 /* Make the buffer much emptier, then let one second elapse. */
132 token_bucket_rw_dec_read(&b, 48*KB);
133 tt_int_op(b.read_bucket.bucket, OP_EQ, 16*KB);
134 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC));
135 tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB - 300);
136 tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB + 300);
138 /* Another half second. */
139 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2));
140 tt_int_op(b.read_bucket.bucket, OP_GT, 40*KB - 400);
141 tt_int_op(b.read_bucket.bucket, OP_LT, 40*KB + 400);
142 tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS + SEC*3/2);
144 /* No time: nothing happens. */
146 const uint32_t bucket_orig = b.read_bucket.bucket;
147 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2));
148 tt_int_op(b.read_bucket.bucket, OP_EQ, bucket_orig);
151 /* Another 30 seconds: fill the bucket. */
152 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2 + SEC*30));
153 tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
154 tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS + SEC*3/2 + SEC*30);
156 /* Another 30 seconds: nothing happens. */
157 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2 + SEC*60));
158 tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
159 tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS + SEC*3/2 + SEC*60);
161 /* Empty the bucket, let two seconds pass, and make sure that a refill is
162 * noticed. */
163 tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, b.cfg.burst));
164 tt_int_op(0, OP_EQ, b.read_bucket.bucket);
165 tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2 + SEC*61));
166 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*3/2 + SEC*62));
167 tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB-400);
168 tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB+400);
170 /* Underflow the bucket, make sure we detect when it has tokens again. */
171 tt_int_op(1, OP_EQ,
172 token_bucket_rw_dec_read(&b, b.read_bucket.bucket+16*KB));
173 tt_int_op(-16*KB, OP_EQ, b.read_bucket.bucket);
174 // half a second passes...
175 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*64));
176 tt_int_op(b.read_bucket.bucket, OP_GT, -8*KB-300);
177 tt_int_op(b.read_bucket.bucket, OP_LT, -8*KB+300);
178 // a second passes
179 tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*65));
180 tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400);
181 tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400);
183 // We step a second backwards, and nothing happens.
184 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + SEC*64));
185 tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400);
186 tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400);
188 // A ridiculous amount of time passes.
189 tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, INT32_MAX));
190 tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst);
192 done:
196 /* Test some helper functions we use within the token bucket interface. */
197 static void
198 test_bwmgt_token_buf_helpers(void *arg)
200 uint32_t ret;
202 (void) arg;
204 /* The returned value will be OS specific but in any case, it should be
205 * greater than 1 since we are passing 1GB/sec rate. */
206 ret = rate_per_sec_to_rate_per_step(1 * GB);
207 tt_u64_op(ret, OP_GT, 1);
209 /* We default to 1 in case rate is 0. */
210 ret = rate_per_sec_to_rate_per_step(0);
211 tt_u64_op(ret, OP_EQ, 1);
213 done:
217 #define BWMGT(name) \
218 { #name, test_bwmgt_ ## name , 0, NULL, NULL }
220 struct testcase_t bwmgt_tests[] = {
221 BWMGT(token_buf_init),
222 BWMGT(token_buf_adjust),
223 BWMGT(token_buf_dec),
224 BWMGT(token_buf_refill),
225 BWMGT(token_buf_helpers),
226 END_OF_TESTCASES