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 crx_downloader_
->set_progress_callback(progress_callback_
);
121 void CrxDownloaderTest::TearDown() {
122 crx_downloader_
.reset();
125 void CrxDownloaderTest::Quit() {
126 if (!quit_closure_
.is_null())
130 void CrxDownloaderTest::DownloadComplete(int crx_context
,
131 const CrxDownloader::Result
& result
) {
132 ++num_download_complete_calls_
;
133 crx_context_
= crx_context
;
134 download_complete_result_
= result
;
138 void CrxDownloaderTest::DownloadProgress(int crx_context
,
139 const CrxDownloader::Result
& result
) {
140 ++num_progress_calls_
;
141 download_progress_result_
= result
;
144 void CrxDownloaderTest::RunThreads() {
145 base::RunLoop runloop
;
146 quit_closure_
= runloop
.QuitClosure();
149 // Since some tests need to drain currently enqueued tasks such as network
150 // intercepts on the IO thread, run the threads until they are
151 // idle. The component updater service won't loop again until the loop count
152 // is set and the service is started.
153 RunThreadsUntilIdle();
156 void CrxDownloaderTest::RunThreadsUntilIdle() {
157 base::RunLoop().RunUntilIdle();
160 // Tests that starting a download without a url results in an error.
161 TEST_F(CrxDownloaderTest
, NoUrl
) {
162 std::vector
<GURL
> urls
;
163 crx_downloader_
->StartDownload(urls
, callback_
);
164 RunThreadsUntilIdle();
166 EXPECT_EQ(1, num_download_complete_calls_
);
167 EXPECT_EQ(kExpectedContext
, crx_context_
);
168 EXPECT_EQ(-1, download_complete_result_
.error
);
169 EXPECT_TRUE(download_complete_result_
.response
.empty());
170 EXPECT_EQ(-1, download_complete_result_
.downloaded_bytes
);
171 EXPECT_EQ(-1, download_complete_result_
.total_bytes
);
172 EXPECT_EQ(0, num_progress_calls_
);
175 // Tests that downloading from one url is successful.
176 TEST_F(CrxDownloaderTest
, OneUrl
) {
177 const GURL expected_crx_url
=
178 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
180 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
181 GetInterceptor interceptor
;
182 interceptor
.SetResponse(expected_crx_url
, test_file
);
184 crx_downloader_
->StartDownloadFromUrl(expected_crx_url
, callback_
);
187 EXPECT_EQ(1, interceptor
.GetHitCount());
189 EXPECT_EQ(1, num_download_complete_calls_
);
190 EXPECT_EQ(kExpectedContext
, crx_context_
);
191 EXPECT_EQ(0, download_complete_result_
.error
);
192 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
193 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
194 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
196 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
198 EXPECT_LE(1, num_progress_calls_
);
199 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
200 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
203 // Tests that specifying from two urls has no side effects. Expect a successful
204 // download, and only one download request be made.
205 // This test is flaky on Android. crbug.com/329883
206 #if defined(OS_ANDROID)
207 #define MAYBE_TwoUrls DISABLED_TwoUrls
209 #define MAYBE_TwoUrls TwoUrls
211 TEST_F(CrxDownloaderTest
, MAYBE_TwoUrls
) {
212 const GURL expected_crx_url
=
213 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
215 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
216 GetInterceptor interceptor
;
217 interceptor
.SetResponse(expected_crx_url
, test_file
);
219 std::vector
<GURL
> urls
;
220 urls
.push_back(expected_crx_url
);
221 urls
.push_back(expected_crx_url
);
223 crx_downloader_
->StartDownload(urls
, callback_
);
226 EXPECT_EQ(1, interceptor
.GetHitCount());
228 EXPECT_EQ(1, num_download_complete_calls_
);
229 EXPECT_EQ(kExpectedContext
, crx_context_
);
230 EXPECT_EQ(0, download_complete_result_
.error
);
231 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
232 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
233 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
235 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
237 EXPECT_LE(1, num_progress_calls_
);
238 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
239 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
242 // Tests that an invalid host results in a download error.
243 TEST_F(CrxDownloaderTest
, OneUrl_InvalidHost
) {
244 const GURL expected_crx_url
=
245 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
247 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
248 GetInterceptor interceptor
;
249 interceptor
.SetResponse(expected_crx_url
, test_file
);
251 crx_downloader_
->StartDownloadFromUrl(
252 GURL("http://no.such.host"
253 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"),
257 EXPECT_EQ(0, interceptor
.GetHitCount());
259 EXPECT_EQ(1, num_download_complete_calls_
);
260 EXPECT_EQ(kExpectedContext
, crx_context_
);
261 EXPECT_NE(0, download_complete_result_
.error
);
262 EXPECT_TRUE(download_complete_result_
.response
.empty());
265 // Tests that an invalid path results in a download error.
266 TEST_F(CrxDownloaderTest
, OneUrl_InvalidPath
) {
267 const GURL expected_crx_url
=
268 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
270 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
271 GetInterceptor interceptor
;
272 interceptor
.SetResponse(expected_crx_url
, test_file
);
274 crx_downloader_
->StartDownloadFromUrl(GURL("http://localhost/no/such/file"),
278 EXPECT_EQ(0, interceptor
.GetHitCount());
280 EXPECT_EQ(1, num_download_complete_calls_
);
281 EXPECT_EQ(kExpectedContext
, crx_context_
);
282 EXPECT_NE(0, download_complete_result_
.error
);
283 EXPECT_TRUE(download_complete_result_
.response
.empty());
286 // Tests that the fallback to a valid url is successful.
287 // This test is flaky on Android. crbug.com/329883
288 #if defined(OS_ANDROID)
289 #define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid
291 #define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid
293 TEST_F(CrxDownloaderTest
, MAYBE_TwoUrls_FirstInvalid
) {
294 const GURL expected_crx_url
=
295 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
297 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
298 GetInterceptor interceptor
;
299 interceptor
.SetResponse(expected_crx_url
, test_file
);
301 std::vector
<GURL
> urls
;
302 urls
.push_back(GURL("http://localhost/no/such/file"));
303 urls
.push_back(expected_crx_url
);
305 crx_downloader_
->StartDownload(urls
, callback_
);
308 EXPECT_EQ(1, interceptor
.GetHitCount());
310 EXPECT_EQ(1, num_download_complete_calls_
);
311 EXPECT_EQ(kExpectedContext
, crx_context_
);
312 EXPECT_EQ(0, download_complete_result_
.error
);
313 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
314 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
315 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
317 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
319 EXPECT_LE(1, num_progress_calls_
);
320 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
321 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
324 // Tests that the download succeeds if the first url is correct and the
325 // second bad url does not have a side-effect.
326 TEST_F(CrxDownloaderTest
, TwoUrls_SecondInvalid
) {
327 const GURL expected_crx_url
=
328 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
330 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
331 GetInterceptor interceptor
;
332 interceptor
.SetResponse(expected_crx_url
, test_file
);
334 std::vector
<GURL
> urls
;
335 urls
.push_back(expected_crx_url
);
336 urls
.push_back(GURL("http://localhost/no/such/file"));
338 crx_downloader_
->StartDownload(urls
, callback_
);
341 EXPECT_EQ(1, interceptor
.GetHitCount());
343 EXPECT_EQ(1, num_download_complete_calls_
);
344 EXPECT_EQ(kExpectedContext
, crx_context_
);
345 EXPECT_EQ(0, download_complete_result_
.error
);
346 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
347 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
348 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
350 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
352 EXPECT_LE(1, num_progress_calls_
);
353 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
354 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
357 // Tests that the download fails if both urls are bad.
358 TEST_F(CrxDownloaderTest
, TwoUrls_BothInvalid
) {
359 const GURL expected_crx_url
=
360 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
362 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
363 GetInterceptor interceptor
;
364 interceptor
.SetResponse(expected_crx_url
, test_file
);
366 std::vector
<GURL
> urls
;
367 urls
.push_back(GURL("http://localhost/no/such/file"));
368 urls
.push_back(GURL("http://no.such.host/"
369 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"));
371 crx_downloader_
->StartDownload(urls
, callback_
);
374 EXPECT_EQ(0, interceptor
.GetHitCount());
376 EXPECT_EQ(1, num_download_complete_calls_
);
377 EXPECT_EQ(kExpectedContext
, crx_context_
);
378 EXPECT_NE(0, download_complete_result_
.error
);
379 EXPECT_TRUE(download_complete_result_
.response
.empty());
382 } // namespace component_updater