#define TOKEN_BUCKET_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
#include "lib/evloop/token_bucket.h"
static const uint32_t START_TS = UINT32_MAX - 1000;
static const uint32_t RATE = 10;
static const uint32_t BURST = 50;
static void
test_token_bucket_ctr_init(void *arg)
{
(void) arg;
token_bucket_ctr_t tb;
token_bucket_ctr_init(&tb, RATE, BURST, START_TS);
tt_uint_op(tb.cfg.rate, OP_EQ, RATE);
tt_uint_op(tb.cfg.burst, OP_EQ, BURST);
tt_uint_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS);
tt_int_op(tb.counter.bucket, OP_EQ, BURST);
done:
;
}
static void
test_token_bucket_ctr_adjust(void *arg)
{
(void) arg;
token_bucket_ctr_t tb;
token_bucket_ctr_init(&tb, RATE, BURST, START_TS);
token_bucket_ctr_adjust(&tb, RATE, BURST * 2);
tt_uint_op(tb.cfg.rate, OP_EQ, RATE);
tt_uint_op(tb.counter.bucket, OP_EQ, BURST);
tt_uint_op(tb.cfg.burst, OP_EQ, BURST * 2);
token_bucket_ctr_adjust(&tb, RATE, BURST + 10);
tt_uint_op(tb.cfg.rate, OP_EQ, RATE);
tt_uint_op(tb.counter.bucket, OP_EQ, BURST);
tt_uint_op(tb.cfg.burst, OP_EQ, BURST + 10);
token_bucket_ctr_adjust(&tb, RATE, BURST - 1);
tt_uint_op(tb.cfg.rate, OP_EQ, RATE);
tt_uint_op(tb.counter.bucket, OP_EQ, BURST - 1);
tt_uint_op(tb.cfg.burst, OP_EQ, BURST - 1);
token_bucket_ctr_adjust(&tb, RATE * 2, BURST);
tt_uint_op(tb.cfg.rate, OP_EQ, RATE * 2);
tt_uint_op(tb.counter.bucket, OP_EQ, BURST - 1);
tt_uint_op(tb.cfg.burst, OP_EQ, BURST);
done:
;
}
static void
test_token_bucket_ctr_dec(void *arg)
{
(void) arg;
token_bucket_ctr_t tb;
token_bucket_ctr_init(&tb, RATE, BURST, START_TS);
tt_uint_op(0, OP_EQ, token_bucket_ctr_dec(&tb, 1));
tt_uint_op(tb.counter.bucket, OP_EQ, BURST - 1);
tt_uint_op(true, OP_EQ, token_bucket_ctr_dec(&tb, BURST - 1));
tt_uint_op(tb.counter.bucket, OP_EQ, 0);
token_bucket_ctr_init(&tb, RATE, BURST, START_TS);
tt_uint_op(true, OP_EQ, token_bucket_ctr_dec(&tb, BURST + 1));
tt_int_op(tb.counter.bucket, OP_EQ, -1);
tt_uint_op(false, OP_EQ, token_bucket_ctr_dec(&tb, BURST));
tt_int_op(tb.counter.bucket, OP_EQ, - (int32_t) (BURST + 1));
done:
;
}
static void
test_token_bucket_ctr_refill(void *arg)
{
(void) arg;
token_bucket_ctr_t tb;
token_bucket_ctr_init(&tb, RATE, BURST, START_TS);
token_bucket_ctr_dec(&tb, BURST / 2);
tt_int_op(tb.counter.bucket, OP_EQ, BURST / 2);
token_bucket_ctr_refill(&tb, START_TS + 1);
tt_int_op(tb.counter.bucket, OP_EQ, (BURST / 2) + RATE);
tt_int_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS + 1);
token_bucket_ctr_refill(&tb, START_TS + 1);
tt_int_op(tb.counter.bucket, OP_EQ, (BURST / 2) + RATE);
tt_int_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS + 1);
token_bucket_ctr_refill(&tb, START_TS + 99);
tt_int_op(tb.counter.bucket, OP_EQ, BURST);
tt_int_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS + 99);
token_bucket_ctr_dec(&tb, BURST);
tt_int_op(tb.counter.bucket, OP_EQ, 0);
token_bucket_ctr_refill(&tb, START_TS + 100);
tt_int_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS + 100);
tt_int_op(tb.counter.bucket, OP_EQ, RATE);
token_bucket_ctr_refill(&tb, START_TS + 101);
tt_int_op(tb.last_refilled_at_timestamp, OP_EQ, START_TS + 101);
tt_int_op(tb.counter.bucket, OP_EQ, RATE * 2);
done:
;
}
#define TOKEN_BUCKET(name) \
{ #name, test_token_bucket_ ## name , 0, NULL, NULL }
struct testcase_t token_bucket_tests[] = {
TOKEN_BUCKET(ctr_init),
TOKEN_BUCKET(ctr_adjust),
TOKEN_BUCKET(ctr_dec),
TOKEN_BUCKET(ctr_refill),
END_OF_TESTCASES
};