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

Side by Side Diff: net/base/network_throttle_manager_unittest.cc

Issue 2130493002: Implement THROTTLED priority semantics. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@NetworkStreamThrottler
Patch Set: Added tests and cleaned up code. Created 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/base/network_throttle_manager.h" 5 #include "net/base/network_throttle_manager_impl.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/callback_helpers.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/test/simple_test_clock.h"
9 #include "net/base/request_priority.h" 14 #include "net/base/request_priority.h"
10 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
11 16
12 namespace net { 17 namespace net {
13 18
14 namespace { 19 namespace {
15 20
16 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
17 22
18 class NetworkThrottleManagerTest : public testing::Test, 23 class NetworkThrottleManagerTest : public testing::Test,
19 NetworkThrottleManager::ThrottleDelegate { 24 NetworkThrottleManager::ThrottleDelegate {
20 public: 25 public:
21 NetworkThrottleManagerTest() 26 NetworkThrottleManagerTest()
22 : throttler_(NetworkThrottleManager::CreateThrottler()) {} 27 : throttle_state_change_count_(0),
28 last_throttle_state_change_(nullptr),
29 throttle_manager_(new NetworkThrottleManagerImpl) {}
23 30
24 protected: 31 protected:
25 std::unique_ptr<NetworkThrottleManager::Throttle> CreateThrottle( 32 std::unique_ptr<NetworkThrottleManager::Throttle> CreateThrottle(
26 net::RequestPriority priority, 33 net::RequestPriority priority,
27 bool expected_throttle_state) { 34 bool expected_throttle_state) {
28 std::unique_ptr<NetworkThrottleManager::Throttle> throttle( 35 std::unique_ptr<NetworkThrottleManager::Throttle> throttle(
29 throttler_->CreateThrottle(this, priority, false)); 36 throttle_manager_->CreateThrottle(this, priority, false));
30 EXPECT_EQ(expected_throttle_state, throttle->IsThrottled()); 37 EXPECT_EQ(expected_throttle_state, throttle->IsBlocked());
38 throttled_blocked_[throttle.get()] = !throttle->IsBlocked();
31 return throttle; 39 return throttle;
32 } 40 }
33 41
42 std::unique_ptr<NetworkThrottleManager::Throttle>
43 CreateThrottleIgnoringLimits(net::RequestPriority priority) {
44 std::unique_ptr<NetworkThrottleManager::Throttle> throttle(
45 throttle_manager_->CreateThrottle(this, priority, true));
46 EXPECT_FALSE(throttle->IsBlocked());
47 throttled_blocked_[throttle.get()] = !throttle->IsBlocked();
48 return throttle;
49 }
50
51 int throttle_state_change_count() { return throttle_state_change_count_; }
52
53 NetworkThrottleManager::Throttle* last_throttle_state_change() {
54 return last_throttle_state_change_;
55 }
56
57 void SetUpcallCallback(const base::Closure& callback) {
58 upcall_callback_ = callback;
59 }
60
61 void SetClock(std::unique_ptr<base::Clock> clock) {
62 throttle_manager_->SetClockForTesting(std::move(clock));
63 }
64
34 private: 65 private:
35 // NetworkThrottleManager::Delegate 66 // NetworkThrottleManager::Delegate
36 void OnThrottleStateChanged() override { ADD_FAILURE(); } 67 void OnThrottleStateChanged(
37 68 NetworkThrottleManager::Throttle* throttle) override {
38 std::unique_ptr<NetworkThrottleManager> throttler_; 69 EXPECT_FALSE(throttled_blocked_.find(throttle) == throttled_blocked_.end());
70 EXPECT_FALSE(throttled_blocked_[throttle]);
71 throttled_blocked_[throttle] = true;
72 ++throttle_state_change_count_;
73 last_throttle_state_change_ = throttle;
74 if (!upcall_callback_.is_null())
75 base::ResetAndReturn(&upcall_callback_).Run();
76 }
77
78 int throttle_state_change_count_;
79 NetworkThrottleManager::Throttle* last_throttle_state_change_;
80 std::unique_ptr<NetworkThrottleManagerImpl> throttle_manager_;
81 std::map<NetworkThrottleManager::Throttle*, bool> throttled_blocked_;
82 base::Closure upcall_callback_;
39 }; 83 };
40 84
41 // Check to confirm that all created throttles start unthrottled for the 85 // Check to confirm that all created throttles at priorities other than
42 // current null implementation. 86 // THROTTLED start unblocked.
43 TEST_F(NetworkThrottleManagerTest, AllUnthrottled) { 87 TEST_F(NetworkThrottleManagerTest, AllUnthrottled) {
44 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { 88 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
89 if (i == THROTTLED)
90 continue;
45 CreateThrottle(static_cast<RequestPriority>(i), false); 91 CreateThrottle(static_cast<RequestPriority>(i), false);
46 } 92 }
47 } 93 }
48 94
95 // Check for basic semantics around the new THROTTLED level.
96 TEST_F(NetworkThrottleManagerTest, ThrottledBlocking) {
97 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
98 CreateThrottle(THROTTLED, false));
99 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
100 CreateThrottle(THROTTLED, false));
101 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
102 CreateThrottle(THROTTLED, true));
103 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
104 CreateThrottle(THROTTLED, true));
105 std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
106 CreateThrottle(THROTTLED, true));
107
108 EXPECT_EQ(0, throttle_state_change_count());
109
110 throttle1.reset();
111 EXPECT_EQ(1, throttle_state_change_count());
112 EXPECT_EQ(throttle3.get(), last_throttle_state_change());
113
114 EXPECT_FALSE(throttle3->IsBlocked());
115 EXPECT_TRUE(throttle4->IsBlocked());
116 EXPECT_TRUE(throttle5->IsBlocked());
117
118 throttle2.reset();
119 EXPECT_EQ(2, throttle_state_change_count());
120 EXPECT_EQ(throttle4.get(), last_throttle_state_change());
121
122 EXPECT_FALSE(throttle3->IsBlocked());
123 EXPECT_FALSE(throttle4->IsBlocked());
124 EXPECT_TRUE(throttle5->IsBlocked());
125 }
126
127 // Check that THROTTLED semantics are dependent on all outstanding requests.
128 TEST_F(NetworkThrottleManagerTest, ThrottledBlockingMultiPriority) {
129 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
130 CreateThrottle(HIGHEST, false));
131 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
132 CreateThrottle(LOW, false));
133 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
134 CreateThrottle(IDLE, false));
135 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
136 CreateThrottle(THROTTLED, true));
137 std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
138 CreateThrottle(THROTTLED, true));
139
140 EXPECT_EQ(0, throttle_state_change_count());
141
142 throttle1.reset();
143 EXPECT_EQ(0, throttle_state_change_count());
144 EXPECT_FALSE(throttle3->IsBlocked());
145 EXPECT_TRUE(throttle4->IsBlocked());
146 EXPECT_TRUE(throttle5->IsBlocked());
147
148 throttle2.reset();
149 EXPECT_EQ(1, throttle_state_change_count());
150 EXPECT_EQ(throttle4.get(), last_throttle_state_change());
151
152 EXPECT_FALSE(throttle3->IsBlocked());
153 EXPECT_FALSE(throttle4->IsBlocked());
154 EXPECT_TRUE(throttle5->IsBlocked());
155
156 throttle3.reset();
157 EXPECT_EQ(2, throttle_state_change_count());
158 EXPECT_EQ(throttle5.get(), last_throttle_state_change());
159
160 EXPECT_FALSE(throttle4->IsBlocked());
161 EXPECT_FALSE(throttle5->IsBlocked());
162 }
163
164 // Check that a SetPriority() away from THROTTLED results in unblocking
165 // and an upcall.
166 TEST_F(NetworkThrottleManagerTest, ThrottledSetPriority) {
167 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
168 CreateThrottle(THROTTLED, false));
169 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
170 CreateThrottle(THROTTLED, false));
171 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
172 CreateThrottle(THROTTLED, true));
173 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
174 CreateThrottle(THROTTLED, true));
175
176 EXPECT_EQ(0, throttle_state_change_count());
177
178 throttle3->SetPriority(LOW);
179 EXPECT_EQ(1, throttle_state_change_count());
180 EXPECT_EQ(throttle3.get(), last_throttle_state_change());
181 EXPECT_FALSE(throttle3->IsBlocked());
182 EXPECT_TRUE(throttle4->IsBlocked());
183 }
184
185 void ResetThrottles(ScopedVector<NetworkThrottleManager::Throttle> throttles) {
186 // All pointers in the vector should be deleted on exit.
187 }
188
189 // Note that this routine is dependent on priority setting
190 // *not* resulting in destruction of any throttle and should only
191 // be used in tests where that is true.
192 void SetAllToPriority(
193 RequestPriority priority,
194 std::vector<NetworkThrottleManager::Throttle*> throttles) {
195 for (size_t i = 0; i < throttles.size(); ++i)
196 throttles[i]->SetPriority(priority);
197 }
198
199 // Check that tearing down all elements in the NTM on a SetPriority
200 // upcall doesn't create any problems.
201 TEST_F(NetworkThrottleManagerTest, ThrottleTeardown) {
202 ScopedVector<NetworkThrottleManager::Throttle> throttles;
203 std::unique_ptr<NetworkThrottleManager::Throttle> throttle_temporary;
204
205 throttle_temporary = CreateThrottle(THROTTLED, false);
206 throttles.push_back(std::move(throttle_temporary.release()));
207
208 throttle_temporary = CreateThrottle(THROTTLED, false);
209 throttles.push_back(std::move(throttle_temporary.release()));
210
211 // Note that if there is more than one throttle blocked, then the
212 // number of throttle state changes is dependent on destruction order.
213 // So only one blocked throttle is created.
214
215 throttle_temporary = CreateThrottle(THROTTLED, true);
216 NetworkThrottleManager::Throttle* throttle3 = throttle_temporary.get();
217 throttles.push_back(std::move(throttle_temporary.release()));
218
219 SetUpcallCallback(base::Bind(&ResetThrottles, base::Passed(&throttles)));
220
221 EXPECT_EQ(0, throttle_state_change_count());
222
223 throttle3->SetPriority(LOW);
224 // If the test is functioning as expected, throttle3 now points to
225 // a deleted object and can no longer be indirected through.
226
227 EXPECT_EQ(1, throttle_state_change_count());
228 EXPECT_EQ(throttle3, last_throttle_state_change());
229 }
230
231 // Check that modifying all the priorities of the allocated throttles in
232 // the callback works properly.
233 TEST_F(NetworkThrottleManagerTest, ThrottlePriorityReset) {
234 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
235 CreateThrottle(THROTTLED, false));
236 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
237 CreateThrottle(THROTTLED, false));
238 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
239 CreateThrottle(THROTTLED, true));
240 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
241 CreateThrottle(THROTTLED, true));
242
243 std::vector<NetworkThrottleManager::Throttle*> throttles;
244 throttles.push_back(throttle1.get());
245 throttles.push_back(throttle2.get());
246 throttles.push_back(throttle3.get());
247
248 SetUpcallCallback(
249 base::Bind(&SetAllToPriority, MEDIUM, base::Passed(&throttles)));
250
251 EXPECT_EQ(0, throttle_state_change_count());
252 throttle3->SetPriority(HIGHEST);
253
254 // Expected result: throttles 1-3 @ medium priority (the callback
255 // should have overridden the priority setting above), only throttle 4
256 // blocked (throttle3 should have been unblocked by either of
257 // the priority changes), and one state changes (the unblocking).
258 EXPECT_EQ(MEDIUM, throttle1->Priority());
259 EXPECT_EQ(MEDIUM, throttle2->Priority());
260 EXPECT_EQ(MEDIUM, throttle3->Priority());
261 EXPECT_EQ(THROTTLED, throttle4->Priority());
262 EXPECT_FALSE(throttle1->IsBlocked());
263 EXPECT_FALSE(throttle2->IsBlocked());
264 EXPECT_FALSE(throttle3->IsBlocked());
265 EXPECT_TRUE(throttle4->IsBlocked());
266 EXPECT_EQ(1, throttle_state_change_count());
267 }
268
269 // Check that modifying the priority of a request from a non-THROTTLED
270 // value to THROTTLED causes no change in behavior.
271 TEST_F(NetworkThrottleManagerTest, ThrottlePriorityResetToThrottled) {
272 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
273 CreateThrottle(THROTTLED, false));
274 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
275 CreateThrottle(THROTTLED, false));
276 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
277 CreateThrottle(LOW, false));
278 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
279 CreateThrottle(THROTTLED, true));
280
281 EXPECT_EQ(0, throttle_state_change_count());
282 throttle3->SetPriority(THROTTLED);
283 EXPECT_EQ(0, throttle_state_change_count());
284
285 EXPECT_FALSE(throttle1->IsBlocked());
286 EXPECT_FALSE(throttle2->IsBlocked());
287 EXPECT_FALSE(throttle3->IsBlocked());
288 EXPECT_TRUE(throttle4->IsBlocked());
289
290 EXPECT_EQ(THROTTLED, throttle1->Priority());
291 EXPECT_EQ(THROTTLED, throttle2->Priority());
292 EXPECT_EQ(THROTTLED, throttle3->Priority());
293 EXPECT_EQ(THROTTLED, throttle4->Priority());
294 }
295
296 // Confirm that old requests don't count against the ilmit.
297 TEST_F(NetworkThrottleManagerTest, DontCountAgedRequests) {
298 base::Time now(base::Time::Now());
299 base::SimpleTestClock* clock(new base::SimpleTestClock);
300
301 SetClock(std::unique_ptr<base::Clock>(clock));
302
303 const int age_in_days_of_old_throttles = 4;
304
305 // Confirm default median and timing means that 4 days is long enough ago
306 // to be aged out.
307 EXPECT_GT(age_in_days_of_old_throttles * 24 * 60 * 60 * 1000,
308 NetworkThrottleManagerImpl::kInitialMedianInMS *
309 NetworkThrottleManagerImpl::kMedianLifetimeMultiple);
310
311 clock->SetNow(now - base::TimeDelta::FromDays(age_in_days_of_old_throttles));
312 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
313 CreateThrottle(IDLE, false));
314 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
315 CreateThrottle(IDLE, false));
316
317 clock->SetNow(now);
318 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
319 CreateThrottle(LOW, false));
320
321 // First throttled request should not be blocked.
322 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
323 CreateThrottle(THROTTLED, false));
324
325 // Second should be.
326 std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
327 CreateThrottle(THROTTLED, true));
328
329 // Destroying the old requests should not result in any upcalls.
330 EXPECT_EQ(0, throttle_state_change_count());
331 throttle1.reset();
332 EXPECT_EQ(0, throttle_state_change_count());
333 throttle2.reset();
334 EXPECT_EQ(0, throttle_state_change_count());
335
336 // But destroying a new request should result in a state change.
337 throttle3.reset();
338 EXPECT_EQ(1, throttle_state_change_count());
339 EXPECT_EQ(throttle5.get(), last_throttle_state_change());
340 }
341
342 // Confirm that a slew of throttles of a specific age will shift the
343 // median for determining "aged requests" to that age.
344 TEST_F(NetworkThrottleManagerTest, ShiftMedian) {
345 base::Time now(base::Time::Now());
346 base::SimpleTestClock* clock(new base::SimpleTestClock);
347
348 SetClock(std::unique_ptr<base::Clock>(clock));
349
350 // Setup two throttles of age *just short* of aging out; confirm
351 // they result in blocked THROTTLED requests.
352 clock->SetNow(now -
353 base::TimeDelta::FromMilliseconds(
354 NetworkThrottleManagerImpl::kInitialMedianInMS *
355 NetworkThrottleManagerImpl::kMedianLifetimeMultiple -
356 1));
357 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
358 CreateThrottle(IDLE, false));
359 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
360 CreateThrottle(IDLE, false));
361 clock->SetNow(now);
362
363 // Two throttles need to be created because of an implementation issue;
364 // there isn't a way to force recomputation of outstanding requests on a
365 // test-provoked time shift, so this test relies on the first throttle
366 // creation to do it for the second throttle.
367 // First one can't be throttled since that result is indeterminate because
368 // of implementation detail (SetNow() doesn't force a recomputation of
369 // how many requests have aged out).
370 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
371 CreateThrottle(IDLE, false));
372 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
373 CreateThrottle(THROTTLED, true));
374
375 throttle1.reset();
376 throttle2.reset();
377 throttle3.reset();
378 throttle4.reset();
379
380 // Create 100 throttles and destroy them, effectively with lifetime zero.
381 // This should substantially decrease the median age estimate.
382 for (int i = 0; i < 100; ++i) {
383 std::unique_ptr<NetworkThrottleManager::Throttle> tmp(
384 CreateThrottle(IDLE, false));
385 }
386
387 // The identical test above should no longer result in blocked throttles.
388 clock->SetNow(now -
389 base::TimeDelta::FromMilliseconds(
390 NetworkThrottleManagerImpl::kInitialMedianInMS *
391 NetworkThrottleManagerImpl::kMedianLifetimeMultiple -
392 1));
393 std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
394 CreateThrottle(IDLE, false));
395 std::unique_ptr<NetworkThrottleManager::Throttle> throttle6(
396 CreateThrottle(IDLE, false));
397 clock->SetNow(now);
398 // First one can't be throttled since that result is indeterminate because
399 // of implementation detail (SetNow() doesn't force a recomputation of
400 // how many requests have aged out).
401 std::unique_ptr<NetworkThrottleManager::Throttle> throttle7(
402 CreateThrottle(IDLE, false));
403 std::unique_ptr<NetworkThrottleManager::Throttle> throttle8(
404 CreateThrottle(THROTTLED, false));
405 }
406
407 // Confirm that "ignore_limits" boolean is respected.
408 TEST_F(NetworkThrottleManagerTest, IgnoreLimits) {
409 std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
410 CreateThrottle(HIGHEST, false));
411 std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
412 CreateThrottle(LOW, false));
413 std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
414 CreateThrottle(IDLE, false));
415 std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
416 CreateThrottle(THROTTLED, true));
417 std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
418 CreateThrottleIgnoringLimits(THROTTLED));
419 }
420
49 } // namespace 421 } // namespace
50 422
51 } // namespace net 423 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698