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/bind_helpers.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/run_loop.h"
14 #include "components/update_client/crx_downloader.h"
15 #include "net/base/net_errors.h"
16 #include "net/url_request/test_url_request_interceptor.h"
17 #include "net/url_request/url_request_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using base::ContentsEqual
;
22 namespace update_client
{
26 // Intercepts HTTP GET requests sent to "localhost".
27 typedef net::LocalHostTestURLRequestInterceptor GetInterceptor
;
29 const char kTestFileName
[] = "jebgalgnebhfojomionfpkfelancnnkf.crx";
31 base::FilePath
MakeTestFilePath(const char* file
) {
33 PathService::Get(base::DIR_SOURCE_ROOT
, &path
);
34 return path
.AppendASCII("components")
37 .AppendASCII("update_client")
43 class CrxDownloaderTest
: public testing::Test
{
46 ~CrxDownloaderTest() override
;
48 // Overrides from testing::Test.
49 void SetUp() override
;
50 void TearDown() override
;
54 void RunThreadsUntilIdle();
56 void DownloadComplete(int crx_context
, const CrxDownloader::Result
& result
);
58 void DownloadProgress(int crx_context
, const CrxDownloader::Result
& result
);
61 scoped_ptr
<CrxDownloader
> crx_downloader_
;
63 scoped_ptr
<GetInterceptor
> get_interceptor_
;
65 CrxDownloader::DownloadCallback callback_
;
66 CrxDownloader::ProgressCallback progress_callback_
;
70 int num_download_complete_calls_
;
71 CrxDownloader::Result download_complete_result_
;
73 // These members are updated by DownloadProgress.
74 int num_progress_calls_
;
75 CrxDownloader::Result download_progress_result_
;
77 // A magic value for the context to be used in the tests.
78 static const int kExpectedContext
= 0xaabb;
81 base::MessageLoopForIO loop_
;
82 scoped_refptr
<net::TestURLRequestContextGetter
> context_
;
83 base::Closure quit_closure_
;
86 const int CrxDownloaderTest::kExpectedContext
;
88 CrxDownloaderTest::CrxDownloaderTest()
89 : callback_(base::Bind(&CrxDownloaderTest::DownloadComplete
,
90 base::Unretained(this),
92 progress_callback_(base::Bind(&CrxDownloaderTest::DownloadProgress
,
93 base::Unretained(this),
96 num_download_complete_calls_(0),
97 num_progress_calls_(0),
98 context_(new net::TestURLRequestContextGetter(
99 base::MessageLoopProxy::current())) {
102 CrxDownloaderTest::~CrxDownloaderTest() {
105 // The GetInterceptor requires the message loop to run to destruct correctly.
106 get_interceptor_
.reset();
107 RunThreadsUntilIdle();
110 void CrxDownloaderTest::SetUp() {
111 num_download_complete_calls_
= 0;
112 download_complete_result_
= CrxDownloader::Result();
113 num_progress_calls_
= 0;
114 download_progress_result_
= CrxDownloader::Result();
116 crx_downloader_
.reset(CrxDownloader::Create(
117 false, // Do not use the background downloader in these tests.
118 context_
.get(), base::MessageLoopProxy::current(),
119 NULL
)); // No |background_task_runner| because no background downloader.
120 crx_downloader_
->set_progress_callback(progress_callback_
);
122 get_interceptor_
.reset(new GetInterceptor(base::MessageLoopProxy::current(),
123 base::MessageLoopProxy::current()));
126 void CrxDownloaderTest::TearDown() {
127 crx_downloader_
.reset();
130 void CrxDownloaderTest::Quit() {
131 if (!quit_closure_
.is_null())
135 void CrxDownloaderTest::DownloadComplete(int crx_context
,
136 const CrxDownloader::Result
& result
) {
137 ++num_download_complete_calls_
;
138 crx_context_
= crx_context
;
139 download_complete_result_
= result
;
143 void CrxDownloaderTest::DownloadProgress(int crx_context
,
144 const CrxDownloader::Result
& result
) {
145 ++num_progress_calls_
;
146 download_progress_result_
= result
;
149 void CrxDownloaderTest::RunThreads() {
150 base::RunLoop runloop
;
151 quit_closure_
= runloop
.QuitClosure();
154 // Since some tests need to drain currently enqueued tasks such as network
155 // intercepts on the IO thread, run the threads until they are
156 // idle. The component updater service won't loop again until the loop count
157 // is set and the service is started.
158 RunThreadsUntilIdle();
161 void CrxDownloaderTest::RunThreadsUntilIdle() {
162 base::RunLoop().RunUntilIdle();
165 // Tests that starting a download without a url results in an error.
166 TEST_F(CrxDownloaderTest
, NoUrl
) {
167 std::vector
<GURL
> urls
;
168 crx_downloader_
->StartDownload(urls
, callback_
);
169 RunThreadsUntilIdle();
171 EXPECT_EQ(1, num_download_complete_calls_
);
172 EXPECT_EQ(kExpectedContext
, crx_context_
);
173 EXPECT_EQ(-1, download_complete_result_
.error
);
174 EXPECT_TRUE(download_complete_result_
.response
.empty());
175 EXPECT_EQ(-1, download_complete_result_
.downloaded_bytes
);
176 EXPECT_EQ(-1, download_complete_result_
.total_bytes
);
177 EXPECT_EQ(0, num_progress_calls_
);
180 // Tests that downloading from one url is successful.
181 TEST_F(CrxDownloaderTest
, OneUrl
) {
182 const GURL expected_crx_url
=
183 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
185 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
186 get_interceptor_
->SetResponse(expected_crx_url
, test_file
);
188 crx_downloader_
->StartDownloadFromUrl(expected_crx_url
, callback_
);
191 EXPECT_EQ(1, get_interceptor_
->GetHitCount());
193 EXPECT_EQ(1, num_download_complete_calls_
);
194 EXPECT_EQ(kExpectedContext
, crx_context_
);
195 EXPECT_EQ(0, download_complete_result_
.error
);
196 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
197 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
198 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
200 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
202 EXPECT_LE(1, num_progress_calls_
);
203 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
204 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
207 // Tests that specifying from two urls has no side effects. Expect a successful
208 // download, and only one download request be made.
209 // This test is flaky on Android. crbug.com/329883
210 #if defined(OS_ANDROID)
211 #define MAYBE_TwoUrls DISABLED_TwoUrls
213 #define MAYBE_TwoUrls TwoUrls
215 TEST_F(CrxDownloaderTest
, MAYBE_TwoUrls
) {
216 const GURL expected_crx_url
=
217 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
219 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
220 get_interceptor_
->SetResponse(expected_crx_url
, test_file
);
222 std::vector
<GURL
> urls
;
223 urls
.push_back(expected_crx_url
);
224 urls
.push_back(expected_crx_url
);
226 crx_downloader_
->StartDownload(urls
, callback_
);
229 EXPECT_EQ(1, get_interceptor_
->GetHitCount());
231 EXPECT_EQ(1, num_download_complete_calls_
);
232 EXPECT_EQ(kExpectedContext
, crx_context_
);
233 EXPECT_EQ(0, download_complete_result_
.error
);
234 EXPECT_EQ(1843, download_complete_result_
.downloaded_bytes
);
235 EXPECT_EQ(1843, download_complete_result_
.total_bytes
);
236 EXPECT_TRUE(ContentsEqual(download_complete_result_
.response
, test_file
));
238 EXPECT_TRUE(base::DeleteFile(download_complete_result_
.response
, false));
240 EXPECT_LE(1, num_progress_calls_
);
241 EXPECT_EQ(1843, download_progress_result_
.downloaded_bytes
);
242 EXPECT_EQ(1843, download_progress_result_
.total_bytes
);
245 // Tests that an invalid host results in a download error.
246 TEST_F(CrxDownloaderTest
, OneUrl_InvalidHost
) {
247 const GURL expected_crx_url
=
248 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
250 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
251 get_interceptor_
->SetResponse(expected_crx_url
, test_file
);
253 crx_downloader_
->StartDownloadFromUrl(
255 "http://no.such.host"
256 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"),
260 EXPECT_EQ(0, get_interceptor_
->GetHitCount());
262 EXPECT_EQ(1, num_download_complete_calls_
);
263 EXPECT_EQ(kExpectedContext
, crx_context_
);
264 EXPECT_NE(0, download_complete_result_
.error
);
265 EXPECT_TRUE(download_complete_result_
.response
.empty());
268 // Tests that an invalid path results in a download error.
269 TEST_F(CrxDownloaderTest
, OneUrl_InvalidPath
) {
270 const GURL expected_crx_url
=
271 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
273 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
274 get_interceptor_
->SetResponse(expected_crx_url
, test_file
);
276 crx_downloader_
->StartDownloadFromUrl(GURL("http://localhost/no/such/file"),
280 EXPECT_EQ(0, get_interceptor_
->GetHitCount());
282 EXPECT_EQ(1, num_download_complete_calls_
);
283 EXPECT_EQ(kExpectedContext
, crx_context_
);
284 EXPECT_NE(0, download_complete_result_
.error
);
285 EXPECT_TRUE(download_complete_result_
.response
.empty());
288 // Tests that the fallback to a valid url is successful.
289 // This test is flaky on Android. crbug.com/329883
290 #if defined(OS_ANDROID)
291 #define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid
293 #define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid
295 TEST_F(CrxDownloaderTest
, MAYBE_TwoUrls_FirstInvalid
) {
296 const GURL expected_crx_url
=
297 GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
299 const base::FilePath
test_file(MakeTestFilePath(kTestFileName
));
300 get_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, get_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 get_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, get_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 get_interceptor_
->SetResponse(expected_crx_url
, test_file
);
365 std::vector
<GURL
> urls
;
366 urls
.push_back(GURL("http://localhost/no/such/file"));
368 "http://no.such.host/"
369 "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"));
371 crx_downloader_
->StartDownload(urls
, callback_
);
374 EXPECT_EQ(0, get_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 update_client