Home | History | Annotate | Download | only in page_cycler
      1 // Copyright (c) 2012 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/file_util.h"
      6 #include "base/path_service.h"
      7 #include "base/prefs/testing_pref_service.h"
      8 #include "base/run_loop.h"
      9 #include "base/strings/string_split.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/threading/sequenced_worker_pool.h"
     13 #include "chrome/app/chrome_command_ids.h"
     14 #include "chrome/browser/browser_process.h"
     15 #include "chrome/browser/page_cycler/page_cycler.h"
     16 #include "chrome/browser/ui/browser.h"
     17 #include "chrome/browser/ui/browser_list.h"
     18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     19 #include "chrome/common/chrome_paths.h"
     20 #include "chrome/common/url_constants.h"
     21 #include "chrome/test/base/browser_with_test_window_test.h"
     22 #include "content/public/browser/render_view_host.h"
     23 #include "content/public/test/test_browser_thread.h"
     24 #include "net/base/net_errors.h"
     25 #include "testing/gmock/include/gmock/gmock.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 
     28 using ::testing::_;
     29 using ::testing::Invoke;
     30 using content::RenderViewHost;
     31 using content::TestBrowserThread;
     32 using content::WebContentsObserver;
     33 using base::ContentsEqual;
     34 using base::PathExists;
     35 
     36 namespace {
     37 const int kFrameID = 1;
     38 const bool kIsMainFrame = true;
     39 const GURL kAboutURL = GURL(content::kAboutBlankURL);
     40 }  // namespace
     41 
     42 class MockPageCycler : public PageCycler {
     43  public:
     44   MockPageCycler(Browser* browser, base::FilePath urls_file,
     45                  base::FilePath errors_file)
     46       : PageCycler(browser, urls_file) {
     47     set_errors_file(errors_file);
     48   }
     49 
     50   MockPageCycler(Browser* browser,
     51                  base::FilePath urls_file,
     52                  base::FilePath errors_file,
     53                  base::FilePath stats_file)
     54       : PageCycler(browser, urls_file) {
     55     set_stats_file(stats_file);
     56     set_errors_file(errors_file);
     57   }
     58 
     59   MOCK_METHOD4(DidFinishLoad, void(int64 frame_id,
     60                                    const GURL& validated_url,
     61                                    bool is_main_frame,
     62                                    RenderViewHost* render_view_host));
     63   MOCK_METHOD6(DidFailProvisionalLoad, void(int64 frame_id,
     64                                             bool is_main_frame,
     65                                             const GURL& validated_url,
     66                                             int error_code,
     67                                             const string16& error_description,
     68                                             RenderViewHost* render_view_host));
     69   MOCK_METHOD1(RenderProcessGone, void(base::TerminationStatus status));
     70 
     71   void PageCyclerDidFailProvisionalLoad(
     72       int64 frame_id,
     73       bool is_main_frame,
     74       const GURL& validated_url,
     75       int error_code,
     76       const string16& error_description,
     77       RenderViewHost* render_view_host) {
     78     PageCycler::DidFailProvisionalLoad(frame_id, is_main_frame,
     79                                        validated_url,
     80                                        error_code, error_description,
     81                                        render_view_host);
     82   }
     83 
     84   void PageCyclerDidFinishLoad(int64 frame_id,
     85                                const GURL& validated_url,
     86                                bool is_main_frame,
     87                                RenderViewHost* render_view_host) {
     88     PageCycler::DidFinishLoad(
     89         frame_id, validated_url, is_main_frame, render_view_host);
     90   }
     91 
     92  private:
     93   // We need to override Finish() because the calls to exit the browser in a
     94   // real PageCycler do not work in unittests (they interfere with later tests).
     95   virtual void Finish() OVERRIDE {
     96     BrowserList::RemoveObserver(this);
     97     Release();
     98   }
     99 
    100   virtual ~MockPageCycler() {}\
    101 
    102   DISALLOW_COPY_AND_ASSIGN(MockPageCycler);
    103 };
    104 
    105 class PageCyclerTest : public BrowserWithTestWindowTest {
    106  public:
    107   PageCyclerTest() {
    108   }
    109 
    110   virtual ~PageCyclerTest() {
    111   }
    112 
    113   virtual void SetUp() OVERRIDE {
    114     PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
    115     test_data_dir_ = test_data_dir_.AppendASCII("page_cycler");
    116 
    117     BrowserWithTestWindowTest::SetUp();
    118     AddTab(browser(), kAboutURL);
    119     ASSERT_FALSE(browser()->tab_strip_model()->GetActiveWebContents() == NULL);
    120   }
    121 
    122   void InitFilePaths(const base::FilePath& temp_path) {
    123     errors_file_ = temp_path.AppendASCII("errors_file");
    124     stats_file_ = temp_path.AppendASCII("stats_file");
    125 
    126     CHECK(!base::PathExists(errors_file_));
    127     CHECK(!base::PathExists(stats_file_));
    128   }
    129 
    130   void FailProvisionalLoad(int error_code, string16& error_description) {
    131     FOR_EACH_OBSERVER(
    132         WebContentsObserver,
    133         observers_,
    134         DidFailProvisionalLoad(kFrameID, kIsMainFrame, kAboutURL, error_code,
    135                                error_description, NULL));
    136     PumpLoop();
    137   }
    138 
    139   void FinishLoad() {
    140     FOR_EACH_OBSERVER(
    141         WebContentsObserver,
    142         observers_,
    143         DidFinishLoad(kFrameID, kAboutURL, kIsMainFrame, NULL));
    144     PumpLoop();
    145   }
    146 
    147   void RunPageCycler() {
    148     page_cycler_->Run();
    149     PumpLoop();
    150   }
    151 
    152   void PumpLoop() {
    153     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    154     base::RunLoop().RunUntilIdle();
    155   }
    156 
    157   void CloseBrowser() {
    158     DestroyBrowserAndProfile();
    159     PumpLoop();
    160   }
    161 
    162   MockPageCycler* page_cycler() {
    163     return page_cycler_.get();
    164   }
    165 
    166   void set_page_cycler(MockPageCycler* page_cycler) {
    167     page_cycler_ = page_cycler;
    168     observers_.AddObserver(page_cycler);
    169   }
    170 
    171   const std::vector<GURL>* urls_for_test() {
    172     return page_cycler_->urls_for_test();
    173   }
    174 
    175   base::FilePath stats_file() {
    176     return stats_file_;
    177   }
    178 
    179   base::FilePath errors_file() {
    180     return errors_file_;
    181   }
    182 
    183   base::FilePath urls_file() {
    184     return test_data_dir_.AppendASCII("about_url");
    185   }
    186 
    187   base::FilePath test_data_dir() {
    188     return test_data_dir_;
    189   }
    190 
    191  private:
    192   ObserverList<WebContentsObserver> observers_;
    193   scoped_refptr<MockPageCycler> page_cycler_;
    194   base::FilePath test_data_dir_;
    195   base::FilePath stats_file_;
    196   base::FilePath errors_file_;
    197   base::FilePath urls_file_;
    198 };
    199 
    200 TEST_F(PageCyclerTest, FailProvisionalLoads) {
    201   const base::FilePath errors_expected_file =
    202       test_data_dir().AppendASCII("errors_expected");
    203 
    204   base::ScopedTempDir temp;
    205   ASSERT_TRUE(temp.CreateUniqueTempDir());
    206   InitFilePaths(temp.path());
    207 
    208   ASSERT_TRUE(PathExists(errors_expected_file));
    209   ASSERT_TRUE(PathExists(urls_file()));
    210 
    211   set_page_cycler(new MockPageCycler(browser(),
    212                                      urls_file(),
    213                                      errors_file()));
    214   RunPageCycler();
    215 
    216   // Page cycler expects browser to automatically start loading the first page.
    217   EXPECT_CALL(*page_cycler(),
    218               DidFinishLoad(kFrameID, kAboutURL, kIsMainFrame, _))
    219       .WillOnce(Invoke(page_cycler(),
    220                        &MockPageCycler::PageCyclerDidFinishLoad));
    221   FinishLoad();
    222 
    223   // DNS server fail error message.
    224   string16 error_string =
    225       string16(ASCIIToUTF16(net::ErrorToString(net::ERR_DNS_SERVER_FAILED)));
    226   EXPECT_CALL(*page_cycler(),
    227               DidFailProvisionalLoad(kFrameID, kIsMainFrame, _,
    228                                      net::ERR_DNS_SERVER_FAILED, error_string,
    229                                      _))
    230       .WillOnce(Invoke(page_cycler(),
    231                        &MockPageCycler::PageCyclerDidFailProvisionalLoad));
    232   FailProvisionalLoad(net::ERR_DNS_SERVER_FAILED, error_string);
    233 
    234   // DNS time-out error message.
    235   error_string = string16(
    236       ASCIIToUTF16(net::ErrorToString(net::ERR_DNS_TIMED_OUT)));
    237   EXPECT_CALL(*page_cycler(),
    238               DidFailProvisionalLoad(kFrameID,
    239                                      kIsMainFrame, _, net::ERR_DNS_TIMED_OUT,
    240                                      error_string, _))
    241       .WillOnce(Invoke(page_cycler(),
    242                        &MockPageCycler::PageCyclerDidFailProvisionalLoad));
    243 
    244   FailProvisionalLoad(net::ERR_DNS_TIMED_OUT, error_string);
    245 
    246   // DNS time-out error message.
    247   error_string = string16(
    248       ASCIIToUTF16(net::ErrorToString(net::ERR_INVALID_URL)));
    249   EXPECT_CALL(*page_cycler(),
    250               DidFailProvisionalLoad(kFrameID, kIsMainFrame, _,
    251                                      net::ERR_INVALID_URL, error_string, _))
    252       .WillOnce(Invoke(page_cycler(),
    253                        &MockPageCycler::PageCyclerDidFailProvisionalLoad));
    254   FailProvisionalLoad(net::ERR_INVALID_URL, error_string);
    255 
    256   PumpLoop();
    257 
    258   std::string errors_output;
    259   std::string errors_expected;
    260   ASSERT_TRUE(file_util::ReadFileToString(errors_file(),
    261                                           &errors_output));
    262   ASSERT_TRUE(file_util::ReadFileToString(errors_expected_file,
    263                                           &errors_expected));
    264   ASSERT_EQ(errors_output, errors_expected);
    265 }
    266 
    267 TEST_F(PageCyclerTest, StatsFile) {
    268   const int kNumLoads = 4;
    269 
    270   base::ScopedTempDir temp;
    271   ASSERT_TRUE(temp.CreateUniqueTempDir());
    272   InitFilePaths(temp.path());
    273 
    274   ASSERT_TRUE(PathExists(urls_file()));
    275 
    276   set_page_cycler(new MockPageCycler(browser(), urls_file(),
    277                                      errors_file()));
    278   page_cycler()->set_stats_file(stats_file());
    279   RunPageCycler();
    280 
    281   for (int i = 0; i < kNumLoads; ++i) {
    282     EXPECT_CALL(*page_cycler(), DidFinishLoad(
    283         kFrameID, kAboutURL, kIsMainFrame, _))
    284         .WillOnce(Invoke(page_cycler(),
    285                          &MockPageCycler::PageCyclerDidFinishLoad));
    286     FinishLoad();
    287   }
    288 
    289   PumpLoop();
    290   EXPECT_FALSE(PathExists(errors_file()));
    291   ASSERT_TRUE(PathExists(stats_file()));
    292 }
    293 
    294 TEST_F(PageCyclerTest, KillBrowserAndAbort) {
    295   const base::FilePath errors_expected_file =
    296       test_data_dir().AppendASCII("abort_expected");
    297 
    298   base::ScopedTempDir temp;
    299   ASSERT_TRUE(temp.CreateUniqueTempDir());
    300   InitFilePaths(temp.path());
    301 
    302   ASSERT_TRUE(PathExists(errors_expected_file));
    303   ASSERT_TRUE(PathExists(urls_file()));
    304 
    305   set_page_cycler(new MockPageCycler(browser(),
    306                                      urls_file(),
    307                                      errors_file()));
    308   RunPageCycler();
    309 
    310   EXPECT_CALL(*page_cycler(),
    311       DidFinishLoad(kFrameID, kAboutURL, kIsMainFrame, _))
    312       .WillOnce(Invoke(page_cycler(),
    313                        &MockPageCycler::PageCyclerDidFinishLoad));
    314   base::RunLoop().RunUntilIdle();
    315 
    316   FinishLoad();
    317 
    318   CloseBrowser();
    319   PumpLoop();
    320 
    321   std::string errors_output;
    322   std::string errors_expected;
    323   ASSERT_TRUE(file_util::ReadFileToString(errors_file(),
    324                                           &errors_output));
    325   ASSERT_TRUE(file_util::ReadFileToString(errors_expected_file,
    326                                           &errors_expected));
    327   ASSERT_EQ(errors_output, errors_expected);
    328 }
    329 
    330 TEST_F(PageCyclerTest, MultipleIterations) {
    331   const int kNumLoads = 4;
    332 
    333   base::ScopedTempDir temp;
    334   ASSERT_TRUE(temp.CreateUniqueTempDir());
    335   InitFilePaths(temp.path());
    336 
    337   ASSERT_TRUE(PathExists(urls_file()));
    338 
    339   set_page_cycler(new MockPageCycler(browser(),
    340                                      urls_file(),
    341                                      errors_file()));
    342   page_cycler()->set_stats_file(stats_file());
    343   RunPageCycler();
    344 
    345   EXPECT_CALL(*page_cycler(),
    346               DidFinishLoad(kFrameID, kAboutURL, kIsMainFrame, _))
    347       .WillRepeatedly(Invoke(page_cycler(),
    348                              &MockPageCycler::PageCyclerDidFinishLoad));
    349 
    350   for (int i = 0; i < kNumLoads; ++i)
    351     FinishLoad();
    352 
    353   PumpLoop();
    354   EXPECT_FALSE(PathExists(errors_file()));
    355   ASSERT_TRUE(PathExists(stats_file()));
    356 }
    357