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

Side by Side Diff: chrome/common/net/url_fetcher_unittest.cc

Issue 4194001: Implement exponential back-off mechanism and enforce it at the URLRequestHttpJob level. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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) 2010 The Chromium Authors. All rights reserved. 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 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 "base/message_loop_proxy.h" 5 #include "base/message_loop_proxy.h"
6 #include "base/thread.h" 6 #include "base/thread.h"
7 #include "base/waitable_event.h" 7 #include "base/waitable_event.h"
8 #include "chrome/common/chrome_plugin_lib.h" 8 #include "chrome/common/chrome_plugin_lib.h"
9 #include "chrome/common/net/url_fetcher.h" 9 #include "chrome/common/net/url_fetcher.h"
10 #include "chrome/common/net/url_fetcher_protect.h"
11 #include "chrome/common/net/url_request_context_getter.h" 10 #include "chrome/common/net/url_request_context_getter.h"
12 #include "net/http/http_response_headers.h" 11 #include "net/http/http_response_headers.h"
12 #include "net/request_throttler/request_throttler_manager.h"
13 #include "net/test/test_server.h"
13 #include "net/url_request/url_request_unittest.h" 14 #include "net/url_request/url_request_unittest.h"
14 #include "net/test/test_server.h"
15 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
16 16
17 using base::Time; 17 using base::Time;
18 using base::TimeDelta; 18 using base::TimeDelta;
19 19
20 // TODO(eroman): Add a regression test for http://crbug.com/40505. 20 // TODO(eroman): Add a regression test for http://crbug.com/40505.
21 21
22 namespace { 22 namespace {
23 23
24 const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); 24 const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 EXPECT_EQ("private", header); 291 EXPECT_EQ("private", header);
292 URLFetcherTest::OnURLFetchComplete(source, url, status, response_code, 292 URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
293 cookies, data); 293 cookies, data);
294 } 294 }
295 295
296 void URLFetcherProtectTest::CreateFetcher(const GURL& url) { 296 void URLFetcherProtectTest::CreateFetcher(const GURL& url) {
297 fetcher_ = new URLFetcher(url, URLFetcher::GET, this); 297 fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
298 fetcher_->set_request_context(new TestURLRequestContextGetter( 298 fetcher_->set_request_context(new TestURLRequestContextGetter(
299 io_message_loop_proxy())); 299 io_message_loop_proxy()));
300 start_time_ = Time::Now(); 300 start_time_ = Time::Now();
301 fetcher_->set_max_retries(11);
301 fetcher_->Start(); 302 fetcher_->Start();
302 } 303 }
303 304
304 void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source, 305 void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source,
305 const GURL& url, 306 const GURL& url,
306 const URLRequestStatus& status, 307 const URLRequestStatus& status,
307 int response_code, 308 int response_code,
308 const ResponseCookies& cookies, 309 const ResponseCookies& cookies,
309 const std::string& data) { 310 const std::string& data) {
310 const TimeDelta one_second = TimeDelta::FromMilliseconds(1000); 311 const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
311 if (response_code >= 500) { 312 if (response_code >= 500) {
312 // Now running ServerUnavailable test. 313 // Now running ServerUnavailable test.
313 // It takes more than 1 second to finish all 11 requests. 314 // It takes more than 1 second to finish all 11 requests.
314 EXPECT_TRUE(Time::Now() - start_time_ >= one_second); 315 EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
315 EXPECT_TRUE(status.is_success()); 316 EXPECT_TRUE(status.is_success());
316 EXPECT_FALSE(data.empty()); 317 EXPECT_FALSE(data.empty());
317 delete fetcher_; 318 delete fetcher_;
318 io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 319 io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
319 } else { 320 } else {
320 // Now running Overload test. 321 // Now running Overload test.
321 static int count = 0; 322 static int count = 0;
322 count++; 323 count++;
323 if (count < 20) { 324 if (count < 20) {
324 fetcher_->Start(); 325 fetcher_->Start();
325 } else { 326 } else {
326 // We have already sent 20 requests continuously. And we expect that 327 // We have already sent 20 requests continuously. And we expect that
327 // it takes more than 1 second due to the overload pretection settings. 328 // it takes more than 1 second due to the overload protection settings.
328 EXPECT_TRUE(Time::Now() - start_time_ >= one_second); 329 EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
329 URLFetcherTest::OnURLFetchComplete(source, url, status, response_code, 330 URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
330 cookies, data); 331 cookies, data);
331 } 332 }
332 } 333 }
333 } 334 }
334 335
335 void URLFetcherProtectTestPassedThrough::CreateFetcher(const GURL& url) { 336 void URLFetcherProtectTestPassedThrough::CreateFetcher(const GURL& url) {
336 fetcher_ = new URLFetcher(url, URLFetcher::GET, this); 337 fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
337 fetcher_->set_request_context(new TestURLRequestContextGetter( 338 fetcher_->set_request_context(new TestURLRequestContextGetter(
338 io_message_loop_proxy())); 339 io_message_loop_proxy()));
339 fetcher_->set_automatically_retry_on_5xx(false); 340 fetcher_->set_automatically_retry_on_5xx(false);
340 start_time_ = Time::Now(); 341 start_time_ = Time::Now();
342 fetcher_->set_max_retries(11);
341 fetcher_->Start(); 343 fetcher_->Start();
342 } 344 }
343 345
344 void URLFetcherProtectTestPassedThrough::OnURLFetchComplete( 346 void URLFetcherProtectTestPassedThrough::OnURLFetchComplete(
345 const URLFetcher* source, 347 const URLFetcher* source,
346 const GURL& url, 348 const GURL& url,
347 const URLRequestStatus& status, 349 const URLRequestStatus& status,
348 int response_code, 350 int response_code,
349 const ResponseCookies& cookies, 351 const ResponseCookies& cookies,
350 const std::string& data) { 352 const std::string& data) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 // The rest is the same as URLFetcherTest::OnURLFetchComplete. 400 // The rest is the same as URLFetcherTest::OnURLFetchComplete.
399 delete fetcher_; 401 delete fetcher_;
400 io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 402 io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
401 } 403 }
402 404
403 void URLFetcherCancelTest::CreateFetcher(const GURL& url) { 405 void URLFetcherCancelTest::CreateFetcher(const GURL& url) {
404 fetcher_ = new URLFetcher(url, URLFetcher::GET, this); 406 fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
405 CancelTestURLRequestContextGetter* context_getter = 407 CancelTestURLRequestContextGetter* context_getter =
406 new CancelTestURLRequestContextGetter(io_message_loop_proxy()); 408 new CancelTestURLRequestContextGetter(io_message_loop_proxy());
407 fetcher_->set_request_context(context_getter); 409 fetcher_->set_request_context(context_getter);
410 fetcher_->set_max_retries(2);
408 fetcher_->Start(); 411 fetcher_->Start();
409 // We need to wait for the creation of the URLRequestContext, since we 412 // We need to wait for the creation of the URLRequestContext, since we
410 // rely on it being destroyed as a signal to end the test. 413 // rely on it being destroyed as a signal to end the test.
411 context_getter->WaitForContextCreation(); 414 context_getter->WaitForContextCreation();
412 CancelRequest(); 415 CancelRequest();
413 } 416 }
414 417
415 void URLFetcherCancelTest::OnURLFetchComplete(const URLFetcher* source, 418 void URLFetcherCancelTest::OnURLFetchComplete(const URLFetcher* source,
416 const GURL& url, 419 const GURL& url,
417 const URLRequestStatus& status, 420 const URLRequestStatus& status,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 482 }
480 483
481 TEST_F(URLFetcherProtectTest, Overload) { 484 TEST_F(URLFetcherProtectTest, Overload) {
482 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); 485 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
483 ASSERT_TRUE(test_server.Start()); 486 ASSERT_TRUE(test_server.Start());
484 487
485 GURL url(test_server.GetURL("defaultresponse")); 488 GURL url(test_server.GetURL("defaultresponse"));
486 489
487 // Registers an entry for test url. It only allows 3 requests to be sent 490 // Registers an entry for test url. It only allows 3 requests to be sent
488 // in 200 milliseconds. 491 // in 200 milliseconds.
489 URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); 492 scoped_refptr<RequestThrottlerEntry> entry(new RequestThrottlerEntry(
490 URLFetcherProtectEntry* entry = 493 200, 3, 1, 0, 2.0, 0.0, 256));
491 new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256); 494 Singleton<RequestThrottlerManager>::get()->OverrideEntry(url, entry);
492 manager->Register(url.host(), entry);
493 495
494 CreateFetcher(url); 496 CreateFetcher(url);
495 497
496 MessageLoop::current()->Run(); 498 MessageLoop::current()->Run();
499
500 Singleton<RequestThrottlerManager>::get()->EraseEntry(url);
497 } 501 }
498 502
499 TEST_F(URLFetcherProtectTest, ServerUnavailable) { 503 TEST_F(URLFetcherProtectTest, ServerUnavailable) {
500 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); 504 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
501 ASSERT_TRUE(test_server.Start()); 505 ASSERT_TRUE(test_server.Start());
502 506
503 GURL url(test_server.GetURL("files/server-unavailable.html")); 507 GURL url(test_server.GetURL("files/server-unavailable.html"));
504 508
505 // Registers an entry for test url. The backoff time is calculated by: 509 // Registers an entry for test url. The backoff time is calculated by:
506 // new_backoff = 2.0 * old_backoff + 0 510 // new_backoff = 2.0 * old_backoff + 0
507 // and maximum backoff time is 256 milliseconds. 511 // and maximum backoff time is 256 milliseconds.
508 // Maximum retries allowed is set to 11. 512 // Maximum retries allowed is set to 11.
509 URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); 513 scoped_refptr<RequestThrottlerEntry> entry(new RequestThrottlerEntry(
510 URLFetcherProtectEntry* entry = 514 200, 3, 1, 0, 2.0, 0.0, 256));
511 new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256); 515 Singleton<RequestThrottlerManager>::get()->OverrideEntry(url, entry);
512 manager->Register(url.host(), entry);
513 516
514 CreateFetcher(url); 517 CreateFetcher(url);
515 518
516 MessageLoop::current()->Run(); 519 MessageLoop::current()->Run();
520
521 Singleton<RequestThrottlerManager>::get()->EraseEntry(url);
517 } 522 }
518 523
519 TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) { 524 TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) {
520 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); 525 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
521 ASSERT_TRUE(test_server.Start()); 526 ASSERT_TRUE(test_server.Start());
522 527
523 GURL url(test_server.GetURL("files/server-unavailable.html")); 528 GURL url(test_server.GetURL("files/server-unavailable.html"));
524 529
525 // Registers an entry for test url. The backoff time is calculated by: 530 // Registers an entry for test url. The backoff time is calculated by:
526 // new_backoff = 2.0 * old_backoff + 0 531 // new_backoff = 2.0 * old_backoff + 0
527 // and maximum backoff time is 256 milliseconds. 532 // and maximum backoff time is 150000 milliseconds.
528 // Maximum retries allowed is set to 11. 533 // Maximum retries allowed is set to 11.
529 URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); 534 scoped_refptr<RequestThrottlerEntry> entry(new RequestThrottlerEntry(
535 200, 3, 100, 0, 2.0, 0.0, 150000));
530 // Total time if *not* for not doing automatic backoff would be 150s. 536 // Total time if *not* for not doing automatic backoff would be 150s.
531 // In reality it should be "as soon as server responds". 537 // In reality it should be "as soon as server responds".
532 URLFetcherProtectEntry* entry = 538 Singleton<RequestThrottlerManager>::get()->OverrideEntry(url, entry);
533 new URLFetcherProtectEntry(200, 3, 11, 100, 2.0, 0, 150000);
534 manager->Register(url.host(), entry);
535 539
536 CreateFetcher(url); 540 CreateFetcher(url);
537 541
538 MessageLoop::current()->Run(); 542 MessageLoop::current()->Run();
543
544 Singleton<RequestThrottlerManager>::get()->EraseEntry(url);
539 } 545 }
540 546
541
542 TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) { 547 TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
543 net::TestServer test_server(net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE, 548 net::TestServer test_server(net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE,
544 FilePath(kDocRoot)); 549 FilePath(kDocRoot));
545 ASSERT_TRUE(test_server.Start()); 550 ASSERT_TRUE(test_server.Start());
546 551
547 CreateFetcher(test_server.GetURL("defaultresponse")); 552 CreateFetcher(test_server.GetURL("defaultresponse"));
548 MessageLoop::current()->Run(); 553 MessageLoop::current()->Run();
549 } 554 }
550 555
551 TEST_F(URLFetcherCancelTest, ReleasesContext) { 556 TEST_F(URLFetcherCancelTest, ReleasesContext) {
552 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); 557 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
553 ASSERT_TRUE(test_server.Start()); 558 ASSERT_TRUE(test_server.Start());
554 559
555 GURL url(test_server.GetURL("files/server-unavailable.html")); 560 GURL url(test_server.GetURL("files/server-unavailable.html"));
556 561
557 // Registers an entry for test url. The backoff time is calculated by: 562 // Registers an entry for test url. The backoff time is calculated by:
558 // new_backoff = 2.0 * old_backoff + 0 563 // new_backoff = 2.0 * old_backoff + 0
559 // The initial backoff is 2 seconds and maximum backoff is 4 seconds. 564 // The initial backoff is 2 seconds and maximum backoff is 4 seconds.
560 // Maximum retries allowed is set to 2. 565 // Maximum retries allowed is set to 2.
561 URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); 566 scoped_refptr<RequestThrottlerEntry> entry(new RequestThrottlerEntry(
562 URLFetcherProtectEntry* entry = 567 200, 3, 2000, 0, 2.0, 0.0, 4000));
563 new URLFetcherProtectEntry(200, 3, 2, 2000, 2.0, 0, 4000); 568 Singleton<RequestThrottlerManager>::get()->OverrideEntry(url, entry);
564 manager->Register(url.host(), entry);
565 569
566 // Create a separate thread that will create the URLFetcher. The current 570 // Create a separate thread that will create the URLFetcher. The current
567 // (main) thread will do the IO, and when the fetch is complete it will 571 // (main) thread will do the IO, and when the fetch is complete it will
568 // terminate the main thread's message loop; then the other thread's 572 // terminate the main thread's message loop; then the other thread's
569 // message loop will be shut down automatically as the thread goes out of 573 // message loop will be shut down automatically as the thread goes out of
570 // scope. 574 // scope.
571 base::Thread t("URLFetcher test thread"); 575 base::Thread t("URLFetcher test thread");
572 ASSERT_TRUE(t.Start()); 576 ASSERT_TRUE(t.Start());
573 t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url)); 577 t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
574 578
575 MessageLoop::current()->Run(); 579 MessageLoop::current()->Run();
580
581 Singleton<RequestThrottlerManager>::get()->EraseEntry(url);
576 } 582 }
577 583
578 TEST_F(URLFetcherCancelTest, CancelWhileDelayedStartTaskPending) { 584 TEST_F(URLFetcherCancelTest, CancelWhileDelayedStartTaskPending) {
579 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); 585 net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
580 ASSERT_TRUE(test_server.Start()); 586 ASSERT_TRUE(test_server.Start());
581 587
582 GURL url(test_server.GetURL("files/server-unavailable.html")); 588 GURL url(test_server.GetURL("files/server-unavailable.html"));
583 589
584 // Register an entry for test url. 590 // Register an entry for test url.
585 // 591 // Using a sliding window of 4 seconds, and max of 1 request, under a fast
586 // Ideally we would mock URLFetcherProtectEntry to return XXX seconds
587 // in response to entry->UpdateBackoff(SEND).
588 //
589 // Unfortunately this function is time sensitive, so we fudge some numbers
590 // to make it at least somewhat likely to have a non-zero deferred
591 // delay when running.
592 //
593 // Using a sliding window of 2 seconds, and max of 1 request, under a fast
594 // run we expect to have a 4 second delay when posting the Start task. 592 // run we expect to have a 4 second delay when posting the Start task.
595 URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); 593 scoped_refptr<RequestThrottlerEntry> entry(new RequestThrottlerEntry(
596 URLFetcherProtectEntry* entry = 594 4000, 1, 2000, 0, 2.0, 0.0, 4000));
597 new URLFetcherProtectEntry(2000, 1, 2, 2000, 2.0, 0, 4000); 595 Singleton<RequestThrottlerManager>::get()->OverrideEntry(url, entry);
598 EXPECT_EQ(0, entry->UpdateBackoff(URLFetcherProtectEntry::SEND)); 596 // Fake that a request has just started.
599 entry->UpdateBackoff(URLFetcherProtectEntry::SEND); // Returns about 2000. 597 entry->GetRecommendedDelayForNextRequest();
600 manager->Register(url.host(), entry);
601 598
602 // The next request we try to send will be delayed by ~4 seconds. 599 // The next request we try to send will be delayed by ~4 seconds.
603 // The slower the test runs, the less the delay will be (since it takes the 600 // The slower the test runs, the less the delay will be (since it takes the
604 // time difference from now). 601 // time difference from now).
605 602
606 base::Thread t("URLFetcher test thread"); 603 base::Thread t("URLFetcher test thread");
607 ASSERT_TRUE(t.Start()); 604 ASSERT_TRUE(t.Start());
608 t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url)); 605 t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
609 606
610 MessageLoop::current()->Run(); 607 MessageLoop::current()->Run();
608
609 Singleton<RequestThrottlerManager>::get()->EraseEntry(url);
611 } 610 }
612 611
613 } // namespace. 612 } // namespace.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698