|  | // Copyright (c) 2012 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 "net/url_request/url_fetcher_impl.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <string> | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/files/file_util.h" | 
|  | #include "base/files/scoped_temp_dir.h" | 
|  | #include "base/message_loop/message_loop_proxy.h" | 
|  | #include "base/path_service.h" | 
|  | #include "base/strings/stringprintf.h" | 
|  | #include "base/synchronization/waitable_event.h" | 
|  | #include "base/threading/thread.h" | 
|  | #include "build/build_config.h" | 
|  | #include "crypto/nss_util.h" | 
|  | #include "net/base/network_change_notifier.h" | 
|  | #include "net/dns/mock_host_resolver.h" | 
|  | #include "net/http/http_response_headers.h" | 
|  | #include "net/test/spawned_test_server/spawned_test_server.h" | 
|  | #include "net/url_request/url_fetcher_delegate.h" | 
|  | #include "net/url_request/url_request_context_getter.h" | 
|  | #include "net/url_request/url_request_test_util.h" | 
|  | #include "net/url_request/url_request_throttler_manager.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | #if defined(USE_NSS) || defined(OS_IOS) | 
|  | #include "net/ocsp/nss_ocsp.h" | 
|  | #endif | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | using base::Time; | 
|  | using base::TimeDelta; | 
|  |  | 
|  | // TODO(eroman): Add a regression test for http://crbug.com/40505. | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // TODO(akalin): Move all the test data to somewhere under net/. | 
|  | const base::FilePath::CharType kDocRoot[] = | 
|  | FILE_PATH_LITERAL("net/data/url_fetcher_impl_unittest"); | 
|  | const char kTestServerFilePrefix[] = "files/"; | 
|  |  | 
|  | class ThrottlingTestURLRequestContext : public TestURLRequestContext { | 
|  | public: | 
|  | ThrottlingTestURLRequestContext() : TestURLRequestContext(true) { | 
|  | set_throttler_manager(&throttler_manager_); | 
|  | Init(); | 
|  | DCHECK(throttler_manager() != NULL); | 
|  | } | 
|  |  | 
|  | private: | 
|  | URLRequestThrottlerManager throttler_manager_; | 
|  | }; | 
|  |  | 
|  | class ThrottlingTestURLRequestContextGetter | 
|  | : public TestURLRequestContextGetter { | 
|  | public: | 
|  | ThrottlingTestURLRequestContextGetter( | 
|  | base::MessageLoopProxy* io_message_loop_proxy, | 
|  | TestURLRequestContext* request_context) | 
|  | : TestURLRequestContextGetter(io_message_loop_proxy), | 
|  | context_(request_context) { | 
|  | } | 
|  |  | 
|  | // TestURLRequestContextGetter: | 
|  | TestURLRequestContext* GetURLRequestContext() override { return context_; } | 
|  |  | 
|  | protected: | 
|  | ~ThrottlingTestURLRequestContextGetter() override {} | 
|  |  | 
|  | TestURLRequestContext* const context_; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | class URLFetcherTest : public testing::Test, | 
|  | public URLFetcherDelegate { | 
|  | public: | 
|  | URLFetcherTest() : fetcher_(NULL) {} | 
|  |  | 
|  | static int GetNumFetcherCores() { | 
|  | return URLFetcherImpl::GetNumFetcherCores(); | 
|  | } | 
|  |  | 
|  | // Creates a URLFetcher, using the program's main thread to do IO. | 
|  | virtual void CreateFetcher(const GURL& url); | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | // Subclasses that override this should either call this function or | 
|  | // CleanupAfterFetchComplete() at the end of their processing, depending on | 
|  | // whether they want to check for a non-empty HTTP 200 response or not. | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | // Deletes |fetcher| and terminates the message loop. | 
|  | void CleanupAfterFetchComplete(); | 
|  |  | 
|  | scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy() { | 
|  | return io_message_loop_proxy_; | 
|  | } | 
|  |  | 
|  | TestURLRequestContext* request_context() { | 
|  | return context_.get(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | // testing::Test: | 
|  | void SetUp() override { | 
|  | testing::Test::SetUp(); | 
|  |  | 
|  | context_.reset(new ThrottlingTestURLRequestContext()); | 
|  | io_message_loop_proxy_ = base::MessageLoopProxy::current(); | 
|  |  | 
|  | #if defined(USE_NSS) || defined(OS_IOS) | 
|  | crypto::EnsureNSSInit(); | 
|  | EnsureNSSHttpIOInit(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void TearDown() override { | 
|  | #if defined(USE_NSS) || defined(OS_IOS) | 
|  | ShutdownNSSHttpIO(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | // 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. | 
|  | scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 
|  |  | 
|  | URLFetcherImpl* fetcher_; | 
|  | scoped_ptr<TestURLRequestContext> context_; | 
|  | }; | 
|  |  | 
|  | // A test fixture that uses a MockHostResolver, so that name resolutions can | 
|  | // be manipulated by the tests to keep connections in the resolving state. | 
|  | class URLFetcherMockDnsTest : public URLFetcherTest { | 
|  | public: | 
|  | // testing::Test: | 
|  | void SetUp() override; | 
|  |  | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | protected: | 
|  | GURL test_url_; | 
|  | scoped_ptr<SpawnedTestServer> test_server_; | 
|  | MockHostResolver resolver_; | 
|  | scoped_ptr<URLFetcher> completed_fetcher_; | 
|  | }; | 
|  |  | 
|  | void URLFetcherTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | EXPECT_TRUE(source->GetStatus().is_success()); | 
|  | EXPECT_EQ(200, source->GetResponseCode());  // HTTP OK | 
|  |  | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_FALSE(data.empty()); | 
|  |  | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | void URLFetcherTest::CleanupAfterFetchComplete() { | 
|  | 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. | 
|  |  | 
|  | io_message_loop_proxy()->PostTask(FROM_HERE, | 
|  | base::MessageLoop::QuitClosure()); | 
|  | // 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. | 
|  | } | 
|  |  | 
|  | void URLFetcherMockDnsTest::SetUp() { | 
|  | URLFetcherTest::SetUp(); | 
|  |  | 
|  | resolver_.set_ondemand_mode(true); | 
|  | resolver_.rules()->AddRule("example.com", "127.0.0.1"); | 
|  |  | 
|  | context_.reset(new TestURLRequestContext(true)); | 
|  | context_->set_host_resolver(&resolver_); | 
|  | context_->Init(); | 
|  |  | 
|  | test_server_.reset(new SpawnedTestServer(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot))); | 
|  | ASSERT_TRUE(test_server_->Start()); | 
|  |  | 
|  | // test_server_.GetURL() returns a URL with 127.0.0.1 (kLocalhost), that is | 
|  | // immediately resolved by the MockHostResolver. Use a hostname instead to | 
|  | // trigger an async resolve. | 
|  | test_url_ = GURL( | 
|  | base::StringPrintf("http://example.com:%d/defaultresponse", | 
|  | test_server_->host_port_pair().port())); | 
|  | ASSERT_TRUE(test_url_.is_valid()); | 
|  | } | 
|  |  | 
|  | void URLFetcherMockDnsTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | } | 
|  |  | 
|  | void URLFetcherMockDnsTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | io_message_loop_proxy()->PostTask(FROM_HERE, | 
|  | base::MessageLoop::QuitClosure()); | 
|  | ASSERT_EQ(fetcher_, source); | 
|  | EXPECT_EQ(test_url_, source->GetOriginalURL()); | 
|  | completed_fetcher_.reset(fetcher_); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Version of URLFetcherTest that does a POST instead | 
|  | class URLFetcherPostTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that does a POST of a file using | 
|  | // SetUploadDataStream | 
|  | class URLFetcherPostFileTest : public URLFetcherTest { | 
|  | public: | 
|  | URLFetcherPostFileTest(); | 
|  |  | 
|  | void SetUploadRange(uint64 range_offset, uint64 range_length) { | 
|  | range_offset_ = range_offset; | 
|  | range_length_ = range_length; | 
|  | } | 
|  |  | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | private: | 
|  | base::FilePath path_; | 
|  | uint64 range_offset_; | 
|  | uint64 range_length_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that does a POST instead with empty upload body | 
|  | class URLFetcherEmptyPostTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests download progress reports. | 
|  | class URLFetcherDownloadProgressTest : public URLFetcherTest { | 
|  | public: | 
|  | URLFetcherDownloadProgressTest() | 
|  | : previous_progress_(0), | 
|  | expected_total_(0) { | 
|  | } | 
|  |  | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchDownloadProgress(const URLFetcher* source, | 
|  | int64 current, | 
|  | int64 total) override; | 
|  |  | 
|  | protected: | 
|  | // Download progress returned by the previous callback. | 
|  | int64 previous_progress_; | 
|  | // Size of the file being downloaded, known in advance (provided by each test | 
|  | // case). | 
|  | int64 expected_total_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests progress reports at cancellation. | 
|  | class URLFetcherDownloadProgressCancelTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  | void OnURLFetchDownloadProgress(const URLFetcher* source, | 
|  | int64 current, | 
|  | int64 total) override; | 
|  |  | 
|  | protected: | 
|  | bool cancelled_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests upload progress reports. | 
|  | class URLFetcherUploadProgressTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchUploadProgress(const URLFetcher* source, | 
|  | int64 current, | 
|  | int64 total) override; | 
|  |  | 
|  | protected: | 
|  | int64 previous_progress_; | 
|  | std::string chunk_; | 
|  | int64 number_of_chunks_added_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests headers. | 
|  | class URLFetcherHeadersTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests SocketAddress. | 
|  | class URLFetcherSocketAddressTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | protected: | 
|  | std::string expected_host_; | 
|  | uint16 expected_port_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests stopping on a redirect. | 
|  | class URLFetcherStopOnRedirectTest : public URLFetcherTest { | 
|  | public: | 
|  | URLFetcherStopOnRedirectTest(); | 
|  | ~URLFetcherStopOnRedirectTest() override; | 
|  |  | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | protected: | 
|  | // The URL we should be redirected to. | 
|  | static const char* kRedirectTarget; | 
|  |  | 
|  | bool callback_called_;  // Set to true in OnURLFetchComplete(). | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests overload protection. | 
|  | class URLFetcherProtectTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | private: | 
|  | Time start_time_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests overload protection, when responses | 
|  | // passed through. | 
|  | class URLFetcherProtectTestPassedThrough : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | private: | 
|  | Time start_time_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests bad HTTPS requests. | 
|  | class URLFetcherBadHTTPSTest : public URLFetcherTest { | 
|  | public: | 
|  | URLFetcherBadHTTPSTest(); | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | private: | 
|  | base::FilePath cert_dir_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests request cancellation on shutdown. | 
|  | class URLFetcherCancelTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherTest: | 
|  | void CreateFetcher(const GURL& url) override; | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | void CancelRequest(); | 
|  | }; | 
|  |  | 
|  | // Version of TestURLRequestContext that posts a Quit task to the IO | 
|  | // thread once it is deleted. | 
|  | class CancelTestURLRequestContext : public ThrottlingTestURLRequestContext { | 
|  | public: | 
|  | explicit CancelTestURLRequestContext() { | 
|  | } | 
|  |  | 
|  | private: | 
|  | ~CancelTestURLRequestContext() override { | 
|  | // The d'tor should execute in the IO thread. Post the quit task to the | 
|  | // current thread. | 
|  | base::MessageLoop::current()->PostTask(FROM_HERE, | 
|  | base::MessageLoop::QuitClosure()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | class CancelTestURLRequestContextGetter | 
|  | : public TestURLRequestContextGetter { | 
|  | public: | 
|  | CancelTestURLRequestContextGetter( | 
|  | base::MessageLoopProxy* io_message_loop_proxy, | 
|  | const GURL& throttle_for_url) | 
|  | : TestURLRequestContextGetter(io_message_loop_proxy), | 
|  | io_message_loop_proxy_(io_message_loop_proxy), | 
|  | context_created_(false, false), | 
|  | throttle_for_url_(throttle_for_url) { | 
|  | } | 
|  |  | 
|  | // TestURLRequestContextGetter: | 
|  | TestURLRequestContext* GetURLRequestContext() override { | 
|  | if (!context_.get()) { | 
|  | context_.reset(new CancelTestURLRequestContext()); | 
|  | DCHECK(context_->throttler_manager()); | 
|  |  | 
|  | // Registers an entry for test url. The backoff time is calculated by: | 
|  | //     new_backoff = 2.0 * old_backoff + 0 | 
|  | // The initial backoff is 2 seconds and maximum backoff is 4 seconds. | 
|  | // Maximum retries allowed is set to 2. | 
|  | scoped_refptr<URLRequestThrottlerEntry> entry( | 
|  | new URLRequestThrottlerEntry(context_->throttler_manager(), | 
|  | std::string(), | 
|  | 200, | 
|  | 3, | 
|  | 2000, | 
|  | 2.0, | 
|  | 0.0, | 
|  | 4000)); | 
|  | context_->throttler_manager() | 
|  | ->OverrideEntryForTests(throttle_for_url_, entry.get()); | 
|  |  | 
|  | context_created_.Signal(); | 
|  | } | 
|  | return context_.get(); | 
|  | } | 
|  |  | 
|  | virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const { | 
|  | return io_message_loop_proxy_; | 
|  | } | 
|  |  | 
|  | void WaitForContextCreation() { | 
|  | context_created_.Wait(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | ~CancelTestURLRequestContextGetter() override {} | 
|  |  | 
|  | private: | 
|  | scoped_ptr<TestURLRequestContext> context_; | 
|  | scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 
|  | base::WaitableEvent context_created_; | 
|  | GURL throttle_for_url_; | 
|  | }; | 
|  |  | 
|  | // Version of URLFetcherTest that tests retying the same request twice. | 
|  | class URLFetcherMultipleAttemptTest : public URLFetcherTest { | 
|  | public: | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | private: | 
|  | std::string data_; | 
|  | }; | 
|  |  | 
|  | class URLFetcherFileTest : public URLFetcherTest { | 
|  | public: | 
|  | URLFetcherFileTest() : take_ownership_of_file_(false), | 
|  | expected_file_error_(OK) {} | 
|  |  | 
|  | void CreateFetcherForFile(const GURL& url, const base::FilePath& file_path); | 
|  | void CreateFetcherForTempFile(const GURL& url); | 
|  |  | 
|  | // URLFetcherDelegate: | 
|  | void OnURLFetchComplete(const URLFetcher* source) override; | 
|  |  | 
|  | protected: | 
|  | base::FilePath expected_file_; | 
|  | base::FilePath file_path_; | 
|  |  | 
|  | // Set by the test. Used in OnURLFetchComplete() to decide if | 
|  | // the URLFetcher should own the temp file, so that we can test | 
|  | // disowning prevents the file from being deleted. | 
|  | bool take_ownership_of_file_; | 
|  |  | 
|  | // Expected file error code for the test.  OK when expecting success. | 
|  | int expected_file_error_; | 
|  | }; | 
|  |  | 
|  | void URLFetcherPostTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::POST, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->SetUploadData("application/x-www-form-urlencoded", "bobsyeruncle"); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherPostTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_EQ(std::string("bobsyeruncle"), data); | 
|  | URLFetcherTest::OnURLFetchComplete(source); | 
|  | } | 
|  |  | 
|  | URLFetcherPostFileTest::URLFetcherPostFileTest() | 
|  | : range_offset_(0), | 
|  | range_length_(kuint64max) { | 
|  | PathService::Get(base::DIR_SOURCE_ROOT, &path_); | 
|  | path_ = path_.Append(FILE_PATH_LITERAL("net")); | 
|  | path_ = path_.Append(FILE_PATH_LITERAL("data")); | 
|  | path_ = path_.Append(FILE_PATH_LITERAL("url_request_unittest")); | 
|  | path_ = path_.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")); | 
|  | } | 
|  |  | 
|  | void URLFetcherPostFileTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::POST, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->SetUploadFilePath("application/x-www-form-urlencoded", | 
|  | path_, | 
|  | range_offset_, | 
|  | range_length_, | 
|  | base::MessageLoopProxy::current()); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherPostFileTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | std::string expected; | 
|  | ASSERT_TRUE(base::ReadFileToString(path_, &expected)); | 
|  | ASSERT_LE(range_offset_, expected.size()); | 
|  | uint64 expected_size = | 
|  | std::min(range_length_, expected.size() - range_offset_); | 
|  |  | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_EQ(expected.substr(range_offset_, expected_size), data); | 
|  | URLFetcherTest::OnURLFetchComplete(source); | 
|  | } | 
|  |  | 
|  | void URLFetcherEmptyPostTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::POST, this); | 
|  | fetcher_->SetRequestContext(new TestURLRequestContextGetter( | 
|  | io_message_loop_proxy())); | 
|  | fetcher_->SetUploadData("text/plain", std::string()); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherEmptyPostTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | EXPECT_TRUE(source->GetStatus().is_success()); | 
|  | EXPECT_EQ(200, source->GetResponseCode());  // HTTP OK | 
|  |  | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_TRUE(data.empty()); | 
|  |  | 
|  | CleanupAfterFetchComplete(); | 
|  | // Do not call the super class method URLFetcherTest::OnURLFetchComplete, | 
|  | // since it expects a non-empty response. | 
|  | } | 
|  |  | 
|  | void URLFetcherDownloadProgressTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherDownloadProgressTest::OnURLFetchDownloadProgress( | 
|  | const URLFetcher* source, int64 progress, int64 total) { | 
|  | // Increasing between 0 and total. | 
|  | EXPECT_LE(0, progress); | 
|  | EXPECT_GE(total, progress); | 
|  | EXPECT_LE(previous_progress_, progress); | 
|  | EXPECT_EQ(expected_total_, total); | 
|  | previous_progress_ = progress; | 
|  | } | 
|  |  | 
|  | void URLFetcherDownloadProgressCancelTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | cancelled_ = false; | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherDownloadProgressCancelTest::OnURLFetchDownloadProgress( | 
|  | const URLFetcher* source, int64 current, int64 total) { | 
|  | EXPECT_FALSE(cancelled_); | 
|  | if (!cancelled_) { | 
|  | cancelled_ = true; | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void URLFetcherDownloadProgressCancelTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | // Should have been cancelled. | 
|  | ADD_FAILURE(); | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | void URLFetcherUploadProgressTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::POST, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | previous_progress_ = 0; | 
|  | // Large enough data to require more than one read from UploadDataStream. | 
|  | chunk_.assign(1<<16, 'a'); | 
|  | // Use chunked upload to wait for a timer event of progress notification. | 
|  | fetcher_->SetChunkedUpload("application/x-www-form-urlencoded"); | 
|  | fetcher_->Start(); | 
|  | number_of_chunks_added_ = 1; | 
|  | fetcher_->AppendChunkToUpload(chunk_, false); | 
|  | } | 
|  |  | 
|  | void URLFetcherUploadProgressTest::OnURLFetchUploadProgress( | 
|  | const URLFetcher* source, int64 current, int64 total) { | 
|  | // Increasing between 0 and total. | 
|  | EXPECT_LE(0, current); | 
|  | EXPECT_GE(static_cast<int64>(chunk_.size()) * number_of_chunks_added_, | 
|  | current); | 
|  | EXPECT_LE(previous_progress_, current); | 
|  | previous_progress_ = current; | 
|  | EXPECT_EQ(-1, total); | 
|  |  | 
|  | if (number_of_chunks_added_ < 2) { | 
|  | number_of_chunks_added_ += 1; | 
|  | fetcher_->AppendChunkToUpload(chunk_, true); | 
|  | } | 
|  | } | 
|  |  | 
|  | void URLFetcherHeadersTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | std::string header; | 
|  | EXPECT_TRUE(source->GetResponseHeaders()->GetNormalizedHeader("cache-control", | 
|  | &header)); | 
|  | EXPECT_EQ("private", header); | 
|  | URLFetcherTest::OnURLFetchComplete(source); | 
|  | } | 
|  |  | 
|  | void URLFetcherSocketAddressTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | EXPECT_EQ("127.0.0.1", source->GetSocketAddress().host()); | 
|  | EXPECT_EQ(expected_port_, source->GetSocketAddress().port()); | 
|  | URLFetcherTest::OnURLFetchComplete(source); | 
|  | } | 
|  |  | 
|  | // static | 
|  | const char* URLFetcherStopOnRedirectTest::kRedirectTarget = | 
|  | "http://redirect.target.com"; | 
|  |  | 
|  | URLFetcherStopOnRedirectTest::URLFetcherStopOnRedirectTest() | 
|  | : callback_called_(false) { | 
|  | } | 
|  |  | 
|  | URLFetcherStopOnRedirectTest::~URLFetcherStopOnRedirectTest() { | 
|  | } | 
|  |  | 
|  | void URLFetcherStopOnRedirectTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->SetStopOnRedirect(true); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherStopOnRedirectTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | callback_called_ = true; | 
|  | EXPECT_EQ(GURL(kRedirectTarget), source->GetURL()); | 
|  | EXPECT_EQ(URLRequestStatus::CANCELED, source->GetStatus().status()); | 
|  | EXPECT_EQ(ERR_ABORTED, source->GetStatus().error()); | 
|  | EXPECT_EQ(301, source->GetResponseCode()); | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | void URLFetcherProtectTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | start_time_ = Time::Now(); | 
|  | fetcher_->SetMaxRetriesOn5xx(11); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | const TimeDelta one_second = TimeDelta::FromMilliseconds(1000); | 
|  | if (source->GetResponseCode() >= 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(source->GetStatus().is_success()); | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_FALSE(data.empty()); | 
|  | CleanupAfterFetchComplete(); | 
|  | } else { | 
|  | // Now running Overload test. | 
|  | static int count = 0; | 
|  | count++; | 
|  | if (count < 20) { | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->Start(); | 
|  | } else { | 
|  | // We have already sent 20 requests continuously. And we expect that | 
|  | // it takes more than 1 second due to the overload protection settings. | 
|  | EXPECT_TRUE(Time::Now() - start_time_ >= one_second); | 
|  | URLFetcherTest::OnURLFetchComplete(source); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void URLFetcherProtectTestPassedThrough::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->SetAutomaticallyRetryOn5xx(false); | 
|  | start_time_ = Time::Now(); | 
|  | fetcher_->SetMaxRetriesOn5xx(11); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherProtectTestPassedThrough::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | const TimeDelta one_minute = TimeDelta::FromMilliseconds(60000); | 
|  | if (source->GetResponseCode() >= 500) { | 
|  | // Now running ServerUnavailable test. | 
|  | // It should get here on the first attempt, so almost immediately and | 
|  | // *not* to attempt to execute all 11 requests (2.5 minutes). | 
|  | EXPECT_TRUE(Time::Now() - start_time_ < one_minute); | 
|  | EXPECT_TRUE(source->GetStatus().is_success()); | 
|  | // Check that suggested back off time is bigger than 0. | 
|  | EXPECT_GT(fetcher_->GetBackoffDelay().InMicroseconds(), 0); | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_FALSE(data.empty()); | 
|  | } else { | 
|  | // We should not get here! | 
|  | ADD_FAILURE(); | 
|  | } | 
|  |  | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  |  | 
|  | URLFetcherBadHTTPSTest::URLFetcherBadHTTPSTest() { | 
|  | PathService::Get(base::DIR_SOURCE_ROOT, &cert_dir_); | 
|  | cert_dir_ = cert_dir_.AppendASCII("chrome"); | 
|  | cert_dir_ = cert_dir_.AppendASCII("test"); | 
|  | cert_dir_ = cert_dir_.AppendASCII("data"); | 
|  | cert_dir_ = cert_dir_.AppendASCII("ssl"); | 
|  | cert_dir_ = cert_dir_.AppendASCII("certificates"); | 
|  | } | 
|  |  | 
|  | // The "server certificate expired" error should result in automatic | 
|  | // cancellation of the request by | 
|  | // URLRequest::Delegate::OnSSLCertificateError. | 
|  | void URLFetcherBadHTTPSTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | // This part is different from URLFetcherTest::OnURLFetchComplete | 
|  | // because this test expects the request to be cancelled. | 
|  | EXPECT_EQ(URLRequestStatus::CANCELED, source->GetStatus().status()); | 
|  | EXPECT_EQ(ERR_ABORTED, source->GetStatus().error()); | 
|  | EXPECT_EQ(-1, source->GetResponseCode()); | 
|  | EXPECT_TRUE(source->GetCookies().empty()); | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_TRUE(data.empty()); | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | void URLFetcherCancelTest::CreateFetcher(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | CancelTestURLRequestContextGetter* context_getter = | 
|  | new CancelTestURLRequestContextGetter(io_message_loop_proxy().get(), url); | 
|  | fetcher_->SetRequestContext(context_getter); | 
|  | fetcher_->SetMaxRetriesOn5xx(2); | 
|  | fetcher_->Start(); | 
|  | // We need to wait for the creation of the URLRequestContext, since we | 
|  | // rely on it being destroyed as a signal to end the test. | 
|  | context_getter->WaitForContextCreation(); | 
|  | CancelRequest(); | 
|  | } | 
|  |  | 
|  | void URLFetcherCancelTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | // We should have cancelled the request before completion. | 
|  | ADD_FAILURE(); | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | void URLFetcherCancelTest::CancelRequest() { | 
|  | delete fetcher_; | 
|  | // The URLFetcher's test context will post a Quit task once it is | 
|  | // deleted. So if this test simply hangs, it means cancellation | 
|  | // did not work. | 
|  | } | 
|  |  | 
|  | void URLFetcherMultipleAttemptTest::OnURLFetchComplete( | 
|  | const URLFetcher* source) { | 
|  | EXPECT_TRUE(source->GetStatus().is_success()); | 
|  | EXPECT_EQ(200, source->GetResponseCode());  // HTTP OK | 
|  | std::string data; | 
|  | EXPECT_TRUE(source->GetResponseAsString(&data)); | 
|  | EXPECT_FALSE(data.empty()); | 
|  | if (!data.empty() && data_.empty()) { | 
|  | data_ = data; | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  | fetcher_->Start(); | 
|  | } else { | 
|  | EXPECT_EQ(data, data_); | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void URLFetcherFileTest::CreateFetcherForFile(const GURL& url, | 
|  | const base::FilePath& file_path) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  |  | 
|  | // Use the IO message loop to do the file operations in this test. | 
|  | fetcher_->SaveResponseToFileAtPath(file_path, io_message_loop_proxy()); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherFileTest::CreateFetcherForTempFile(const GURL& url) { | 
|  | fetcher_ = new URLFetcherImpl(url, URLFetcher::GET, this); | 
|  | fetcher_->SetRequestContext(new ThrottlingTestURLRequestContextGetter( | 
|  | io_message_loop_proxy().get(), request_context())); | 
|  |  | 
|  | // Use the IO message loop to do the file operations in this test. | 
|  | fetcher_->SaveResponseToTemporaryFile(io_message_loop_proxy()); | 
|  | fetcher_->Start(); | 
|  | } | 
|  |  | 
|  | void URLFetcherFileTest::OnURLFetchComplete(const URLFetcher* source) { | 
|  | if (expected_file_error_ == OK) { | 
|  | EXPECT_TRUE(source->GetStatus().is_success()); | 
|  | EXPECT_EQ(OK, source->GetStatus().error()); | 
|  | EXPECT_EQ(200, source->GetResponseCode()); | 
|  |  | 
|  | EXPECT_TRUE(source->GetResponseAsFilePath( | 
|  | take_ownership_of_file_, &file_path_)); | 
|  |  | 
|  | EXPECT_TRUE(base::ContentsEqual(expected_file_, file_path_)); | 
|  | } else { | 
|  | EXPECT_FALSE(source->GetStatus().is_success()); | 
|  | EXPECT_EQ(expected_file_error_, source->GetStatus().error()); | 
|  | } | 
|  | CleanupAfterFetchComplete(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherTest, SameThreadsTest) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // 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. | 
|  | CreateFetcher(test_server.GetURL("defaultresponse")); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherTest, DifferentThreadsTest) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // 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. | 
|  | base::Thread t("URLFetcher test thread"); | 
|  | ASSERT_TRUE(t.Start()); | 
|  | t.message_loop()->PostTask( | 
|  | FROM_HERE, | 
|  | base::Bind(&URLFetcherTest::CreateFetcher, | 
|  | base::Unretained(this), | 
|  | test_server.GetURL("defaultresponse"))); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | void CancelAllOnIO() { | 
|  | EXPECT_EQ(1, URLFetcherTest::GetNumFetcherCores()); | 
|  | URLFetcherImpl::CancelAll(); | 
|  | EXPECT_EQ(0, URLFetcherTest::GetNumFetcherCores()); | 
|  | } | 
|  |  | 
|  | // Tests to make sure CancelAll() will successfully cancel existing URLFetchers. | 
|  | TEST_F(URLFetcherTest, CancelAll) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("defaultresponse")); | 
|  | io_message_loop_proxy()->PostTaskAndReply( | 
|  | FROM_HERE, base::Bind(&CancelAllOnIO), base::MessageLoop::QuitClosure()); | 
|  | base::MessageLoop::current()->Run(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | delete fetcher_; | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherMockDnsTest, DontRetryOnNetworkChangedByDefault) { | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  |  | 
|  | // This posts a task to start the fetcher. | 
|  | CreateFetcher(test_url_); | 
|  | fetcher_->Start(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  |  | 
|  | // The fetcher is now running, but is pending the host resolve. | 
|  | EXPECT_EQ(1, GetNumFetcherCores()); | 
|  | EXPECT_TRUE(resolver_.has_pending_requests()); | 
|  | ASSERT_FALSE(completed_fetcher_); | 
|  |  | 
|  | // A network change notification aborts the connect job. | 
|  | NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  | ASSERT_TRUE(completed_fetcher_); | 
|  |  | 
|  | // And the owner of the fetcher gets the ERR_NETWORK_CHANGED error. | 
|  | EXPECT_EQ(ERR_NETWORK_CHANGED, completed_fetcher_->GetStatus().error()); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherMockDnsTest, RetryOnNetworkChangedAndFail) { | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  |  | 
|  | // This posts a task to start the fetcher. | 
|  | CreateFetcher(test_url_); | 
|  | fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 
|  | fetcher_->Start(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  |  | 
|  | // The fetcher is now running, but is pending the host resolve. | 
|  | EXPECT_EQ(1, GetNumFetcherCores()); | 
|  | EXPECT_TRUE(resolver_.has_pending_requests()); | 
|  | ASSERT_FALSE(completed_fetcher_); | 
|  |  | 
|  | // Make it fail 3 times. | 
|  | for (int i = 0; i < 3; ++i) { | 
|  | // A network change notification aborts the connect job. | 
|  | NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  |  | 
|  | // But the fetcher retries automatically. | 
|  | EXPECT_EQ(1, GetNumFetcherCores()); | 
|  | EXPECT_TRUE(resolver_.has_pending_requests()); | 
|  | ASSERT_FALSE(completed_fetcher_); | 
|  | } | 
|  |  | 
|  | // A 4th failure doesn't trigger another retry, and propagates the error | 
|  | // to the owner of the fetcher. | 
|  | NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  | ASSERT_TRUE(completed_fetcher_); | 
|  |  | 
|  | // And the owner of the fetcher gets the ERR_NETWORK_CHANGED error. | 
|  | EXPECT_EQ(ERR_NETWORK_CHANGED, completed_fetcher_->GetStatus().error()); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherMockDnsTest, RetryOnNetworkChangedAndSucceed) { | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  |  | 
|  | // This posts a task to start the fetcher. | 
|  | CreateFetcher(test_url_); | 
|  | fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 
|  | fetcher_->Start(); | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  |  | 
|  | // The fetcher is now running, but is pending the host resolve. | 
|  | EXPECT_EQ(1, GetNumFetcherCores()); | 
|  | EXPECT_TRUE(resolver_.has_pending_requests()); | 
|  | ASSERT_FALSE(completed_fetcher_); | 
|  |  | 
|  | // Make it fail 3 times. | 
|  | for (int i = 0; i < 3; ++i) { | 
|  | // A network change notification aborts the connect job. | 
|  | NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  |  | 
|  | // But the fetcher retries automatically. | 
|  | EXPECT_EQ(1, GetNumFetcherCores()); | 
|  | EXPECT_TRUE(resolver_.has_pending_requests()); | 
|  | ASSERT_FALSE(completed_fetcher_); | 
|  | } | 
|  |  | 
|  | // Now let it succeed by resolving the pending request. | 
|  | resolver_.ResolveAllPending(); | 
|  | base::MessageLoop::current()->Run(); | 
|  |  | 
|  | // URLFetcherMockDnsTest::OnURLFetchComplete() will quit the loop. | 
|  | EXPECT_EQ(0, GetNumFetcherCores()); | 
|  | EXPECT_FALSE(resolver_.has_pending_requests()); | 
|  | ASSERT_TRUE(completed_fetcher_); | 
|  |  | 
|  | // This time the request succeeded. | 
|  | EXPECT_EQ(OK, completed_fetcher_->GetStatus().error()); | 
|  | EXPECT_EQ(200, completed_fetcher_->GetResponseCode()); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherPostTest, Basic) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("echo")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherPostFileTest, Basic) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("echo")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherPostFileTest, Range) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | SetUploadRange(30, 100); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("echo")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherEmptyPostTest, Basic) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("echo")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherUploadProgressTest, Basic) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("echo")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherDownloadProgressTest, Basic) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // Get a file large enough to require more than one read into | 
|  | // URLFetcher::Core's IOBuffer. | 
|  | static const char kFileToFetch[] = "animate1.gif"; | 
|  | // Hardcoded file size - it cannot be easily fetched when a remote http server | 
|  | // is used for testing. | 
|  | static const int64 kFileSize = 19021; | 
|  |  | 
|  | expected_total_ = kFileSize; | 
|  |  | 
|  | CreateFetcher(test_server.GetURL( | 
|  | std::string(kTestServerFilePrefix) + kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherDownloadProgressCancelTest, CancelWhileProgressReport) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // Get a file large enough to require more than one read into | 
|  | // URLFetcher::Core's IOBuffer. | 
|  | static const char kFileToFetch[] = "animate1.gif"; | 
|  | CreateFetcher(test_server.GetURL( | 
|  | std::string(kTestServerFilePrefix) + kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherHeadersTest, Headers) { | 
|  | SpawnedTestServer test_server( | 
|  | SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("files/with-headers.html")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | // The actual tests are in the URLFetcherHeadersTest fixture. | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherSocketAddressTest, SocketAddress) { | 
|  | SpawnedTestServer test_server( | 
|  | SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  | expected_port_ = test_server.host_port_pair().port(); | 
|  |  | 
|  | // Reusing "with-headers.html" but doesn't really matter. | 
|  | CreateFetcher(test_server.GetURL("files/with-headers.html")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | // The actual tests are in the URLFetcherSocketAddressTest fixture. | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherStopOnRedirectTest, StopOnRedirect) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher( | 
|  | test_server.GetURL(std::string("server-redirect?") + kRedirectTarget)); | 
|  | base::MessageLoop::current()->Run(); | 
|  | EXPECT_TRUE(callback_called_); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherProtectTest, Overload) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::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. | 
|  | scoped_refptr<URLRequestThrottlerEntry> entry( | 
|  | new URLRequestThrottlerEntry(request_context()->throttler_manager(), | 
|  | std::string(), | 
|  | 200, | 
|  | 3, | 
|  | 1, | 
|  | 2.0, | 
|  | 0.0, | 
|  | 256)); | 
|  | request_context()->throttler_manager() | 
|  | ->OverrideEntryForTests(url, entry.get()); | 
|  |  | 
|  | CreateFetcher(url); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherProtectTest, ServerUnavailable) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | GURL url(test_server.GetURL("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. | 
|  | scoped_refptr<URLRequestThrottlerEntry> entry( | 
|  | new URLRequestThrottlerEntry(request_context()->throttler_manager(), | 
|  | std::string(), | 
|  | 200, | 
|  | 3, | 
|  | 1, | 
|  | 2.0, | 
|  | 0.0, | 
|  | 256)); | 
|  | request_context()->throttler_manager() | 
|  | ->OverrideEntryForTests(url, entry.get()); | 
|  |  | 
|  | CreateFetcher(url); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | GURL url(test_server.GetURL("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 150000 milliseconds. | 
|  | // Maximum retries allowed is set to 11. | 
|  | scoped_refptr<URLRequestThrottlerEntry> entry( | 
|  | new URLRequestThrottlerEntry(request_context()->throttler_manager(), | 
|  | std::string(), | 
|  | 200, | 
|  | 3, | 
|  | 100, | 
|  | 2.0, | 
|  | 0.0, | 
|  | 150000)); | 
|  | // Total time if *not* for not doing automatic backoff would be 150s. | 
|  | // In reality it should be "as soon as server responds". | 
|  | request_context()->throttler_manager() | 
|  | ->OverrideEntryForTests(url, entry.get()); | 
|  |  | 
|  | CreateFetcher(url); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) { | 
|  | SpawnedTestServer::SSLOptions ssl_options( | 
|  | SpawnedTestServer::SSLOptions::CERT_EXPIRED); | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, | 
|  | ssl_options, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | CreateFetcher(test_server.GetURL("defaultresponse")); | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherCancelTest, ReleasesContext) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | GURL url(test_server.GetURL("files/server-unavailable.html")); | 
|  |  | 
|  | // 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. | 
|  | base::Thread t("URLFetcher test thread"); | 
|  | ASSERT_TRUE(t.Start()); | 
|  | t.message_loop()->PostTask( | 
|  | FROM_HERE, | 
|  | base::Bind(&URLFetcherCancelTest::CreateFetcher, | 
|  | base::Unretained(this), url)); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherCancelTest, CancelWhileDelayedStartTaskPending) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | GURL url(test_server.GetURL("files/server-unavailable.html")); | 
|  |  | 
|  | // Register an entry for test url. | 
|  | // Using a sliding window of 4 seconds, and max of 1 request, under a fast | 
|  | // run we expect to have a 4 second delay when posting the Start task. | 
|  | scoped_refptr<URLRequestThrottlerEntry> entry( | 
|  | new URLRequestThrottlerEntry(request_context()->throttler_manager(), | 
|  | std::string(), | 
|  | 4000, | 
|  | 1, | 
|  | 2000, | 
|  | 2.0, | 
|  | 0.0, | 
|  | 4000)); | 
|  | request_context()->throttler_manager() | 
|  | ->OverrideEntryForTests(url, entry.get()); | 
|  | // Fake that a request has just started. | 
|  | entry->ReserveSendingTimeForNextRequest(base::TimeTicks()); | 
|  |  | 
|  | // The next request we try to send will be delayed by ~4 seconds. | 
|  | // The slower the test runs, the less the delay will be (since it takes the | 
|  | // time difference from now). | 
|  |  | 
|  | base::Thread t("URLFetcher test thread"); | 
|  | ASSERT_TRUE(t.Start()); | 
|  | t.message_loop()->PostTask( | 
|  | FROM_HERE, | 
|  | base::Bind(&URLFetcherTest::CreateFetcher, base::Unretained(this), url)); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherMultipleAttemptTest, SameData) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // 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. | 
|  | CreateFetcher(test_server.GetURL("defaultresponse")); | 
|  |  | 
|  | base::MessageLoop::current()->Run(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, SmallGet) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | base::ScopedTempDir temp_dir; | 
|  | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  |  | 
|  | // Get a small file. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), | 
|  | temp_dir.path().AppendASCII(kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  |  | 
|  | ASSERT_FALSE(base::PathExists(file_path_)) | 
|  | << file_path_.value() << " not removed."; | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, LargeGet) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | base::ScopedTempDir temp_dir; | 
|  | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  |  | 
|  | // Get a file large enough to require more than one read into | 
|  | // URLFetcher::Core's IOBuffer. | 
|  | static const char kFileToFetch[] = "animate1.gif"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), | 
|  | temp_dir.path().AppendASCII(kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, SavedOutputFileOwnerhisp) { | 
|  | // If the caller takes the ownership of the output file, the file should | 
|  | // persist even after URLFetcher is gone. If not, the file must be deleted. | 
|  | const bool kTake[] = {false, true}; | 
|  | for (size_t i = 0; i < arraysize(kTake); ++i) { | 
|  | take_ownership_of_file_ = kTake[i]; | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | base::ScopedTempDir temp_dir; | 
|  | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  |  | 
|  | // Get a small file. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), | 
|  | temp_dir.path().AppendASCII(kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  |  | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  | ASSERT_EQ(kTake[i], base::PathExists(file_path_)) << | 
|  | "FilePath: " << file_path_.value(); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, OverwriteExistingFile) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | base::ScopedTempDir temp_dir; | 
|  | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  |  | 
|  | // Create a file before trying to fetch. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | std::string data(10000, '?');  // Meant to be larger than simple.html. | 
|  | file_path_ = temp_dir.path().AppendASCII(kFileToFetch); | 
|  | ASSERT_EQ(static_cast<int>(data.size()), | 
|  | base::WriteFile(file_path_, data.data(), data.size())); | 
|  | ASSERT_TRUE(base::PathExists(file_path_)); | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | ASSERT_FALSE(base::ContentsEqual(file_path_, expected_file_)); | 
|  |  | 
|  | // Get a small file. | 
|  | CreateFetcherForFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), | 
|  | file_path_); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, TryToOverwriteDirectory) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | base::ScopedTempDir temp_dir; | 
|  | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  |  | 
|  | // Create a directory before trying to fetch. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | file_path_ = temp_dir.path().AppendASCII(kFileToFetch); | 
|  | ASSERT_TRUE(base::CreateDirectory(file_path_)); | 
|  | ASSERT_TRUE(base::PathExists(file_path_)); | 
|  |  | 
|  | // Get a small file. | 
|  | expected_file_error_ = ERR_ACCESS_DENIED; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch), | 
|  | file_path_); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  |  | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, SmallGetToTempFile) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // Get a small file. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForTempFile( | 
|  | test_server.GetURL(std::string(kTestServerFilePrefix) + kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  |  | 
|  | ASSERT_FALSE(base::PathExists(file_path_)) | 
|  | << file_path_.value() << " not removed."; | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, LargeGetToTempFile) { | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // Get a file large enough to require more than one read into | 
|  | // URLFetcher::Core's IOBuffer. | 
|  | static const char kFileToFetch[] = "animate1.gif"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForTempFile(test_server.GetURL( | 
|  | std::string(kTestServerFilePrefix) + kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  | } | 
|  |  | 
|  | TEST_F(URLFetcherFileTest, SavedOutputTempFileOwnerhisp) { | 
|  | // If the caller takes the ownership of the temp file, the file should persist | 
|  | // even after URLFetcher is gone. If not, the file must be deleted. | 
|  | const bool kTake[] = {false, true}; | 
|  | for (size_t i = 0; i < arraysize(kTake); ++i) { | 
|  | take_ownership_of_file_ = kTake[i]; | 
|  |  | 
|  | SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, | 
|  | SpawnedTestServer::kLocalhost, | 
|  | base::FilePath(kDocRoot)); | 
|  | ASSERT_TRUE(test_server.Start()); | 
|  |  | 
|  | // Get a small file. | 
|  | static const char kFileToFetch[] = "simple.html"; | 
|  | expected_file_ = test_server.GetDocumentRoot().AppendASCII(kFileToFetch); | 
|  | CreateFetcherForTempFile(test_server.GetURL( | 
|  | std::string(kTestServerFilePrefix) + kFileToFetch)); | 
|  |  | 
|  | base::MessageLoop::current()->Run();  // OnURLFetchComplete() will Quit(). | 
|  |  | 
|  | base::MessageLoop::current()->RunUntilIdle(); | 
|  | ASSERT_EQ(kTake[i], base::PathExists(file_path_)) << | 
|  | "FilePath: " << file_path_.value(); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | }  // namespace net |