Home | History | Annotate | Download | only in test
      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.
      4 
      5 #include "base/bind.h"
      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/component_updater/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"
     19 
     20 using base::ContentsEqual;
     21 
     22 namespace component_updater {
     23 
     24 namespace {
     25 
     26 // Intercepts HTTP GET requests sent to "localhost".
     27 typedef net::LocalHostTestURLRequestInterceptor GetInterceptor;
     28 
     29 const char kTestFileName[] = "jebgalgnebhfojomionfpkfelancnnkf.crx";
     30 
     31 base::FilePath MakeTestFilePath(const char* file) {
     32   base::FilePath path;
     33   PathService::Get(base::DIR_SOURCE_ROOT, &path);
     34   return path.AppendASCII("components").AppendASCII("test").AppendASCII("data")
     35       .AppendASCII("component_updater").AppendASCII(file);
     36 }
     37 
     38 }  // namespace
     39 
     40 class CrxDownloaderTest : public testing::Test {
     41  public:
     42   CrxDownloaderTest();
     43   virtual ~CrxDownloaderTest();
     44 
     45   // Overrides from testing::Test.
     46   virtual void SetUp() OVERRIDE;
     47   virtual void TearDown() OVERRIDE;
     48 
     49   void Quit();
     50   void RunThreads();
     51   void RunThreadsUntilIdle();
     52 
     53   void DownloadComplete(int crx_context, const CrxDownloader::Result& result);
     54 
     55   void DownloadProgress(int crx_context, const CrxDownloader::Result& result);
     56 
     57  protected:
     58   scoped_ptr<CrxDownloader> crx_downloader_;
     59 
     60   scoped_ptr<GetInterceptor> get_interceptor_;
     61 
     62   CrxDownloader::DownloadCallback callback_;
     63   CrxDownloader::ProgressCallback progress_callback_;
     64 
     65   int crx_context_;
     66 
     67   int num_download_complete_calls_;
     68   CrxDownloader::Result download_complete_result_;
     69 
     70   // These members are updated by DownloadProgress.
     71   int num_progress_calls_;
     72   CrxDownloader::Result download_progress_result_;
     73 
     74   // A magic value for the context to be used in the tests.
     75   static const int kExpectedContext = 0xaabb;
     76 
     77  private:
     78   base::MessageLoopForIO loop_;
     79   scoped_refptr<net::TestURLRequestContextGetter> context_;
     80   base::Closure quit_closure_;
     81 };
     82 
     83 const int CrxDownloaderTest::kExpectedContext;
     84 
     85 CrxDownloaderTest::CrxDownloaderTest()
     86     : callback_(base::Bind(&CrxDownloaderTest::DownloadComplete,
     87                            base::Unretained(this),
     88                            kExpectedContext)),
     89       progress_callback_(base::Bind(&CrxDownloaderTest::DownloadProgress,
     90                                     base::Unretained(this),
     91                                     kExpectedContext)),
     92       crx_context_(0),
     93       num_download_complete_calls_(0),
     94       num_progress_calls_(0),
     95       context_(new net::TestURLRequestContextGetter(
     96           base::MessageLoopProxy::current())) {
     97 }
     98 
     99 CrxDownloaderTest::~CrxDownloaderTest() {
    100   context_ = NULL;
    101 
    102   // The GetInterceptor requires the message loop to run to destruct correctly.
    103   get_interceptor_.reset();
    104   RunThreadsUntilIdle();
    105 }
    106 
    107 void CrxDownloaderTest::SetUp() {
    108   num_download_complete_calls_ = 0;
    109   download_complete_result_ = CrxDownloader::Result();
    110   num_progress_calls_ = 0;
    111   download_progress_result_ = CrxDownloader::Result();
    112 
    113   crx_downloader_.reset(CrxDownloader::Create(
    114       false,  // Do not use the background downloader in these tests.
    115       context_.get(),
    116       base::MessageLoopProxy::current(),
    117       NULL));  // No |background_task_runner| because no background downloader.
    118   crx_downloader_->set_progress_callback(progress_callback_);
    119 
    120   get_interceptor_.reset(new GetInterceptor(base::MessageLoopProxy::current(),
    121                                             base::MessageLoopProxy::current()));
    122 }
    123 
    124 void CrxDownloaderTest::TearDown() {
    125   crx_downloader_.reset();
    126 }
    127 
    128 void CrxDownloaderTest::Quit() {
    129   if (!quit_closure_.is_null())
    130     quit_closure_.Run();
    131 }
    132 
    133 void CrxDownloaderTest::DownloadComplete(int crx_context,
    134                                          const CrxDownloader::Result& result) {
    135   ++num_download_complete_calls_;
    136   crx_context_ = crx_context;
    137   download_complete_result_ = result;
    138   Quit();
    139 }
    140 
    141 void CrxDownloaderTest::DownloadProgress(int crx_context,
    142                                          const CrxDownloader::Result& result) {
    143   ++num_progress_calls_;
    144   download_progress_result_ = result;
    145 }
    146 
    147 void CrxDownloaderTest::RunThreads() {
    148   base::RunLoop runloop;
    149   quit_closure_ = runloop.QuitClosure();
    150   runloop.Run();
    151 
    152   // Since some tests need to drain currently enqueued tasks such as network
    153   // intercepts on the IO thread, run the threads until they are
    154   // idle. The component updater service won't loop again until the loop count
    155   // is set and the service is started.
    156   RunThreadsUntilIdle();
    157 }
    158 
    159 void CrxDownloaderTest::RunThreadsUntilIdle() {
    160   base::RunLoop().RunUntilIdle();
    161 }
    162 
    163 // Tests that starting a download without a url results in an error.
    164 TEST_F(CrxDownloaderTest, NoUrl) {
    165   std::vector<GURL> urls;
    166   crx_downloader_->StartDownload(urls, callback_);
    167   RunThreadsUntilIdle();
    168 
    169   EXPECT_EQ(1, num_download_complete_calls_);
    170   EXPECT_EQ(kExpectedContext, crx_context_);
    171   EXPECT_EQ(-1, download_complete_result_.error);
    172   EXPECT_TRUE(download_complete_result_.response.empty());
    173   EXPECT_EQ(-1, download_complete_result_.downloaded_bytes);
    174   EXPECT_EQ(-1, download_complete_result_.total_bytes);
    175   EXPECT_EQ(0, num_progress_calls_);
    176 }
    177 
    178 // Tests that downloading from one url is successful.
    179 TEST_F(CrxDownloaderTest, OneUrl) {
    180   const GURL expected_crx_url =
    181       GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
    182 
    183   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    184   get_interceptor_->SetResponse(expected_crx_url, test_file);
    185 
    186   crx_downloader_->StartDownloadFromUrl(expected_crx_url, callback_);
    187   RunThreads();
    188 
    189   EXPECT_EQ(1, get_interceptor_->GetHitCount());
    190 
    191   EXPECT_EQ(1, num_download_complete_calls_);
    192   EXPECT_EQ(kExpectedContext, crx_context_);
    193   EXPECT_EQ(0, download_complete_result_.error);
    194   EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
    195   EXPECT_EQ(1843, download_complete_result_.total_bytes);
    196   EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
    197 
    198   EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
    199 
    200   EXPECT_LE(1, num_progress_calls_);
    201   EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
    202   EXPECT_EQ(1843, download_progress_result_.total_bytes);
    203 }
    204 
    205 // Tests that specifying from two urls has no side effects. Expect a successful
    206 // download, and only one download request be made.
    207 // This test is flaky on Android. crbug.com/329883
    208 #if defined(OS_ANDROID)
    209 #define MAYBE_TwoUrls DISABLED_TwoUrls
    210 #else
    211 #define MAYBE_TwoUrls TwoUrls
    212 #endif
    213 TEST_F(CrxDownloaderTest, MAYBE_TwoUrls) {
    214   const GURL expected_crx_url =
    215       GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
    216 
    217   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    218   get_interceptor_->SetResponse(expected_crx_url, test_file);
    219 
    220   std::vector<GURL> urls;
    221   urls.push_back(expected_crx_url);
    222   urls.push_back(expected_crx_url);
    223 
    224   crx_downloader_->StartDownload(urls, callback_);
    225   RunThreads();
    226 
    227   EXPECT_EQ(1, get_interceptor_->GetHitCount());
    228 
    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));
    235 
    236   EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
    237 
    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);
    241 }
    242 
    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");
    247 
    248   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    249   get_interceptor_->SetResponse(expected_crx_url, test_file);
    250 
    251   crx_downloader_->StartDownloadFromUrl(
    252       GURL("http://no.such.host"
    253            "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"),
    254       callback_);
    255   RunThreads();
    256 
    257   EXPECT_EQ(0, get_interceptor_->GetHitCount());
    258 
    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());
    263 }
    264 
    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");
    269 
    270   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    271   get_interceptor_->SetResponse(expected_crx_url, test_file);
    272 
    273   crx_downloader_->StartDownloadFromUrl(GURL("http://localhost/no/such/file"),
    274                                         callback_);
    275   RunThreads();
    276 
    277   EXPECT_EQ(0, get_interceptor_->GetHitCount());
    278 
    279   EXPECT_EQ(1, num_download_complete_calls_);
    280   EXPECT_EQ(kExpectedContext, crx_context_);
    281   EXPECT_NE(0, download_complete_result_.error);
    282   EXPECT_TRUE(download_complete_result_.response.empty());
    283 }
    284 
    285 // Tests that the fallback to a valid url is successful.
    286 // This test is flaky on Android. crbug.com/329883
    287 #if defined(OS_ANDROID)
    288 #define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid
    289 #else
    290 #define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid
    291 #endif
    292 TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) {
    293   const GURL expected_crx_url =
    294       GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
    295 
    296   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    297   get_interceptor_->SetResponse(expected_crx_url, test_file);
    298 
    299   std::vector<GURL> urls;
    300   urls.push_back(GURL("http://localhost/no/such/file"));
    301   urls.push_back(expected_crx_url);
    302 
    303   crx_downloader_->StartDownload(urls, callback_);
    304   RunThreads();
    305 
    306   EXPECT_EQ(1, get_interceptor_->GetHitCount());
    307 
    308   EXPECT_EQ(1, num_download_complete_calls_);
    309   EXPECT_EQ(kExpectedContext, crx_context_);
    310   EXPECT_EQ(0, download_complete_result_.error);
    311   EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
    312   EXPECT_EQ(1843, download_complete_result_.total_bytes);
    313   EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
    314 
    315   EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
    316 
    317   EXPECT_LE(1, num_progress_calls_);
    318   EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
    319   EXPECT_EQ(1843, download_progress_result_.total_bytes);
    320 }
    321 
    322 // Tests that the download succeeds if the first url is correct and the
    323 // second bad url does not have a side-effect.
    324 TEST_F(CrxDownloaderTest, TwoUrls_SecondInvalid) {
    325   const GURL expected_crx_url =
    326       GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
    327 
    328   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    329   get_interceptor_->SetResponse(expected_crx_url, test_file);
    330 
    331   std::vector<GURL> urls;
    332   urls.push_back(expected_crx_url);
    333   urls.push_back(GURL("http://localhost/no/such/file"));
    334 
    335   crx_downloader_->StartDownload(urls, callback_);
    336   RunThreads();
    337 
    338   EXPECT_EQ(1, get_interceptor_->GetHitCount());
    339 
    340   EXPECT_EQ(1, num_download_complete_calls_);
    341   EXPECT_EQ(kExpectedContext, crx_context_);
    342   EXPECT_EQ(0, download_complete_result_.error);
    343   EXPECT_EQ(1843, download_complete_result_.downloaded_bytes);
    344   EXPECT_EQ(1843, download_complete_result_.total_bytes);
    345   EXPECT_TRUE(ContentsEqual(download_complete_result_.response, test_file));
    346 
    347   EXPECT_TRUE(base::DeleteFile(download_complete_result_.response, false));
    348 
    349   EXPECT_LE(1, num_progress_calls_);
    350   EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
    351   EXPECT_EQ(1843, download_progress_result_.total_bytes);
    352 }
    353 
    354 // Tests that the download fails if both urls are bad.
    355 TEST_F(CrxDownloaderTest, TwoUrls_BothInvalid) {
    356   const GURL expected_crx_url =
    357       GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
    358 
    359   const base::FilePath test_file(MakeTestFilePath(kTestFileName));
    360   get_interceptor_->SetResponse(expected_crx_url, test_file);
    361 
    362   std::vector<GURL> urls;
    363   urls.push_back(GURL("http://localhost/no/such/file"));
    364   urls.push_back(GURL("http://no.such.host/"
    365                       "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"));
    366 
    367   crx_downloader_->StartDownload(urls, callback_);
    368   RunThreads();
    369 
    370   EXPECT_EQ(0, get_interceptor_->GetHitCount());
    371 
    372   EXPECT_EQ(1, num_download_complete_calls_);
    373   EXPECT_EQ(kExpectedContext, crx_context_);
    374   EXPECT_NE(0, download_complete_result_.error);
    375   EXPECT_TRUE(download_complete_result_.response.empty());
    376 }
    377 
    378 }  // namespace component_updater
    379