| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_TEST_UI_UI_LAYOUT_TEST_H_ |
| 6 #define CHROME_TEST_UI_UI_LAYOUT_TEST_H_ |
| 7 |
| 5 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 6 #include "base/file_util.h" | |
| 7 #include "base/path_service.h" | |
| 8 #include "base/platform_thread.h" | |
| 9 #include "base/string_util.h" | |
| 10 #include "chrome/browser/worker_host/worker_service.h" | |
| 11 #include "chrome/common/chrome_paths.h" | |
| 12 #include "chrome/test/automation/browser_proxy.h" | |
| 13 #include "chrome/test/automation/tab_proxy.h" | |
| 14 #include "chrome/test/ui/ui_test.h" | 9 #include "chrome/test/ui/ui_test.h" |
| 15 #include "net/base/escape.h" | |
| 16 #include "net/base/net_util.h" | |
| 17 | 10 |
| 18 #if defined(OS_WIN) | 11 class UILayoutTest : public UITest { |
| 19 const char kPlatformName[] = "chromium-win"; | |
| 20 #elif defined(OS_MACOSX) | |
| 21 const char kPlatformName[] = "chromium-mac"; | |
| 22 #elif defined(OS_LINUX) | |
| 23 const char kPlatformName[] = "chromium-linux"; | |
| 24 #else | |
| 25 #error No known OS defined | |
| 26 #endif | |
| 27 | |
| 28 const char kTestCompleteCookie[] = "status"; | |
| 29 const char kTestCompleteSuccess[] = "OK"; | |
| 30 const int kTestIntervalMs = 250; | |
| 31 const int kTestWaitTimeoutMs = 60 * 1000; | |
| 32 | |
| 33 class WorkerTest : public UITest { | |
| 34 protected: | 12 protected: |
| 35 WorkerTest(); | 13 UILayoutTest(); |
| 36 virtual ~WorkerTest(); | 14 virtual ~UILayoutTest(); |
| 37 | |
| 38 void RunTest(const std::wstring& test_case); | |
| 39 | 15 |
| 40 void InitializeForLayoutTest(const FilePath& test_parent_dir, | 16 void InitializeForLayoutTest(const FilePath& test_parent_dir, |
| 41 const FilePath& test_case_dir, | 17 const FilePath& test_case_dir, |
| 42 bool is_http_test); | 18 bool is_http_test); |
| 43 void RunLayoutTest(const std::string& test_case_file_name, bool is_http_test); | 19 void RunLayoutTest(const std::string& test_case_file_name, |
| 20 bool is_http_test); |
| 44 | 21 |
| 45 protected: | |
| 46 bool ReadExpectedResult(const FilePath& result_dir_path, | 22 bool ReadExpectedResult(const FilePath& result_dir_path, |
| 47 const std::string test_case_file_name, | 23 const std::string test_case_file_name, |
| 48 std::string* expected_result_value); | 24 std::string* expected_result_value); |
| 49 | 25 |
| 50 bool initialized_for_layout_test_; | 26 bool initialized_for_layout_test_; |
| 51 int test_count_; | 27 int test_count_; |
| 52 FilePath temp_test_dir_; | 28 FilePath temp_test_dir_; |
| 53 FilePath layout_test_dir_; | 29 FilePath layout_test_dir_; |
| 54 FilePath test_case_dir_; | 30 FilePath test_case_dir_; |
| 55 FilePath new_http_root_dir_; | 31 FilePath new_http_root_dir_; |
| 56 FilePath new_layout_test_dir_; | 32 FilePath new_layout_test_dir_; |
| 57 FilePath rebase_result_dir_; | 33 FilePath rebase_result_dir_; |
| 58 FilePath rebase_result_win_dir_; | 34 FilePath rebase_result_win_dir_; |
| 59 std::string layout_test_controller_; | 35 std::string layout_test_controller_; |
| 36 |
| 37 static const int kTestIntervalMs = 250; |
| 38 static const int kTestWaitTimeoutMs = 60 * 1000; |
| 60 }; | 39 }; |
| 61 | 40 |
| 62 WorkerTest::WorkerTest() | 41 #endif // CHROME_TEST_UI_UI_LAYOUT_TEST_H_ |
| 63 : UITest(), initialized_for_layout_test_(false), test_count_(0) { | |
| 64 } | |
| 65 | |
| 66 WorkerTest::~WorkerTest() { | |
| 67 // The deletion might fail because HTTP server process might not been | |
| 68 // completely shut down yet and is still holding certain handle to it. | |
| 69 // To work around this problem, we try to repeat the deletion several | |
| 70 // times. | |
| 71 if (!temp_test_dir_.empty()) { | |
| 72 static const int kRetryNum = 10; | |
| 73 static const int kRetryDelayTimeMs = 500; | |
| 74 | |
| 75 int retry_time = 0; | |
| 76 for (int i = 0; i < kRetryNum; ++i) { | |
| 77 file_util::Delete(temp_test_dir_, true); | |
| 78 if (!file_util::DirectoryExists(temp_test_dir_)) | |
| 79 break; | |
| 80 | |
| 81 PlatformThread::Sleep(kRetryDelayTimeMs); | |
| 82 retry_time += kRetryDelayTimeMs; | |
| 83 } | |
| 84 | |
| 85 if (retry_time) | |
| 86 printf("Retrying %d ms to delete temp worker directory.\n", retry_time); | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 void WorkerTest::RunTest(const std::wstring& test_case) { | |
| 91 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
| 92 ASSERT_TRUE(tab.get()); | |
| 93 | |
| 94 GURL url = GetTestUrl(L"workers", test_case); | |
| 95 ASSERT_TRUE(tab->NavigateToURL(url)); | |
| 96 | |
| 97 std::string value = WaitUntilCookieNonEmpty(tab.get(), url, | |
| 98 kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs); | |
| 99 ASSERT_STREQ(kTestCompleteSuccess, value.c_str()); | |
| 100 } | |
| 101 | |
| 102 void WorkerTest::InitializeForLayoutTest(const FilePath& test_parent_dir, | |
| 103 const FilePath& test_case_dir, | |
| 104 bool is_http_test) { | |
| 105 FilePath src_dir; | |
| 106 PathService::Get(base::DIR_SOURCE_ROOT, &src_dir); | |
| 107 | |
| 108 // Gets the file path to WebKit layout tests for workers, that is, | |
| 109 // chrome/test/data/workers/LayoutTests/.../workers | |
| 110 // Note that we have to use our copy of WebKit layout tests for workers. | |
| 111 // This is because our build machines do not have WebKit layout tests added. | |
| 112 layout_test_dir_ = src_dir.AppendASCII("chrome"); | |
| 113 layout_test_dir_ = layout_test_dir_.AppendASCII("test"); | |
| 114 layout_test_dir_ = layout_test_dir_.AppendASCII("data"); | |
| 115 layout_test_dir_ = layout_test_dir_.AppendASCII("workers"); | |
| 116 layout_test_dir_ = layout_test_dir_.Append(test_parent_dir); | |
| 117 layout_test_dir_ = layout_test_dir_.Append(test_case_dir); | |
| 118 | |
| 119 // If not found, try to use the original copy of WebKit layout tests for | |
| 120 // workers. For testing only in local machine only. | |
| 121 // third_party/LayoutTests/.../workers | |
| 122 if (!file_util::DirectoryExists(layout_test_dir_)) { | |
| 123 layout_test_dir_ = src_dir.AppendASCII("third_party"); | |
| 124 layout_test_dir_ = layout_test_dir_.Append(test_parent_dir); | |
| 125 layout_test_dir_ = layout_test_dir_.Append(test_case_dir); | |
| 126 ASSERT_TRUE(file_util::DirectoryExists(layout_test_dir_)); | |
| 127 } | |
| 128 | |
| 129 // Gets the file path to rebased expected result directory for workers for | |
| 130 // current platform. | |
| 131 // webkit/data/layout_tests/platform/chromium_***/LayoutTests/.../workers | |
| 132 rebase_result_dir_ = src_dir.AppendASCII("webkit"); | |
| 133 rebase_result_dir_ = rebase_result_dir_.AppendASCII("data"); | |
| 134 rebase_result_dir_ = rebase_result_dir_.AppendASCII("layout_tests"); | |
| 135 rebase_result_dir_ = rebase_result_dir_.AppendASCII("platform"); | |
| 136 rebase_result_dir_ = rebase_result_dir_.AppendASCII(kPlatformName); | |
| 137 rebase_result_dir_ = rebase_result_dir_.Append(test_parent_dir); | |
| 138 rebase_result_dir_ = rebase_result_dir_.Append(test_case_dir); | |
| 139 | |
| 140 // Gets the file path to rebased expected result directory for workers under | |
| 141 // win32 platform. This is used by other non-win32 platform to use the same | |
| 142 // rebased expected results. | |
| 143 #if !defined(OS_WIN) | |
| 144 rebase_result_win_dir_ = src_dir.AppendASCII("webkit"); | |
| 145 rebase_result_win_dir_ = rebase_result_win_dir_.AppendASCII("data"); | |
| 146 rebase_result_win_dir_ = rebase_result_win_dir_.AppendASCII("layout_tests"); | |
| 147 rebase_result_win_dir_ = rebase_result_win_dir_.AppendASCII("platform"); | |
| 148 rebase_result_win_dir_ = rebase_result_win_dir_.AppendASCII("chromium-win"); | |
| 149 rebase_result_win_dir_ = rebase_result_win_dir_.Append(test_parent_dir); | |
| 150 rebase_result_win_dir_ = rebase_result_win_dir_.Append(test_case_dir); | |
| 151 #endif | |
| 152 | |
| 153 // Creates the temporary directory. | |
| 154 ASSERT_TRUE(file_util::CreateNewTempDirectory( | |
| 155 FILE_PATH_LITERAL("chrome_worker_test_"), &temp_test_dir_)); | |
| 156 | |
| 157 // Creates the new layout test subdirectory under the temp directory. | |
| 158 // Note that we have to mimic the same layout test directory structure, | |
| 159 // like .../LayoutTests/fast/workers/.... Otherwise those layout tests | |
| 160 // dealing with location property, like worker-location.html, could fail. | |
| 161 new_layout_test_dir_ = temp_test_dir_; | |
| 162 new_layout_test_dir_ = new_layout_test_dir_.Append(test_parent_dir); | |
| 163 if (is_http_test) { | |
| 164 new_http_root_dir_ = new_layout_test_dir_; | |
| 165 test_case_dir_ = test_case_dir; | |
| 166 } | |
| 167 new_layout_test_dir_ = new_layout_test_dir_.Append(test_case_dir); | |
| 168 ASSERT_TRUE(file_util::CreateDirectory(new_layout_test_dir_)); | |
| 169 | |
| 170 // Copies the resource subdirectory. | |
| 171 FilePath layout_test_resource_path(layout_test_dir_); | |
| 172 layout_test_resource_path = | |
| 173 layout_test_resource_path.AppendASCII("resources"); | |
| 174 FilePath new_layout_test_resource_path(new_layout_test_dir_); | |
| 175 new_layout_test_resource_path = | |
| 176 new_layout_test_resource_path.AppendASCII("resources"); | |
| 177 ASSERT_TRUE(file_util::CopyDirectory( | |
| 178 layout_test_resource_path, new_layout_test_resource_path, true)); | |
| 179 | |
| 180 // Copies the parent resource subdirectory. This is needed in order to run | |
| 181 // http layout tests. | |
| 182 if (is_http_test) { | |
| 183 FilePath parent_resource_path(layout_test_dir_.DirName()); | |
| 184 parent_resource_path = parent_resource_path.AppendASCII("resources"); | |
| 185 FilePath new_parent_resource_path(new_layout_test_dir_.DirName()); | |
| 186 new_parent_resource_path = | |
| 187 new_parent_resource_path.AppendASCII("resources"); | |
| 188 ASSERT_TRUE(file_util::CopyDirectory( | |
| 189 parent_resource_path, new_parent_resource_path, true)); | |
| 190 } | |
| 191 | |
| 192 // Reads the layout test controller simulation script. | |
| 193 FilePath path; | |
| 194 PathService::Get(chrome::DIR_TEST_DATA, &path); | |
| 195 path = path.AppendASCII("workers"); | |
| 196 path = path.AppendASCII("layout_test_controller.html"); | |
| 197 ASSERT_TRUE(file_util::ReadFileToString(path, &layout_test_controller_)); | |
| 198 } | |
| 199 | |
| 200 void WorkerTest::RunLayoutTest(const std::string& test_case_file_name, | |
| 201 bool is_http_test) { | |
| 202 SCOPED_TRACE(test_case_file_name.c_str()); | |
| 203 | |
| 204 ASSERT_TRUE(!layout_test_controller_.empty()); | |
| 205 | |
| 206 // Creates a new cookie name. We will have to use a new cookie because | |
| 207 // this function could be called multiple times. | |
| 208 std::string status_cookie(kTestCompleteCookie); | |
| 209 status_cookie += IntToString(test_count_); | |
| 210 test_count_++; | |
| 211 | |
| 212 // Reads the layout test HTML file. | |
| 213 FilePath test_file_path(layout_test_dir_); | |
| 214 test_file_path = test_file_path.AppendASCII(test_case_file_name); | |
| 215 std::string test_html; | |
| 216 ASSERT_TRUE(file_util::ReadFileToString(test_file_path, &test_html)); | |
| 217 | |
| 218 // Injects the layout test controller into the test HTML. | |
| 219 test_html.insert(0, layout_test_controller_); | |
| 220 ReplaceSubstringsAfterOffset( | |
| 221 &test_html, 0, "%COOKIE%", status_cookie.c_str()); | |
| 222 | |
| 223 // Creates the new layout test HTML file. | |
| 224 FilePath new_test_file_path(new_layout_test_dir_); | |
| 225 new_test_file_path = new_test_file_path.AppendASCII(test_case_file_name); | |
| 226 ASSERT_TRUE(file_util::WriteFile(new_test_file_path, | |
| 227 &test_html.at(0), | |
| 228 static_cast<int>(test_html.size()))); | |
| 229 | |
| 230 scoped_ptr<GURL> new_test_url; | |
| 231 if (is_http_test) | |
| 232 new_test_url.reset(new GURL( | |
| 233 std::string("http://localhost:8080/") + | |
| 234 WideToUTF8(test_case_dir_.ToWStringHack()) + | |
| 235 "/" + | |
| 236 test_case_file_name)); | |
| 237 else | |
| 238 new_test_url.reset(new GURL(net::FilePathToFileURL(new_test_file_path))); | |
| 239 | |
| 240 // Runs the new layout test. | |
| 241 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
| 242 ASSERT_TRUE(tab.get()); | |
| 243 ASSERT_TRUE(tab->NavigateToURL(*new_test_url.get())); | |
| 244 std::string escaped_value = | |
| 245 WaitUntilCookieNonEmpty(tab.get(), *new_test_url.get(), | |
| 246 status_cookie.c_str(), kTestIntervalMs, kTestWaitTimeoutMs); | |
| 247 | |
| 248 // Unescapes and normalizes the actual result. | |
| 249 std::string value = UnescapeURLComponent(escaped_value, | |
| 250 UnescapeRule::NORMAL | UnescapeRule::SPACES | | |
| 251 UnescapeRule::URL_SPECIAL_CHARS | UnescapeRule::CONTROL_CHARS); | |
| 252 value += "\n"; | |
| 253 ReplaceSubstringsAfterOffset(&value, 0, "\r", ""); | |
| 254 | |
| 255 // Reads the expected result. First try to read from rebase directory. | |
| 256 // If failed, read from original directory. | |
| 257 std::string expected_result_value; | |
| 258 if (!ReadExpectedResult(rebase_result_dir_, | |
| 259 test_case_file_name, | |
| 260 &expected_result_value)) { | |
| 261 if (rebase_result_win_dir_.empty() || | |
| 262 !ReadExpectedResult(rebase_result_win_dir_, | |
| 263 test_case_file_name, | |
| 264 &expected_result_value)) | |
| 265 ReadExpectedResult(layout_test_dir_, | |
| 266 test_case_file_name, | |
| 267 &expected_result_value); | |
| 268 } | |
| 269 ASSERT_TRUE(!expected_result_value.empty()); | |
| 270 | |
| 271 // Normalizes the expected result. | |
| 272 ReplaceSubstringsAfterOffset(&expected_result_value, 0, "\r", ""); | |
| 273 | |
| 274 // Compares the results. | |
| 275 EXPECT_STREQ(expected_result_value.c_str(), value.c_str()); | |
| 276 } | |
| 277 | |
| 278 bool WorkerTest::ReadExpectedResult(const FilePath& result_dir_path, | |
| 279 const std::string test_case_file_name, | |
| 280 std::string* expected_result_value) { | |
| 281 FilePath expected_result_path(result_dir_path); | |
| 282 expected_result_path = expected_result_path.AppendASCII(test_case_file_name); | |
| 283 expected_result_path = expected_result_path.InsertBeforeExtension( | |
| 284 FILE_PATH_LITERAL("-expected")); | |
| 285 expected_result_path = | |
| 286 expected_result_path.ReplaceExtension(FILE_PATH_LITERAL("txt")); | |
| 287 return file_util::ReadFileToString(expected_result_path, | |
| 288 expected_result_value); | |
| 289 } | |
| 290 | |
| 291 TEST_F(WorkerTest, SingleWorker) { | |
| 292 RunTest(L"single_worker.html"); | |
| 293 } | |
| 294 | |
| 295 TEST_F(WorkerTest, MultipleWorkers) { | |
| 296 RunTest(L"multi_worker.html"); | |
| 297 } | |
| 298 | |
| 299 TEST_F(WorkerTest, WorkerFastLayoutTests) { | |
| 300 static const char* kLayoutTestFiles[] = { | |
| 301 "stress-js-execution.html", | |
| 302 "use-machine-stack.html", | |
| 303 "worker-close.html", | |
| 304 //"worker-constructor.html", | |
| 305 "worker-context-gc.html", | |
| 306 "worker-event-listener.html", | |
| 307 "worker-gc.html", | |
| 308 "worker-location.html", | |
| 309 "worker-navigator.html", | |
| 310 "worker-replace-global-constructor.html", | |
| 311 "worker-replace-self.html", | |
| 312 "worker-script-error.html", | |
| 313 "worker-terminate.html", | |
| 314 "worker-timeout.html" | |
| 315 }; | |
| 316 | |
| 317 FilePath fast_test_dir; | |
| 318 fast_test_dir = fast_test_dir.AppendASCII("LayoutTests"); | |
| 319 fast_test_dir = fast_test_dir.AppendASCII("fast"); | |
| 320 | |
| 321 FilePath worker_test_dir; | |
| 322 worker_test_dir = worker_test_dir.AppendASCII("workers"); | |
| 323 InitializeForLayoutTest(fast_test_dir, worker_test_dir, false); | |
| 324 | |
| 325 for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) | |
| 326 RunLayoutTest(kLayoutTestFiles[i], false); | |
| 327 } | |
| 328 | |
| 329 TEST_F(WorkerTest, WorkerHttpLayoutTests) { | |
| 330 static const char* kLayoutTestFiles[] = { | |
| 331 // flakey? BUG 16934 "text-encoding.html", | |
| 332 "worker-importScripts.html", | |
| 333 //"worker-redirect.html", | |
| 334 }; | |
| 335 | |
| 336 FilePath http_test_dir; | |
| 337 http_test_dir = http_test_dir.AppendASCII("LayoutTests"); | |
| 338 http_test_dir = http_test_dir.AppendASCII("http"); | |
| 339 http_test_dir = http_test_dir.AppendASCII("tests"); | |
| 340 | |
| 341 FilePath worker_test_dir; | |
| 342 worker_test_dir = worker_test_dir.AppendASCII("workers"); | |
| 343 InitializeForLayoutTest(http_test_dir, worker_test_dir, true); | |
| 344 | |
| 345 StartHttpServer(new_http_root_dir_); | |
| 346 for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) | |
| 347 RunLayoutTest(kLayoutTestFiles[i], true); | |
| 348 StopHttpServer(); | |
| 349 } | |
| 350 | |
| 351 TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) { | |
| 352 static const char* kLayoutTestFiles[] = { | |
| 353 "abort-exception-assert.html", | |
| 354 "close.html", | |
| 355 //"methods-async.html", | |
| 356 //"methods.html", | |
| 357 "xmlhttprequest-file-not-found.html" | |
| 358 }; | |
| 359 | |
| 360 FilePath http_test_dir; | |
| 361 http_test_dir = http_test_dir.AppendASCII("LayoutTests"); | |
| 362 http_test_dir = http_test_dir.AppendASCII("http"); | |
| 363 http_test_dir = http_test_dir.AppendASCII("tests"); | |
| 364 | |
| 365 FilePath worker_test_dir; | |
| 366 worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest"); | |
| 367 worker_test_dir = worker_test_dir.AppendASCII("workers"); | |
| 368 InitializeForLayoutTest(http_test_dir, worker_test_dir, true); | |
| 369 | |
| 370 StartHttpServer(new_http_root_dir_); | |
| 371 for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) | |
| 372 RunLayoutTest(kLayoutTestFiles[i], true); | |
| 373 StopHttpServer(); | |
| 374 } | |
| 375 | |
| 376 TEST_F(WorkerTest, LimitPerPage) { | |
| 377 int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate; | |
| 378 GURL url = GetTestUrl(L"workers", L"many_workers.html"); | |
| 379 url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1)); | |
| 380 | |
| 381 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
| 382 ASSERT_TRUE(tab.get()); | |
| 383 ASSERT_TRUE(tab->NavigateToURL(url)); | |
| 384 | |
| 385 EXPECT_EQ(max_workers_per_tab + 1 + (UITest::in_process_renderer() ? 0 : 1), | |
| 386 UITest::GetBrowserProcessCount()); | |
| 387 } | |
| 388 | |
| 389 TEST_F(WorkerTest, LimitTotal) { | |
| 390 int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate; | |
| 391 int total_workers = WorkerService::kMaxWorkersWhenSeparate; | |
| 392 | |
| 393 int tab_count = (total_workers / max_workers_per_tab) + 1; | |
| 394 GURL url = GetTestUrl(L"workers", L"many_workers.html"); | |
| 395 url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab)); | |
| 396 | |
| 397 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
| 398 ASSERT_TRUE(tab.get()); | |
| 399 ASSERT_TRUE(tab->NavigateToURL(url)); | |
| 400 scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); | |
| 401 for (int i = 1; i < tab_count; ++i) | |
| 402 window->AppendTab(url); | |
| 403 | |
| 404 // Check that we didn't create more than the max number of workers. | |
| 405 EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count), | |
| 406 UITest::GetBrowserProcessCount()); | |
| 407 | |
| 408 // Now close the first tab and check that the queued workers were started. | |
| 409 tab->Close(true); | |
| 410 tab->NavigateToURL(GetTestUrl(L"google", L"google.html")); | |
| 411 | |
| 412 EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count), | |
| 413 UITest::GetBrowserProcessCount()); | |
| 414 } | |
| OLD | NEW |