root/components/policy/core/common/cloud/rate_limiter_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. limiter_
  2. Callback
  3. TEST_F
  4. TEST_F
  5. TEST_F

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/policy/core/common/cloud/rate_limiter.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace policy {

class RateLimiterTest : public testing::Test {
 public:
  RateLimiterTest()
      : task_runner_(new base::TestSimpleTaskRunner()),
        clock_(new base::SimpleTestTickClock()),
        callbacks_(0),
        max_requests_(5),
        duration_(base::TimeDelta::FromHours(1)),
        small_delta_(base::TimeDelta::FromMinutes(1)),
        limiter_(max_requests_,
                 duration_,
                 base::Bind(&RateLimiterTest::Callback, base::Unretained(this)),
                 task_runner_,
                 scoped_ptr<base::TickClock>(clock_).Pass()) {}
  virtual ~RateLimiterTest() {}

 protected:
  void Callback() {
    callbacks_++;
  }

  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
  base::SimpleTestTickClock* clock_;
  size_t callbacks_;
  const size_t max_requests_;
  const base::TimeDelta duration_;
  const base::TimeDelta small_delta_;
  RateLimiter limiter_;
};

TEST_F(RateLimiterTest, LimitRequests) {
  size_t count = 0;
  for (size_t i = 0; i < max_requests_; ++i) {
    EXPECT_EQ(count, callbacks_);
    limiter_.PostRequest();
    ++count;
    EXPECT_EQ(count, callbacks_);
    EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
    clock_->Advance(small_delta_);
  }

  for (size_t i = 0; i < 10; ++i) {
    limiter_.PostRequest();
    EXPECT_EQ(max_requests_, callbacks_);
    clock_->Advance(small_delta_);
    EXPECT_FALSE(task_runner_->GetPendingTasks().empty());
  }

  // Now advance the clock beyond the duration. The callback is invoked once.
  callbacks_ = 0;
  clock_->Advance(duration_);
  task_runner_->RunPendingTasks();
  EXPECT_EQ(1u, callbacks_);
  EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
}

TEST_F(RateLimiterTest, Steady) {
  const base::TimeDelta delta = duration_ / 2;
  size_t count = 0;
  for (int i = 0; i < 100; ++i) {
    EXPECT_EQ(count, callbacks_);
    limiter_.PostRequest();
    ++count;
    EXPECT_EQ(count, callbacks_);
    EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
    clock_->Advance(delta);
  }
}

TEST_F(RateLimiterTest, RetryAfterDelay) {
  size_t count = 0;
  base::TimeDelta total_delta;
  // Fill the queue.
  for (size_t i = 0; i < max_requests_; ++i) {
    EXPECT_EQ(count, callbacks_);
    limiter_.PostRequest();
    ++count;
    EXPECT_EQ(count, callbacks_);
    EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
    clock_->Advance(small_delta_);
    total_delta += small_delta_;
  }

  // Now post a request that will be delayed.
  EXPECT_EQ(max_requests_, callbacks_);
  limiter_.PostRequest();
  EXPECT_EQ(max_requests_, callbacks_);
  EXPECT_FALSE(task_runner_->GetPendingTasks().empty());

  while (total_delta < duration_) {
    task_runner_->RunPendingTasks();
    // The queue is still full, so another task is immediately posted.
    EXPECT_FALSE(task_runner_->GetPendingTasks().empty());
    clock_->Advance(small_delta_);
    total_delta += small_delta_;
  }

  // Now advance time beyond the initial duration. It will immediately execute
  // the callback.
  EXPECT_EQ(max_requests_, callbacks_);
  task_runner_->RunPendingTasks();
  EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
  EXPECT_EQ(max_requests_ + 1, callbacks_);
}

}  // namespace policy

/* [<][>][^][v][top][bottom][index][help] */