1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* Original author: bcampen@mozilla.com */
8 
9 #include "simpletokenbucket.h"
10 
11 #define GTEST_HAS_RTTI 0
12 #include "gtest/gtest.h"
13 #include "gtest_utils.h"
14 
15 using mozilla::SimpleTokenBucket;
16 
17 class TestSimpleTokenBucket : public SimpleTokenBucket {
18  public:
TestSimpleTokenBucket(size_t bucketSize,size_t tokensPerSecond)19   TestSimpleTokenBucket(size_t bucketSize, size_t tokensPerSecond)
20       : SimpleTokenBucket(bucketSize, tokensPerSecond) {}
21 
fastForward(int32_t timeMilliSeconds)22   void fastForward(int32_t timeMilliSeconds) {
23     if (timeMilliSeconds >= 0) {
24       last_time_tokens_added_ -= PR_MillisecondsToInterval(timeMilliSeconds);
25     } else {
26       last_time_tokens_added_ += PR_MillisecondsToInterval(-timeMilliSeconds);
27     }
28   }
29 };
30 
TEST(SimpleTokenBucketTest,TestConstruct)31 TEST(SimpleTokenBucketTest, TestConstruct)
32 { TestSimpleTokenBucket b(10, 1); }
33 
TEST(SimpleTokenBucketTest,TestGet)34 TEST(SimpleTokenBucketTest, TestGet)
35 {
36   TestSimpleTokenBucket b(10, 1);
37   ASSERT_EQ(5U, b.getTokens(5));
38 }
39 
TEST(SimpleTokenBucketTest,TestGetAll)40 TEST(SimpleTokenBucketTest, TestGetAll)
41 {
42   TestSimpleTokenBucket b(10, 1);
43   ASSERT_EQ(10U, b.getTokens(10));
44 }
45 
TEST(SimpleTokenBucketTest,TestGetInsufficient)46 TEST(SimpleTokenBucketTest, TestGetInsufficient)
47 {
48   TestSimpleTokenBucket b(10, 1);
49   ASSERT_EQ(5U, b.getTokens(5));
50   ASSERT_EQ(5U, b.getTokens(6));
51 }
52 
TEST(SimpleTokenBucketTest,TestGetBucketCount)53 TEST(SimpleTokenBucketTest, TestGetBucketCount)
54 {
55   TestSimpleTokenBucket b(10, 1);
56   ASSERT_EQ(10U, b.getTokens(UINT32_MAX));
57   ASSERT_EQ(5U, b.getTokens(5));
58   ASSERT_EQ(5U, b.getTokens(UINT32_MAX));
59 }
60 
TEST(SimpleTokenBucketTest,TestTokenRefill)61 TEST(SimpleTokenBucketTest, TestTokenRefill)
62 {
63   TestSimpleTokenBucket b(10, 1);
64   ASSERT_EQ(5U, b.getTokens(5));
65   b.fastForward(1000);
66   ASSERT_EQ(6U, b.getTokens(6));
67 }
68 
TEST(SimpleTokenBucketTest,TestNoTimeWasted)69 TEST(SimpleTokenBucketTest, TestNoTimeWasted)
70 {
71   // Makes sure that when the time elapsed is insufficient to add any
72   // tokens to the bucket, the internal timestamp that is used in this
73   // calculation is not updated (ie; two subsequent 0.5 second elapsed times
74   // counts as a full second)
75   TestSimpleTokenBucket b(10, 1);
76   ASSERT_EQ(5U, b.getTokens(5));
77   b.fastForward(500);
78   ASSERT_EQ(5U, b.getTokens(6));
79   b.fastForward(500);
80   ASSERT_EQ(6U, b.getTokens(6));
81 }
82 
TEST(SimpleTokenBucketTest,TestNegativeTime)83 TEST(SimpleTokenBucketTest, TestNegativeTime)
84 {
85   TestSimpleTokenBucket b(10, 1);
86   b.fastForward(-1000);
87   // Make sure we don't end up with an invalid number of tokens, but otherwise
88   // permit anything.
89   ASSERT_GT(11U, b.getTokens(100));
90 }
91 
TEST(SimpleTokenBucketTest,TestEmptyBucket)92 TEST(SimpleTokenBucketTest, TestEmptyBucket)
93 {
94   TestSimpleTokenBucket b(10, 1);
95   ASSERT_EQ(10U, b.getTokens(10));
96   ASSERT_EQ(0U, b.getTokens(10));
97 }
98 
TEST(SimpleTokenBucketTest,TestEmptyThenFillBucket)99 TEST(SimpleTokenBucketTest, TestEmptyThenFillBucket)
100 {
101   TestSimpleTokenBucket b(10, 1);
102   ASSERT_EQ(10U, b.getTokens(10));
103   ASSERT_EQ(0U, b.getTokens(1));
104   b.fastForward(50000);
105   ASSERT_EQ(10U, b.getTokens(10));
106 }
107 
TEST(SimpleTokenBucketTest,TestNoOverflow)108 TEST(SimpleTokenBucketTest, TestNoOverflow)
109 {
110   TestSimpleTokenBucket b(10, 1);
111   ASSERT_EQ(10U, b.getTokens(10));
112   ASSERT_EQ(0U, b.getTokens(1));
113   b.fastForward(50000);
114   ASSERT_EQ(10U, b.getTokens(11));
115 }
116