| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/url_request/url_request_throttler_manager.h" | 5 #include "net/url_request/url_request_throttler_manager.h" |
| 6 | 6 |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/metrics/histogram_samples.h" | 8 #include "base/metrics/histogram_samples.h" |
| 9 #include "base/pickle.h" | 9 #include "base/pickle.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 const char kRequestThrottledHistogramName[] = "Throttling.RequestThrottled"; | 32 const char kRequestThrottledHistogramName[] = "Throttling.RequestThrottled"; |
| 33 | 33 |
| 34 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { | 34 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { |
| 35 public: | 35 public: |
| 36 explicit MockURLRequestThrottlerEntry( | 36 explicit MockURLRequestThrottlerEntry( |
| 37 URLRequestThrottlerManager* manager) | 37 URLRequestThrottlerManager* manager) |
| 38 : URLRequestThrottlerEntry(manager, std::string()), | 38 : URLRequestThrottlerEntry(manager, std::string()), |
| 39 mock_backoff_entry_(&backoff_policy_) { | 39 backoff_entry_(&backoff_policy_, &fake_clock_) { |
| 40 InitPolicy(); | 40 InitPolicy(); |
| 41 } | 41 } |
| 42 MockURLRequestThrottlerEntry( | 42 MockURLRequestThrottlerEntry( |
| 43 URLRequestThrottlerManager* manager, | 43 URLRequestThrottlerManager* manager, |
| 44 const TimeTicks& exponential_backoff_release_time, | 44 const TimeTicks& exponential_backoff_release_time, |
| 45 const TimeTicks& sliding_window_release_time, | 45 const TimeTicks& sliding_window_release_time, |
| 46 const TimeTicks& fake_now) | 46 const TimeTicks& fake_now) |
| 47 : URLRequestThrottlerEntry(manager, std::string()), | 47 : URLRequestThrottlerEntry(manager, std::string()), |
| 48 fake_time_now_(fake_now), | 48 fake_clock_(fake_now), |
| 49 mock_backoff_entry_(&backoff_policy_) { | 49 backoff_entry_(&backoff_policy_, &fake_clock_) { |
| 50 InitPolicy(); | 50 InitPolicy(); |
| 51 | 51 |
| 52 mock_backoff_entry_.set_fake_now(fake_now); | |
| 53 set_exponential_backoff_release_time(exponential_backoff_release_time); | 52 set_exponential_backoff_release_time(exponential_backoff_release_time); |
| 54 set_sliding_window_release_time(sliding_window_release_time); | 53 set_sliding_window_release_time(sliding_window_release_time); |
| 55 } | 54 } |
| 56 | 55 |
| 57 void InitPolicy() { | 56 void InitPolicy() { |
| 58 // Some tests become flaky if we have jitter. | 57 // Some tests become flaky if we have jitter. |
| 59 backoff_policy_.jitter_factor = 0.0; | 58 backoff_policy_.jitter_factor = 0.0; |
| 60 | 59 |
| 61 // This lets us avoid having to make multiple failures initially (this | 60 // This lets us avoid having to make multiple failures initially (this |
| 62 // logic is already tested in the BackoffEntry unit tests). | 61 // logic is already tested in the BackoffEntry unit tests). |
| 63 backoff_policy_.num_errors_to_ignore = 0; | 62 backoff_policy_.num_errors_to_ignore = 0; |
| 64 } | 63 } |
| 65 | 64 |
| 66 const BackoffEntry* GetBackoffEntry() const override { | 65 const BackoffEntry* GetBackoffEntry() const override { |
| 67 return &mock_backoff_entry_; | 66 return &backoff_entry_; |
| 68 } | 67 } |
| 69 | 68 |
| 70 BackoffEntry* GetBackoffEntry() override { return &mock_backoff_entry_; } | 69 BackoffEntry* GetBackoffEntry() override { return &backoff_entry_; } |
| 71 | 70 |
| 72 static bool ExplicitUserRequest(int load_flags) { | 71 static bool ExplicitUserRequest(int load_flags) { |
| 73 return URLRequestThrottlerEntry::ExplicitUserRequest(load_flags); | 72 return URLRequestThrottlerEntry::ExplicitUserRequest(load_flags); |
| 74 } | 73 } |
| 75 | 74 |
| 76 void ResetToBlank(const TimeTicks& time_now) { | 75 void ResetToBlank(const TimeTicks& time_now) { |
| 77 fake_time_now_ = time_now; | 76 fake_clock_.set_now(time_now); |
| 78 mock_backoff_entry_.set_fake_now(time_now); | |
| 79 | 77 |
| 80 GetBackoffEntry()->Reset(); | 78 GetBackoffEntry()->Reset(); |
| 81 GetBackoffEntry()->SetCustomReleaseTime(time_now); | |
| 82 set_sliding_window_release_time(time_now); | 79 set_sliding_window_release_time(time_now); |
| 83 } | 80 } |
| 84 | 81 |
| 85 // Overridden for tests. | 82 // Overridden for tests. |
| 86 TimeTicks ImplGetTimeNow() const override { return fake_time_now_; } | 83 TimeTicks ImplGetTimeNow() const override { return fake_clock_.NowTicks(); } |
| 87 | 84 |
| 88 void set_exponential_backoff_release_time( | 85 void set_fake_now(const TimeTicks& now) { fake_clock_.set_now(now); } |
| 89 const base::TimeTicks& release_time) { | 86 |
| 87 void set_exponential_backoff_release_time(const TimeTicks& release_time) { |
| 90 GetBackoffEntry()->SetCustomReleaseTime(release_time); | 88 GetBackoffEntry()->SetCustomReleaseTime(release_time); |
| 91 } | 89 } |
| 92 | 90 |
| 93 base::TimeTicks sliding_window_release_time() const { | 91 TimeTicks sliding_window_release_time() const { |
| 94 return URLRequestThrottlerEntry::sliding_window_release_time(); | 92 return URLRequestThrottlerEntry::sliding_window_release_time(); |
| 95 } | 93 } |
| 96 | 94 |
| 97 void set_sliding_window_release_time( | 95 void set_sliding_window_release_time(const TimeTicks& release_time) { |
| 98 const base::TimeTicks& release_time) { | 96 URLRequestThrottlerEntry::set_sliding_window_release_time(release_time); |
| 99 URLRequestThrottlerEntry::set_sliding_window_release_time( | |
| 100 release_time); | |
| 101 } | 97 } |
| 102 | 98 |
| 103 TimeTicks fake_time_now_; | |
| 104 MockBackoffEntry mock_backoff_entry_; | |
| 105 | |
| 106 protected: | 99 protected: |
| 107 ~MockURLRequestThrottlerEntry() override {} | 100 ~MockURLRequestThrottlerEntry() override {} |
| 101 |
| 102 private: |
| 103 mutable TestTickClock fake_clock_; |
| 104 BackoffEntry backoff_entry_; |
| 108 }; | 105 }; |
| 109 | 106 |
| 110 class MockURLRequestThrottlerManager : public URLRequestThrottlerManager { | 107 class MockURLRequestThrottlerManager : public URLRequestThrottlerManager { |
| 111 public: | 108 public: |
| 112 MockURLRequestThrottlerManager() : create_entry_index_(0) {} | 109 MockURLRequestThrottlerManager() : create_entry_index_(0) {} |
| 113 | 110 |
| 114 // Method to process the URL using URLRequestThrottlerManager protected | 111 // Method to process the URL using URLRequestThrottlerManager protected |
| 115 // method. | 112 // method. |
| 116 std::string DoGetUrlIdFromUrl(const GURL& url) { return GetIdFromUrl(url); } | 113 std::string DoGetUrlIdFromUrl(const GURL& url) { return GetIdFromUrl(url); } |
| 117 | 114 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 187 } |
| 191 | 188 |
| 192 std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) { | 189 std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) { |
| 193 return out << time.ToInternalValue(); | 190 return out << time.ToInternalValue(); |
| 194 } | 191 } |
| 195 | 192 |
| 196 TEST_F(URLRequestThrottlerEntryTest, CanThrottleRequest) { | 193 TEST_F(URLRequestThrottlerEntryTest, CanThrottleRequest) { |
| 197 TestNetworkDelegate d; | 194 TestNetworkDelegate d; |
| 198 context_.set_network_delegate(&d); | 195 context_.set_network_delegate(&d); |
| 199 entry_->set_exponential_backoff_release_time( | 196 entry_->set_exponential_backoff_release_time( |
| 200 entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1)); | 197 entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(1)); |
| 201 | 198 |
| 202 d.set_can_throttle_requests(false); | 199 d.set_can_throttle_requests(false); |
| 203 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, | 200 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, |
| 204 context_.network_delegate())); | 201 context_.network_delegate())); |
| 205 d.set_can_throttle_requests(true); | 202 d.set_can_throttle_requests(true); |
| 206 EXPECT_TRUE(entry_->ShouldRejectRequest(*request_, | 203 EXPECT_TRUE(entry_->ShouldRejectRequest(*request_, |
| 207 context_.network_delegate())); | 204 context_.network_delegate())); |
| 208 } | 205 } |
| 209 | 206 |
| 210 TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) { | 207 TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) { |
| 211 base::HistogramTester histogram_tester; | 208 base::HistogramTester histogram_tester; |
| 212 entry_->set_exponential_backoff_release_time( | 209 entry_->set_exponential_backoff_release_time( |
| 213 entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1)); | 210 entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(1)); |
| 214 EXPECT_TRUE(entry_->ShouldRejectRequest(*request_, | 211 EXPECT_TRUE(entry_->ShouldRejectRequest(*request_, |
| 215 context_.network_delegate())); | 212 context_.network_delegate())); |
| 216 | 213 |
| 217 // Also end-to-end test the load flags exceptions. | 214 // Also end-to-end test the load flags exceptions. |
| 218 request_->SetLoadFlags(LOAD_MAYBE_USER_GESTURE); | 215 request_->SetLoadFlags(LOAD_MAYBE_USER_GESTURE); |
| 219 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, | 216 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, |
| 220 context_.network_delegate())); | 217 context_.network_delegate())); |
| 221 | 218 |
| 222 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 0, 1); | 219 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 0, 1); |
| 223 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 1, 1); | 220 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 1, 1); |
| 224 } | 221 } |
| 225 | 222 |
| 226 TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) { | 223 TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) { |
| 227 base::HistogramTester histogram_tester; | 224 base::HistogramTester histogram_tester; |
| 228 entry_->set_exponential_backoff_release_time(entry_->fake_time_now_); | 225 entry_->set_exponential_backoff_release_time(entry_->ImplGetTimeNow()); |
| 229 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, | 226 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, |
| 230 context_.network_delegate())); | 227 context_.network_delegate())); |
| 231 entry_->set_exponential_backoff_release_time( | 228 entry_->set_exponential_backoff_release_time( |
| 232 entry_->fake_time_now_ - TimeDelta::FromMilliseconds(1)); | 229 entry_->ImplGetTimeNow() - TimeDelta::FromMilliseconds(1)); |
| 233 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, | 230 EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, |
| 234 context_.network_delegate())); | 231 context_.network_delegate())); |
| 235 | 232 |
| 236 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 0, 2); | 233 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 0, 2); |
| 237 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 1, 0); | 234 histogram_tester.ExpectBucketCount(kRequestThrottledHistogramName, 1, 0); |
| 238 } | 235 } |
| 239 | 236 |
| 240 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) { | 237 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) { |
| 241 MockURLRequestThrottlerHeaderAdapter failure_response(503); | 238 MockURLRequestThrottlerHeaderAdapter failure_response(503); |
| 242 entry_->UpdateWithResponse(std::string(), &failure_response); | 239 entry_->UpdateWithResponse(std::string(), &failure_response); |
| 243 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 240 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), |
| 241 entry_->ImplGetTimeNow()) |
| 244 << "A failure should increase the release_time"; | 242 << "A failure should increase the release_time"; |
| 245 } | 243 } |
| 246 | 244 |
| 247 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) { | 245 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) { |
| 248 MockURLRequestThrottlerHeaderAdapter success_response(200); | 246 MockURLRequestThrottlerHeaderAdapter success_response(200); |
| 249 entry_->UpdateWithResponse(std::string(), &success_response); | 247 entry_->UpdateWithResponse(std::string(), &success_response); |
| 250 EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 248 EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), |
| 249 entry_->ImplGetTimeNow()) |
| 251 << "A success should not add any delay"; | 250 << "A success should not add any delay"; |
| 252 } | 251 } |
| 253 | 252 |
| 254 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) { | 253 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) { |
| 255 MockURLRequestThrottlerHeaderAdapter failure_response(503); | 254 MockURLRequestThrottlerHeaderAdapter failure_response(503); |
| 256 MockURLRequestThrottlerHeaderAdapter success_response(200); | 255 MockURLRequestThrottlerHeaderAdapter success_response(200); |
| 257 entry_->UpdateWithResponse(std::string(), &success_response); | 256 entry_->UpdateWithResponse(std::string(), &success_response); |
| 258 entry_->UpdateWithResponse(std::string(), &failure_response); | 257 entry_->UpdateWithResponse(std::string(), &failure_response); |
| 259 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) | 258 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), |
| 259 entry_->ImplGetTimeNow()) |
| 260 << "This scenario should add delay"; | 260 << "This scenario should add delay"; |
| 261 entry_->UpdateWithResponse(std::string(), &success_response); | 261 entry_->UpdateWithResponse(std::string(), &success_response); |
| 262 } | 262 } |
| 263 | 263 |
| 264 TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) { | 264 TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) { |
| 265 TimeDelta lifetime = TimeDelta::FromMilliseconds( | 265 TimeDelta lifetime = TimeDelta::FromMilliseconds( |
| 266 MockURLRequestThrottlerEntry::kDefaultEntryLifetimeMs); | 266 MockURLRequestThrottlerEntry::kDefaultEntryLifetimeMs); |
| 267 const TimeDelta kFiveMs = TimeDelta::FromMilliseconds(5); | 267 const TimeDelta kFiveMs = TimeDelta::FromMilliseconds(5); |
| 268 | 268 |
| 269 TimeAndBool test_values[] = { | 269 TimeAndBool test_values[] = { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 MockURLRequestThrottlerHeaderAdapter success_adapter(200); | 308 MockURLRequestThrottlerHeaderAdapter success_adapter(200); |
| 309 entry_->UpdateWithResponse(std::string(), &success_adapter); | 309 entry_->UpdateWithResponse(std::string(), &success_adapter); |
| 310 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), release_after_failures); | 310 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), release_after_failures); |
| 311 } | 311 } |
| 312 | 312 |
| 313 TEST_F(URLRequestThrottlerEntryTest, SlidingWindow) { | 313 TEST_F(URLRequestThrottlerEntryTest, SlidingWindow) { |
| 314 int max_send = URLRequestThrottlerEntry::kDefaultMaxSendThreshold; | 314 int max_send = URLRequestThrottlerEntry::kDefaultMaxSendThreshold; |
| 315 int sliding_window = | 315 int sliding_window = |
| 316 URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs; | 316 URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs; |
| 317 | 317 |
| 318 TimeTicks time_1 = entry_->fake_time_now_ + | 318 TimeTicks time_1 = entry_->ImplGetTimeNow() + |
| 319 TimeDelta::FromMilliseconds(sliding_window / 3); | 319 TimeDelta::FromMilliseconds(sliding_window / 3); |
| 320 TimeTicks time_2 = entry_->fake_time_now_ + | 320 TimeTicks time_2 = entry_->ImplGetTimeNow() + |
| 321 TimeDelta::FromMilliseconds(2 * sliding_window / 3); | 321 TimeDelta::FromMilliseconds(2 * sliding_window / 3); |
| 322 TimeTicks time_3 = entry_->fake_time_now_ + | 322 TimeTicks time_3 = entry_->ImplGetTimeNow() + |
| 323 TimeDelta::FromMilliseconds(sliding_window); | 323 TimeDelta::FromMilliseconds(sliding_window); |
| 324 TimeTicks time_4 = entry_->fake_time_now_ + | 324 TimeTicks time_4 = entry_->ImplGetTimeNow() + |
| 325 TimeDelta::FromMilliseconds(sliding_window + 2 * sliding_window / 3); | 325 TimeDelta::FromMilliseconds(sliding_window + 2 * sliding_window / 3); |
| 326 | 326 |
| 327 entry_->set_exponential_backoff_release_time(time_1); | 327 entry_->set_exponential_backoff_release_time(time_1); |
| 328 | 328 |
| 329 for (int i = 0; i < max_send / 2; ++i) { | 329 for (int i = 0; i < max_send / 2; ++i) { |
| 330 EXPECT_EQ(2 * sliding_window / 3, | 330 EXPECT_EQ(2 * sliding_window / 3, |
| 331 entry_->ReserveSendingTimeForNextRequest(time_2)); | 331 entry_->ReserveSendingTimeForNextRequest(time_2)); |
| 332 } | 332 } |
| 333 EXPECT_EQ(time_2, entry_->sliding_window_release_time()); | 333 EXPECT_EQ(time_2, entry_->sliding_window_release_time()); |
| 334 | 334 |
| 335 entry_->fake_time_now_ = time_3; | 335 entry_->set_fake_now(time_3); |
| 336 | 336 |
| 337 for (int i = 0; i < (max_send + 1) / 2; ++i) | 337 for (int i = 0; i < (max_send + 1) / 2; ++i) |
| 338 EXPECT_EQ(0, entry_->ReserveSendingTimeForNextRequest(TimeTicks())); | 338 EXPECT_EQ(0, entry_->ReserveSendingTimeForNextRequest(TimeTicks())); |
| 339 | 339 |
| 340 EXPECT_EQ(time_4, entry_->sliding_window_release_time()); | 340 EXPECT_EQ(time_4, entry_->sliding_window_release_time()); |
| 341 } | 341 } |
| 342 | 342 |
| 343 TEST_F(URLRequestThrottlerEntryTest, ExplicitUserRequest) { | 343 TEST_F(URLRequestThrottlerEntryTest, ExplicitUserRequest) { |
| 344 ASSERT_FALSE(MockURLRequestThrottlerEntry::ExplicitUserRequest(0)); | 344 ASSERT_FALSE(MockURLRequestThrottlerEntry::ExplicitUserRequest(0)); |
| 345 ASSERT_TRUE(MockURLRequestThrottlerEntry::ExplicitUserRequest( | 345 ASSERT_TRUE(MockURLRequestThrottlerEntry::ExplicitUserRequest( |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 } | 517 } |
| 518 | 518 |
| 519 scoped_refptr<URLRequestThrottlerEntryInterface> entry_after = | 519 scoped_refptr<URLRequestThrottlerEntryInterface> entry_after = |
| 520 manager.RegisterRequestUrl(GURL("http://www.example.com/")); | 520 manager.RegisterRequestUrl(GURL("http://www.example.com/")); |
| 521 EXPECT_FALSE(entry_after->ShouldRejectRequest( | 521 EXPECT_FALSE(entry_after->ShouldRejectRequest( |
| 522 *request_, context_.network_delegate())); | 522 *request_, context_.network_delegate())); |
| 523 } | 523 } |
| 524 } | 524 } |
| 525 | 525 |
| 526 } // namespace net | 526 } // namespace net |
| OLD | NEW |