Index: chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc |
=================================================================== |
--- chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc (revision 0) |
+++ chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc (revision 0) |
@@ -0,0 +1,353 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/command_line.h" |
+#include "base/message_loop_proxy.h" |
+#include "base/ref_counted.h" |
+#include "base/thread.h" |
+#include "base/waitable_event.h" |
+#include "chrome/common/net/url_fetcher_protect.h" |
+#include "chrome/common/net/url_request_context_getter.h" |
+#include "chrome/service/service_process.h" |
+#include "chrome/service/cloud_print/cloud_print_url_fetcher.h" |
+#include "googleurl/src/gurl.h" |
+#include "net/test/test_server.h" |
+#include "net/url_request/url_request_unittest.h" |
+#include "net/url_request/url_request_status.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using base::Time; |
+using base::TimeDelta; |
+ |
+namespace { |
+ |
+const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); |
+ |
+int g_request_context_getter_instances = 0; |
+class TestURLRequestContextGetter : public URLRequestContextGetter { |
+ public: |
+ explicit TestURLRequestContextGetter( |
+ base::MessageLoopProxy* io_message_loop_proxy) |
+ : io_message_loop_proxy_(io_message_loop_proxy) { |
+ g_request_context_getter_instances++; |
+ } |
+ virtual URLRequestContext* GetURLRequestContext() { |
+ if (!context_) |
+ context_ = new TestURLRequestContext(); |
+ return context_; |
+ } |
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const { |
+ return io_message_loop_proxy_; |
+ } |
+ |
+ protected: |
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
+ |
+ private: |
+ ~TestURLRequestContextGetter() { |
+ g_request_context_getter_instances--; |
+ } |
+ |
+ scoped_refptr<URLRequestContext> context_; |
+}; |
+ |
+class TestCloudPrintURLFetcher : public CloudPrintURLFetcher { |
+ public: |
+ explicit TestCloudPrintURLFetcher( |
+ base::MessageLoopProxy* io_message_loop_proxy) |
+ : io_message_loop_proxy_(io_message_loop_proxy) { |
+ } |
+ |
+ virtual URLRequestContextGetter* GetRequestContextGetter() { |
+ return new TestURLRequestContextGetter(io_message_loop_proxy_.get()); |
+ } |
+ private: |
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
+}; |
+ |
+class CloudPrintURLFetcherTest : public testing::Test, |
+ public CloudPrintURLFetcher::Delegate { |
+ public: |
+ CloudPrintURLFetcherTest() : fetcher_(NULL) { } |
+ |
+ // Creates a URLFetcher, using the program's main thread to do IO. |
+ virtual void CreateFetcher(const GURL& url, const std::string& retry_policy); |
+ |
+ // CloudPrintURLFetcher::Delegate |
+ virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const URLRequestStatus& status, |
+ int response_code, |
+ const ResponseCookies& cookies, |
+ const std::string& data); |
+ |
+ virtual void OnRequestAuthError() { |
+ ADD_FAILURE(); |
+ } |
+ |
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy() { |
+ return io_message_loop_proxy_; |
+ } |
+ |
+ protected: |
+ virtual void SetUp() { |
+ testing::Test::SetUp(); |
+ |
+ io_message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread(); |
+ } |
+ |
+ virtual void TearDown() { |
+ fetcher_ = NULL; |
+ // Deleting the fetcher causes a task to be posted to the IO thread to |
+ // release references to the URLRequestContextGetter. We need to run all |
+ // pending tasks to execute that (this is the IO thread). |
+ MessageLoop::current()->RunAllPending(); |
+ EXPECT_EQ(0, g_request_context_getter_instances); |
+ } |
+ |
+ // URLFetcher is designed to run on the main UI thread, but in our tests |
+ // we assume that the current thread is the IO thread where the URLFetcher |
+ // dispatches its requests to. When we wish to simulate being used from |
+ // a UI thread, we dispatch a worker thread to do so. |
+ MessageLoopForIO io_loop_; |
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
+ std::string retry_policy_; |
+ Time start_time_; |
+ scoped_refptr<CloudPrintURLFetcher> fetcher_; |
+}; |
+ |
+class CloudPrintURLFetcherBasicTest : public CloudPrintURLFetcherTest { |
+ public: |
+ CloudPrintURLFetcherBasicTest() |
+ : handle_raw_response_(false), handle_raw_data_(false) { } |
+ // CloudPrintURLFetcher::Delegate |
+ virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const URLRequestStatus& status, |
+ int response_code, |
+ const ResponseCookies& cookies, |
+ const std::string& data); |
+ |
+ virtual CloudPrintURLFetcher::ResponseAction HandleRawData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data); |
+ |
+ virtual CloudPrintURLFetcher::ResponseAction HandleJSONData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ DictionaryValue* json_data, |
+ bool succeeded); |
+ |
+ void SetHandleRawResponse(bool handle_raw_response) { |
+ handle_raw_response_ = handle_raw_response; |
+ } |
+ void SetHandleRawData(bool handle_raw_data) { |
+ handle_raw_data_ = handle_raw_data; |
+ } |
+ private: |
+ bool handle_raw_response_; |
+ bool handle_raw_data_; |
+}; |
+ |
+// Version of CloudPrintURLFetcherTest that tests overload protection. |
+class CloudPrintURLFetcherOverloadTest : public CloudPrintURLFetcherTest { |
+ public: |
+ CloudPrintURLFetcherOverloadTest() : response_count_(0) { |
+ } |
+ |
+ // CloudPrintURLFetcher::Delegate |
+ virtual CloudPrintURLFetcher::ResponseAction HandleRawData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data); |
+ |
+ private: |
+ int response_count_; |
+}; |
+ |
+// Version of CloudPrintURLFetcherTest that tests backoff protection. |
+class CloudPrintURLFetcherRetryBackoffTest : public CloudPrintURLFetcherTest { |
+ public: |
+ CloudPrintURLFetcherRetryBackoffTest() : response_count_(0) { |
+ } |
+ |
+ // CloudPrintURLFetcher::Delegate |
+ virtual CloudPrintURLFetcher::ResponseAction HandleRawData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data); |
+ |
+ virtual void OnRequestGiveUp(); |
+ |
+ private: |
+ int response_count_; |
+}; |
+ |
+ |
+void CloudPrintURLFetcherTest::CreateFetcher(const GURL& url, |
+ const std::string& retry_policy) { |
+ fetcher_ = new TestCloudPrintURLFetcher(io_message_loop_proxy()); |
+ retry_policy_ = retry_policy; |
+ start_time_ = Time::Now(); |
+ fetcher_->StartGetRequest(url, this, "", retry_policy_); |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherTest::HandleRawResponse( |
+ 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()); |
+ return CloudPrintURLFetcher::CONTINUE_PROCESSING; |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherBasicTest::HandleRawResponse( |
+ 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()); |
+ |
+ if (handle_raw_response_) { |
+ // If the current message loop is not the IO loop, it will be shut down when |
+ // the main loop returns and this thread subsequently goes out of scope. |
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+ return CloudPrintURLFetcher::STOP_PROCESSING; |
+ } |
+ return CloudPrintURLFetcher::CONTINUE_PROCESSING; |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherBasicTest::HandleRawData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data) { |
+ // We should never get here if we returned true in HandleRawResponse |
+ EXPECT_FALSE(handle_raw_response_); |
+ if (handle_raw_data_) { |
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+ return CloudPrintURLFetcher::STOP_PROCESSING; |
+ } |
+ return CloudPrintURLFetcher::CONTINUE_PROCESSING; |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherBasicTest::HandleJSONData( |
+ const URLFetcher* source, |
+ const GURL& url, |
+ DictionaryValue* json_data, |
+ bool succeeded) { |
+ // We should never get here if we returned true in one of the above methods. |
+ EXPECT_FALSE(handle_raw_response_); |
+ EXPECT_FALSE(handle_raw_data_); |
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+ return CloudPrintURLFetcher::STOP_PROCESSING; |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherOverloadTest::HandleRawData(const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data) { |
+ const TimeDelta one_second = TimeDelta::FromMilliseconds(1000); |
+ response_count_++; |
+ if (response_count_ < 20) { |
+ fetcher_->StartGetRequest(url, this, "", retry_policy_); |
+ } 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); |
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+ } |
+ return CloudPrintURLFetcher::STOP_PROCESSING; |
+} |
+ |
+CloudPrintURLFetcher::ResponseAction |
+CloudPrintURLFetcherRetryBackoffTest::HandleRawData(const URLFetcher* source, |
+ const GURL& url, |
+ const std::string& data) { |
+ response_count_++; |
+ // First attempt + 11 retries = 12 total responses. |
+ EXPECT_LE(response_count_, 12); |
+ return CloudPrintURLFetcher::RETRY_REQUEST; |
+} |
+ |
+void CloudPrintURLFetcherRetryBackoffTest::OnRequestGiveUp() { |
+ const TimeDelta one_second = TimeDelta::FromMilliseconds(1000); |
+ // It takes more than 1 second to finish all 11 requests. |
+ EXPECT_TRUE(Time::Now() - start_time_ >= one_second); |
+ io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+} |
+ |
+TEST_F(CloudPrintURLFetcherBasicTest, HandleRawResponse) { |
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); |
+ ASSERT_TRUE(test_server.Start()); |
+ SetHandleRawResponse(true); |
+ |
+ CreateFetcher(test_server.GetURL("echo"), "DummyRetryPolicy"); |
+ MessageLoop::current()->Run(); |
+} |
+ |
+TEST_F(CloudPrintURLFetcherBasicTest, HandleRawData) { |
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); |
+ ASSERT_TRUE(test_server.Start()); |
+ |
+ SetHandleRawData(true); |
+ CreateFetcher(test_server.GetURL("echo"), "DummyRetryPolicy"); |
+ MessageLoop::current()->Run(); |
+} |
+ |
+TEST_F(CloudPrintURLFetcherOverloadTest, Protect) { |
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); |
+ ASSERT_TRUE(test_server.Start()); |
+ |
+ GURL url(test_server.GetURL("defaultresponse")); |
+ |
+ // Registers an entry for test url. It only allows 3 requests to be sent |
+ // in 200 milliseconds. |
+ std::string retry_policy = "OverloadTestPolicy"; |
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); |
+ URLFetcherProtectEntry* entry = |
+ new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256); |
+ manager->Register(retry_policy, entry); |
+ |
+ CreateFetcher(url, retry_policy); |
+ |
+ MessageLoop::current()->Run(); |
+} |
+ |
+TEST_F(CloudPrintURLFetcherRetryBackoffTest, GiveUp) { |
+ net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)); |
+ ASSERT_TRUE(test_server.Start()); |
+ |
+ GURL url(test_server.GetURL("defaultresponse")); |
+ |
+ // 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. |
+ std::string retry_policy = "BackoffTestPolicy"; |
+ URLFetcherProtectManager* manager = URLFetcherProtectManager::GetInstance(); |
+ URLFetcherProtectEntry* entry = |
+ new URLFetcherProtectEntry(200, 3, 11, 1, 2.0, 0, 256); |
+ manager->Register(retry_policy, entry); |
+ |
+ CreateFetcher(url, retry_policy); |
+ |
+ MessageLoop::current()->Run(); |
+} |
+ |
+} // namespace. |
Property changes on: chrome\service\cloud_print\cloud_print_url_fetcher_unittest.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |