Index: components/update_client/test/crx_downloader_unittest.cc |
diff --git a/components/update_client/test/crx_downloader_unittest.cc b/components/update_client/test/crx_downloader_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5b01b42294d56a6d28be90504e5529542cb588ba |
--- /dev/null |
+++ b/components/update_client/test/crx_downloader_unittest.cc |
@@ -0,0 +1,382 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/files/file_path.h" |
+#include "base/files/file_util.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/path_service.h" |
+#include "base/run_loop.h" |
+#include "components/update_client/crx_downloader.h" |
+#include "net/base/net_errors.h" |
+#include "net/url_request/test_url_request_interceptor.h" |
+#include "net/url_request/url_request_test_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using base::ContentsEqual; |
+ |
+namespace update_client { |
+ |
+namespace { |
+ |
+// Intercepts HTTP GET requests sent to "localhost". |
+typedef net::LocalHostTestURLRequestInterceptor GetInterceptor; |
+ |
+const char kTestFileName[] = "jebgalgnebhfojomionfpkfelancnnkf.crx"; |
+ |
+base::FilePath MakeTestFilePath(const char* file) { |
+ base::FilePath path; |
+ PathService::Get(base::DIR_SOURCE_ROOT, &path); |
+ return path.AppendASCII("components") |
+ .AppendASCII("test") |
+ .AppendASCII("data") |
+ .AppendASCII("update_client") |
+ .AppendASCII(file); |
+} |
+ |
+} // namespace |
+ |
+class CrxDownloaderTest : public testing::Test { |
+ public: |
+ CrxDownloaderTest(); |
+ ~CrxDownloaderTest() override; |
+ |
+ // Overrides from testing::Test. |
+ void SetUp() override; |
+ void TearDown() override; |
+ |
+ void Quit(); |
+ void RunThreads(); |
+ void RunThreadsUntilIdle(); |
+ |
+ void DownloadComplete(int crx_context, const CrxDownloader::Result& result); |
+ |
+ void DownloadProgress(int crx_context, const CrxDownloader::Result& result); |
+ |
+ protected: |
+ scoped_ptr<CrxDownloader> crx_downloader_; |
+ |
+ scoped_ptr<GetInterceptor> get_interceptor_; |
+ |
+ CrxDownloader::DownloadCallback callback_; |
+ CrxDownloader::ProgressCallback progress_callback_; |
+ |
+ int crx_context_; |
+ |
+ int num_download_complete_calls_; |
+ CrxDownloader::Result download_complete_result_; |
+ |
+ // These members are updated by DownloadProgress. |
+ int num_progress_calls_; |
+ CrxDownloader::Result download_progress_result_; |
+ |
+ // A magic value for the context to be used in the tests. |
+ static const int kExpectedContext = 0xaabb; |
+ |
+ private: |
+ base::MessageLoopForIO loop_; |
+ scoped_refptr<net::TestURLRequestContextGetter> context_; |
+ base::Closure quit_closure_; |
+}; |
+ |
+const int CrxDownloaderTest::kExpectedContext; |
+ |
+CrxDownloaderTest::CrxDownloaderTest() |
+ : callback_(base::Bind(&CrxDownloaderTest::DownloadComplete, |
+ base::Unretained(this), |
+ kExpectedContext)), |
+ progress_callback_(base::Bind(&CrxDownloaderTest::DownloadProgress, |
+ base::Unretained(this), |
+ kExpectedContext)), |
+ crx_context_(0), |
+ num_download_complete_calls_(0), |
+ num_progress_calls_(0), |
+ context_(new net::TestURLRequestContextGetter( |
+ base::MessageLoopProxy::current())) { |
+} |
+ |
+CrxDownloaderTest::~CrxDownloaderTest() { |
+ context_ = NULL; |
+ |
+ // The GetInterceptor requires the message loop to run to destruct correctly. |
+ get_interceptor_.reset(); |
+ RunThreadsUntilIdle(); |
+} |
+ |
+void CrxDownloaderTest::SetUp() { |
+ num_download_complete_calls_ = 0; |
+ download_complete_result_ = CrxDownloader::Result(); |
+ num_progress_calls_ = 0; |
+ download_progress_result_ = CrxDownloader::Result(); |
+ |
+ crx_downloader_.reset(CrxDownloader::Create( |
+ false, // Do not use the background downloader in these tests. |
+ context_.get(), base::MessageLoopProxy::current(), |
+ NULL)); // No |background_task_runner| because no background downloader. |
+ crx_downloader_->set_progress_callback(progress_callback_); |
+ |
+ get_interceptor_.reset(new GetInterceptor(base::MessageLoopProxy::current(), |
+ base::MessageLoopProxy::current())); |
+} |
+ |
+void CrxDownloaderTest::TearDown() { |
+ crx_downloader_.reset(); |
+} |
+ |
+void CrxDownloaderTest::Quit() { |
+ if (!quit_closure_.is_null()) |
+ quit_closure_.Run(); |
+} |
+ |
+void CrxDownloaderTest::DownloadComplete(int crx_context, |
+ const CrxDownloader::Result& result) { |
+ ++num_download_complete_calls_; |
+ crx_context_ = crx_context; |
+ download_complete_result_ = result; |
+ Quit(); |
+} |
+ |
+void CrxDownloaderTest::DownloadProgress(int crx_context, |
+ const CrxDownloader::Result& result) { |
+ ++num_progress_calls_; |
+ download_progress_result_ = result; |
+} |
+ |
+void CrxDownloaderTest::RunThreads() { |
+ base::RunLoop runloop; |
+ quit_closure_ = runloop.QuitClosure(); |
+ runloop.Run(); |
+ |
+ // Since some tests need to drain currently enqueued tasks such as network |
+ // intercepts on the IO thread, run the threads until they are |
+ // idle. The component updater service won't loop again until the loop count |
+ // is set and the service is started. |
+ RunThreadsUntilIdle(); |
+} |
+ |
+void CrxDownloaderTest::RunThreadsUntilIdle() { |
+ base::RunLoop().RunUntilIdle(); |
+} |
+ |
+// Tests that starting a download without a url results in an error. |
+TEST_F(CrxDownloaderTest, NoUrl) { |
+ std::vector<GURL> urls; |
+ crx_downloader_->StartDownload(urls, callback_); |
+ RunThreadsUntilIdle(); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_EQ(-1, download_complete_result_.error); |
+ EXPECT_TRUE(download_complete_result_.response.empty()); |
+ EXPECT_EQ(-1, download_complete_result_.downloaded_bytes); |
+ EXPECT_EQ(-1, download_complete_result_.total_bytes); |
+ EXPECT_EQ(0, num_progress_calls_); |
+} |
+ |
+// Tests that downloading from one url is successful. |
+TEST_F(CrxDownloaderTest, OneUrl) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ crx_downloader_->StartDownloadFromUrl(expected_crx_url, callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(1, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_EQ(0, download_complete_result_.error); |
+ EXPECT_EQ(1843, download_complete_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_complete_result_.total_bytes); |
+ EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file)); |
+ |
+ EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false)); |
+ |
+ EXPECT_LE(1, num_progress_calls_); |
+ EXPECT_EQ(1843, download_progress_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_progress_result_.total_bytes); |
+} |
+ |
+// Tests that specifying from two urls has no side effects. Expect a successful |
+// download, and only one download request be made. |
+// This test is flaky on Android. crbug.com/329883 |
+#if defined(OS_ANDROID) |
+#define MAYBE_TwoUrls DISABLED_TwoUrls |
+#else |
+#define MAYBE_TwoUrls TwoUrls |
+#endif |
+TEST_F(CrxDownloaderTest, MAYBE_TwoUrls) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ std::vector<GURL> urls; |
+ urls.push_back(expected_crx_url); |
+ urls.push_back(expected_crx_url); |
+ |
+ crx_downloader_->StartDownload(urls, callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(1, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_EQ(0, download_complete_result_.error); |
+ EXPECT_EQ(1843, download_complete_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_complete_result_.total_bytes); |
+ EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file)); |
+ |
+ EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false)); |
+ |
+ EXPECT_LE(1, num_progress_calls_); |
+ EXPECT_EQ(1843, download_progress_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_progress_result_.total_bytes); |
+} |
+ |
+// Tests that an invalid host results in a download error. |
+TEST_F(CrxDownloaderTest, OneUrl_InvalidHost) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ crx_downloader_->StartDownloadFromUrl( |
+ GURL( |
+ "http://no.such.host" |
+ "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"), |
+ callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(0, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_NE(0, download_complete_result_.error); |
+ EXPECT_TRUE(download_complete_result_.response.empty()); |
+} |
+ |
+// Tests that an invalid path results in a download error. |
+TEST_F(CrxDownloaderTest, OneUrl_InvalidPath) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ crx_downloader_->StartDownloadFromUrl(GURL("http://localhost/no/such/file"), |
+ callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(0, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_NE(0, download_complete_result_.error); |
+ EXPECT_TRUE(download_complete_result_.response.empty()); |
+} |
+ |
+// Tests that the fallback to a valid url is successful. |
+// This test is flaky on Android. crbug.com/329883 |
+#if defined(OS_ANDROID) |
+#define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid |
+#else |
+#define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid |
+#endif |
+TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ std::vector<GURL> urls; |
+ urls.push_back(GURL("http://localhost/no/such/file")); |
+ urls.push_back(expected_crx_url); |
+ |
+ crx_downloader_->StartDownload(urls, callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(1, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_EQ(0, download_complete_result_.error); |
+ EXPECT_EQ(1843, download_complete_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_complete_result_.total_bytes); |
+ EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file)); |
+ |
+ EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false)); |
+ |
+ EXPECT_LE(1, num_progress_calls_); |
+ EXPECT_EQ(1843, download_progress_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_progress_result_.total_bytes); |
+} |
+ |
+// Tests that the download succeeds if the first url is correct and the |
+// second bad url does not have a side-effect. |
+TEST_F(CrxDownloaderTest, TwoUrls_SecondInvalid) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ std::vector<GURL> urls; |
+ urls.push_back(expected_crx_url); |
+ urls.push_back(GURL("http://localhost/no/such/file")); |
+ |
+ crx_downloader_->StartDownload(urls, callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(1, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_EQ(0, download_complete_result_.error); |
+ EXPECT_EQ(1843, download_complete_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_complete_result_.total_bytes); |
+ EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file)); |
+ |
+ EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false)); |
+ |
+ EXPECT_LE(1, num_progress_calls_); |
+ EXPECT_EQ(1843, download_progress_result_.downloaded_bytes); |
+ EXPECT_EQ(1843, download_progress_result_.total_bytes); |
+} |
+ |
+// Tests that the download fails if both urls are bad. |
+TEST_F(CrxDownloaderTest, TwoUrls_BothInvalid) { |
+ const GURL expected_crx_url = |
+ GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"); |
+ |
+ const base::FilePath test_file(MakeTestFilePath(kTestFileName)); |
+ get_interceptor_->SetResponse(expected_crx_url, test_file); |
+ |
+ std::vector<GURL> urls; |
+ urls.push_back(GURL("http://localhost/no/such/file")); |
+ urls.push_back(GURL( |
+ "http://no.such.host/" |
+ "/download/jebgalgnebhfojomionfpkfelancnnkf.crx")); |
+ |
+ crx_downloader_->StartDownload(urls, callback_); |
+ RunThreads(); |
+ |
+ EXPECT_EQ(0, get_interceptor_->GetHitCount()); |
+ |
+ EXPECT_EQ(1, num_download_complete_calls_); |
+ EXPECT_EQ(kExpectedContext, crx_context_); |
+ EXPECT_NE(0, download_complete_result_.error); |
+ EXPECT_TRUE(download_complete_result_.response.empty()); |
+} |
+ |
+} // namespace update_client |