1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/policy/cloud/rate_limiter.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/test/simple_test_tick_clock.h" 10 #include "base/test/test_simple_task_runner.h" 11 #include "base/time/tick_clock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace policy { 15 16 class RateLimiterTest : public testing::Test { 17 public: 18 RateLimiterTest() 19 : task_runner_(new base::TestSimpleTaskRunner()), 20 clock_(new base::SimpleTestTickClock()), 21 callbacks_(0), 22 max_requests_(5), 23 duration_(base::TimeDelta::FromHours(1)), 24 small_delta_(base::TimeDelta::FromMinutes(1)), 25 limiter_(max_requests_, 26 duration_, 27 base::Bind(&RateLimiterTest::Callback, base::Unretained(this)), 28 task_runner_, 29 scoped_ptr<base::TickClock>(clock_).Pass()) {} 30 virtual ~RateLimiterTest() {} 31 32 protected: 33 void Callback() { 34 callbacks_++; 35 } 36 37 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; 38 base::SimpleTestTickClock* clock_; 39 size_t callbacks_; 40 const size_t max_requests_; 41 const base::TimeDelta duration_; 42 const base::TimeDelta small_delta_; 43 RateLimiter limiter_; 44 }; 45 46 TEST_F(RateLimiterTest, LimitRequests) { 47 size_t count = 0; 48 for (size_t i = 0; i < max_requests_; ++i) { 49 EXPECT_EQ(count, callbacks_); 50 limiter_.PostRequest(); 51 ++count; 52 EXPECT_EQ(count, callbacks_); 53 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); 54 clock_->Advance(small_delta_); 55 } 56 57 for (size_t i = 0; i < 10; ++i) { 58 limiter_.PostRequest(); 59 EXPECT_EQ(max_requests_, callbacks_); 60 clock_->Advance(small_delta_); 61 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); 62 } 63 64 // Now advance the clock beyond the duration. The callback is invoked once. 65 callbacks_ = 0; 66 clock_->Advance(duration_); 67 task_runner_->RunPendingTasks(); 68 EXPECT_EQ(1u, callbacks_); 69 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); 70 } 71 72 TEST_F(RateLimiterTest, Steady) { 73 const base::TimeDelta delta = duration_ / 2; 74 size_t count = 0; 75 for (int i = 0; i < 100; ++i) { 76 EXPECT_EQ(count, callbacks_); 77 limiter_.PostRequest(); 78 ++count; 79 EXPECT_EQ(count, callbacks_); 80 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); 81 clock_->Advance(delta); 82 } 83 } 84 85 TEST_F(RateLimiterTest, RetryAfterDelay) { 86 size_t count = 0; 87 base::TimeDelta total_delta; 88 // Fill the queue. 89 for (size_t i = 0; i < max_requests_; ++i) { 90 EXPECT_EQ(count, callbacks_); 91 limiter_.PostRequest(); 92 ++count; 93 EXPECT_EQ(count, callbacks_); 94 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); 95 clock_->Advance(small_delta_); 96 total_delta += small_delta_; 97 } 98 99 // Now post a request that will be delayed. 100 EXPECT_EQ(max_requests_, callbacks_); 101 limiter_.PostRequest(); 102 EXPECT_EQ(max_requests_, callbacks_); 103 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); 104 105 while (total_delta < duration_) { 106 task_runner_->RunPendingTasks(); 107 // The queue is still full, so another task is immediately posted. 108 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); 109 clock_->Advance(small_delta_); 110 total_delta += small_delta_; 111 } 112 113 // Now advance time beyond the initial duration. It will immediately execute 114 // the callback. 115 EXPECT_EQ(max_requests_, callbacks_); 116 task_runner_->RunPendingTasks(); 117 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); 118 EXPECT_EQ(max_requests_ + 1, callbacks_); 119 } 120 121 } // namespace policy 122