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

Side by Side Diff: net/url_request/url_request_throttler_unittest.cc

Issue 5276007: Implement exponential back-off mechanism. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: pull latest to merge Created 10 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/url_request/url_request_throttler_manager.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "base/pickle.h"
6 #include "base/scoped_ptr.h"
7 #include "base/string_number_conversions.h"
8 #include "base/time.h"
9 #include "net/base/test_completion_callback.h"
10 #include "net/url_request/url_request_context.h"
11 #include "net/url_request/url_request_throttler_header_interface.h"
12 #include "net/url_request/url_request_throttler_manager.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 using base::TimeDelta;
16 using base::TimeTicks;
17
18 namespace {
19 class MockURLRequestThrottlerManager;
20
21 class MockURLRequestThrottlerEntry : public net::URLRequestThrottlerEntry {
22 public :
23 MockURLRequestThrottlerEntry() {}
24 MockURLRequestThrottlerEntry(
25 const TimeTicks& exponential_backoff_release_time,
26 const TimeTicks& sliding_window_release_time,
27 const TimeTicks& fake_now)
28 : fake_time_now_(fake_now) {
29 set_exponential_backoff_release_time(exponential_backoff_release_time);
30 set_sliding_window_release_time(sliding_window_release_time);
31 }
32 virtual ~MockURLRequestThrottlerEntry() {}
33
34 void ResetToBlank(const TimeTicks& time_now) {
35 fake_time_now_ = time_now;
36 set_exponential_backoff_release_time(time_now);
37 set_failure_count(0);
38 set_sliding_window_release_time(time_now);
39 }
40
41 // Overridden for tests.
42 virtual TimeTicks GetTimeNow() const { return fake_time_now_; }
43
44 void set_exponential_backoff_release_time(
45 const base::TimeTicks& release_time) {
46 net::URLRequestThrottlerEntry::set_exponential_backoff_release_time(
47 release_time);
48 }
49
50 base::TimeTicks sliding_window_release_time() const {
51 return net::URLRequestThrottlerEntry::sliding_window_release_time();
52 }
53
54 void set_sliding_window_release_time(
55 const base::TimeTicks& release_time) {
56 net::URLRequestThrottlerEntry::set_sliding_window_release_time(
57 release_time);
58 }
59
60 TimeTicks fake_time_now_;
61 };
62
63 class MockURLRequestThrottlerHeaderAdapter
64 : public net::URLRequestThrottlerHeaderInterface {
65 public:
66 MockURLRequestThrottlerHeaderAdapter()
67 : fake_retry_value_("0.0"),
68 fake_response_code_(0) {
69 }
70
71 MockURLRequestThrottlerHeaderAdapter(const std::string& retry_value,
72 int response_code)
73 : fake_retry_value_(retry_value),
74 fake_response_code_(response_code) {
75 }
76
77 virtual ~MockURLRequestThrottlerHeaderAdapter() {}
78
79 virtual std::string GetNormalizedValue(const std::string& key) const {
80 if (key == MockURLRequestThrottlerEntry::kRetryHeaderName)
81 return fake_retry_value_;
82 return "";
83 }
84
85 virtual int GetResponseCode() const { return fake_response_code_; }
86
87 std::string fake_retry_value_;
88 int fake_response_code_;
89 };
90
91 class MockURLRequestThrottlerManager : public net::URLRequestThrottlerManager {
92 public:
93 MockURLRequestThrottlerManager() : create_entry_index_(0) {}
94
95 // Method to process the URL using URLRequestThrottlerManager protected
96 // method.
97 std::string DoGetUrlIdFromUrl(const GURL& url) { return GetIdFromUrl(url); }
98
99 // Method to use the garbage collecting method of URLRequestThrottlerManager.
100 void DoGarbageCollectEntries() { GarbageCollectEntries(); }
101
102 // Returns the number of entries in the map.
103 int GetNumberOfEntries() const { return GetNumberOfEntriesForTests(); }
104
105 void CreateEntry(bool is_outdated) {
106 TimeTicks time = TimeTicks::Now();
107 if (is_outdated) {
108 time -= TimeDelta::FromMilliseconds(
109 MockURLRequestThrottlerEntry::kDefaultEntryLifetimeMs + 1000);
110 }
111 std::string fake_url_string("http://www.fakeurl.com/");
112 fake_url_string.append(base::IntToString(create_entry_index_++));
113 GURL fake_url(fake_url_string);
114 OverrideEntryForTests(
115 fake_url,
116 new MockURLRequestThrottlerEntry(time, TimeTicks::Now(),
117 TimeTicks::Now()));
118 }
119
120 private:
121 int create_entry_index_;
122 };
123
124 struct TimeAndBool {
125 TimeAndBool(const TimeTicks& time_value, bool expected, int line_num) {
126 time = time_value;
127 result = expected;
128 line = line_num;
129 }
130 TimeTicks time;
131 bool result;
132 int line;
133 };
134
135 struct GurlAndString {
136 GurlAndString(const GURL& url_value,
137 const std::string& expected,
138 int line_num) {
139 url = url_value;
140 result = expected;
141 line = line_num;
142 }
143 GURL url;
144 std::string result;
145 int line;
146 };
147
148 } // namespace
149
150 class URLRequestThrottlerEntryTest : public testing::Test {
151 protected:
152 virtual void SetUp();
153 TimeTicks now_;
154 scoped_refptr<MockURLRequestThrottlerEntry> entry_;
155 };
156
157 void URLRequestThrottlerEntryTest::SetUp() {
158 now_ = TimeTicks::Now();
159 entry_ = new MockURLRequestThrottlerEntry();
160 entry_->ResetToBlank(now_);
161 }
162
163 std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) {
164 return out << time.ToInternalValue();
165 }
166
167 TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) {
168 entry_->set_exponential_backoff_release_time(
169 entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1));
170 EXPECT_TRUE(entry_->IsDuringExponentialBackoff());
171 }
172
173 TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) {
174 entry_->set_exponential_backoff_release_time(entry_->fake_time_now_);
175 EXPECT_FALSE(entry_->IsDuringExponentialBackoff());
176 entry_->set_exponential_backoff_release_time(
177 entry_->fake_time_now_ - TimeDelta::FromMilliseconds(1));
178 EXPECT_FALSE(entry_->IsDuringExponentialBackoff());
179 }
180
181 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateRetryAfter) {
182 // If the response we received has a retry-after field,
183 // the request should be delayed.
184 MockURLRequestThrottlerHeaderAdapter header_w_delay_header("5.5", 200);
185 entry_->UpdateWithResponse(&header_w_delay_header);
186 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
187 << "When the server put a positive value in retry-after we should "
188 "increase release_time";
189
190 entry_->ResetToBlank(now_);
191 header_w_delay_header.fake_retry_value_ = "-5.5";
192 EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
193 << "When given a negative value, it should not change the release_time";
194 }
195
196 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) {
197 MockURLRequestThrottlerHeaderAdapter failure_response("0", 505);
198 entry_->UpdateWithResponse(&failure_response);
199 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
200 << "A failure should increase the release_time";
201 }
202
203 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) {
204 MockURLRequestThrottlerHeaderAdapter success_response("0", 200);
205 entry_->UpdateWithResponse(&success_response);
206 EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
207 << "A success should not add any delay";
208 }
209
210 TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) {
211 MockURLRequestThrottlerHeaderAdapter failure_response("0", 500);
212 MockURLRequestThrottlerHeaderAdapter success_response("0", 200);
213 entry_->UpdateWithResponse(&success_response);
214 entry_->UpdateWithResponse(&failure_response);
215 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
216 << "This scenario should add delay";
217 }
218
219 TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) {
220 TimeDelta lifetime = TimeDelta::FromMilliseconds(
221 MockURLRequestThrottlerEntry::kDefaultEntryLifetimeMs);
222 const TimeDelta kFiveMs = TimeDelta::FromMilliseconds(5);
223
224 TimeAndBool test_values[] = {
225 TimeAndBool(now_, false, __LINE__),
226 TimeAndBool(now_ - kFiveMs, false, __LINE__),
227 TimeAndBool(now_ + kFiveMs, false, __LINE__),
228 TimeAndBool(now_ - lifetime, false, __LINE__),
229 TimeAndBool(now_ - (lifetime + kFiveMs), true, __LINE__)};
230
231 for (unsigned int i = 0; i < arraysize(test_values); ++i) {
232 entry_->set_exponential_backoff_release_time(test_values[i].time);
233 EXPECT_EQ(entry_->IsEntryOutdated(), test_values[i].result) <<
234 "Test case #" << i << " line " << test_values[i].line << " failed";
235 }
236 }
237
238 TEST_F(URLRequestThrottlerEntryTest, MaxAllowedBackoff) {
239 for (int i = 0; i < 30; ++i) {
240 MockURLRequestThrottlerHeaderAdapter response_adapter("0.0", 505);
241 entry_->UpdateWithResponse(&response_adapter);
242 }
243
244 TimeDelta delay = entry_->GetExponentialBackoffReleaseTime() - now_;
245 EXPECT_EQ(delay.InMilliseconds(),
246 MockURLRequestThrottlerEntry::kDefaultMaximumBackoffMs);
247 }
248
249 TEST_F(URLRequestThrottlerEntryTest, MalformedContent) {
250 MockURLRequestThrottlerHeaderAdapter response_adapter("0.0", 505);
251 for (int i = 0; i < 5; ++i)
252 entry_->UpdateWithResponse(&response_adapter);
253
254 TimeTicks release_after_failures = entry_->GetExponentialBackoffReleaseTime();
255
256 // Inform the entry that a response body was malformed, which is supposed to
257 // increase the back-off time.
258 entry_->ReceivedContentWasMalformed();
259 EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), release_after_failures);
260 }
261
262 TEST_F(URLRequestThrottlerEntryTest, SlidingWindow) {
263 int max_send = net::URLRequestThrottlerEntry::kDefaultMaxSendThreshold;
264 int sliding_window =
265 net::URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs;
266
267 TimeTicks time_1 = entry_->fake_time_now_ +
268 TimeDelta::FromMilliseconds(sliding_window / 3);
269 TimeTicks time_2 = entry_->fake_time_now_ +
270 TimeDelta::FromMilliseconds(2 * sliding_window / 3);
271 TimeTicks time_3 = entry_->fake_time_now_ +
272 TimeDelta::FromMilliseconds(sliding_window);
273 TimeTicks time_4 = entry_->fake_time_now_ +
274 TimeDelta::FromMilliseconds(sliding_window + 2 * sliding_window / 3);
275
276 entry_->set_exponential_backoff_release_time(time_1);
277
278 for (int i = 0; i < max_send / 2; ++i) {
279 EXPECT_EQ(2 * sliding_window / 3,
280 entry_->ReserveSendingTimeForNextRequest(time_2));
281 }
282 EXPECT_EQ(time_2, entry_->sliding_window_release_time());
283
284 entry_->fake_time_now_ = time_3;
285
286 for (int i = 0; i < (max_send + 1) / 2; ++i)
287 EXPECT_EQ(0, entry_->ReserveSendingTimeForNextRequest(TimeTicks()));
288
289 EXPECT_EQ(time_4, entry_->sliding_window_release_time());
290 }
291
292 TEST(URLRequestThrottlerManager, IsUrlStandardised) {
293 MockURLRequestThrottlerManager manager;
294 GurlAndString test_values[] = {
295 GurlAndString(GURL("http://www.example.com"),
296 std::string("http://www.example.com/"), __LINE__),
297 GurlAndString(GURL("http://www.Example.com"),
298 std::string("http://www.example.com/"), __LINE__),
299 GurlAndString(GURL("http://www.ex4mple.com/Pr4c71c41"),
300 std::string("http://www.ex4mple.com/pr4c71c41"), __LINE__),
301 GurlAndString(GURL("http://www.example.com/0/token/false"),
302 std::string("http://www.example.com/0/token/false"),
303 __LINE__),
304 GurlAndString(GURL("http://www.example.com/index.php?code=javascript"),
305 std::string("http://www.example.com/index.php"), __LINE__),
306 GurlAndString(GURL("http://www.example.com/index.php?code=1#superEntry"),
307 std::string("http://www.example.com/index.php"),
308 __LINE__),
309 GurlAndString(GURL("http://www.example.com:1234/"),
310 std::string("http://www.example.com:1234/"), __LINE__)};
311
312 for (unsigned int i = 0; i < arraysize(test_values); ++i) {
313 std::string temp = manager.DoGetUrlIdFromUrl(test_values[i].url);
314 EXPECT_EQ(temp, test_values[i].result) <<
315 "Test case #" << i << " line " << test_values[i].line << " failed";
316 }
317 }
318
319 TEST(URLRequestThrottlerManager, AreEntriesBeingCollected) {
320 MockURLRequestThrottlerManager manager;
321
322 manager.CreateEntry(true); // true = Entry is outdated.
323 manager.CreateEntry(true);
324 manager.CreateEntry(true);
325 manager.DoGarbageCollectEntries();
326 EXPECT_EQ(0, manager.GetNumberOfEntries());
327
328 manager.CreateEntry(false);
329 manager.CreateEntry(false);
330 manager.CreateEntry(false);
331 manager.CreateEntry(true);
332 manager.DoGarbageCollectEntries();
333 EXPECT_EQ(3, manager.GetNumberOfEntries());
334 }
335
336 TEST(URLRequestThrottlerManager, IsHostBeingRegistered) {
337 MockURLRequestThrottlerManager manager;
338
339 manager.RegisterRequestUrl(GURL("http://www.example.com/"));
340 manager.RegisterRequestUrl(GURL("http://www.google.com/"));
341 manager.RegisterRequestUrl(GURL("http://www.google.com/index/0"));
342 manager.RegisterRequestUrl(GURL("http://www.google.com/index/0?code=1"));
343 manager.RegisterRequestUrl(GURL("http://www.google.com/index/0#lolsaure"));
344
345 EXPECT_EQ(3, manager.GetNumberOfEntries());
346 }
OLDNEW
« no previous file with comments | « net/url_request/url_request_throttler_manager.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698