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

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

Issue 10440119: Introduce a delegate to avoid hardcoding "chrome-extension" in net/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review nit and merge to LKGR for commit. Created 8 years, 6 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 | Annotate | Revision Log
OLDNEW
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 // The tests in this file attempt to verify the following through simulation: 5 // The tests in this file attempt to verify the following through simulation:
6 // a) That a server experiencing overload will actually benefit from the 6 // a) That a server experiencing overload will actually benefit from the
7 // anti-DDoS throttling logic, i.e. that its traffic spike will subside 7 // anti-DDoS throttling logic, i.e. that its traffic spike will subside
8 // and be distributed over a longer period of time; 8 // and be distributed over a longer period of time;
9 // b) That "well-behaved" clients of a server under DDoS attack actually 9 // b) That "well-behaved" clients of a server under DDoS attack actually
10 // benefit from the anti-DDoS throttling logic; and 10 // benefit from the anti-DDoS throttling logic; and
11 // c) That the approximate increase in "perceived downtime" introduced by 11 // c) That the approximate increase in "perceived downtime" introduced by
12 // anti-DDoS throttling for various different actual downtimes is what 12 // anti-DDoS throttling for various different actual downtimes is what
13 // we expect it to be. 13 // we expect it to be.
14 14
15 #include <cmath> 15 #include <cmath>
16 #include <limits> 16 #include <limits>
17 #include <vector> 17 #include <vector>
18 18
19 #include "base/environment.h" 19 #include "base/environment.h"
20 #include "base/memory/scoped_vector.h" 20 #include "base/memory/scoped_vector.h"
21 #include "base/rand_util.h" 21 #include "base/rand_util.h"
22 #include "base/time.h" 22 #include "base/time.h"
23 #include "net/url_request/url_request_test_util.h"
23 #include "net/url_request/url_request_throttler_manager.h" 24 #include "net/url_request/url_request_throttler_manager.h"
24 #include "net/url_request/url_request_throttler_test_support.h" 25 #include "net/url_request/url_request_throttler_test_support.h"
25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
26 27
27 using base::TimeDelta; 28 using base::TimeDelta;
28 using base::TimeTicks; 29 using base::TimeTicks;
29 30
30 namespace net { 31 namespace net {
31 namespace { 32 namespace {
32 33
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 // after all |Requester| objects. 116 // after all |Requester| objects.
116 class Server : public DiscreteTimeSimulation::Actor { 117 class Server : public DiscreteTimeSimulation::Actor {
117 public: 118 public:
118 Server(int max_queries_per_tick, 119 Server(int max_queries_per_tick,
119 double request_drop_ratio) 120 double request_drop_ratio)
120 : max_queries_per_tick_(max_queries_per_tick), 121 : max_queries_per_tick_(max_queries_per_tick),
121 request_drop_ratio_(request_drop_ratio), 122 request_drop_ratio_(request_drop_ratio),
122 num_overloaded_ticks_remaining_(0), 123 num_overloaded_ticks_remaining_(0),
123 num_current_tick_queries_(0), 124 num_current_tick_queries_(0),
124 num_overloaded_ticks_(0), 125 num_overloaded_ticks_(0),
125 max_experienced_queries_per_tick_(0) { 126 max_experienced_queries_per_tick_(0),
127 mock_request_(GURL(), NULL) {
126 } 128 }
127 129
128 void SetDowntime(const TimeTicks& start_time, const TimeDelta& duration) { 130 void SetDowntime(const TimeTicks& start_time, const TimeDelta& duration) {
129 start_downtime_ = start_time; 131 start_downtime_ = start_time;
130 end_downtime_ = start_time + duration; 132 end_downtime_ = start_time + duration;
131 } 133 }
132 134
133 virtual void AdvanceTime(const TimeTicks& absolute_time) OVERRIDE { 135 virtual void AdvanceTime(const TimeTicks& absolute_time) OVERRIDE {
134 now_ = absolute_time; 136 now_ = absolute_time;
135 } 137 }
(...skipping 16 matching lines...) Expand all
152 requests_per_tick_.push_back(num_current_tick_queries_); 154 requests_per_tick_.push_back(num_current_tick_queries_);
153 num_current_tick_queries_ = 0; 155 num_current_tick_queries_ = 0;
154 } 156 }
155 157
156 // This is called by Requester. It returns the response code from 158 // This is called by Requester. It returns the response code from
157 // the server. 159 // the server.
158 int HandleRequest() { 160 int HandleRequest() {
159 ++num_current_tick_queries_; 161 ++num_current_tick_queries_;
160 if (!start_downtime_.is_null() && 162 if (!start_downtime_.is_null() &&
161 start_downtime_ < now_ && now_ < end_downtime_) { 163 start_downtime_ < now_ && now_ < end_downtime_) {
162 // TODO(joi): For the simulation measuring the increase in perceived 164 // For the simulation measuring the increase in perceived
163 // downtime, it might be interesting to count separately the 165 // downtime, it might be interesting to count separately the
164 // queries seen by the server (assuming a front-end reverse proxy 166 // queries seen by the server (assuming a front-end reverse proxy
165 // is what actually serves up the 503s in this case) so that we could 167 // is what actually serves up the 503s in this case) so that we could
166 // visualize the traffic spike seen by the server when it comes up, 168 // visualize the traffic spike seen by the server when it comes up,
167 // which would in many situations be ameliorated by the anti-DDoS 169 // which would in many situations be ameliorated by the anti-DDoS
168 // throttling. 170 // throttling.
169 return 503; 171 return 503;
170 } 172 }
171 173
172 if ((num_overloaded_ticks_remaining_ > 0 || 174 if ((num_overloaded_ticks_remaining_ > 0 ||
173 num_current_tick_queries_ > max_queries_per_tick_) && 175 num_current_tick_queries_ > max_queries_per_tick_) &&
174 base::RandDouble() < request_drop_ratio_) { 176 base::RandDouble() < request_drop_ratio_) {
175 return 503; 177 return 503;
176 } 178 }
177 179
178 return 200; 180 return 200;
179 } 181 }
180 182
181 int num_overloaded_ticks() const { 183 int num_overloaded_ticks() const {
182 return num_overloaded_ticks_; 184 return num_overloaded_ticks_;
183 } 185 }
184 186
185 int max_experienced_queries_per_tick() const { 187 int max_experienced_queries_per_tick() const {
186 return max_experienced_queries_per_tick_; 188 return max_experienced_queries_per_tick_;
187 } 189 }
188 190
191 const URLRequest& mock_request() const {
192 return mock_request_;
193 }
194
189 std::string VisualizeASCII(int terminal_width) { 195 std::string VisualizeASCII(int terminal_width) {
190 // Account for | characters we place at left of graph. 196 // Account for | characters we place at left of graph.
191 terminal_width -= 1; 197 terminal_width -= 1;
192 198
193 VerboseOut("Overloaded for %d of %d ticks.\n", 199 VerboseOut("Overloaded for %d of %d ticks.\n",
194 num_overloaded_ticks_, requests_per_tick_.size()); 200 num_overloaded_ticks_, requests_per_tick_.size());
195 VerboseOut("Got maximum of %d requests in a tick.\n\n", 201 VerboseOut("Got maximum of %d requests in a tick.\n\n",
196 max_experienced_queries_per_tick_); 202 max_experienced_queries_per_tick_);
197 203
198 VerboseOut("Traffic graph:\n\n"); 204 VerboseOut("Traffic graph:\n\n");
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 TimeTicks now_; 280 TimeTicks now_;
275 TimeTicks start_downtime_; // Can be 0 to say "no downtime". 281 TimeTicks start_downtime_; // Can be 0 to say "no downtime".
276 TimeTicks end_downtime_; 282 TimeTicks end_downtime_;
277 const int max_queries_per_tick_; 283 const int max_queries_per_tick_;
278 const double request_drop_ratio_; // Ratio of requests to 503 when failing. 284 const double request_drop_ratio_; // Ratio of requests to 503 when failing.
279 int num_overloaded_ticks_remaining_; 285 int num_overloaded_ticks_remaining_;
280 int num_current_tick_queries_; 286 int num_current_tick_queries_;
281 int num_overloaded_ticks_; 287 int num_overloaded_ticks_;
282 int max_experienced_queries_per_tick_; 288 int max_experienced_queries_per_tick_;
283 std::vector<int> requests_per_tick_; 289 std::vector<int> requests_per_tick_;
290 TestURLRequest mock_request_;
284 291
285 DISALLOW_COPY_AND_ASSIGN(Server); 292 DISALLOW_COPY_AND_ASSIGN(Server);
286 }; 293 };
287 294
288 class TestingURLRequestThrottlerManager : public URLRequestThrottlerManager {
289 public:
290 TestingURLRequestThrottlerManager() : URLRequestThrottlerManager() {
291 }
292 };
293
294 // Mock throttler entry used by Requester class. 295 // Mock throttler entry used by Requester class.
295 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { 296 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry {
296 public: 297 public:
297 explicit MockURLRequestThrottlerEntry( 298 explicit MockURLRequestThrottlerEntry(
298 URLRequestThrottlerManager* manager) 299 URLRequestThrottlerManager* manager)
299 : URLRequestThrottlerEntry(manager, ""), 300 : URLRequestThrottlerEntry(manager, ""),
300 mock_backoff_entry_(&backoff_policy_) { 301 mock_backoff_entry_(&backoff_policy_) {
301 } 302 }
302 303
303 virtual const BackoffEntry* GetBackoffEntry() const OVERRIDE { 304 virtual const BackoffEntry* GetBackoffEntry() const OVERRIDE {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 TimeDelta current_jitter = TimeDelta::FromMilliseconds( 421 TimeDelta current_jitter = TimeDelta::FromMilliseconds(
421 request_jitter_.InMilliseconds() * base::RandDouble()); 422 request_jitter_.InMilliseconds() * base::RandDouble());
422 if (base::RandInt(0, 1)) { 423 if (base::RandInt(0, 1)) {
423 effective_delay -= current_jitter; 424 effective_delay -= current_jitter;
424 } else { 425 } else {
425 effective_delay += current_jitter; 426 effective_delay += current_jitter;
426 } 427 }
427 428
428 if (throttler_entry_->fake_now() - time_of_last_attempt_ > 429 if (throttler_entry_->fake_now() - time_of_last_attempt_ >
429 effective_delay) { 430 effective_delay) {
430 if (!throttler_entry_->ShouldRejectRequest(0)) { 431 if (!throttler_entry_->ShouldRejectRequest(server_->mock_request())) {
431 int status_code = server_->HandleRequest(); 432 int status_code = server_->HandleRequest();
432 MockURLRequestThrottlerHeaderAdapter response_headers(status_code); 433 MockURLRequestThrottlerHeaderAdapter response_headers(status_code);
433 throttler_entry_->UpdateWithResponse("", &response_headers); 434 throttler_entry_->UpdateWithResponse("", &response_headers);
434 435
435 if (status_code == 200) { 436 if (status_code == 200) {
436 if (results_) 437 if (results_)
437 results_->AddSuccess(); 438 results_->AddSuccess();
438 439
439 if (last_attempt_was_failure_) { 440 if (last_attempt_was_failure_) {
440 last_downtime_duration_ = 441 last_downtime_duration_ =
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 DISALLOW_COPY_AND_ASSIGN(Requester); 487 DISALLOW_COPY_AND_ASSIGN(Requester);
487 }; 488 };
488 489
489 void SimulateAttack(Server* server, 490 void SimulateAttack(Server* server,
490 RequesterResults* attacker_results, 491 RequesterResults* attacker_results,
491 RequesterResults* client_results, 492 RequesterResults* client_results,
492 bool enable_throttling) { 493 bool enable_throttling) {
493 const size_t kNumAttackers = 50; 494 const size_t kNumAttackers = 50;
494 const size_t kNumClients = 50; 495 const size_t kNumClients = 50;
495 DiscreteTimeSimulation simulation; 496 DiscreteTimeSimulation simulation;
496 TestingURLRequestThrottlerManager manager; 497 URLRequestThrottlerManager manager;
497 ScopedVector<Requester> requesters; 498 ScopedVector<Requester> requesters;
498 for (size_t i = 0; i < kNumAttackers; ++i) { 499 for (size_t i = 0; i < kNumAttackers; ++i) {
499 // Use a tiny time_between_requests so the attackers will ping the 500 // Use a tiny time_between_requests so the attackers will ping the
500 // server at every tick of the simulation. 501 // server at every tick of the simulation.
501 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( 502 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry(
502 new MockURLRequestThrottlerEntry(&manager)); 503 new MockURLRequestThrottlerEntry(&manager));
503 if (!enable_throttling) 504 if (!enable_throttling)
504 throttler_entry->DisableBackoffThrottling(); 505 throttler_entry->DisableBackoffThrottling();
505 506
506 Requester* attacker = new Requester(throttler_entry.get(), 507 Requester* attacker = new Requester(throttler_entry.get(),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 double SimulateDowntime(const TimeDelta& duration, 590 double SimulateDowntime(const TimeDelta& duration,
590 const TimeDelta& average_client_interval, 591 const TimeDelta& average_client_interval,
591 bool enable_throttling) { 592 bool enable_throttling) {
592 TimeDelta time_between_ticks = duration / 200; 593 TimeDelta time_between_ticks = duration / 200;
593 TimeTicks start_downtime = TimeTicks() + (duration / 2); 594 TimeTicks start_downtime = TimeTicks() + (duration / 2);
594 595
595 // A server that never rejects requests, but will go down for maintenance. 596 // A server that never rejects requests, but will go down for maintenance.
596 Server server(std::numeric_limits<int>::max(), 1.0); 597 Server server(std::numeric_limits<int>::max(), 1.0);
597 server.SetDowntime(start_downtime, duration); 598 server.SetDowntime(start_downtime, duration);
598 599
599 TestingURLRequestThrottlerManager manager; 600 URLRequestThrottlerManager manager;
600 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( 601 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry(
601 new MockURLRequestThrottlerEntry(&manager)); 602 new MockURLRequestThrottlerEntry(&manager));
602 if (!enable_throttling) 603 if (!enable_throttling)
603 throttler_entry->DisableBackoffThrottling(); 604 throttler_entry->DisableBackoffThrottling();
604 605
605 Requester requester( 606 Requester requester(
606 throttler_entry.get(), average_client_interval, &server, NULL); 607 throttler_entry.get(), average_client_interval, &server, NULL);
607 requester.SetStartupJitter(duration / 3); 608 requester.SetStartupJitter(duration / 3);
608 requester.SetRequestJitter(average_client_interval); 609 requester.SetRequestJitter(average_client_interval);
609 610
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 trials[i].PrintTrialDescription(); 746 trials[i].PrintTrialDescription();
746 trials[i].stats.ReportTrialResult(increase_ratio); 747 trials[i].stats.ReportTrialResult(increase_ratio);
747 } 748 }
748 749
749 VerboseOut("Average increase ratio was %.4f\n", average_increase_ratio); 750 VerboseOut("Average increase ratio was %.4f\n", average_increase_ratio);
750 VerboseOut("Maximum increase ratio was %.4f\n", max_increase_ratio); 751 VerboseOut("Maximum increase ratio was %.4f\n", max_increase_ratio);
751 } 752 }
752 753
753 } // namespace 754 } // namespace
754 } // namespace net 755 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_throttler_manager.cc ('k') | net/url_request/url_request_throttler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698