OLD | NEW |
(Empty) | |
| 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/command_line.h" |
| 6 #include "base/file_path.h" |
| 7 #include "base/file_util.h" |
| 8 #include "base/path_service.h" |
| 9 #include "base/string_split.h" |
| 10 #include "base/string_util.h" |
| 11 #include "base/threading/sequenced_worker_pool.h" |
| 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/page_cycler/page_cycler.h" |
| 14 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/profiles/profile_manager.h" |
| 16 #include "chrome/browser/ui/browser_list.h" |
| 17 #include "chrome/common/chrome_notification_types.h" |
| 18 #include "chrome/common/chrome_paths.h" |
| 19 #include "chrome/common/chrome_switches.h" |
| 20 #include "chrome/test/base/in_process_browser_test.h" |
| 21 #include "chrome/test/base/testing_profile.h" |
| 22 #include "chrome/test/base/ui_test_utils.h" |
| 23 #include "content/public/browser/notification_observer.h" |
| 24 #include "content/public/browser/notification_registrar.h" |
| 25 #include "content/public/browser/notification_service.h" |
| 26 #include "content/public/common/content_switches.h" |
| 27 #include "content/public/common/url_constants.h" |
| 28 #include "googleurl/src/gurl.h" |
| 29 |
| 30 // Basic PageCyclerBrowserTest structure; used in testing most of PageCycler's |
| 31 // functionality. |
| 32 class PageCyclerBrowserTest : public content::NotificationObserver, |
| 33 public InProcessBrowserTest { |
| 34 public: |
| 35 PageCyclerBrowserTest() : page_cycler_(NULL) { |
| 36 } |
| 37 |
| 38 virtual ~PageCyclerBrowserTest() { |
| 39 } |
| 40 |
| 41 // Initialize file paths within a temporary directory; this should be |
| 42 // empty and nonexistent. |
| 43 virtual void InitFilePaths(FilePath temp_path) { |
| 44 temp_path_ = temp_path; |
| 45 urls_file_ = temp_path.AppendASCII("urls_file"); |
| 46 errors_file_ = temp_path.AppendASCII("errors"); |
| 47 stats_file_ = temp_path.AppendASCII("stats"); |
| 48 |
| 49 ASSERT_FALSE(file_util::PathExists(urls_file_)); |
| 50 ASSERT_FALSE(file_util::PathExists(errors_file_)); |
| 51 ASSERT_FALSE(file_util::PathExists(stats_file_)); |
| 52 } |
| 53 |
| 54 // Initialize a PageCycler using either the base fields, or using provided |
| 55 // ones. |
| 56 void InitPageCycler() { |
| 57 page_cycler_ = new PageCycler(browser(), urls_file()); |
| 58 page_cycler_->set_errors_file(errors_file()); |
| 59 page_cycler_->set_stats_file(stats_file()); |
| 60 } |
| 61 |
| 62 void InitPageCycler(FilePath urls_file, |
| 63 FilePath errors_file, |
| 64 FilePath stats_file) { |
| 65 page_cycler_ = new PageCycler(browser(), urls_file); |
| 66 page_cycler_->set_errors_file(errors_file); |
| 67 page_cycler_->set_stats_file(stats_file); |
| 68 } |
| 69 |
| 70 void RegisterForNotifications() { |
| 71 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, |
| 72 content::NotificationService::AllSources()); |
| 73 } |
| 74 |
| 75 // Get a collection of basic urls which are stored in the test directory. |
| 76 // NOTE: |test_server| must be started first! |
| 77 std::vector<GURL> GetURLs() { |
| 78 std::vector<GURL> urls; |
| 79 urls.push_back(test_server()->GetURL("files/page_cycler/basic_html.html")); |
| 80 urls.push_back(test_server()->GetURL("files/page_cycler/basic_js.html")); |
| 81 urls.push_back(test_server()->GetURL("files/page_cycler/basic_css.html")); |
| 82 return urls; |
| 83 } |
| 84 |
| 85 // Read the errors file, and generate a vector of error strings. |
| 86 std::vector<std::string> GetErrorsFromFile() { |
| 87 std::string error_file_contents; |
| 88 CHECK(file_util::ReadFileToString(errors_file_, |
| 89 &error_file_contents)); |
| 90 if (error_file_contents[error_file_contents.size() - 1] == '\n') |
| 91 error_file_contents.resize(error_file_contents.size() - 1); |
| 92 |
| 93 std::vector<std::string> errors; |
| 94 base::SplitString(error_file_contents, '\n', &errors); |
| 95 |
| 96 return errors; |
| 97 } |
| 98 |
| 99 // Convert a vector of GURLs into a newline-separated string, ready to be |
| 100 // written to the urls file for PageCycler to use. |
| 101 std::string GetStringFromURLs(std::vector<GURL> urls) { |
| 102 std::string urls_string; |
| 103 for (std::vector<GURL>::const_iterator iter = urls.begin(); |
| 104 iter != urls.end(); ++iter) |
| 105 urls_string.append(iter->spec() + "\n"); |
| 106 return urls_string; |
| 107 } |
| 108 |
| 109 // content::NotificationObserver. |
| 110 virtual void Observe(int type, |
| 111 const content::NotificationSource& source, |
| 112 const content::NotificationDetails& details) { |
| 113 switch (type) { |
| 114 case chrome::NOTIFICATION_BROWSER_CLOSED: |
| 115 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
| 116 break; |
| 117 default: |
| 118 NOTREACHED(); |
| 119 break; |
| 120 } |
| 121 } |
| 122 |
| 123 FilePath urls_file() { return urls_file_; } |
| 124 FilePath errors_file() { return errors_file_; } |
| 125 FilePath stats_file() { return stats_file_; } |
| 126 PageCycler* page_cycler() { return page_cycler_; } |
| 127 |
| 128 protected: |
| 129 FilePath temp_path_; |
| 130 FilePath urls_file_; |
| 131 FilePath errors_file_; |
| 132 FilePath stats_file_; |
| 133 PageCycler* page_cycler_; |
| 134 content::NotificationRegistrar registrar_; |
| 135 }; |
| 136 |
| 137 // Structure used for testing PageCycler's ability to playback a series of |
| 138 // URLs given a cache directory. |
| 139 class PageCyclerCachedBrowserTest : public PageCyclerBrowserTest { |
| 140 public: |
| 141 // For a cached test, we use the provided user data directory from the test |
| 142 // directory. |
| 143 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 144 InProcessBrowserTest::SetUpCommandLine(command_line); |
| 145 |
| 146 FilePath test_dir; |
| 147 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); |
| 148 test_dir = test_dir.AppendASCII("page_cycler"); |
| 149 |
| 150 FilePath source_data_dir = test_dir.AppendASCII("cached_data_dir"); |
| 151 CHECK(file_util::PathExists(source_data_dir)); |
| 152 |
| 153 CHECK(user_data_dir_.CreateUniqueTempDir()); |
| 154 |
| 155 FilePath dest_data_dir = |
| 156 user_data_dir_.path().AppendASCII("cached_data_dir"); |
| 157 CHECK(!file_util::PathExists(dest_data_dir)); |
| 158 |
| 159 CHECK(file_util::CopyDirectory(source_data_dir, |
| 160 user_data_dir_.path(), |
| 161 true)); // recursive. |
| 162 CHECK(file_util::PathExists(dest_data_dir)); |
| 163 |
| 164 command_line->AppendSwitchPath(switches::kUserDataDir, |
| 165 dest_data_dir); |
| 166 command_line->AppendSwitch(switches::kPlaybackMode); |
| 167 } |
| 168 |
| 169 // Initialize the file paths to use the UserDataDir's urls file, instead |
| 170 // of one to be written. |
| 171 virtual void InitFilePaths(FilePath temp_path) OVERRIDE { |
| 172 urls_file_ = user_data_dir_.path().AppendASCII("cached_data_dir") |
| 173 .AppendASCII("urls"); |
| 174 errors_file_ = temp_path.AppendASCII("errors"); |
| 175 stats_file_ = temp_path.AppendASCII("stats"); |
| 176 |
| 177 ASSERT_TRUE(file_util::PathExists(urls_file_)); |
| 178 ASSERT_FALSE(file_util::PathExists(errors_file_)); |
| 179 ASSERT_FALSE(file_util::PathExists(stats_file_)); |
| 180 } |
| 181 |
| 182 private: |
| 183 // The directory storing the copy of the UserDataDir. |
| 184 ScopedTempDir user_data_dir_; |
| 185 }; |
| 186 |
| 187 // Sanity check; iterate through a series of URLs and make sure there are no |
| 188 // errors. |
| 189 IN_PROC_BROWSER_TEST_F(PageCyclerBrowserTest, BasicTest) { |
| 190 const size_t kNumIterations = 3; |
| 191 ScopedTempDir temp; |
| 192 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 193 |
| 194 RegisterForNotifications(); |
| 195 InitFilePaths(temp.path()); |
| 196 |
| 197 ASSERT_TRUE(test_server()->Start()); |
| 198 |
| 199 std::string urls_string = GetStringFromURLs(GetURLs());; |
| 200 |
| 201 ASSERT_TRUE(file_util::WriteFile(urls_file(), urls_string.c_str(), |
| 202 urls_string.size())); |
| 203 |
| 204 InitPageCycler(); |
| 205 page_cycler()->Run(kNumIterations); |
| 206 |
| 207 ui_test_utils::RunMessageLoop(); |
| 208 ASSERT_FALSE(file_util::PathExists(errors_file())); |
| 209 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 210 } |
| 211 |
| 212 // Test to make sure that PageCycler will recognize unvisitable URLs, and will |
| 213 // handle them appropriately. |
| 214 IN_PROC_BROWSER_TEST_F(PageCyclerBrowserTest, UnvisitableURL) { |
| 215 const size_t kNumIterations = 3; |
| 216 const char kFakeURL[] = "http://www.pleasenoonehavethisurlanytimeinthenext" |
| 217 "century.com/gibberish"; |
| 218 ScopedTempDir temp; |
| 219 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 220 |
| 221 RegisterForNotifications(); |
| 222 InitFilePaths(temp.path()); |
| 223 |
| 224 ASSERT_TRUE(test_server()->Start()); |
| 225 |
| 226 std::vector<GURL> urls = GetURLs(); |
| 227 urls.push_back(GURL(kFakeURL)); |
| 228 std::string urls_string = GetStringFromURLs(urls); |
| 229 |
| 230 ASSERT_TRUE(file_util::WriteFile(urls_file(), urls_string.c_str(), |
| 231 urls_string.size())); |
| 232 |
| 233 InitPageCycler(); |
| 234 page_cycler()->Run(kNumIterations); |
| 235 |
| 236 ui_test_utils::RunMessageLoop(); |
| 237 ASSERT_TRUE(file_util::PathExists(errors_file())); |
| 238 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 239 |
| 240 std::vector<std::string> errors = GetErrorsFromFile(); |
| 241 |
| 242 size_t num_errors = errors.size(); |
| 243 ASSERT_EQ(kNumIterations, num_errors); |
| 244 |
| 245 // Check that each error message contains the fake URL (i.e., that it wasn't |
| 246 // from a valid URL, and that the fake URL was caught each time). |
| 247 for (std::vector<std::string>::const_iterator iter = errors.begin(); |
| 248 iter != errors.end(); ++iter) { |
| 249 ASSERT_NE(iter->find(kFakeURL), std::string::npos); |
| 250 } |
| 251 } |
| 252 |
| 253 // Test that PageCycler will remove an invalid URL prior to running. |
| 254 IN_PROC_BROWSER_TEST_F(PageCyclerBrowserTest, InvalidURL) { |
| 255 const size_t kNumIterations = 1; |
| 256 const char kBadURL[] = "notarealurl"; |
| 257 |
| 258 ScopedTempDir temp; |
| 259 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 260 |
| 261 RegisterForNotifications(); |
| 262 InitFilePaths(temp.path()); |
| 263 |
| 264 ASSERT_TRUE(test_server()->Start()); |
| 265 |
| 266 std::string urls_string = GetStringFromURLs(GetURLs()); |
| 267 urls_string.append(kBadURL).append("\n"); |
| 268 |
| 269 ASSERT_TRUE(file_util::WriteFile(urls_file(), urls_string.c_str(), |
| 270 urls_string.size())); |
| 271 |
| 272 InitPageCycler(); |
| 273 page_cycler()->Run(kNumIterations); |
| 274 |
| 275 ui_test_utils::RunMessageLoop(); |
| 276 ASSERT_TRUE(file_util::PathExists(errors_file())); |
| 277 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 278 |
| 279 std::vector<std::string> errors = GetErrorsFromFile(); |
| 280 ASSERT_EQ(1u, errors.size()); |
| 281 |
| 282 std::string expected_error = "Omitting invalid URL: "; |
| 283 expected_error.append(kBadURL).append("."); |
| 284 |
| 285 ASSERT_FALSE(errors[0].compare(expected_error)); |
| 286 } |
| 287 |
| 288 // Test that PageCycler will remove a Chrome Error URL prior to running. |
| 289 IN_PROC_BROWSER_TEST_F(PageCyclerBrowserTest, ChromeErrorURL) { |
| 290 const size_t kNumIterations = 1; |
| 291 ScopedTempDir temp; |
| 292 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 293 |
| 294 RegisterForNotifications(); |
| 295 InitFilePaths(temp.path()); |
| 296 |
| 297 ASSERT_TRUE(test_server()->Start()); |
| 298 |
| 299 std::vector<GURL> urls = GetURLs(); |
| 300 urls.push_back(GURL(content::kUnreachableWebDataURL)); |
| 301 std::string urls_string = GetStringFromURLs(urls); |
| 302 |
| 303 ASSERT_TRUE(file_util::WriteFile(urls_file(), urls_string.c_str(), |
| 304 urls_string.size())); |
| 305 |
| 306 InitPageCycler(); |
| 307 page_cycler()->Run(kNumIterations); |
| 308 |
| 309 ui_test_utils::RunMessageLoop(); |
| 310 ASSERT_TRUE(file_util::PathExists(errors_file())); |
| 311 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 312 |
| 313 std::vector<std::string> errors = GetErrorsFromFile(); |
| 314 ASSERT_EQ(1u, errors.size()); |
| 315 |
| 316 std::string expected_error = "Chrome error pages are not allowed as urls. " |
| 317 "Omitting url: "; |
| 318 expected_error.append(content::kUnreachableWebDataURL).append("."); |
| 319 |
| 320 ASSERT_FALSE(errors[0].compare(expected_error)); |
| 321 } |
| 322 |
| 323 // Test that PageCycler will visit all the urls from a cache directory |
| 324 // successfully while in playback mode. |
| 325 IN_PROC_BROWSER_TEST_F(PageCyclerCachedBrowserTest, PlaybackMode) { |
| 326 const size_t kNumIterations = 1; |
| 327 ScopedTempDir temp; |
| 328 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 329 |
| 330 RegisterForNotifications(); |
| 331 InitFilePaths(temp.path()); |
| 332 |
| 333 InitPageCycler(); |
| 334 |
| 335 page_cycler()->Run(kNumIterations); |
| 336 |
| 337 ui_test_utils::RunMessageLoop(); |
| 338 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 339 ASSERT_FALSE(file_util::PathExists(errors_file())); |
| 340 } |
| 341 |
| 342 // Test that PageCycler will have a cache miss if a URL is missing from the |
| 343 // cache directory while in playback mode. |
| 344 IN_PROC_BROWSER_TEST_F(PageCyclerCachedBrowserTest, URLNotInCache) { |
| 345 const size_t kNumIterations = 1; |
| 346 const char kCacheMissURL[] = "http://www.images.google.com/"; |
| 347 |
| 348 ScopedTempDir temp; |
| 349 ASSERT_TRUE(temp.CreateUniqueTempDir()); |
| 350 |
| 351 RegisterForNotifications(); |
| 352 InitFilePaths(temp.path()); |
| 353 |
| 354 std::string urls_string; |
| 355 ASSERT_TRUE(file_util::ReadFileToString(urls_file(), |
| 356 &urls_string)); |
| 357 |
| 358 urls_string.append("\n").append(kCacheMissURL); |
| 359 FilePath new_urls_file = temp.path().AppendASCII("urls"); |
| 360 ASSERT_FALSE(file_util::PathExists(new_urls_file)); |
| 361 |
| 362 ASSERT_TRUE(file_util::WriteFile(new_urls_file, urls_string.c_str(), |
| 363 urls_string.size())); |
| 364 |
| 365 InitPageCycler(new_urls_file, errors_file(), stats_file()); |
| 366 page_cycler()->Run(kNumIterations); |
| 367 |
| 368 ui_test_utils::RunMessageLoop(); |
| 369 ASSERT_TRUE(file_util::PathExists(errors_file())); |
| 370 ASSERT_TRUE(file_util::PathExists(stats_file())); |
| 371 |
| 372 std::vector<std::string> errors = GetErrorsFromFile(); |
| 373 ASSERT_EQ(1u, errors.size()); |
| 374 |
| 375 std::string expected_error; |
| 376 expected_error.append("Failed to load the page at: ") |
| 377 .append(kCacheMissURL) |
| 378 .append(": The requested entry was not found in the cache."); |
| 379 |
| 380 ASSERT_FALSE(errors[0].compare(expected_error)); |
| 381 } |
OLD | NEW |