Home | History | Annotate | Download | only in cloud
      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