Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Unified Diff: net/request_throttler/request_throttler_unittest.cc

Issue 2487001: Request Throttler : Exponential back-off (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Corrected a flaky test due to having 2 implementation of request throttling Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/request_throttler/request_throttler_manager.cc ('k') | net/url_request/url_request_http_job.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/request_throttler/request_throttler_unittest.cc
===================================================================
--- net/request_throttler/request_throttler_unittest.cc (revision 0)
+++ net/request_throttler/request_throttler_unittest.cc (revision 0)
@@ -0,0 +1,301 @@
+// Copyright (c) 2010 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 "base/pickle.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "net/base/test_completion_callback.h"
+#include "net/request_throttler/request_throttler_manager.h"
+#include "net/request_throttler/request_throttler_header_interface.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace {
+class MockRequestThrottlerManager;
+
+class MockRequestThrottlerEntry : public RequestThrottlerEntry {
+ public :
+ MockRequestThrottlerEntry() {}
+ MockRequestThrottlerEntry(TimeTicks release_time, TimeTicks fake_now)
+ : fake_time_now_(fake_now) {
+ release_time_ = release_time;
+ }
+ virtual ~MockRequestThrottlerEntry() {}
+
+ void ResetToBlank(TimeTicks time_now) {
+ fake_time_now_ = time_now;
+ release_time_ = time_now;
+ num_times_delayed_ = 0;
+ }
+
+ // Overloaded for test
+ virtual TimeTicks GetTimeNow() const { return fake_time_now_; }
+
+ TimeTicks release_time() const { return release_time_; }
+ void set_release_time(TimeTicks time) { release_time_ = time; }
+
+ TimeTicks fake_time_now_;
+};
+
+class MockRequestThrottlerHeaderAdapter
+ : public RequestThrottlerHeaderInterface {
+ public:
+ MockRequestThrottlerHeaderAdapter()
+ : fake_retry_value_("0.0"),
+ fake_response_code_(0) {
+ }
+
+ MockRequestThrottlerHeaderAdapter(const std::string& retry_value,
+ const int response_code)
+ : fake_retry_value_(retry_value),
+ fake_response_code_(response_code) {
+ }
+
+ ~MockRequestThrottlerHeaderAdapter() {}
+
+ virtual std::string GetNormalizedValue(const std::string& key) const {
+ if (key == MockRequestThrottlerEntry::kRetryHeaderName)
+ return fake_retry_value_;
+ return "";
+ }
+
+ virtual int GetResponseCode() const { return fake_response_code_; }
+
+ std::string fake_retry_value_;
+ int fake_response_code_;
+};
+
+class MockRequestThrottlerManager : public RequestThrottlerManager {
+ public:
+ MockRequestThrottlerManager() {}
+ virtual ~MockRequestThrottlerManager() {}
+
+ // Method to process the url using RequestThrottlerManager protected method.
+ std::string DoGetUrlIdFromUrl(const GURL& url) { return GetIdFromUrl(url); }
+
+ // Method to use the garbage collecting method of RequestThrottlerManager.
+ void DoGarbageCollectEntries() { GarbageCollectEntries(); }
+
+ // Returns the number of entries in the host map.
+ int GetNumberOfEntries() { return url_entries_.size(); }
+
+ void CreateEntry(const bool is_outdated);
+
+ static int create_entry_index;
+};
+
+/*------------------ Mock request throttler manager --------------------------*/
+int MockRequestThrottlerManager::create_entry_index = 0;
+
+void MockRequestThrottlerManager::CreateEntry(const bool is_outdated) {
+ TimeTicks time = TimeTicks::Now();
+ if (is_outdated) {
+ time -= TimeDelta::FromSeconds(
+ MockRequestThrottlerEntry::kEntryLifetimeSec);
+ time -= TimeDelta::FromSeconds(1);
+ }
+ std::string index = IntToString(create_entry_index++);
+ url_entries_[index] = new MockRequestThrottlerEntry(time, TimeTicks::Now());
+}
+
+/* ---------------- Request throttler entry test -----------------------------*/
+struct TimeAndBool {
+ TimeAndBool(TimeTicks time_value, bool expected, int line_num) {
+ time = time_value;
+ result = expected;
+ line = line_num;
+ }
+ TimeTicks time;
+ bool result;
+ int line;
+};
+
+struct GurlAndString {
+ GurlAndString(GURL url_value, const std::string& expected, int line_num) {
+ url = url_value;
+ result = expected;
+ line = line_num;
+ }
+ GURL url;
+ std::string result;
+ int line;
+};
+
+} // namespace
+
+class RequestThrottlerEntryTest : public ::testing::Test {
+ protected:
+ virtual void SetUp();
+ TimeTicks now_;
+ TimeDelta delay_;
+ scoped_refptr<MockRequestThrottlerEntry> entry_;
+};
+
+void RequestThrottlerEntryTest::SetUp() {
+ now_ = TimeTicks::Now();
+ entry_ = new MockRequestThrottlerEntry();
+ entry_->ResetToBlank(now_);
+}
+
+std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) {
+ return out << time.ToInternalValue();
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceRequestNotAllowed) {
+ entry_->set_release_time(entry_->fake_time_now_ +
+ TimeDelta::FromMilliseconds(1));
+ EXPECT_FALSE(entry_->IsRequestAllowed());
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceRequestAllowed) {
+ entry_->set_release_time(entry_->fake_time_now_);
+ EXPECT_TRUE(entry_->IsRequestAllowed());
+ entry_->set_release_time(entry_->fake_time_now_ -
+ TimeDelta::FromMilliseconds(1));
+ EXPECT_TRUE(entry_->IsRequestAllowed());
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceUpdateRetryAfter) {
+ // If the response we received as a retry-after field,
+ // the request should be delayed.
+ MockRequestThrottlerHeaderAdapter header_w_delay_header("5.5", 200);
+ entry_->UpdateWithResponse(&header_w_delay_header);
+ EXPECT_GT(entry_->release_time(), entry_->fake_time_now_) <<
+ "When the server put a positive value in retry-after we should "
+ "increase release_time";
+
+ entry_->ResetToBlank(now_);
+ header_w_delay_header.fake_retry_value_ = "-5.5";
+ EXPECT_EQ(entry_->release_time(), entry_->fake_time_now_) <<
+ "When given a negative value, it should not change the release_time";
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceUpdateFailure) {
+ MockRequestThrottlerHeaderAdapter failure_response("0", 505);
+ entry_->UpdateWithResponse(&failure_response);
+ EXPECT_GT(entry_->release_time(), entry_->fake_time_now_) <<
+ "A failure should increase the release_time";
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceUpdateSuccess) {
+ MockRequestThrottlerHeaderAdapter success_response("0", 200);
+ entry_->UpdateWithResponse(&success_response);
+ EXPECT_EQ(entry_->release_time(), entry_->fake_time_now_) <<
+ "A success should not add any delay";
+}
+
+TEST_F(RequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) {
+ MockRequestThrottlerHeaderAdapter failure_response("0", 500),
+ success_response("0", 200);
+ entry_->UpdateWithResponse(&success_response);
+ entry_->UpdateWithResponse(&failure_response);
+ EXPECT_GT(entry_->release_time(), entry_->fake_time_now_) <<
+ "This scenario should add delay";
+}
+
+TEST_F(RequestThrottlerEntryTest, IsEntryReallyOutdated) {
+ TimeDelta lifetime = TimeDelta::FromSeconds(
+ MockRequestThrottlerEntry::kEntryLifetimeSec);
+ const TimeDelta kFiveMs = TimeDelta::FromMilliseconds(5);
+
+ TimeAndBool test_values[] = {
+ TimeAndBool(now_, false, __LINE__),
+ TimeAndBool(now_ - kFiveMs, false, __LINE__),
+ TimeAndBool(now_ + kFiveMs, false, __LINE__),
+ TimeAndBool(now_ - lifetime, false, __LINE__),
+ TimeAndBool(now_ - (lifetime + kFiveMs), true, __LINE__)};
+
+ for (unsigned int i = 0; i < arraysize(test_values); ++i) {
+ entry_->set_release_time(test_values[i].time);
+ EXPECT_EQ(entry_->IsEntryOutdated(), test_values[i].result) <<
+ "Test case #" << i << " line " << test_values[i].line << " failed";
+ }
+}
+
+TEST_F(RequestThrottlerEntryTest, MaxAllowedBackoff) {
+ for (int i = 0; i < 30; ++i) {
+ MockRequestThrottlerHeaderAdapter response_adapter("0.0", 505);
+ entry_->UpdateWithResponse(&response_adapter);
+ }
+
+ delay_ = entry_->release_time() - now_;
+ EXPECT_EQ(delay_.InMilliseconds(),
+ MockRequestThrottlerEntry::kMaximumBackoffMs);
+}
+
+TEST_F(RequestThrottlerEntryTest, MalformedContent) {
+ for (int i = 0; i < 5; ++i) {
+ MockRequestThrottlerHeaderAdapter response_adapter("0.0", 505);
+ entry_->UpdateWithResponse(&response_adapter);
+ }
+ TimeTicks release_after_failures = entry_->release_time();
+
+ // Send a success code to reset backoff.
+ MockRequestThrottlerHeaderAdapter response_adapter("0.0", 200);
+ entry_->UpdateWithResponse(&response_adapter);
+ EXPECT_EQ(entry_->release_time(), release_after_failures);
+
+ // Then inform the entry that previous package was malformed
+ // it is suppose to regenerate previous state.
+ entry_->ReceivedContentWasMalformed();
+ EXPECT_GT(entry_->release_time(), release_after_failures);
+}
+
+TEST(RequestThrottlerManager, IsUrlStandardised) {
+ MockRequestThrottlerManager manager;
+ GurlAndString test_values[] = {
+ GurlAndString(GURL("http://www.example.com"),
+ std::string("http://www.example.com/"), __LINE__),
+ GurlAndString(GURL("http://www.Example.com"),
+ std::string("http://www.example.com/"), __LINE__),
+ GurlAndString(GURL("http://www.ex4mple.com/Pr4c71c41"),
+ std::string("http://www.ex4mple.com/pr4c71c41"), __LINE__),
+ GurlAndString(GURL("http://www.example.com/0/token/false"),
+ std::string("http://www.example.com/0/token/false"),
+ __LINE__),
+ GurlAndString(GURL("http://www.example.com/index.php?code=javascript"),
+ std::string("http://www.example.com/index.php"), __LINE__),
+ GurlAndString(GURL("http://www.example.com/index.php?code=1#superEntry"),
+ std::string("http://www.example.com/index.php"),
+ __LINE__)};
+
+ for (unsigned int i = 0; i < arraysize(test_values); ++i) {
+ std::string temp = manager.DoGetUrlIdFromUrl(test_values[i].url);
+ EXPECT_EQ(temp, test_values[i].result) <<
+ "Test case #" << i << " line " << test_values[i].line << " failed";
+ }
+}
+
+TEST(RequestThrottlerManager, AreEntriesBeingCollected ) {
+ MockRequestThrottlerManager manager;
+
+ manager.CreateEntry(true); // true = Entry is outdated.
+ manager.CreateEntry(true);
+ manager.CreateEntry(true);
+ manager.DoGarbageCollectEntries();
+ EXPECT_EQ(0, manager.GetNumberOfEntries());
+
+ manager.CreateEntry(false);
+ manager.CreateEntry(false);
+ manager.CreateEntry(false);
+ manager.CreateEntry(true);
+ manager.DoGarbageCollectEntries();
+ EXPECT_EQ(3, manager.GetNumberOfEntries());
+}
+
+TEST(RequestThrottlerManager, IsHostBeingRegistered) {
+ MockRequestThrottlerManager manager;
+
+ manager.RegisterRequestUrl(GURL("http://www.example.com/"));
+ manager.RegisterRequestUrl(GURL("http://www.google.com/"));
+ manager.RegisterRequestUrl(GURL("http://www.google.com/index/0"));
+ manager.RegisterRequestUrl(GURL("http://www.google.com/index/0?code=1"));
+ manager.RegisterRequestUrl(GURL("http://www.google.com/index/0#lolsaure"));
+
+ EXPECT_EQ(3, manager.GetNumberOfEntries());
+}
« no previous file with comments | « net/request_throttler/request_throttler_manager.cc ('k') | net/url_request/url_request_http_job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698