summaryrefslogtreecommitdiffstats
path: root/chrome/browser/url_fetcher_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/url_fetcher_unittest.cc')
-rw-r--r--chrome/browser/url_fetcher_unittest.cc359
1 files changed, 359 insertions, 0 deletions
diff --git a/chrome/browser/url_fetcher_unittest.cc b/chrome/browser/url_fetcher_unittest.cc
new file mode 100644
index 0000000..2a3b034
--- /dev/null
+++ b/chrome/browser/url_fetcher_unittest.cc
@@ -0,0 +1,359 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "base/thread.h"
+#include "base/time.h"
+#include "chrome/browser/url_fetcher.h"
+#include "chrome/browser/url_fetcher_protect.h"
+#include "net/url_request/url_request_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+ const wchar_t kDocRoot[] = L"chrome/test/data";
+ const char kHostName[] = "127.0.0.1";
+ const int kBadHTTPSPort = 9666;
+
+ class URLFetcherTest : public testing::Test, public URLFetcher::Delegate {
+ public:
+ URLFetcherTest() : main_loop_(MessageLoop::current()), fetcher_(NULL) { }
+
+ // Creates a URLFetcher, using the program's main thread to do IO.
+ virtual void CreateFetcher(const GURL& url);
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ protected:
+ MessageLoop* main_loop_;
+ URLFetcher* fetcher_;
+ };
+
+ // Version of URLFetcherTest that does a POST instead
+ class URLFetcherPostTest : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ };
+
+ // Version of URLFetcherTest that tests headers.
+ class URLFetcherHeadersTest : public URLFetcherTest {
+ public:
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ };
+
+ // Version of URLFetcherTest that tests overload proctection.
+ class URLFetcherProtectTest : public URLFetcherTest {
+ public:
+ virtual void CreateFetcher(const GURL& url);
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ private:
+ Time start_time_;
+ };
+
+ // Version of URLFetcherTest that tests bad HTTPS requests.
+ class URLFetcherBadHTTPSTest : public URLFetcherTest {
+ public:
+ URLFetcherBadHTTPSTest();
+
+ // URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+
+ protected:
+ std::wstring GetExpiredCertPath();
+
+ private:
+ std::wstring cert_dir_;
+ };
+
+ // Wrapper that lets us call CreateFetcher() on a thread of our choice. We
+ // could make URLFetcherTest refcounted and use PostTask(FROM_HERE.. ) to call
+ // CreateFetcher() directly, but the ownership of the URLFetcherTest is a bit
+ // confusing in that case because GTest doesn't know about the refcounting.
+ // It's less confusing to just do it this way.
+ class FetcherWrapperTask : public Task {
+ public:
+ FetcherWrapperTask(URLFetcherTest* test, const GURL& url)
+ : test_(test), url_(url) { }
+ virtual void Run();
+
+ private:
+ URLFetcherTest* test_;
+ GURL url_;
+ };
+
+ void URLFetcherTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ fetcher_->set_request_context(new TestURLRequestContext());
+ fetcher_->set_io_loop(main_loop_);
+ fetcher_->Start();
+ }
+
+ void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ EXPECT_TRUE(status.is_success());
+ EXPECT_EQ(200, response_code); // HTTP OK
+ EXPECT_FALSE(data.empty());
+
+ delete fetcher_; // Have to delete this here and not in the destructor,
+ // because the destructor won't necessarily run on the
+ // same thread that CreateFetcher() did.
+
+ main_loop_->Quit();
+ // If MessageLoop::current() != main_loop_, it will be shut down when the
+ // main loop returns and this thread subsequently goes out of scope.
+ }
+
+
+ void FetcherWrapperTask::Run() {
+ test_->CreateFetcher(url_);
+ }
+
+ void URLFetcherPostTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::POST, this);
+ fetcher_->set_request_context(new TestURLRequestContext());
+ fetcher_->set_io_loop(main_loop_);
+ fetcher_->set_upload_data("application/x-www-form-urlencoded",
+ "bobsyeruncle");
+ fetcher_->Start();
+ }
+
+ void URLFetcherPostTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ EXPECT_EQ(std::string("bobsyeruncle"), data);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+ }
+
+ void URLFetcherHeadersTest::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ std::string header;
+ EXPECT_TRUE(source->response_headers()->GetNormalizedHeader("cache-control",
+ &header));
+ EXPECT_EQ("private", header);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+ }
+
+ void URLFetcherProtectTest::CreateFetcher(const GURL& url) {
+ fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
+ fetcher_->set_request_context(new TestURLRequestContext());
+ fetcher_->set_io_loop(main_loop_);
+ start_time_ = Time::Now();
+ fetcher_->Start();
+ }
+
+ void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
+ if (response_code >= 500) {
+ // Now running ServerUnavailable test.
+ // It takes more than 1 second to finish all 11 requests.
+ EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
+ EXPECT_TRUE(status.is_success());
+ EXPECT_FALSE(data.empty());
+ delete fetcher_;
+ main_loop_->Quit();
+ } else {
+ // Now running Overload test.
+ static int count = 0;
+ count++;
+ if (count < 20) {
+ fetcher_->Start();
+ } else {
+ // We have already sent 20 requests continuously. And we expect that
+ // it takes more than 1 second due to the overload pretection settings.
+ EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
+ URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
+ cookies, data);
+ }
+ }
+ }
+
+ URLFetcherBadHTTPSTest::URLFetcherBadHTTPSTest() {
+ PathService::Get(base::DIR_SOURCE_ROOT, &cert_dir_);
+ cert_dir_ += L"/chrome/test/data/ssl/certs/";
+ std::replace(cert_dir_.begin(), cert_dir_.end(),
+ L'/', file_util::kPathSeparator);
+ }
+
+ // The "server certificate expired" error should result in automatic
+ // cancellation of the request by
+ // URLRequest::Delegate::OnSSLCertificateError.
+ void URLFetcherBadHTTPSTest::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ // This part is different from URLFetcherTest::OnURLFetchComplete
+ // because this test expects the request to be cancelled.
+ EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+ EXPECT_EQ(net::ERR_ABORTED, status.os_error());
+ EXPECT_EQ(-1, response_code);
+ EXPECT_TRUE(cookies.empty());
+ EXPECT_TRUE(data.empty());
+
+ // The rest is the same as URLFetcherTest::OnURLFetchComplete.
+ delete fetcher_;
+ main_loop_->Quit();
+ }
+
+ std::wstring URLFetcherBadHTTPSTest::GetExpiredCertPath() {
+ std::wstring path(cert_dir_);
+ file_util::AppendToPath(&path, L"expired_cert.pem");
+ return path;
+ }
+};
+
+TEST_F(URLFetcherTest, SameThreadsTest) {
+ // Create the fetcher on the main thread. Since IO will happen on the main
+ // thread, this will test URLFetcher's ability to do everything on one
+ // thread.
+ TestServer server(kDocRoot);
+
+ CreateFetcher(GURL(server.TestServerPage("defaultresponse")));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherTest, DifferentThreadsTest) {
+ TestServer server(kDocRoot);
+ // Create a separate thread that will create the URLFetcher. The current
+ // (main) thread will do the IO, and when the fetch is complete it will
+ // terminate the main thread's message loop; then the other thread's
+ // message loop will be shut down automatically as the thread goes out of
+ // scope.
+ Thread t("URLFetcher test thread");
+ t.Start();
+ t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this,
+ GURL(server.TestServerPage("defaultresponse"))));
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherPostTest, Basic) {
+ TestServer server(kDocRoot);
+ CreateFetcher(GURL(server.TestServerPage("echo")));
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherHeadersTest, Headers) {
+ TestServer server(L"net/data/url_request_unittest");
+ CreateFetcher(GURL(server.TestServerPage("files/with-headers.html")));
+ MessageLoop::current()->Run();
+ // The actual tests are in the URLFetcherHeadersTest fixture.
+}
+
+TEST_F(URLFetcherProtectTest, Overload) {
+ TestServer server(kDocRoot);
+ GURL url = GURL(server.TestServerPage("defaultresponse"));
+
+ // Registers an entry for test url. It only allows 3 requests to be sent
+ // in 200 milliseconds.
+ ProtectManager* manager = ProtectManager::GetInstance();
+ ProtectEntry* entry = new ProtectEntry(200, 3, 11, 1, 2.0, 0, 256);
+ manager->Register(url.host(), entry);
+
+ CreateFetcher(url);
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherProtectTest, ServerUnavailable) {
+ TestServer server(L"chrome/test/data");
+ GURL url = GURL(server.TestServerPage("files/server-unavailable.html"));
+
+ // Registers an entry for test url. The backoff time is calculated by:
+ // new_backoff = 2.0 * old_backoff + 0
+ // and maximum backoff time is 256 milliseconds.
+ // Maximum retries allowed is set to 11.
+ ProtectManager* manager = ProtectManager::GetInstance();
+ ProtectEntry* entry = new ProtectEntry(200, 3, 11, 1, 2.0, 0, 256);
+ manager->Register(url.host(), entry);
+
+ CreateFetcher(url);
+
+ MessageLoop::current()->Run();
+}
+
+TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
+ HTTPSTestServer server(kHostName, kBadHTTPSPort,
+ kDocRoot, GetExpiredCertPath());
+
+ CreateFetcher(GURL(server.TestServerPage("defaultresponse")));
+
+ MessageLoop::current()->Run();
+}