| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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. |
| OLD | NEW |