1 // Copyright 2013 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.
6 #include "base/file_util.h"
7 #include "base/files/file_path.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/run_loop.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/browser/component_updater/crx_downloader.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "content/test/net/url_request_prepackaged_interceptor.h"
18 #include "net/base/net_errors.h"
19 #include "net/url_request/url_request_test_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using content::BrowserThread;
23 using base::ContentsEqual;
25 namespace component_updater {
29 // Intercepts HTTP GET requests sent to "localhost".
30 typedef content::URLLocalHostRequestPrepackagedInterceptor GetInterceptor;
32 const char kTestFileName[] = "jebgalgnebhfojomionfpkfelancnnkf.crx";
34 base::FilePath MakeTestFilePath(const char* file) {
36 PathService::Get(chrome::DIR_TEST_DATA, &path);
37 return path.AppendASCII("components").AppendASCII(file);
42 class CrxDownloaderTest : public testing::Test {
45 virtual ~CrxDownloaderTest();
47 // Overrides from testing::Test.
48 virtual void SetUp() OVERRIDE;
49 virtual void TearDown() OVERRIDE;
53 void RunThreadsUntilIdle();
55 void DownloadComplete(int crx_context, const CrxDownloader::Result& result);
57 void DownloadProgress(int crx_context, const CrxDownloader::Result& result);
60 scoped_ptr<CrxDownloader> crx_downloader_;
62 CrxDownloader::DownloadCallback callback_;
63 CrxDownloader::ProgressCallback progress_callback_;
67 int num_download_complete_calls_;
68 CrxDownloader::Result download_complete_result_;
70 // These members are updated by DownloadProgress.
71 int num_progress_calls_;
72 CrxDownloader::Result download_progress_result_;
74 // A magic value for the context to be used in the tests.
75 static const int kExpectedContext = 0xaabb;
78 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
79 scoped_refptr<net::TestURLRequestContextGetter> context_;
80 content::TestBrowserThreadBundle thread_bundle_;
81 base::Closure quit_closure_;
84 const int CrxDownloaderTest::kExpectedContext;
86 CrxDownloaderTest::CrxDownloaderTest()
87 : callback_(base::Bind(&CrxDownloaderTest::DownloadComplete,
88 base::Unretained(this),
90 progress_callback_(base::Bind(&CrxDownloaderTest::DownloadProgress,
91 base::Unretained(this),
94 num_download_complete_calls_(0),
95 num_progress_calls_(0),
96 blocking_task_runner_(BrowserThread::GetBlockingPool()->
97 GetSequencedTaskRunnerWithShutdownBehavior(
98 BrowserThread::GetBlockingPool()->GetSequenceToken(),
99 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
100 context_(new net::TestURLRequestContextGetter(
101 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))),
102 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
105 CrxDownloaderTest::~CrxDownloaderTest() {
109 void CrxDownloaderTest::SetUp() {
110 num_download_complete_calls_ = 0;
111 download_complete_result_ = CrxDownloader::Result();
112 num_progress_calls_ = 0;
113 download_progress_result_ = CrxDownloader::Result();
114 crx_downloader_.reset(CrxDownloader::Create(
115 false, // Do not use the background downloader in these tests.
117 blocking_task_runner_,
118 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
119 crx_downloader_->set_progress_callback(progress_callback_);
122 void CrxDownloaderTest::TearDown() {
123 crx_downloader_.reset();
126 void CrxDownloaderTest::Quit() {
127 if (!quit_closure_.is_null())
131 void CrxDownloaderTest::DownloadComplete(int crx_context,
132 const CrxDownloader::Result& result) {
133 ++num_download_complete_calls_;
134 crx_context_ = crx_context;
135 download_complete_result_ = result;
139 void CrxDownloaderTest::DownloadProgress(int crx_context,
140 const CrxDownloader::Result& result) {
141 ++num_progress_calls_;
142 download_progress_result_ = result;
145 void CrxDownloaderTest::RunThreads() {
146 base::RunLoop runloop;
147 quit_closure_ = runloop.QuitClosure();
150 // Since some tests need to drain currently enqueued tasks such as network
151 // intercepts on the IO thread, run the threads until they are
152 // idle. The component updater service won't loop again until the loop count
153 // is set and the service is started.
154 RunThreadsUntilIdle();
157 void CrxDownloaderTest::RunThreadsUntilIdle() {
158 base::RunLoop().RunUntilIdle();
161 // Tests that starting a download without a url results in an error.
162 TEST_F(CrxDownloaderTest, NoUrl) {
163 std::vector<GURL> urls;
164 crx_downloader_->StartDownload(urls, callback_);
165 RunThreadsUntilIdle();
167 EXPECT_EQ(1, num_download_complete_calls_);
168 EXPECT_EQ(kExpectedContext, crx_context_);
169 EXPECT_EQ(-1, download_complete_result_.error);
170 EXPECT_TRUE(download_complete_result_.response.empty());
171 EXPECT_EQ(-1, download_complete_result_.downloaded_bytes);
172 EXPECT_EQ(-1, download_complete_result_.total_bytes);
173 EXPECT_EQ(0, num_progress_calls_);
176 // Tests that downloading from one url is successful.
177 TEST_F(CrxDownloaderTest, OneUrl) {
178 const GURL expected_crx_url =
179 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
181 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
182 GetInterceptor interceptor;
183 interceptor.SetResponse(expected_crx_url, test_file);
185 crx_downloader_->StartDownloadFromUrl(expected_crx_url, callback_);
188 EXPECT_EQ(1, interceptor.GetHitCount());
190 EXPECT_EQ(1, num_download_complete_calls_);
191 EXPECT_EQ(kExpectedContext, crx_context_);
192 EXPECT_EQ(0, download_complete_result_.error);
193 EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
194 EXPECT_EQ(1843, download_complete_result_.total_bytes);
195 EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
197 EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
199 EXPECT_LE(1, num_progress_calls_);
200 EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
201 EXPECT_EQ(1843, download_progress_result_.total_bytes);
204 // Tests that specifying from two urls has no side effects. Expect a successful
205 // download, and only one download request be made.
206 // This test is flaky on Android. crbug.com/329883
207 #if defined(OS_ANDROID)
208 #define MAYBE_TwoUrls DISABLED_TwoUrls
210 #define MAYBE_TwoUrls TwoUrls
212 TEST_F(CrxDownloaderTest, MAYBE_TwoUrls) {
213 const GURL expected_crx_url =
214 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
216 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
217 GetInterceptor interceptor;
218 interceptor.SetResponse(expected_crx_url, test_file);
220 std::vector<GURL> urls;
221 urls.push_back(expected_crx_url);
222 urls.push_back(expected_crx_url);
224 crx_downloader_->StartDownload(urls, callback_);
227 EXPECT_EQ(1, interceptor.GetHitCount());
229 EXPECT_EQ(1, num_download_complete_calls_);
230 EXPECT_EQ(kExpectedContext, crx_context_);
231 EXPECT_EQ(0, download_complete_result_.error);
232 EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
233 EXPECT_EQ(1843, download_complete_result_.total_bytes);
234 EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
236 EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
238 EXPECT_LE(1, num_progress_calls_);
239 EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
240 EXPECT_EQ(1843, download_progress_result_.total_bytes);
243 // Tests that an invalid host results in a download error.
244 TEST_F(CrxDownloaderTest, OneUrl_InvalidHost) {
245 const GURL expected_crx_url =
246 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
248 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
249 GetInterceptor interceptor;
250 interceptor.SetResponse(expected_crx_url, test_file);
252 crx_downloader_->StartDownloadFromUrl(
253 GURL("http://no.such.host"
254 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"),
258 EXPECT_EQ(0, interceptor.GetHitCount());
260 EXPECT_EQ(1, num_download_complete_calls_);
261 EXPECT_EQ(kExpectedContext, crx_context_);
262 EXPECT_NE(0, download_complete_result_.error);
263 EXPECT_TRUE(download_complete_result_.response.empty());
266 // Tests that an invalid path results in a download error.
267 TEST_F(CrxDownloaderTest, OneUrl_InvalidPath) {
268 const GURL expected_crx_url =
269 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
271 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
272 GetInterceptor interceptor;
273 interceptor.SetResponse(expected_crx_url, test_file);
275 crx_downloader_->StartDownloadFromUrl(GURL("http://localhost/no/such/file"),
279 EXPECT_EQ(0, interceptor.GetHitCount());
281 EXPECT_EQ(1, num_download_complete_calls_);
282 EXPECT_EQ(kExpectedContext, crx_context_);
283 EXPECT_NE(0, download_complete_result_.error);
284 EXPECT_TRUE(download_complete_result_.response.empty());
287 // Tests that the fallback to a valid url is successful.
288 // This test is flaky on Android. crbug.com/329883
289 #if defined(OS_ANDROID)
290 #define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid
292 #define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid
294 TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) {
295 const GURL expected_crx_url =
296 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
298 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
299 GetInterceptor interceptor;
300 interceptor.SetResponse(expected_crx_url, test_file);
302 std::vector<GURL> urls;
303 urls.push_back(GURL("http://localhost/no/such/file"));
304 urls.push_back(expected_crx_url);
306 crx_downloader_->StartDownload(urls, callback_);
309 EXPECT_EQ(1, interceptor.GetHitCount());
311 EXPECT_EQ(1, num_download_complete_calls_);
312 EXPECT_EQ(kExpectedContext, crx_context_);
313 EXPECT_EQ(0, download_complete_result_.error);
314 EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
315 EXPECT_EQ(1843, download_complete_result_.total_bytes);
316 EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
318 EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
320 EXPECT_LE(1, num_progress_calls_);
321 EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
322 EXPECT_EQ(1843, download_progress_result_.total_bytes);
325 // Tests that the download succeeds if the first url is correct and the
326 // second bad url does not have a side-effect.
327 TEST_F(CrxDownloaderTest, TwoUrls_SecondInvalid) {
328 const GURL expected_crx_url =
329 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
331 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
332 GetInterceptor interceptor;
333 interceptor.SetResponse(expected_crx_url, test_file);
335 std::vector<GURL> urls;
336 urls.push_back(expected_crx_url);
337 urls.push_back(GURL("http://localhost/no/such/file"));
339 crx_downloader_->StartDownload(urls, callback_);
342 EXPECT_EQ(1, interceptor.GetHitCount());
344 EXPECT_EQ(1, num_download_complete_calls_);
345 EXPECT_EQ(kExpectedContext, crx_context_);
346 EXPECT_EQ(0, download_complete_result_.error);
347 EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
348 EXPECT_EQ(1843, download_complete_result_.total_bytes);
349 EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
351 EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
353 EXPECT_LE(1, num_progress_calls_);
354 EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
355 EXPECT_EQ(1843, download_progress_result_.total_bytes);
358 // Tests that the download fails if both urls are bad.
359 TEST_F(CrxDownloaderTest, TwoUrls_BothInvalid) {
360 const GURL expected_crx_url =
361 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
363 const base::FilePath test_file(MakeTestFilePath(kTestFileName));
364 GetInterceptor interceptor;
365 interceptor.SetResponse(expected_crx_url, test_file);
367 std::vector<GURL> urls;
368 urls.push_back(GURL("http://localhost/no/such/file"));
369 urls.push_back(GURL("http://no.such.host/"
370 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"));
372 crx_downloader_->StartDownload(urls, callback_);
375 EXPECT_EQ(0, interceptor.GetHitCount());
377 EXPECT_EQ(1, num_download_complete_calls_);
378 EXPECT_EQ(kExpectedContext, crx_context_);
379 EXPECT_NE(0, download_complete_result_.error);
380 EXPECT_TRUE(download_complete_result_.response.empty());
383 } // namespace component_updater