Chromium Code Reviews| Index: net/url_request/url_request_throttler_unittest.cc | 
| diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc | 
| index 6b4526f1da31300d8df01db92bc46c6fef314c01..0cd215d311b953b392e22c2a665b697d62ecd654 100644 | 
| --- a/net/url_request/url_request_throttler_unittest.cc | 
| +++ b/net/url_request/url_request_throttler_unittest.cc | 
| @@ -1,4 +1,4 @@ | 
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| +// Copyright (c) 2011 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. | 
| @@ -41,18 +41,20 @@ class MockBackoffEntry : public net::BackoffEntry { | 
| class MockURLRequestThrottlerEntry : public net::URLRequestThrottlerEntry { | 
| public : | 
| - MockURLRequestThrottlerEntry() : mock_backoff_entry_(&backoff_policy_) { | 
| - // Some tests become flaky if we have jitter. | 
| - backoff_policy_.jitter_factor = 0.0; | 
| + MockURLRequestThrottlerEntry(net::URLRequestThrottlerManager* manager) | 
| 
 
yzshen1
2011/03/18 22:49:51
Make it explicit, please.
 
Jói
2011/03/23 23:38:24
Done.
 
 | 
| + : net::URLRequestThrottlerEntry(manager), | 
| + mock_backoff_entry_(&backoff_policy_) { | 
| + InitPolicy(); | 
| } | 
| MockURLRequestThrottlerEntry( | 
| + net::URLRequestThrottlerManager* manager, | 
| const TimeTicks& exponential_backoff_release_time, | 
| const TimeTicks& sliding_window_release_time, | 
| const TimeTicks& fake_now) | 
| - : fake_time_now_(fake_now), | 
| + : net::URLRequestThrottlerEntry(manager), | 
| + fake_time_now_(fake_now), | 
| mock_backoff_entry_(&backoff_policy_) { | 
| - // Some tests become flaky if we have jitter. | 
| - backoff_policy_.jitter_factor = 0.0; | 
| + InitPolicy(); | 
| mock_backoff_entry_.SetFakeNow(fake_now); | 
| set_exponential_backoff_release_time(exponential_backoff_release_time); | 
| @@ -60,6 +62,15 @@ class MockURLRequestThrottlerEntry : public net::URLRequestThrottlerEntry { | 
| } | 
| virtual ~MockURLRequestThrottlerEntry() {} | 
| + void InitPolicy() { | 
| + // Some tests become flaky if we have jitter. | 
| + backoff_policy_.jitter_factor = 0.0; | 
| + | 
| + // This lets us avoid having to make multiple failures initially (this | 
| + // logic is already tested in the BackoffEntry unit tests). | 
| + backoff_policy_.num_errors_to_ignore = 0; | 
| + } | 
| + | 
| const net::BackoffEntry* GetBackoffEntry() const { | 
| return &mock_backoff_entry_; | 
| } | 
| @@ -103,27 +114,43 @@ class MockURLRequestThrottlerHeaderAdapter | 
| : public net::URLRequestThrottlerHeaderInterface { | 
| public: | 
| MockURLRequestThrottlerHeaderAdapter() | 
| - : fake_retry_value_("0.0"), | 
| + : fake_retry_value_(""), | 
| + fake_opt_out_value_(""), | 
| fake_response_code_(0) { | 
| } | 
| + explicit MockURLRequestThrottlerHeaderAdapter(int response_code) | 
| + : fake_retry_value_(""), | 
| + fake_opt_out_value_(""), | 
| + fake_response_code_(response_code) { | 
| + } | 
| + | 
| MockURLRequestThrottlerHeaderAdapter(const std::string& retry_value, | 
| + const std::string& opt_out_value, | 
| int response_code) | 
| : fake_retry_value_(retry_value), | 
| + fake_opt_out_value_(opt_out_value), | 
| fake_response_code_(response_code) { | 
| } | 
| virtual ~MockURLRequestThrottlerHeaderAdapter() {} | 
| virtual std::string GetNormalizedValue(const std::string& key) const { | 
| - if (key == MockURLRequestThrottlerEntry::kRetryHeaderName) | 
| + if (key == MockURLRequestThrottlerEntry::kRetryHeaderName && | 
| + !fake_retry_value_.empty()) { | 
| 
 
yzshen1
2011/03/18 22:49:51
[minor]
You don't need to test !fake_retry_value_.
 
Jói
2011/03/23 23:38:24
Agreed, I just preferred to be explicit rather tha
 
yzshen1
2011/03/24 20:06:37
Okay. :)
On 2011/03/23 23:38:24, Jói wrote:
 
 | 
| return fake_retry_value_; | 
| + } else if (key == | 
| + MockURLRequestThrottlerEntry::kExponentialThrottlingHeader && | 
| + !fake_opt_out_value_.empty()) { | 
| + return fake_opt_out_value_; | 
| + } | 
| return ""; | 
| } | 
| virtual int GetResponseCode() const { return fake_response_code_; } | 
| std::string fake_retry_value_; | 
| + std::string fake_opt_out_value_; | 
| int fake_response_code_; | 
| }; | 
| @@ -152,7 +179,7 @@ class MockURLRequestThrottlerManager : public net::URLRequestThrottlerManager { | 
| GURL fake_url(fake_url_string); | 
| OverrideEntryForTests( | 
| fake_url, | 
| - new MockURLRequestThrottlerEntry(time, TimeTicks::Now(), | 
| + new MockURLRequestThrottlerEntry(this, time, TimeTicks::Now(), | 
| TimeTicks::Now())); | 
| } | 
| @@ -190,12 +217,13 @@ class URLRequestThrottlerEntryTest : public testing::Test { | 
| protected: | 
| virtual void SetUp(); | 
| TimeTicks now_; | 
| + MockURLRequestThrottlerManager manager_; // Dummy object, not used. | 
| scoped_refptr<MockURLRequestThrottlerEntry> entry_; | 
| }; | 
| void URLRequestThrottlerEntryTest::SetUp() { | 
| now_ = TimeTicks::Now(); | 
| - entry_ = new MockURLRequestThrottlerEntry(); | 
| + entry_ = new MockURLRequestThrottlerEntry(&manager_); | 
| entry_->ResetToBlank(now_); | 
| } | 
| @@ -220,8 +248,8 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) { | 
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateRetryAfter) { | 
| // If the response we received has a retry-after field, | 
| // the request should be delayed. | 
| - MockURLRequestThrottlerHeaderAdapter header_w_delay_header("5.5", 200); | 
| - entry_->UpdateWithResponse(&header_w_delay_header); | 
| + MockURLRequestThrottlerHeaderAdapter header_w_delay_header("5.5", "", 200); | 
| + entry_->UpdateWithResponse("", &header_w_delay_header); | 
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 
| << "When the server put a positive value in retry-after we should " | 
| "increase release_time"; | 
| @@ -233,24 +261,24 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateRetryAfter) { | 
| } | 
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) { | 
| - MockURLRequestThrottlerHeaderAdapter failure_response("0", 505); | 
| - entry_->UpdateWithResponse(&failure_response); | 
| + MockURLRequestThrottlerHeaderAdapter failure_response(505); | 
| + entry_->UpdateWithResponse("", &failure_response); | 
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 
| << "A failure should increase the release_time"; | 
| } | 
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) { | 
| - MockURLRequestThrottlerHeaderAdapter success_response("0", 200); | 
| - entry_->UpdateWithResponse(&success_response); | 
| + MockURLRequestThrottlerHeaderAdapter success_response(200); | 
| + entry_->UpdateWithResponse("", &success_response); | 
| EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 
| << "A success should not add any delay"; | 
| } | 
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) { | 
| - MockURLRequestThrottlerHeaderAdapter failure_response("0", 500); | 
| - MockURLRequestThrottlerHeaderAdapter success_response("0", 200); | 
| - entry_->UpdateWithResponse(&success_response); | 
| - entry_->UpdateWithResponse(&failure_response); | 
| + MockURLRequestThrottlerHeaderAdapter failure_response(500); | 
| + MockURLRequestThrottlerHeaderAdapter success_response(200); | 
| + entry_->UpdateWithResponse("", &success_response); | 
| + entry_->UpdateWithResponse("", &failure_response); | 
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 
| << "This scenario should add delay"; | 
| } | 
| @@ -277,8 +305,8 @@ TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) { | 
| TEST_F(URLRequestThrottlerEntryTest, MaxAllowedBackoff) { | 
| for (int i = 0; i < 30; ++i) { | 
| - MockURLRequestThrottlerHeaderAdapter response_adapter("0.0", 505); | 
| - entry_->UpdateWithResponse(&response_adapter); | 
| + MockURLRequestThrottlerHeaderAdapter response_adapter(505); | 
| + entry_->UpdateWithResponse("", &response_adapter); | 
| } | 
| TimeDelta delay = entry_->GetExponentialBackoffReleaseTime() - now_; | 
| @@ -287,9 +315,9 @@ TEST_F(URLRequestThrottlerEntryTest, MaxAllowedBackoff) { | 
| } | 
| TEST_F(URLRequestThrottlerEntryTest, MalformedContent) { | 
| - MockURLRequestThrottlerHeaderAdapter response_adapter("0.0", 505); | 
| + MockURLRequestThrottlerHeaderAdapter response_adapter(505); | 
| for (int i = 0; i < 5; ++i) | 
| - entry_->UpdateWithResponse(&response_adapter); | 
| + entry_->UpdateWithResponse("", &response_adapter); | 
| TimeTicks release_after_failures = entry_->GetExponentialBackoffReleaseTime(); | 
| @@ -389,3 +417,62 @@ TEST(URLRequestThrottlerManager, IsHostBeingRegistered) { | 
| EXPECT_EQ(3, manager.GetNumberOfEntries()); | 
| } | 
| + | 
| +void ExpectEntryAllowsAllOnErrorIfOptedOut( | 
| + net::URLRequestThrottlerEntryInterface* entry, | 
| + bool opted_out) { | 
| + EXPECT_FALSE(entry->IsDuringExponentialBackoff()); | 
| + MockURLRequestThrottlerHeaderAdapter failure_adapter(503); | 
| + for (int i = 0; i < 10; ++i) { | 
| + // Host doesn't really matter in this scenario so we skip it. | 
| + entry->UpdateWithResponse("", &failure_adapter); | 
| + } | 
| + EXPECT_NE(opted_out, entry->IsDuringExponentialBackoff()); | 
| + | 
| + if (opted_out) { | 
| + // We're not mocking out GetTimeNow() in this scenario | 
| + // so add a 100 ms buffer to avoid flakiness (that should always | 
| + // give enough time to get from the TimeTicks::Now() call here | 
| + // to the TimeTicks::Now() call in the entry class). | 
| + EXPECT_GT(TimeTicks::Now() + TimeDelta::FromMilliseconds(100), | 
| + entry->GetExponentialBackoffReleaseTime()); | 
| + } else { | 
| + // As above, add 100 ms. | 
| + EXPECT_LT(TimeTicks::Now() + TimeDelta::FromMilliseconds(100), | 
| + entry->GetExponentialBackoffReleaseTime()); | 
| + } | 
| +} | 
| + | 
| +TEST(URLRequestThrottlerManager, OptOutHeader) { | 
| + MockURLRequestThrottlerManager manager; | 
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> entry = | 
| + manager.RegisterRequestUrl(GURL("http://www.google.com/yodude")); | 
| + | 
| + // Fake a response with the opt-out header. | 
| + MockURLRequestThrottlerHeaderAdapter response_adapter( | 
| + "", | 
| + MockURLRequestThrottlerEntry::kExponentialThrottlingDisableValue, | 
| + 200); | 
| + entry->UpdateWithResponse("www.google.com", &response_adapter); | 
| + | 
| + // Ensure that the same entry on error always allows everything. | 
| + ExpectEntryAllowsAllOnErrorIfOptedOut(entry, true); | 
| + | 
| + // Ensure that a freshly created entry (for a different URL on an | 
| + // already opted-out host) also gets "always allow" behavior. | 
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> other_entry = | 
| + manager.RegisterRequestUrl(GURL("http://www.google.com/bingobob")); | 
| + ExpectEntryAllowsAllOnErrorIfOptedOut(other_entry, true); | 
| + | 
| + // Fake a response with the opt-out header incorrectly specified. | 
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> no_opt_out_entry = | 
| + manager.RegisterRequestUrl(GURL("http://www.nike.com/justdoit")); | 
| + MockURLRequestThrottlerHeaderAdapter wrong_adapter("", "yesplease", 200); | 
| + no_opt_out_entry->UpdateWithResponse("www.nike.com", &wrong_adapter); | 
| + ExpectEntryAllowsAllOnErrorIfOptedOut(no_opt_out_entry, false); | 
| + | 
| + // A localhost entry should always be opted out. | 
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> localhost_entry = | 
| + manager.RegisterRequestUrl(GURL("http://localhost/hello")); | 
| + ExpectEntryAllowsAllOnErrorIfOptedOut(localhost_entry, true); | 
| +} |