Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / chrome / service / cloud_print / cloud_print_url_fetcher_unittest.cc
blob3f1a116343001778651684f7ec074472b3acc858
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
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/message_loop/message_loop_proxy.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread.h"
10 #include "base/values.h"
11 #include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
12 #include "chrome/service/service_process.h"
13 #include "net/test/spawned_test_server/spawned_test_server.h"
14 #include "net/url_request/url_request_context_getter.h"
15 #include "net/url_request/url_request_status.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "net/url_request/url_request_throttler_manager.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
21 using base::Time;
22 using base::TimeDelta;
24 namespace cloud_print {
26 const base::FilePath::CharType kDocRoot[] =
27 FILE_PATH_LITERAL("chrome/test/data");
29 int g_request_context_getter_instances = 0;
30 class TrackingTestURLRequestContextGetter
31 : public net::TestURLRequestContextGetter {
32 public:
33 explicit TrackingTestURLRequestContextGetter(
34 base::MessageLoopProxy* io_message_loop_proxy,
35 net::URLRequestThrottlerManager* throttler_manager)
36 : TestURLRequestContextGetter(io_message_loop_proxy),
37 throttler_manager_(throttler_manager) {
38 g_request_context_getter_instances++;
41 virtual net::TestURLRequestContext* GetURLRequestContext() OVERRIDE {
42 if (!context_.get()) {
43 context_.reset(new net::TestURLRequestContext(true));
44 context_->set_throttler_manager(throttler_manager_);
45 context_->Init();
47 return context_.get();
50 protected:
51 virtual ~TrackingTestURLRequestContextGetter() {
52 g_request_context_getter_instances--;
55 private:
56 // Not owned here.
57 net::URLRequestThrottlerManager* throttler_manager_;
58 scoped_ptr<net::TestURLRequestContext> context_;
61 class TestCloudPrintURLFetcher : public CloudPrintURLFetcher {
62 public:
63 explicit TestCloudPrintURLFetcher(
64 base::MessageLoopProxy* io_message_loop_proxy)
65 : io_message_loop_proxy_(io_message_loop_proxy) {
68 virtual net::URLRequestContextGetter* GetRequestContextGetter() OVERRIDE {
69 return new TrackingTestURLRequestContextGetter(
70 io_message_loop_proxy_.get(), throttler_manager());
73 net::URLRequestThrottlerManager* throttler_manager() {
74 return &throttler_manager_;
77 private:
78 virtual ~TestCloudPrintURLFetcher() {}
80 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
82 // We set this as the throttler manager for the
83 // TestURLRequestContext we create.
84 net::URLRequestThrottlerManager throttler_manager_;
87 class CloudPrintURLFetcherTest : public testing::Test,
88 public CloudPrintURLFetcherDelegate {
89 public:
90 CloudPrintURLFetcherTest() : max_retries_(0), fetcher_(NULL) { }
92 // Creates a URLFetcher, using the program's main thread to do IO.
93 virtual void CreateFetcher(const GURL& url, int max_retries);
95 // CloudPrintURLFetcher::Delegate
96 virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse(
97 const net::URLFetcher* source,
98 const GURL& url,
99 const net::URLRequestStatus& status,
100 int response_code,
101 const net::ResponseCookies& cookies,
102 const std::string& data) OVERRIDE;
104 virtual CloudPrintURLFetcher::ResponseAction OnRequestAuthError() OVERRIDE {
105 ADD_FAILURE();
106 return CloudPrintURLFetcher::STOP_PROCESSING;
109 virtual std::string GetAuthHeader() OVERRIDE {
110 return std::string();
113 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy() {
114 return io_message_loop_proxy_;
117 protected:
118 virtual void SetUp() {
119 testing::Test::SetUp();
121 io_message_loop_proxy_ = base::MessageLoopProxy::current();
124 virtual void TearDown() {
125 fetcher_ = NULL;
126 // Deleting the fetcher causes a task to be posted to the IO thread to
127 // release references to the URLRequestContextGetter. We need to run all
128 // pending tasks to execute that (this is the IO thread).
129 base::MessageLoop::current()->RunUntilIdle();
130 EXPECT_EQ(0, g_request_context_getter_instances);
133 // URLFetcher is designed to run on the main UI thread, but in our tests
134 // we assume that the current thread is the IO thread where the URLFetcher
135 // dispatches its requests to. When we wish to simulate being used from
136 // a UI thread, we dispatch a worker thread to do so.
137 base::MessageLoopForIO io_loop_;
138 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
139 int max_retries_;
140 Time start_time_;
141 scoped_refptr<TestCloudPrintURLFetcher> fetcher_;
144 class CloudPrintURLFetcherBasicTest : public CloudPrintURLFetcherTest {
145 public:
146 CloudPrintURLFetcherBasicTest()
147 : handle_raw_response_(false), handle_raw_data_(false) { }
148 // CloudPrintURLFetcher::Delegate
149 virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse(
150 const net::URLFetcher* source,
151 const GURL& url,
152 const net::URLRequestStatus& status,
153 int response_code,
154 const net::ResponseCookies& cookies,
155 const std::string& data) OVERRIDE;
157 virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
158 const net::URLFetcher* source,
159 const GURL& url,
160 const std::string& data) OVERRIDE;
162 virtual CloudPrintURLFetcher::ResponseAction HandleJSONData(
163 const net::URLFetcher* source,
164 const GURL& url,
165 base::DictionaryValue* json_data,
166 bool succeeded) OVERRIDE;
168 void SetHandleRawResponse(bool handle_raw_response) {
169 handle_raw_response_ = handle_raw_response;
171 void SetHandleRawData(bool handle_raw_data) {
172 handle_raw_data_ = handle_raw_data;
174 private:
175 bool handle_raw_response_;
176 bool handle_raw_data_;
179 // Version of CloudPrintURLFetcherTest that tests overload protection.
180 class CloudPrintURLFetcherOverloadTest : public CloudPrintURLFetcherTest {
181 public:
182 CloudPrintURLFetcherOverloadTest() : response_count_(0) {
185 // CloudPrintURLFetcher::Delegate
186 virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
187 const net::URLFetcher* source,
188 const GURL& url,
189 const std::string& data) OVERRIDE;
191 private:
192 int response_count_;
195 // Version of CloudPrintURLFetcherTest that tests backoff protection.
196 class CloudPrintURLFetcherRetryBackoffTest : public CloudPrintURLFetcherTest {
197 public:
198 CloudPrintURLFetcherRetryBackoffTest() : response_count_(0) {
201 // CloudPrintURLFetcher::Delegate
202 virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
203 const net::URLFetcher* source,
204 const GURL& url,
205 const std::string& data) OVERRIDE;
207 virtual void OnRequestGiveUp() OVERRIDE;
209 private:
210 int response_count_;
214 void CloudPrintURLFetcherTest::CreateFetcher(const GURL& url, int max_retries) {
215 fetcher_ = new TestCloudPrintURLFetcher(io_message_loop_proxy().get());
217 // Registers an entry for test url. It only allows 3 requests to be sent
218 // in 200 milliseconds.
219 scoped_refptr<net::URLRequestThrottlerEntry>
220 entry(new net::URLRequestThrottlerEntry(
221 fetcher_->throttler_manager(), std::string(), 200, 3, 1, 2.0, 0.0, 256));
222 fetcher_->throttler_manager()->OverrideEntryForTests(url, entry.get());
224 max_retries_ = max_retries;
225 start_time_ = Time::Now();
226 fetcher_->StartGetRequest(CloudPrintURLFetcher::REQUEST_MAX, url, this,
227 max_retries_, std::string());
230 CloudPrintURLFetcher::ResponseAction
231 CloudPrintURLFetcherTest::HandleRawResponse(
232 const net::URLFetcher* source,
233 const GURL& url,
234 const net::URLRequestStatus& status,
235 int response_code,
236 const net::ResponseCookies& cookies,
237 const std::string& data) {
238 EXPECT_TRUE(status.is_success());
239 EXPECT_EQ(200, response_code); // HTTP OK
240 EXPECT_FALSE(data.empty());
241 return CloudPrintURLFetcher::CONTINUE_PROCESSING;
244 CloudPrintURLFetcher::ResponseAction
245 CloudPrintURLFetcherBasicTest::HandleRawResponse(
246 const net::URLFetcher* source,
247 const GURL& url,
248 const net::URLRequestStatus& status,
249 int response_code,
250 const net::ResponseCookies& cookies,
251 const std::string& data) {
252 EXPECT_TRUE(status.is_success());
253 EXPECT_EQ(200, response_code); // HTTP OK
254 EXPECT_FALSE(data.empty());
256 if (handle_raw_response_) {
257 // If the current message loop is not the IO loop, it will be shut down when
258 // the main loop returns and this thread subsequently goes out of scope.
259 io_message_loop_proxy()->PostTask(FROM_HERE,
260 base::MessageLoop::QuitClosure());
261 return CloudPrintURLFetcher::STOP_PROCESSING;
263 return CloudPrintURLFetcher::CONTINUE_PROCESSING;
266 CloudPrintURLFetcher::ResponseAction
267 CloudPrintURLFetcherBasicTest::HandleRawData(
268 const net::URLFetcher* source,
269 const GURL& url,
270 const std::string& data) {
271 // We should never get here if we returned true in HandleRawResponse
272 EXPECT_FALSE(handle_raw_response_);
273 if (handle_raw_data_) {
274 io_message_loop_proxy()->PostTask(FROM_HERE,
275 base::MessageLoop::QuitClosure());
276 return CloudPrintURLFetcher::STOP_PROCESSING;
278 return CloudPrintURLFetcher::CONTINUE_PROCESSING;
281 CloudPrintURLFetcher::ResponseAction
282 CloudPrintURLFetcherBasicTest::HandleJSONData(
283 const net::URLFetcher* source,
284 const GURL& url,
285 base::DictionaryValue* json_data,
286 bool succeeded) {
287 // We should never get here if we returned true in one of the above methods.
288 EXPECT_FALSE(handle_raw_response_);
289 EXPECT_FALSE(handle_raw_data_);
290 io_message_loop_proxy()->PostTask(FROM_HERE,
291 base::MessageLoop::QuitClosure());
292 return CloudPrintURLFetcher::STOP_PROCESSING;
295 CloudPrintURLFetcher::ResponseAction
296 CloudPrintURLFetcherOverloadTest::HandleRawData(
297 const net::URLFetcher* source,
298 const GURL& url,
299 const std::string& data) {
300 const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
301 response_count_++;
302 if (response_count_ < 20) {
303 fetcher_->StartGetRequest(CloudPrintURLFetcher::REQUEST_MAX, url, this,
304 max_retries_, std::string());
305 } else {
306 // We have already sent 20 requests continuously. And we expect that
307 // it takes more than 1 second due to the overload protection settings.
308 EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
309 io_message_loop_proxy()->PostTask(FROM_HERE,
310 base::MessageLoop::QuitClosure());
312 return CloudPrintURLFetcher::STOP_PROCESSING;
315 CloudPrintURLFetcher::ResponseAction
316 CloudPrintURLFetcherRetryBackoffTest::HandleRawData(
317 const net::URLFetcher* source,
318 const GURL& url,
319 const std::string& data) {
320 response_count_++;
321 // First attempt + 11 retries = 12 total responses.
322 EXPECT_LE(response_count_, 12);
323 return CloudPrintURLFetcher::RETRY_REQUEST;
326 void CloudPrintURLFetcherRetryBackoffTest::OnRequestGiveUp() {
327 // It takes more than 200 ms to finish all 11 requests.
328 EXPECT_TRUE(Time::Now() - start_time_ >= TimeDelta::FromMilliseconds(200));
329 io_message_loop_proxy()->PostTask(FROM_HERE,
330 base::MessageLoop::QuitClosure());
333 TEST_F(CloudPrintURLFetcherBasicTest, HandleRawResponse) {
334 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTP,
335 net::SpawnedTestServer::kLocalhost,
336 base::FilePath(kDocRoot));
337 ASSERT_TRUE(test_server.Start());
338 SetHandleRawResponse(true);
340 CreateFetcher(test_server.GetURL("echo"), 0);
341 base::MessageLoop::current()->Run();
344 TEST_F(CloudPrintURLFetcherBasicTest, HandleRawData) {
345 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTP,
346 net::SpawnedTestServer::kLocalhost,
347 base::FilePath(kDocRoot));
348 ASSERT_TRUE(test_server.Start());
350 SetHandleRawData(true);
351 CreateFetcher(test_server.GetURL("echo"), 0);
352 base::MessageLoop::current()->Run();
355 TEST_F(CloudPrintURLFetcherOverloadTest, Protect) {
356 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTP,
357 net::SpawnedTestServer::kLocalhost,
358 base::FilePath(kDocRoot));
359 ASSERT_TRUE(test_server.Start());
361 GURL url(test_server.GetURL("defaultresponse"));
362 CreateFetcher(url, 11);
364 base::MessageLoop::current()->Run();
367 TEST_F(CloudPrintURLFetcherRetryBackoffTest, GiveUp) {
368 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTP,
369 net::SpawnedTestServer::kLocalhost,
370 base::FilePath(kDocRoot));
371 ASSERT_TRUE(test_server.Start());
373 GURL url(test_server.GetURL("defaultresponse"));
374 CreateFetcher(url, 11);
376 base::MessageLoop::current()->Run();
379 } // namespace cloud_print