url_fetcher_unittest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 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.
4
5#include "base/message_loop_proxy.h"
6#include "base/synchronization/waitable_event.h"
7#include "base/threading/thread.h"
8#include "build/build_config.h"
9#include "chrome/common/chrome_plugin_lib.h"
10#include "chrome/common/net/url_fetcher.h"
11#include "chrome/common/net/url_request_context_getter.h"
12#include "net/http/http_response_headers.h"
13#include "net/test/test_server.h"
14#include "net/url_request/url_request_test_util.h"
15#include "net/url_request/url_request_throttler_manager.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18#if defined(USE_NSS)
19#include "net/ocsp/nss_ocsp.h"
20#endif
21
22using base::Time;
23using base::TimeDelta;
24
25// TODO(eroman): Add a regression test for http://crbug.com/40505.
26
27namespace {
28
29const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
30
31class TestURLRequestContextGetter : public URLRequestContextGetter {
32 public:
33  explicit TestURLRequestContextGetter(
34      base::MessageLoopProxy* io_message_loop_proxy)
35          : io_message_loop_proxy_(io_message_loop_proxy) {
36  }
37  virtual net::URLRequestContext* GetURLRequestContext() {
38    if (!context_)
39      context_ = new TestURLRequestContext();
40    return context_;
41  }
42  virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
43    return io_message_loop_proxy_;
44  }
45
46 protected:
47  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
48
49 private:
50  ~TestURLRequestContextGetter() {}
51
52  scoped_refptr<net::URLRequestContext> context_;
53};
54
55class URLFetcherTest : public testing::Test, public URLFetcher::Delegate {
56 public:
57  URLFetcherTest() : fetcher_(NULL) { }
58
59  // Creates a URLFetcher, using the program's main thread to do IO.
60  virtual void CreateFetcher(const GURL& url);
61
62  // URLFetcher::Delegate
63  virtual void OnURLFetchComplete(const URLFetcher* source,
64                                  const GURL& url,
65                                  const net::URLRequestStatus& status,
66                                  int response_code,
67                                  const ResponseCookies& cookies,
68                                  const std::string& data);
69
70  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy() {
71    return io_message_loop_proxy_;
72  }
73
74 protected:
75  virtual void SetUp() {
76    testing::Test::SetUp();
77
78    io_message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
79
80    // Ensure that any plugin operations done by other tests are cleaned up.
81    ChromePluginLib::UnloadAllPlugins();
82#if defined(USE_NSS)
83    net::EnsureOCSPInit();
84#endif
85  }
86
87  virtual void TearDown() {
88#if defined(USE_NSS)
89    net::ShutdownOCSP();
90#endif
91  }
92
93  // URLFetcher is designed to run on the main UI thread, but in our tests
94  // we assume that the current thread is the IO thread where the URLFetcher
95  // dispatches its requests to.  When we wish to simulate being used from
96  // a UI thread, we dispatch a worker thread to do so.
97  MessageLoopForIO io_loop_;
98  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
99
100  URLFetcher* fetcher_;
101};
102
103// Version of URLFetcherTest that does a POST instead
104class URLFetcherPostTest : public URLFetcherTest {
105 public:
106  virtual void CreateFetcher(const GURL& url);
107
108  // URLFetcher::Delegate
109  virtual void OnURLFetchComplete(const URLFetcher* source,
110                                  const GURL& url,
111                                  const net::URLRequestStatus& status,
112                                  int response_code,
113                                  const ResponseCookies& cookies,
114                                  const std::string& data);
115};
116
117// Version of URLFetcherTest that tests headers.
118class URLFetcherHeadersTest : public URLFetcherTest {
119 public:
120  // URLFetcher::Delegate
121  virtual void OnURLFetchComplete(const URLFetcher* source,
122                                  const GURL& url,
123                                  const net::URLRequestStatus& status,
124                                  int response_code,
125                                  const ResponseCookies& cookies,
126                                  const std::string& data);
127};
128
129// Version of URLFetcherTest that tests overload protection.
130class URLFetcherProtectTest : public URLFetcherTest {
131 public:
132  virtual void CreateFetcher(const GURL& url);
133  // URLFetcher::Delegate
134  virtual void OnURLFetchComplete(const URLFetcher* source,
135                                  const GURL& url,
136                                  const net::URLRequestStatus& status,
137                                  int response_code,
138                                  const ResponseCookies& cookies,
139                                  const std::string& data);
140 private:
141  Time start_time_;
142};
143
144// Version of URLFetcherTest that tests overload protection, when responses
145// passed through.
146class URLFetcherProtectTestPassedThrough : public URLFetcherTest {
147 public:
148  virtual void CreateFetcher(const GURL& url);
149  // URLFetcher::Delegate
150  virtual void OnURLFetchComplete(const URLFetcher* source,
151                                  const GURL& url,
152                                  const net::URLRequestStatus& status,
153                                  int response_code,
154                                  const ResponseCookies& cookies,
155                                  const std::string& data);
156 private:
157  Time start_time_;
158};
159
160// Version of URLFetcherTest that tests bad HTTPS requests.
161class URLFetcherBadHTTPSTest : public URLFetcherTest {
162 public:
163  URLFetcherBadHTTPSTest();
164
165  // URLFetcher::Delegate
166  virtual void OnURLFetchComplete(const URLFetcher* source,
167                                  const GURL& url,
168                                  const net::URLRequestStatus& status,
169                                  int response_code,
170                                  const ResponseCookies& cookies,
171                                  const std::string& data);
172
173 private:
174  FilePath cert_dir_;
175};
176
177// Version of URLFetcherTest that tests request cancellation on shutdown.
178class URLFetcherCancelTest : public URLFetcherTest {
179 public:
180  virtual void CreateFetcher(const GURL& url);
181  // URLFetcher::Delegate
182  virtual void OnURLFetchComplete(const URLFetcher* source,
183                                  const GURL& url,
184                                  const net::URLRequestStatus& status,
185                                  int response_code,
186                                  const ResponseCookies& cookies,
187                                  const std::string& data);
188
189  void CancelRequest();
190};
191
192// Version of TestURLRequestContext that posts a Quit task to the IO
193// thread once it is deleted.
194class CancelTestURLRequestContext : public TestURLRequestContext {
195  virtual ~CancelTestURLRequestContext() {
196    // The d'tor should execute in the IO thread. Post the quit task to the
197    // current thread.
198    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
199  }
200};
201
202class CancelTestURLRequestContextGetter : public URLRequestContextGetter {
203 public:
204  explicit CancelTestURLRequestContextGetter(
205      base::MessageLoopProxy* io_message_loop_proxy)
206      : io_message_loop_proxy_(io_message_loop_proxy),
207        context_created_(false, false) {
208  }
209  virtual net::URLRequestContext* GetURLRequestContext() {
210    if (!context_) {
211      context_ = new CancelTestURLRequestContext();
212      context_created_.Signal();
213    }
214    return context_;
215  }
216  virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
217    return io_message_loop_proxy_;
218  }
219  void WaitForContextCreation() {
220    context_created_.Wait();
221  }
222
223 private:
224  ~CancelTestURLRequestContextGetter() {}
225
226  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
227  base::WaitableEvent context_created_;
228  scoped_refptr<net::URLRequestContext> context_;
229};
230
231// Version of URLFetcherTest that tests retying the same request twice.
232class URLFetcherMultipleAttemptTest : public URLFetcherTest {
233 public:
234  // URLFetcher::Delegate
235  virtual void OnURLFetchComplete(const URLFetcher* source,
236                                  const GURL& url,
237                                  const net::URLRequestStatus& status,
238                                  int response_code,
239                                  const ResponseCookies& cookies,
240                                  const std::string& data);
241 private:
242  std::string data_;
243};
244
245// Wrapper that lets us call CreateFetcher() on a thread of our choice.  We
246// could make URLFetcherTest refcounted and use PostTask(FROM_HERE.. ) to call
247// CreateFetcher() directly, but the ownership of the URLFetcherTest is a bit
248// confusing in that case because GTest doesn't know about the refcounting.
249// It's less confusing to just do it this way.
250class FetcherWrapperTask : public Task {
251 public:
252  FetcherWrapperTask(URLFetcherTest* test, const GURL& url)
253      : test_(test), url_(url) { }
254  virtual void Run() {
255    test_->CreateFetcher(url_);
256  }
257
258 private:
259  URLFetcherTest* test_;
260  GURL url_;
261};
262
263void URLFetcherTest::CreateFetcher(const GURL& url) {
264  fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
265  fetcher_->set_request_context(new TestURLRequestContextGetter(
266      io_message_loop_proxy()));
267  fetcher_->Start();
268}
269
270void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source,
271                                        const GURL& url,
272                                        const net::URLRequestStatus& status,
273                                        int response_code,
274                                        const ResponseCookies& cookies,
275                                        const std::string& data) {
276  EXPECT_TRUE(status.is_success());
277  EXPECT_EQ(200, response_code);  // HTTP OK
278  EXPECT_FALSE(data.empty());
279
280  delete fetcher_;  // Have to delete this here and not in the destructor,
281                    // because the destructor won't necessarily run on the
282                    // same thread that CreateFetcher() did.
283
284  io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
285  // If the current message loop is not the IO loop, it will be shut down when
286  // the main loop returns and this thread subsequently goes out of scope.
287}
288
289void URLFetcherPostTest::CreateFetcher(const GURL& url) {
290  fetcher_ = new URLFetcher(url, URLFetcher::POST, this);
291  fetcher_->set_request_context(new TestURLRequestContextGetter(
292      io_message_loop_proxy()));
293  fetcher_->set_upload_data("application/x-www-form-urlencoded",
294                            "bobsyeruncle");
295  fetcher_->Start();
296}
297
298void URLFetcherPostTest::OnURLFetchComplete(const URLFetcher* source,
299                                            const GURL& url,
300                                            const net::URLRequestStatus& status,
301                                            int response_code,
302                                            const ResponseCookies& cookies,
303                                            const std::string& data) {
304  EXPECT_EQ(std::string("bobsyeruncle"), data);
305  URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
306                                     cookies, data);
307}
308
309void URLFetcherHeadersTest::OnURLFetchComplete(
310    const URLFetcher* source,
311    const GURL& url,
312    const net::URLRequestStatus& status,
313    int response_code,
314    const ResponseCookies& cookies,
315    const std::string& data) {
316  std::string header;
317  EXPECT_TRUE(source->response_headers()->GetNormalizedHeader("cache-control",
318                                                              &header));
319  EXPECT_EQ("private", header);
320  URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
321                                     cookies, data);
322}
323
324void URLFetcherProtectTest::CreateFetcher(const GURL& url) {
325  fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
326  fetcher_->set_request_context(new TestURLRequestContextGetter(
327      io_message_loop_proxy()));
328  start_time_ = Time::Now();
329  fetcher_->set_max_retries(11);
330  fetcher_->Start();
331}
332
333void URLFetcherProtectTest::OnURLFetchComplete(
334    const URLFetcher* source,
335    const GURL& url,
336    const net::URLRequestStatus& status,
337    int response_code,
338    const ResponseCookies& cookies,
339    const std::string& data) {
340  const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
341  if (response_code >= 500) {
342    // Now running ServerUnavailable test.
343    // It takes more than 1 second to finish all 11 requests.
344    EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
345    EXPECT_TRUE(status.is_success());
346    EXPECT_FALSE(data.empty());
347    delete fetcher_;
348    io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
349  } else {
350    // Now running Overload test.
351    static int count = 0;
352    count++;
353    if (count < 20) {
354      fetcher_->Start();
355    } else {
356      // We have already sent 20 requests continuously. And we expect that
357      // it takes more than 1 second due to the overload protection settings.
358      EXPECT_TRUE(Time::Now() - start_time_ >= one_second);
359      URLFetcherTest::OnURLFetchComplete(source, url, status, response_code,
360                                         cookies, data);
361    }
362  }
363}
364
365void URLFetcherProtectTestPassedThrough::CreateFetcher(const GURL& url) {
366  fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
367  fetcher_->set_request_context(new TestURLRequestContextGetter(
368      io_message_loop_proxy()));
369  fetcher_->set_automatically_retry_on_5xx(false);
370  start_time_ = Time::Now();
371  fetcher_->set_max_retries(11);
372  fetcher_->Start();
373}
374
375void URLFetcherProtectTestPassedThrough::OnURLFetchComplete(
376    const URLFetcher* source,
377    const GURL& url,
378    const net::URLRequestStatus& status,
379    int response_code,
380    const ResponseCookies& cookies,
381    const std::string& data) {
382  const TimeDelta one_minute = TimeDelta::FromMilliseconds(60000);
383  if (response_code >= 500) {
384    // Now running ServerUnavailable test.
385    // It should get here on the first attempt, so almost immediately and
386    // *not* to attempt to execute all 11 requests (2.5 minutes).
387    EXPECT_TRUE(Time::Now() - start_time_ < one_minute);
388    EXPECT_TRUE(status.is_success());
389    // Check that suggested back off time is bigger than 0.
390    EXPECT_GT(fetcher_->backoff_delay().InMicroseconds(), 0);
391    EXPECT_FALSE(data.empty());
392  } else {
393    // We should not get here!
394    ADD_FAILURE();
395  }
396
397  delete fetcher_;
398  io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
399}
400
401
402URLFetcherBadHTTPSTest::URLFetcherBadHTTPSTest() {
403  PathService::Get(base::DIR_SOURCE_ROOT, &cert_dir_);
404  cert_dir_ = cert_dir_.AppendASCII("chrome");
405  cert_dir_ = cert_dir_.AppendASCII("test");
406  cert_dir_ = cert_dir_.AppendASCII("data");
407  cert_dir_ = cert_dir_.AppendASCII("ssl");
408  cert_dir_ = cert_dir_.AppendASCII("certificates");
409}
410
411// The "server certificate expired" error should result in automatic
412// cancellation of the request by
413// net::URLRequest::Delegate::OnSSLCertificateError.
414void URLFetcherBadHTTPSTest::OnURLFetchComplete(
415    const URLFetcher* source,
416    const GURL& url,
417    const net::URLRequestStatus& status,
418    int response_code,
419    const ResponseCookies& cookies,
420    const std::string& data) {
421  // This part is different from URLFetcherTest::OnURLFetchComplete
422  // because this test expects the request to be cancelled.
423  EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
424  EXPECT_EQ(net::ERR_ABORTED, status.os_error());
425  EXPECT_EQ(-1, response_code);
426  EXPECT_TRUE(cookies.empty());
427  EXPECT_TRUE(data.empty());
428
429  // The rest is the same as URLFetcherTest::OnURLFetchComplete.
430  delete fetcher_;
431  io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
432}
433
434void URLFetcherCancelTest::CreateFetcher(const GURL& url) {
435  fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
436  CancelTestURLRequestContextGetter* context_getter =
437      new CancelTestURLRequestContextGetter(io_message_loop_proxy());
438  fetcher_->set_request_context(context_getter);
439  fetcher_->set_max_retries(2);
440  fetcher_->Start();
441  // We need to wait for the creation of the net::URLRequestContext, since we
442  // rely on it being destroyed as a signal to end the test.
443  context_getter->WaitForContextCreation();
444  CancelRequest();
445}
446
447void URLFetcherCancelTest::OnURLFetchComplete(
448    const URLFetcher* source,
449    const GURL& url,
450    const net::URLRequestStatus& status,
451    int response_code,
452    const ResponseCookies& cookies,
453    const std::string& data) {
454  // We should have cancelled the request before completion.
455  ADD_FAILURE();
456  delete fetcher_;
457  io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
458}
459
460void URLFetcherCancelTest::CancelRequest() {
461  delete fetcher_;
462  // The URLFetcher's test context will post a Quit task once it is
463  // deleted. So if this test simply hangs, it means cancellation
464  // did not work.
465}
466
467void URLFetcherMultipleAttemptTest::OnURLFetchComplete(
468    const URLFetcher* source,
469    const GURL& url,
470    const net::URLRequestStatus& status,
471    int response_code,
472    const ResponseCookies& cookies,
473    const std::string& data) {
474  EXPECT_TRUE(status.is_success());
475  EXPECT_EQ(200, response_code);  // HTTP OK
476  EXPECT_FALSE(data.empty());
477  if (!data.empty() && data_.empty()) {
478    data_ = data;
479    fetcher_->Start();
480  } else {
481    EXPECT_EQ(data, data_);
482    delete fetcher_;  // Have to delete this here and not in the destructor,
483                      // because the destructor won't necessarily run on the
484                      // same thread that CreateFetcher() did.
485
486    io_message_loop_proxy()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
487    // If the current message loop is not the IO loop, it will be shut down when
488    // the main loop returns and this thread subsequently goes out of scope.
489  }
490}
491
492TEST_F(URLFetcherTest, SameThreadsTest) {
493  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
494  ASSERT_TRUE(test_server.Start());
495
496  // Create the fetcher on the main thread.  Since IO will happen on the main
497  // thread, this will test URLFetcher's ability to do everything on one
498  // thread.
499  CreateFetcher(test_server.GetURL("defaultresponse"));
500
501  MessageLoop::current()->Run();
502}
503
504#if defined(OS_MACOSX)
505// SIGSEGV on Mac: http://crbug.com/60426
506TEST_F(URLFetcherTest, DISABLED_DifferentThreadsTest) {
507#else
508TEST_F(URLFetcherTest, DifferentThreadsTest) {
509#endif
510  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
511  ASSERT_TRUE(test_server.Start());
512
513  // Create a separate thread that will create the URLFetcher.  The current
514  // (main) thread will do the IO, and when the fetch is complete it will
515  // terminate the main thread's message loop; then the other thread's
516  // message loop will be shut down automatically as the thread goes out of
517  // scope.
518  base::Thread t("URLFetcher test thread");
519  ASSERT_TRUE(t.Start());
520  t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this,
521      test_server.GetURL("defaultresponse")));
522
523  MessageLoop::current()->Run();
524}
525
526#if defined(OS_MACOSX)
527// SIGSEGV on Mac: http://crbug.com/60426
528TEST_F(URLFetcherPostTest, DISABLED_Basic) {
529#else
530TEST_F(URLFetcherPostTest, Basic) {
531#endif
532  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
533  ASSERT_TRUE(test_server.Start());
534
535  CreateFetcher(test_server.GetURL("echo"));
536  MessageLoop::current()->Run();
537}
538
539TEST_F(URLFetcherHeadersTest, Headers) {
540  net::TestServer test_server(net::TestServer::TYPE_HTTP,
541      FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
542  ASSERT_TRUE(test_server.Start());
543
544  CreateFetcher(test_server.GetURL("files/with-headers.html"));
545  MessageLoop::current()->Run();
546  // The actual tests are in the URLFetcherHeadersTest fixture.
547}
548
549TEST_F(URLFetcherProtectTest, Overload) {
550  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
551  ASSERT_TRUE(test_server.Start());
552
553  GURL url(test_server.GetURL("defaultresponse"));
554
555  // Registers an entry for test url. It only allows 3 requests to be sent
556  // in 200 milliseconds.
557  scoped_refptr<net::URLRequestThrottlerEntry> entry(
558      new net::URLRequestThrottlerEntry(200, 3, 1, 0, 2.0, 0.0, 256));
559  net::URLRequestThrottlerManager::GetInstance()->OverrideEntryForTests(
560      url, entry);
561
562  CreateFetcher(url);
563
564  MessageLoop::current()->Run();
565
566  net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
567}
568
569TEST_F(URLFetcherProtectTest, ServerUnavailable) {
570  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
571  ASSERT_TRUE(test_server.Start());
572
573  GURL url(test_server.GetURL("files/server-unavailable.html"));
574
575  // Registers an entry for test url. The backoff time is calculated by:
576  //     new_backoff = 2.0 * old_backoff + 0
577  // and maximum backoff time is 256 milliseconds.
578  // Maximum retries allowed is set to 11.
579  scoped_refptr<net::URLRequestThrottlerEntry> entry(
580      new net::URLRequestThrottlerEntry(200, 3, 1, 0, 2.0, 0.0, 256));
581  net::URLRequestThrottlerManager::GetInstance()->OverrideEntryForTests(
582      url, entry);
583
584  CreateFetcher(url);
585
586  MessageLoop::current()->Run();
587
588  net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
589}
590
591TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) {
592  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
593  ASSERT_TRUE(test_server.Start());
594
595  GURL url(test_server.GetURL("files/server-unavailable.html"));
596
597  // Registers an entry for test url. The backoff time is calculated by:
598  //     new_backoff = 2.0 * old_backoff + 0
599  // and maximum backoff time is 150000 milliseconds.
600  // Maximum retries allowed is set to 11.
601  scoped_refptr<net::URLRequestThrottlerEntry> entry(
602      new net::URLRequestThrottlerEntry(200, 3, 100, 0, 2.0, 0.0, 150000));
603  // Total time if *not* for not doing automatic backoff would be 150s.
604  // In reality it should be "as soon as server responds".
605  net::URLRequestThrottlerManager::GetInstance()->OverrideEntryForTests(
606      url, entry);
607
608  CreateFetcher(url);
609
610  MessageLoop::current()->Run();
611
612  net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
613}
614
615#if defined(OS_MACOSX)
616// SIGSEGV on Mac: http://crbug.com/60426
617TEST_F(URLFetcherBadHTTPSTest, DISABLED_BadHTTPSTest) {
618#else
619TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
620#endif
621  net::TestServer::HTTPSOptions https_options(
622      net::TestServer::HTTPSOptions::CERT_EXPIRED);
623  net::TestServer test_server(https_options, FilePath(kDocRoot));
624  ASSERT_TRUE(test_server.Start());
625
626  CreateFetcher(test_server.GetURL("defaultresponse"));
627  MessageLoop::current()->Run();
628}
629
630#if defined(OS_MACOSX)
631// SIGSEGV on Mac: http://crbug.com/60426
632TEST_F(URLFetcherCancelTest, DISABLED_ReleasesContext) {
633#else
634TEST_F(URLFetcherCancelTest, ReleasesContext) {
635#endif
636  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
637  ASSERT_TRUE(test_server.Start());
638
639  GURL url(test_server.GetURL("files/server-unavailable.html"));
640
641  // Registers an entry for test url. The backoff time is calculated by:
642  //     new_backoff = 2.0 * old_backoff + 0
643  // The initial backoff is 2 seconds and maximum backoff is 4 seconds.
644  // Maximum retries allowed is set to 2.
645  scoped_refptr<net::URLRequestThrottlerEntry> entry(
646      new net::URLRequestThrottlerEntry(200, 3, 2000, 0, 2.0, 0.0, 4000));
647  net::URLRequestThrottlerManager::GetInstance()->OverrideEntryForTests(
648      url, entry);
649
650  // Create a separate thread that will create the URLFetcher.  The current
651  // (main) thread will do the IO, and when the fetch is complete it will
652  // terminate the main thread's message loop; then the other thread's
653  // message loop will be shut down automatically as the thread goes out of
654  // scope.
655  base::Thread t("URLFetcher test thread");
656  ASSERT_TRUE(t.Start());
657  t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
658
659  MessageLoop::current()->Run();
660
661  net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
662}
663
664TEST_F(URLFetcherCancelTest, CancelWhileDelayedStartTaskPending) {
665  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
666  ASSERT_TRUE(test_server.Start());
667
668  GURL url(test_server.GetURL("files/server-unavailable.html"));
669
670  // Register an entry for test url.
671  // Using a sliding window of 4 seconds, and max of 1 request, under a fast
672  // run we expect to have a 4 second delay when posting the Start task.
673  scoped_refptr<net::URLRequestThrottlerEntry> entry(
674      new net::URLRequestThrottlerEntry(4000, 1, 2000, 0, 2.0, 0.0, 4000));
675  net::URLRequestThrottlerManager::GetInstance()->OverrideEntryForTests(
676      url, entry);
677  // Fake that a request has just started.
678  entry->ReserveSendingTimeForNextRequest(base::TimeTicks());
679
680  // The next request we try to send will be delayed by ~4 seconds.
681  // The slower the test runs, the less the delay will be (since it takes the
682  // time difference from now).
683
684  base::Thread t("URLFetcher test thread");
685  ASSERT_TRUE(t.Start());
686  t.message_loop()->PostTask(FROM_HERE, new FetcherWrapperTask(this, url));
687
688  MessageLoop::current()->Run();
689
690  net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
691}
692
693TEST_F(URLFetcherMultipleAttemptTest, SameData) {
694  net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
695  ASSERT_TRUE(test_server.Start());
696
697  // Create the fetcher on the main thread.  Since IO will happen on the main
698  // thread, this will test URLFetcher's ability to do everything on one
699  // thread.
700  CreateFetcher(test_server.GetURL("defaultresponse"));
701
702  MessageLoop::current()->Run();
703}
704
705}  // namespace.
706