| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "chrome/test/ui/ui_test.h" | 5 #include "chrome/test/ui/ui_perf_test.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #include "base/path_service.h" |
| 8 #include <signal.h> | 8 #include "base/string_number_conversions.h" |
| 9 #include <sys/types.h> | 9 #include "chrome/common/chrome_paths.h" |
| 10 #endif | 10 #include "chrome/test/chrome_process_util.h" |
| 11 | 11 |
| 12 #include <set> | 12 void UIPerfTest::PrintResult(const std::string& measurement, |
| 13 #include <vector> | |
| 14 | |
| 15 #include "app/sql/connection.h" | |
| 16 #include "base/base_switches.h" | |
| 17 #include "base/command_line.h" | |
| 18 #include "base/file_path.h" | |
| 19 #include "base/file_util.h" | |
| 20 #include "base/path_service.h" | |
| 21 #include "base/platform_thread.h" | |
| 22 #include "base/process_util.h" | |
| 23 #include "base/scoped_ptr.h" | |
| 24 #include "base/scoped_temp_dir.h" | |
| 25 #include "base/string_number_conversions.h" | |
| 26 #include "base/test/test_file_util.h" | |
| 27 #include "base/time.h" | |
| 28 #include "base/utf_string_conversions.h" | |
| 29 #include "chrome/app/chrome_dll_resource.h" | |
| 30 #include "chrome/browser/net/url_fixer_upper.h" | |
| 31 #include "chrome/common/chrome_constants.h" | |
| 32 #include "chrome/common/chrome_paths.h" | |
| 33 #include "chrome/common/chrome_switches.h" | |
| 34 #include "chrome/common/debug_flags.h" | |
| 35 #include "chrome/common/logging_chrome.h" | |
| 36 #include "chrome/common/json_value_serializer.h" | |
| 37 #include "chrome/common/url_constants.h" | |
| 38 #include "chrome/test/automation/automation_messages.h" | |
| 39 #include "chrome/test/automation/automation_proxy.h" | |
| 40 #include "chrome/test/automation/browser_proxy.h" | |
| 41 #include "chrome/test/automation/javascript_execution_controller.h" | |
| 42 #include "chrome/test/automation/tab_proxy.h" | |
| 43 #include "chrome/test/automation/window_proxy.h" | |
| 44 #include "chrome/test/chrome_process_util.h" | |
| 45 #include "googleurl/src/gurl.h" | |
| 46 #include "net/base/net_util.h" | |
| 47 | |
| 48 #if defined(OS_WIN) | |
| 49 #include "base/win_util.h" | |
| 50 #endif | |
| 51 | |
| 52 | |
| 53 using base::Time; | |
| 54 using base::TimeDelta; | |
| 55 using base::TimeTicks; | |
| 56 | |
| 57 // Delay to let browser complete a requested action. | |
| 58 static const int kWaitForActionMsec = 2000; | |
| 59 static const int kWaitForActionMaxMsec = 15000; | |
| 60 // Command execution timeout passed to AutomationProxy. | |
| 61 static const int kCommandExecutionTimeout = 25000; | |
| 62 // Delay to let the browser shut down before trying more brutal methods. | |
| 63 static const int kWaitForTerminateMsec = 15000; | |
| 64 // Passed as value of kTestType. | |
| 65 static const char kUITestType[] = "ui"; | |
| 66 | |
| 67 const wchar_t UITestBase::kFailedNoCrashService[] = | |
| 68 #if defined(OS_WIN) | |
| 69 L"NOTE: This test is expected to fail if crash_service.exe is not " | |
| 70 L"running. Start it manually before running this test (see the build " | |
| 71 L"output directory)."; | |
| 72 #elif defined(OS_LINUX) | |
| 73 L"NOTE: This test is expected to fail if breakpad is not built in " | |
| 74 L"or if chromium is not running headless (try CHROME_HEADLESS=1)."; | |
| 75 #else | |
| 76 L"NOTE: Crash service not ported to this platform!"; | |
| 77 #endif | |
| 78 bool UITestBase::in_process_renderer_ = false; | |
| 79 bool UITestBase::no_sandbox_ = false; | |
| 80 bool UITestBase::full_memory_dump_ = false; | |
| 81 bool UITestBase::safe_plugins_ = false; | |
| 82 bool UITestBase::show_error_dialogs_ = true; | |
| 83 bool UITestBase::dump_histograms_on_exit_ = false; | |
| 84 bool UITestBase::enable_dcheck_ = false; | |
| 85 bool UITestBase::silent_dump_on_dcheck_ = false; | |
| 86 bool UITestBase::disable_breakpad_ = false; | |
| 87 int UITestBase::timeout_ms_ = 10 * 60 * 1000; | |
| 88 std::string UITestBase::js_flags_ = ""; | |
| 89 std::string UITestBase::log_level_ = ""; | |
| 90 | |
| 91 // Specify the time (in milliseconds) that the ui_tests should wait before | |
| 92 // timing out. This is used to specify longer timeouts when running under Purify | |
| 93 // which requires much more time. | |
| 94 const char kUiTestTimeout[] = "ui-test-timeout"; | |
| 95 const char kUiTestActionTimeout[] = "ui-test-action-timeout"; | |
| 96 const char kUiTestActionMaxTimeout[] = "ui-test-action-max-timeout"; | |
| 97 const char kUiTestSleepTimeout[] = "ui-test-sleep-timeout"; | |
| 98 const char kUiTestTerminateTimeout[] = "ui-test-terminate-timeout"; | |
| 99 | |
| 100 const char kExtraChromeFlagsSwitch[] = "extra-chrome-flags"; | |
| 101 | |
| 102 // By default error dialogs are hidden, which makes debugging failures in the | |
| 103 // slave process frustrating. By passing this in error dialogs are enabled. | |
| 104 const char kEnableErrorDialogs[] = "enable-errdialogs"; | |
| 105 | |
| 106 // Uncomment this line to have the spawned process wait for the debugger to | |
| 107 // attach. This only works on Windows. On posix systems, you can set the | |
| 108 // BROWSER_WRAPPER env variable to wrap the browser process. | |
| 109 // #define WAIT_FOR_DEBUGGER_ON_OPEN 1 | |
| 110 | |
| 111 UITestBase::UITestBase() | |
| 112 : launch_arguments_(CommandLine::ARGUMENTS_ONLY), | |
| 113 expected_errors_(0), | |
| 114 expected_crashes_(0), | |
| 115 homepage_(chrome::kAboutBlankURL), | |
| 116 wait_for_initial_loads_(true), | |
| 117 dom_automation_enabled_(false), | |
| 118 process_(base::kNullProcessHandle), | |
| 119 process_id_(-1), | |
| 120 show_window_(false), | |
| 121 clear_profile_(true), | |
| 122 include_testing_id_(true), | |
| 123 enable_file_cookies_(true), | |
| 124 profile_type_(UITestBase::DEFAULT_THEME), | |
| 125 shutdown_type_(UITestBase::WINDOW_CLOSE), | |
| 126 test_start_time_(Time::NowFromSystemTime()), | |
| 127 command_execution_timeout_ms_(kCommandExecutionTimeout), | |
| 128 action_timeout_ms_(kWaitForActionMsec), | |
| 129 action_max_timeout_ms_(kWaitForActionMaxMsec), | |
| 130 sleep_timeout_ms_(kWaitForActionMsec), | |
| 131 terminate_timeout_ms_(kWaitForTerminateMsec), | |
| 132 temp_profile_dir_(new ScopedTempDir()) { | |
| 133 PathService::Get(chrome::DIR_APP, &browser_directory_); | |
| 134 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | |
| 135 } | |
| 136 | |
| 137 UITestBase::UITestBase(MessageLoop::Type msg_loop_type) | |
| 138 : launch_arguments_(CommandLine::ARGUMENTS_ONLY), | |
| 139 expected_errors_(0), | |
| 140 expected_crashes_(0), | |
| 141 homepage_(chrome::kAboutBlankURL), | |
| 142 wait_for_initial_loads_(true), | |
| 143 dom_automation_enabled_(false), | |
| 144 process_(base::kNullProcessHandle), | |
| 145 process_id_(-1), | |
| 146 show_window_(false), | |
| 147 clear_profile_(true), | |
| 148 include_testing_id_(true), | |
| 149 enable_file_cookies_(true), | |
| 150 profile_type_(UITestBase::DEFAULT_THEME), | |
| 151 shutdown_type_(UITestBase::WINDOW_CLOSE), | |
| 152 test_start_time_(Time::NowFromSystemTime()), | |
| 153 command_execution_timeout_ms_(kCommandExecutionTimeout), | |
| 154 action_timeout_ms_(kWaitForActionMsec), | |
| 155 action_max_timeout_ms_(kWaitForActionMaxMsec), | |
| 156 sleep_timeout_ms_(kWaitForActionMsec), | |
| 157 terminate_timeout_ms_(kWaitForTerminateMsec) { | |
| 158 PathService::Get(chrome::DIR_APP, &browser_directory_); | |
| 159 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | |
| 160 } | |
| 161 | |
| 162 UITestBase::~UITestBase() { | |
| 163 } | |
| 164 | |
| 165 void UITestBase::SetUp() { | |
| 166 AssertAppNotRunning(L"Please close any other instances " | |
| 167 L"of the app before testing."); | |
| 168 | |
| 169 InitializeTimeouts(); | |
| 170 JavaScriptExecutionController::set_timeout(action_max_timeout_ms_); | |
| 171 LaunchBrowserAndServer(); | |
| 172 } | |
| 173 | |
| 174 void UITestBase::TearDown() { | |
| 175 CloseBrowserAndServer(); | |
| 176 | |
| 177 // Make sure that we didn't encounter any assertion failures | |
| 178 logging::AssertionList assertions; | |
| 179 logging::GetFatalAssertions(&assertions); | |
| 180 | |
| 181 // If there were errors, get all the error strings for display. | |
| 182 std::wstring failures = | |
| 183 L"The following error(s) occurred in the application during this test:"; | |
| 184 if (assertions.size() > expected_errors_) { | |
| 185 logging::AssertionList::const_iterator iter = assertions.begin(); | |
| 186 for (; iter != assertions.end(); ++iter) { | |
| 187 failures.append(L"\n\n"); | |
| 188 failures.append(*iter); | |
| 189 } | |
| 190 } | |
| 191 EXPECT_EQ(expected_errors_, assertions.size()) << failures; | |
| 192 | |
| 193 // Check for crashes during the test | |
| 194 FilePath crash_dump_path; | |
| 195 PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); | |
| 196 int actual_crashes = | |
| 197 file_util::CountFilesCreatedAfter(crash_dump_path, test_start_time_); | |
| 198 | |
| 199 #if defined(OS_WIN) | |
| 200 // Each crash creates two dump files, so we divide by two here. | |
| 201 actual_crashes /= 2; | |
| 202 #endif | |
| 203 | |
| 204 std::wstring error_msg = | |
| 205 L"Encountered an unexpected crash in the program during this test."; | |
| 206 if (expected_crashes_ > 0 && actual_crashes == 0) { | |
| 207 error_msg += L" "; | |
| 208 error_msg += kFailedNoCrashService; | |
| 209 } | |
| 210 EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg; | |
| 211 } | |
| 212 | |
| 213 void UITestBase::set_command_execution_timeout_ms(int timeout) { | |
| 214 if (server_.get()) { | |
| 215 // automation channel already created. Set its timeout for use by | |
| 216 // subsequent automation calls. | |
| 217 server_->set_command_execution_timeout_ms(timeout); | |
| 218 } | |
| 219 command_execution_timeout_ms_ = timeout; | |
| 220 LOG(INFO) << "Automation command execution timeout set to " | |
| 221 << timeout << " milli secs."; | |
| 222 } | |
| 223 | |
| 224 // Pick up the various test time out values from the command line. | |
| 225 void UITestBase::InitializeTimeouts() { | |
| 226 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
| 227 if (command_line.HasSwitch(kUiTestTimeout)) { | |
| 228 std::string timeout_str = command_line.GetSwitchValueASCII(kUiTestTimeout); | |
| 229 int timeout; | |
| 230 base::StringToInt(timeout_str, &timeout); | |
| 231 command_execution_timeout_ms_ = std::max(kCommandExecutionTimeout, timeout); | |
| 232 } | |
| 233 | |
| 234 if (command_line.HasSwitch(kUiTestActionTimeout)) { | |
| 235 std::string act_str = | |
| 236 command_line.GetSwitchValueASCII(kUiTestActionTimeout); | |
| 237 int act_timeout; | |
| 238 base::StringToInt(act_str, &act_timeout); | |
| 239 action_timeout_ms_ = std::max(kWaitForActionMsec, act_timeout); | |
| 240 } | |
| 241 | |
| 242 if (command_line.HasSwitch(kUiTestActionMaxTimeout)) { | |
| 243 std::string action_max_str = | |
| 244 command_line.GetSwitchValueASCII(kUiTestActionMaxTimeout); | |
| 245 int max_timeout; | |
| 246 base::StringToInt(action_max_str, &max_timeout); | |
| 247 action_max_timeout_ms_ = std::max(kWaitForActionMaxMsec, max_timeout); | |
| 248 } | |
| 249 | |
| 250 if (CommandLine::ForCurrentProcess()->HasSwitch(kUiTestSleepTimeout)) { | |
| 251 std::string sleep_timeout_str = | |
| 252 command_line.GetSwitchValueASCII(kUiTestSleepTimeout); | |
| 253 int sleep_timeout; | |
| 254 base::StringToInt(sleep_timeout_str, &sleep_timeout); | |
| 255 sleep_timeout_ms_ = std::max(kWaitForActionMsec, sleep_timeout); | |
| 256 } | |
| 257 | |
| 258 if (CommandLine::ForCurrentProcess()->HasSwitch(kUiTestTerminateTimeout)) { | |
| 259 std::string terminate_timeout_str = | |
| 260 command_line.GetSwitchValueASCII(kUiTestTerminateTimeout); | |
| 261 int terminate_timeout; | |
| 262 base::StringToInt(terminate_timeout_str, &terminate_timeout); | |
| 263 terminate_timeout_ms_ = std::max(kWaitForActionMsec, terminate_timeout); | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 AutomationProxy* UITestBase::CreateAutomationProxy(int execution_timeout) { | |
| 268 return new AutomationProxy(execution_timeout, false); | |
| 269 } | |
| 270 | |
| 271 void UITestBase::LaunchBrowserAndServer() { | |
| 272 // Set up IPC testing interface server. | |
| 273 server_.reset(CreateAutomationProxy(command_execution_timeout_ms_)); | |
| 274 | |
| 275 LaunchBrowser(launch_arguments_, clear_profile_); | |
| 276 server_->WaitForAppLaunch(); | |
| 277 if (wait_for_initial_loads_) | |
| 278 ASSERT_TRUE(server_->WaitForInitialLoads()); | |
| 279 else | |
| 280 PlatformThread::Sleep(sleep_timeout_ms()); | |
| 281 | |
| 282 EXPECT_TRUE(automation()->SetFilteredInet(ShouldFilterInet())); | |
| 283 } | |
| 284 | |
| 285 void UITestBase::CloseBrowserAndServer() { | |
| 286 QuitBrowser(); | |
| 287 CleanupAppProcesses(); | |
| 288 | |
| 289 // Suppress spammy failures that seem to be occurring when running | |
| 290 // the UI tests in single-process mode. | |
| 291 // TODO(jhughes): figure out why this is necessary at all, and fix it | |
| 292 if (!in_process_renderer_) | |
| 293 AssertAppNotRunning(StringPrintf( | |
| 294 L"Unable to quit all browser processes. Original PID %d", process_id_)); | |
| 295 | |
| 296 server_.reset(); // Shut down IPC testing interface. | |
| 297 } | |
| 298 | |
| 299 static CommandLine* CreatePythonCommandLine() { | |
| 300 return new CommandLine(FilePath(FILE_PATH_LITERAL("python"))); | |
| 301 } | |
| 302 | |
| 303 static CommandLine* CreateHttpServerCommandLine() { | |
| 304 FilePath src_path; | |
| 305 // Get to 'src' dir. | |
| 306 PathService::Get(base::DIR_SOURCE_ROOT, &src_path); | |
| 307 | |
| 308 FilePath script_path(src_path); | |
| 309 script_path = script_path.AppendASCII("third_party"); | |
| 310 script_path = script_path.AppendASCII("WebKit"); | |
| 311 script_path = script_path.AppendASCII("WebKitTools"); | |
| 312 script_path = script_path.AppendASCII("Scripts"); | |
| 313 script_path = script_path.AppendASCII("new-run-webkit-httpd"); | |
| 314 | |
| 315 CommandLine* cmd_line = CreatePythonCommandLine(); | |
| 316 cmd_line->AppendArgPath(script_path); | |
| 317 return cmd_line; | |
| 318 } | |
| 319 | |
| 320 static void RunCommand(const CommandLine& cmd_line) { | |
| 321 #if defined(OS_WIN) | |
| 322 // For Win32, use this 'version' of base::LaunchApp() with bInheritHandles | |
| 323 // parameter to CreateProcess set to TRUE. This is needed in test harness | |
| 324 // because it launches all the processes with 'chained' standard i/o pipes. | |
| 325 STARTUPINFO startup_info = {0}; | |
| 326 startup_info.cb = sizeof(startup_info); | |
| 327 PROCESS_INFORMATION process_info; | |
| 328 if (!CreateProcess( | |
| 329 NULL, | |
| 330 const_cast<wchar_t*>(cmd_line.command_line_string().c_str()), | |
| 331 NULL, NULL, | |
| 332 TRUE, // Inherit the standard pipes, needed when | |
| 333 // running in test harnesses. | |
| 334 0, NULL, NULL, &startup_info, &process_info)) | |
| 335 return; | |
| 336 | |
| 337 // Handles must be closed or they will leak | |
| 338 CloseHandle(process_info.hThread); | |
| 339 WaitForSingleObject(process_info.hProcess, INFINITE); | |
| 340 CloseHandle(process_info.hProcess); | |
| 341 #else | |
| 342 base::LaunchApp(cmd_line, true, false, NULL); | |
| 343 #endif | |
| 344 } | |
| 345 | |
| 346 void UITestBase::StartHttpServer(const FilePath& root_directory) { | |
| 347 StartHttpServerWithPort(root_directory, 0); | |
| 348 } | |
| 349 | |
| 350 void UITestBase::StartHttpServerWithPort(const FilePath& root_directory, | |
| 351 int port) { | |
| 352 scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine()); | |
| 353 ASSERT_TRUE(cmd_line.get()); | |
| 354 cmd_line->AppendSwitchASCII("server", "start"); | |
| 355 cmd_line->AppendSwitch("register_cygwin"); | |
| 356 cmd_line->AppendSwitchPath("root", root_directory); | |
| 357 | |
| 358 // For Windows 7, if we start the lighttpd server on the foreground mode, | |
| 359 // it will mess up with the command window and cause conhost.exe to crash. To | |
| 360 // work around this, we start the http server on the background mode. | |
| 361 #if defined(OS_WIN) | |
| 362 if (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) | |
| 363 cmd_line->AppendSwitch("run_background"); | |
| 364 #endif | |
| 365 | |
| 366 if (port) | |
| 367 cmd_line->AppendSwitchASCII("port", base::IntToString(port)); | |
| 368 RunCommand(*cmd_line.get()); | |
| 369 } | |
| 370 | |
| 371 void UITestBase::StopHttpServer() { | |
| 372 scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine()); | |
| 373 ASSERT_TRUE(cmd_line.get()); | |
| 374 cmd_line->AppendSwitchASCII("server", "stop"); | |
| 375 RunCommand(*cmd_line.get()); | |
| 376 } | |
| 377 | |
| 378 void UITestBase::LaunchBrowser(const CommandLine& arguments, | |
| 379 bool clear_profile) { | |
| 380 if (clear_profile || !temp_profile_dir_->IsValid()) { | |
| 381 temp_profile_dir_.reset(new ScopedTempDir()); | |
| 382 ASSERT_TRUE(temp_profile_dir_->CreateUniqueTempDir()); | |
| 383 | |
| 384 // Update the information about user data directory location on the ui_test | |
| 385 // side. Using PathService seems to be the most reliable, consistent way | |
| 386 // to do that. | |
| 387 ASSERT_TRUE(PathService::Override(chrome::DIR_USER_DATA, user_data_dir())); | |
| 388 } | |
| 389 | |
| 390 if (!template_user_data_.empty()) { | |
| 391 // Recursively copy the template directory to the user_data_dir. | |
| 392 ASSERT_TRUE(file_util::CopyRecursiveDirNoCache( | |
| 393 template_user_data_, | |
| 394 user_data_dir())); | |
| 395 // If we're using the complex theme data, we need to write the | |
| 396 // user_data_dir_ to our preferences file. | |
| 397 if (profile_type_ == UITestBase::COMPLEX_THEME) { | |
| 398 RewritePreferencesFile(user_data_dir()); | |
| 399 } | |
| 400 | |
| 401 // Update the history file to include recent dates. | |
| 402 UpdateHistoryDates(); | |
| 403 } | |
| 404 | |
| 405 ASSERT_TRUE(LaunchBrowserHelper(arguments, false, &process_)); | |
| 406 process_id_ = base::GetProcId(process_); | |
| 407 } | |
| 408 | |
| 409 bool UITestBase::LaunchAnotherBrowserBlockUntilClosed( | |
| 410 const CommandLine& cmdline) { | |
| 411 return LaunchBrowserHelper(cmdline, true, NULL); | |
| 412 } | |
| 413 | |
| 414 void UITestBase::QuitBrowser() { | |
| 415 if (SESSION_ENDING == shutdown_type_) { | |
| 416 TerminateBrowser(); | |
| 417 return; | |
| 418 } | |
| 419 | |
| 420 // There's nothing to do here if the browser is not running. | |
| 421 if (IsBrowserRunning()) { | |
| 422 TimeTicks quit_start = TimeTicks::Now(); | |
| 423 EXPECT_TRUE(automation()->SetFilteredInet(false)); | |
| 424 | |
| 425 if (WINDOW_CLOSE == shutdown_type_) { | |
| 426 int window_count = 0; | |
| 427 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
| 428 | |
| 429 // Synchronously close all but the last browser window. Closing them | |
| 430 // one-by-one may help with stability. | |
| 431 while (window_count > 1) { | |
| 432 scoped_refptr<BrowserProxy> browser_proxy = | |
| 433 automation()->GetBrowserWindow(0); | |
| 434 EXPECT_TRUE(browser_proxy.get()); | |
| 435 if (browser_proxy.get()) { | |
| 436 EXPECT_TRUE(browser_proxy->RunCommand(IDC_CLOSE_WINDOW)); | |
| 437 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
| 438 } else { | |
| 439 break; | |
| 440 } | |
| 441 } | |
| 442 | |
| 443 // Close the last window asynchronously, because the browser may | |
| 444 // shutdown faster than it will be able to send a synchronous response | |
| 445 // to our message. | |
| 446 scoped_refptr<BrowserProxy> browser_proxy = | |
| 447 automation()->GetBrowserWindow(0); | |
| 448 EXPECT_TRUE(browser_proxy.get()); | |
| 449 if (browser_proxy.get()) { | |
| 450 EXPECT_TRUE(browser_proxy->ApplyAccelerator(IDC_CLOSE_WINDOW)); | |
| 451 browser_proxy = NULL; | |
| 452 } | |
| 453 } else if (USER_QUIT == shutdown_type_) { | |
| 454 scoped_refptr<BrowserProxy> browser_proxy = | |
| 455 automation()->GetBrowserWindow(0); | |
| 456 EXPECT_TRUE(browser_proxy.get()); | |
| 457 if (browser_proxy.get()) { | |
| 458 EXPECT_TRUE(browser_proxy->RunCommandAsync(IDC_EXIT)); | |
| 459 } | |
| 460 } else { | |
| 461 NOTREACHED() << "Invalid shutdown type " << shutdown_type_; | |
| 462 } | |
| 463 | |
| 464 // Now, drop the automation IPC channel so that the automation provider in | |
| 465 // the browser notices and drops its reference to the browser process. | |
| 466 automation()->Disconnect(); | |
| 467 | |
| 468 // Wait for the browser process to quit. It should quit once all tabs have | |
| 469 // been closed. | |
| 470 int timeout = terminate_timeout_ms_; | |
| 471 #ifdef WAIT_FOR_DEBUGGER_ON_OPEN | |
| 472 timeout = 500000; | |
| 473 #endif | |
| 474 if (!base::WaitForSingleProcess(process_, timeout)) { | |
| 475 // We need to force the browser to quit because it didn't quit fast | |
| 476 // enough. Take no chance and kill every chrome processes. | |
| 477 CleanupAppProcesses(); | |
| 478 } | |
| 479 browser_quit_time_ = TimeTicks::Now() - quit_start; | |
| 480 } | |
| 481 | |
| 482 // Don't forget to close the handle | |
| 483 base::CloseProcessHandle(process_); | |
| 484 process_ = base::kNullProcessHandle; | |
| 485 process_id_ = -1; | |
| 486 } | |
| 487 | |
| 488 void UITestBase::TerminateBrowser() { | |
| 489 if (IsBrowserRunning()) { | |
| 490 TimeTicks quit_start = TimeTicks::Now(); | |
| 491 EXPECT_TRUE(automation()->SetFilteredInet(false)); | |
| 492 #if defined(OS_WIN) | |
| 493 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); | |
| 494 ASSERT_TRUE(browser.get()); | |
| 495 ASSERT_TRUE(browser->TerminateSession()); | |
| 496 #endif // defined(OS_WIN) | |
| 497 | |
| 498 // Now, drop the automation IPC channel so that the automation provider in | |
| 499 // the browser notices and drops its reference to the browser process. | |
| 500 automation()->Disconnect(); | |
| 501 | |
| 502 #if defined(OS_POSIX) | |
| 503 EXPECT_EQ(kill(process_, SIGTERM), 0); | |
| 504 #endif // OS_POSIX | |
| 505 | |
| 506 // Wait for the browser process to quit. | |
| 507 int timeout = terminate_timeout_ms_; | |
| 508 #ifdef WAIT_FOR_DEBUGGER_ON_OPEN | |
| 509 timeout = 500000; | |
| 510 #endif | |
| 511 if (!base::WaitForSingleProcess(process_, timeout)) { | |
| 512 // We need to force the browser to quit because it didn't quit fast | |
| 513 // enough. Take no chance and kill every chrome processes. | |
| 514 CleanupAppProcesses(); | |
| 515 } | |
| 516 browser_quit_time_ = TimeTicks::Now() - quit_start; | |
| 517 } | |
| 518 | |
| 519 // Don't forget to close the handle | |
| 520 base::CloseProcessHandle(process_); | |
| 521 process_ = base::kNullProcessHandle; | |
| 522 process_id_ = -1; | |
| 523 } | |
| 524 | |
| 525 void UITestBase::AssertAppNotRunning(const std::wstring& error_message) { | |
| 526 std::wstring final_error_message(error_message); | |
| 527 | |
| 528 ChromeProcessList processes = GetRunningChromeProcesses(process_id_); | |
| 529 if (!processes.empty()) { | |
| 530 final_error_message += L" Leftover PIDs: ["; | |
| 531 for (ChromeProcessList::const_iterator it = processes.begin(); | |
| 532 it != processes.end(); ++it) { | |
| 533 final_error_message += StringPrintf(L" %d", *it); | |
| 534 } | |
| 535 final_error_message += L" ]"; | |
| 536 } | |
| 537 ASSERT_TRUE(processes.empty()) << final_error_message; | |
| 538 } | |
| 539 | |
| 540 void UITestBase::CleanupAppProcesses() { | |
| 541 TerminateAllChromeProcesses(process_id_); | |
| 542 } | |
| 543 | |
| 544 scoped_refptr<TabProxy> UITestBase::GetActiveTab(int window_index) { | |
| 545 EXPECT_GE(window_index, 0); | |
| 546 int window_count = -1; | |
| 547 // We have to use EXPECT rather than ASSERT here because ASSERT_* only works | |
| 548 // in functions that return void. | |
| 549 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
| 550 if (window_count == -1) | |
| 551 return NULL; | |
| 552 EXPECT_GT(window_count, window_index); | |
| 553 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
| 554 GetBrowserWindow(window_index)); | |
| 555 EXPECT_TRUE(window_proxy.get()); | |
| 556 if (!window_proxy.get()) | |
| 557 return NULL; | |
| 558 | |
| 559 int active_tab_index = -1; | |
| 560 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); | |
| 561 if (active_tab_index == -1) | |
| 562 return NULL; | |
| 563 | |
| 564 return window_proxy->GetTab(active_tab_index); | |
| 565 } | |
| 566 | |
| 567 scoped_refptr<TabProxy> UITestBase::GetActiveTab() { | |
| 568 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
| 569 GetBrowserWindow(0)); | |
| 570 EXPECT_TRUE(window_proxy.get()); | |
| 571 if (!window_proxy.get()) | |
| 572 return NULL; | |
| 573 | |
| 574 scoped_refptr<TabProxy> tab_proxy = window_proxy->GetActiveTab(); | |
| 575 EXPECT_TRUE(tab_proxy.get()); | |
| 576 return tab_proxy; | |
| 577 } | |
| 578 | |
| 579 void UITestBase::NavigateToURLAsync(const GURL& url) { | |
| 580 scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); | |
| 581 ASSERT_TRUE(tab_proxy.get()); | |
| 582 ASSERT_TRUE(tab_proxy->NavigateToURLAsync(url)); | |
| 583 } | |
| 584 | |
| 585 void UITestBase::NavigateToURL(const GURL& url) { | |
| 586 NavigateToURL(url, 0, GetActiveTabIndex(0)); | |
| 587 } | |
| 588 | |
| 589 void UITestBase::NavigateToURL(const GURL& url, int window_index, int | |
| 590 tab_index) { | |
| 591 NavigateToURLBlockUntilNavigationsComplete(url, 1, window_index, tab_index); | |
| 592 } | |
| 593 | |
| 594 void UITestBase::NavigateToURLBlockUntilNavigationsComplete( | |
| 595 const GURL& url, int number_of_navigations) { | |
| 596 scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); | |
| 597 ASSERT_TRUE(tab_proxy.get()); | |
| 598 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, | |
| 599 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( | |
| 600 url, number_of_navigations)) << url.spec(); | |
| 601 } | |
| 602 | |
| 603 void UITestBase::NavigateToURLBlockUntilNavigationsComplete( | |
| 604 const GURL& url, int number_of_navigations, int window_index, | |
| 605 int tab_index) { | |
| 606 scoped_refptr<BrowserProxy> window = | |
| 607 automation()->GetBrowserWindow(window_index); | |
| 608 ASSERT_TRUE(window.get()); | |
| 609 scoped_refptr<TabProxy> tab_proxy(window->GetTab(tab_index)); | |
| 610 ASSERT_TRUE(tab_proxy.get()); | |
| 611 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, | |
| 612 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( | |
| 613 url, number_of_navigations)) << url.spec(); | |
| 614 } | |
| 615 | |
| 616 bool UITestBase::WaitForDownloadShelfVisible(BrowserProxy* browser) { | |
| 617 return WaitForDownloadShelfVisibilityChange(browser, true); | |
| 618 } | |
| 619 | |
| 620 bool UITestBase::WaitForDownloadShelfInvisible(BrowserProxy* browser) { | |
| 621 return WaitForDownloadShelfVisibilityChange(browser, false); | |
| 622 } | |
| 623 | |
| 624 bool UITestBase::WaitForDownloadShelfVisibilityChange(BrowserProxy* browser, | |
| 625 bool wait_for_open) { | |
| 626 const int kCycles = 10; | |
| 627 for (int i = 0; i < kCycles; i++) { | |
| 628 // Give it a chance to catch up. | |
| 629 bool browser_survived = CrashAwareSleep(sleep_timeout_ms() / kCycles); | |
| 630 EXPECT_TRUE(browser_survived); | |
| 631 if (!browser_survived) | |
| 632 return false; | |
| 633 | |
| 634 bool visible = !wait_for_open; | |
| 635 if (!browser->IsShelfVisible(&visible)) | |
| 636 continue; | |
| 637 if (visible == wait_for_open) | |
| 638 return true; // Got the download shelf. | |
| 639 } | |
| 640 | |
| 641 ADD_FAILURE() << "Timeout reached in WaitForDownloadShelfVisibilityChange"; | |
| 642 return false; | |
| 643 } | |
| 644 | |
| 645 bool UITestBase::WaitForFindWindowVisibilityChange(BrowserProxy* browser, | |
| 646 bool wait_for_open) { | |
| 647 const int kCycles = 10; | |
| 648 for (int i = 0; i < kCycles; i++) { | |
| 649 bool visible = false; | |
| 650 if (!browser->IsFindWindowFullyVisible(&visible)) | |
| 651 return false; // Some error. | |
| 652 if (visible == wait_for_open) | |
| 653 return true; // Find window visibility change complete. | |
| 654 | |
| 655 // Give it a chance to catch up. | |
| 656 bool browser_survived = CrashAwareSleep(sleep_timeout_ms() / kCycles); | |
| 657 EXPECT_TRUE(browser_survived); | |
| 658 if (!browser_survived) | |
| 659 return false; | |
| 660 } | |
| 661 | |
| 662 ADD_FAILURE() << "Timeout reached in WaitForFindWindowVisibilityChange"; | |
| 663 return false; | |
| 664 } | |
| 665 | |
| 666 bool UITestBase::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, | |
| 667 bool wait_for_open) { | |
| 668 const int kCycles = 10; | |
| 669 for (int i = 0; i < kCycles; i++) { | |
| 670 bool visible = false; | |
| 671 bool animating = true; | |
| 672 if (!browser->GetBookmarkBarVisibility(&visible, &animating)) | |
| 673 return false; // Some error. | |
| 674 if (visible == wait_for_open && !animating) | |
| 675 return true; // Bookmark bar visibility change complete. | |
| 676 | |
| 677 // Give it a chance to catch up. | |
| 678 bool browser_survived = CrashAwareSleep(sleep_timeout_ms() / kCycles); | |
| 679 EXPECT_TRUE(browser_survived); | |
| 680 if (!browser_survived) | |
| 681 return false; | |
| 682 } | |
| 683 | |
| 684 ADD_FAILURE() << "Timeout reached in WaitForBookmarkBarVisibilityChange"; | |
| 685 return false; | |
| 686 } | |
| 687 | |
| 688 GURL UITestBase::GetActiveTabURL(int window_index) { | |
| 689 scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); | |
| 690 EXPECT_TRUE(tab_proxy.get()); | |
| 691 if (!tab_proxy.get()) | |
| 692 return GURL(); | |
| 693 | |
| 694 GURL url; | |
| 695 bool success = tab_proxy->GetCurrentURL(&url); | |
| 696 EXPECT_TRUE(success); | |
| 697 if (!success) | |
| 698 return GURL(); | |
| 699 return url; | |
| 700 } | |
| 701 | |
| 702 std::wstring UITestBase::GetActiveTabTitle(int window_index) { | |
| 703 std::wstring title; | |
| 704 scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); | |
| 705 EXPECT_TRUE(tab_proxy.get()); | |
| 706 if (!tab_proxy.get()) | |
| 707 return title; | |
| 708 | |
| 709 EXPECT_TRUE(tab_proxy->GetTabTitle(&title)); | |
| 710 return title; | |
| 711 } | |
| 712 | |
| 713 int UITestBase::GetActiveTabIndex(int window_index) { | |
| 714 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
| 715 GetBrowserWindow(window_index)); | |
| 716 EXPECT_TRUE(window_proxy.get()); | |
| 717 if (!window_proxy.get()) | |
| 718 return -1; | |
| 719 | |
| 720 int active_tab_index = -1; | |
| 721 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); | |
| 722 return active_tab_index; | |
| 723 } | |
| 724 | |
| 725 bool UITestBase::IsBrowserRunning() { | |
| 726 return CrashAwareSleep(0); | |
| 727 } | |
| 728 | |
| 729 bool UITestBase::CrashAwareSleep(int time_out_ms) { | |
| 730 return base::CrashAwareSleep(process_, time_out_ms); | |
| 731 } | |
| 732 | |
| 733 int UITestBase::GetBrowserProcessCount() { | |
| 734 return GetRunningChromeProcesses(process_id_).size(); | |
| 735 } | |
| 736 | |
| 737 static DictionaryValue* LoadDictionaryValueFromPath(const FilePath& path) { | |
| 738 if (path.empty()) | |
| 739 return NULL; | |
| 740 | |
| 741 JSONFileValueSerializer serializer(path); | |
| 742 scoped_ptr<Value> root_value(serializer.Deserialize(NULL, NULL)); | |
| 743 if (!root_value.get() || root_value->GetType() != Value::TYPE_DICTIONARY) | |
| 744 return NULL; | |
| 745 | |
| 746 return static_cast<DictionaryValue*>(root_value.release()); | |
| 747 } | |
| 748 | |
| 749 DictionaryValue* UITestBase::GetLocalState() { | |
| 750 FilePath local_state_path; | |
| 751 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); | |
| 752 return LoadDictionaryValueFromPath(local_state_path); | |
| 753 } | |
| 754 | |
| 755 DictionaryValue* UITestBase::GetDefaultProfilePreferences() { | |
| 756 FilePath path; | |
| 757 PathService::Get(chrome::DIR_USER_DATA, &path); | |
| 758 path = path.AppendASCII(WideToUTF8(chrome::kNotSignedInProfile)); | |
| 759 return LoadDictionaryValueFromPath(path.Append(chrome::kPreferencesFilename)); | |
| 760 } | |
| 761 | |
| 762 int UITestBase::GetTabCount() { | |
| 763 return GetTabCount(0); | |
| 764 } | |
| 765 | |
| 766 int UITestBase::GetTabCount(int window_index) { | |
| 767 scoped_refptr<BrowserProxy> window( | |
| 768 automation()->GetBrowserWindow(window_index)); | |
| 769 EXPECT_TRUE(window.get()); | |
| 770 if (!window.get()) | |
| 771 return 0; | |
| 772 | |
| 773 int result = 0; | |
| 774 EXPECT_TRUE(window->GetTabCount(&result)); | |
| 775 | |
| 776 return result; | |
| 777 } | |
| 778 | |
| 779 bool UITestBase::WaitUntilCookieValue(TabProxy* tab, | |
| 780 const GURL& url, | |
| 781 const char* cookie_name, | |
| 782 int time_out_ms, | |
| 783 const char* expected_value) { | |
| 784 const int kIntervalMs = 250; | |
| 785 const int kMaxIntervals = time_out_ms / kIntervalMs; | |
| 786 | |
| 787 std::string cookie_value; | |
| 788 for (int i = 0; i < kMaxIntervals; ++i) { | |
| 789 bool browser_survived = CrashAwareSleep(kIntervalMs); | |
| 790 EXPECT_TRUE(browser_survived); | |
| 791 if (!browser_survived) | |
| 792 return false; | |
| 793 | |
| 794 EXPECT_TRUE(tab->GetCookieByName(url, cookie_name, &cookie_value)); | |
| 795 if (cookie_value == expected_value) | |
| 796 return true; | |
| 797 } | |
| 798 | |
| 799 ADD_FAILURE() << "Timeout reached in WaitUntilCookieValue"; | |
| 800 return false; | |
| 801 } | |
| 802 | |
| 803 std::string UITestBase::WaitUntilCookieNonEmpty(TabProxy* tab, | |
| 804 const GURL& url, | |
| 805 const char* cookie_name, | |
| 806 int time_out_ms) { | |
| 807 const int kIntervalMs = 250; | |
| 808 const int kMaxIntervals = time_out_ms / kIntervalMs; | |
| 809 | |
| 810 for (int i = 0; i < kMaxIntervals; ++i) { | |
| 811 bool browser_survived = CrashAwareSleep(kIntervalMs); | |
| 812 EXPECT_TRUE(browser_survived); | |
| 813 if (!browser_survived) | |
| 814 return std::string(); | |
| 815 | |
| 816 std::string cookie_value; | |
| 817 EXPECT_TRUE(tab->GetCookieByName(url, cookie_name, &cookie_value)); | |
| 818 if (!cookie_value.empty()) | |
| 819 return cookie_value; | |
| 820 } | |
| 821 | |
| 822 ADD_FAILURE() << "Timeout reached in WaitUntilCookieNonEmpty"; | |
| 823 return std::string(); | |
| 824 } | |
| 825 | |
| 826 bool UITestBase::WaitUntilJavaScriptCondition(TabProxy* tab, | |
| 827 const std::wstring& frame_xpath, | |
| 828 const std::wstring& jscript, | |
| 829 int time_out_ms) { | |
| 830 const int kIntervalMs = 250; | |
| 831 const int kMaxIntervals = time_out_ms / kIntervalMs; | |
| 832 | |
| 833 // Wait until the test signals it has completed. | |
| 834 for (int i = 0; i < kMaxIntervals; ++i) { | |
| 835 bool browser_survived = CrashAwareSleep(kIntervalMs); | |
| 836 EXPECT_TRUE(browser_survived); | |
| 837 if (!browser_survived) | |
| 838 return false; | |
| 839 | |
| 840 bool done_value = false; | |
| 841 bool success = tab->ExecuteAndExtractBool(frame_xpath, jscript, | |
| 842 &done_value); | |
| 843 EXPECT_TRUE(success); | |
| 844 if (!success) | |
| 845 return false; | |
| 846 if (done_value) | |
| 847 return true; | |
| 848 } | |
| 849 | |
| 850 ADD_FAILURE() << "Timeout reached in WaitUntilJavaScriptCondition"; | |
| 851 return false; | |
| 852 } | |
| 853 | |
| 854 void UITestBase::WaitUntilTabCount(int tab_count) { | |
| 855 const int kMaxIntervals = 10; | |
| 856 const int kIntervalMs = sleep_timeout_ms() / kMaxIntervals; | |
| 857 | |
| 858 for (int i = 0; i < kMaxIntervals; ++i) { | |
| 859 bool browser_survived = CrashAwareSleep(kIntervalMs); | |
| 860 EXPECT_TRUE(browser_survived); | |
| 861 if (!browser_survived) | |
| 862 return; | |
| 863 if (GetTabCount() == tab_count) | |
| 864 return; | |
| 865 } | |
| 866 | |
| 867 ADD_FAILURE() << "Timeout reached in WaitUntilTabCount"; | |
| 868 } | |
| 869 | |
| 870 FilePath UITestBase::GetDownloadDirectory() { | |
| 871 scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); | |
| 872 EXPECT_TRUE(tab_proxy.get()); | |
| 873 if (!tab_proxy.get()) | |
| 874 return FilePath(); | |
| 875 | |
| 876 FilePath download_directory; | |
| 877 EXPECT_TRUE(tab_proxy->GetDownloadDirectory(&download_directory)); | |
| 878 return download_directory; | |
| 879 } | |
| 880 | |
| 881 void UITestBase::CloseBrowserAsync(BrowserProxy* browser) const { | |
| 882 ASSERT_TRUE(server_->Send( | |
| 883 new AutomationMsg_CloseBrowserRequestAsync(0, browser->handle()))); | |
| 884 } | |
| 885 | |
| 886 bool UITestBase::CloseBrowser(BrowserProxy* browser, | |
| 887 bool* application_closed) const { | |
| 888 DCHECK(application_closed); | |
| 889 if (!browser->is_valid() || !browser->handle()) | |
| 890 return false; | |
| 891 | |
| 892 bool result = true; | |
| 893 | |
| 894 bool succeeded = server_->Send(new AutomationMsg_CloseBrowser( | |
| 895 0, browser->handle(), &result, application_closed)); | |
| 896 | |
| 897 if (!succeeded) | |
| 898 return false; | |
| 899 | |
| 900 if (*application_closed) { | |
| 901 // Let's wait until the process dies (if it is not gone already). | |
| 902 bool success = base::WaitForSingleProcess(process_, base::kNoTimeout); | |
| 903 EXPECT_TRUE(success); | |
| 904 } | |
| 905 | |
| 906 return result; | |
| 907 } | |
| 908 | |
| 909 void UITestBase::WaitForFinish(const std::string &name, | |
| 910 const std::string &id, | |
| 911 const GURL &url, | |
| 912 const std::string& test_complete_cookie, | |
| 913 const std::string& expected_cookie_value, | |
| 914 const int wait_time) { | |
| 915 // The webpage being tested has javascript which sets a cookie | |
| 916 // which signals completion of the test. The cookie name is | |
| 917 // a concatenation of the test name and the test id. This allows | |
| 918 // us to run multiple tests within a single webpage and test | |
| 919 // that they all c | |
| 920 std::string cookie_name = name; | |
| 921 cookie_name.append("."); | |
| 922 cookie_name.append(id); | |
| 923 cookie_name.append("."); | |
| 924 cookie_name.append(test_complete_cookie); | |
| 925 | |
| 926 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
| 927 ASSERT_TRUE(tab.get()); | |
| 928 std::string cookie_value = WaitUntilCookieNonEmpty(tab.get(), url, | |
| 929 cookie_name.c_str(), | |
| 930 wait_time); | |
| 931 EXPECT_EQ(expected_cookie_value, cookie_value); | |
| 932 } | |
| 933 | |
| 934 void UITestBase::PrintResult(const std::string& measurement, | |
| 935 const std::string& modifier, | 13 const std::string& modifier, |
| 936 const std::string& trace, | 14 const std::string& trace, |
| 937 size_t value, | 15 size_t value, |
| 938 const std::string& units, | 16 const std::string& units, |
| 939 bool important) { | 17 bool important) { |
| 940 PrintResultsImpl(measurement, modifier, trace, base::UintToString(value), | 18 PrintResultsImpl(measurement, modifier, trace, base::UintToString(value), |
| 941 "", "", units, important); | 19 "", "", units, important); |
| 942 } | 20 } |
| 943 | 21 |
| 944 void UITestBase::PrintResult(const std::string& measurement, | 22 void UIPerfTest::PrintResult(const std::string& measurement, |
| 945 const std::string& modifier, | 23 const std::string& modifier, |
| 946 const std::string& trace, | 24 const std::string& trace, |
| 947 const std::string& value, | 25 const std::string& value, |
| 948 const std::string& units, | 26 const std::string& units, |
| 949 bool important) { | 27 bool important) { |
| 950 PrintResultsImpl(measurement, modifier, trace, value, "", "", units, | 28 PrintResultsImpl(measurement, modifier, trace, value, "", "", units, |
| 951 important); | 29 important); |
| 952 } | 30 } |
| 953 | 31 |
| 954 void UITestBase::PrintResultMeanAndError(const std::string& measurement, | 32 void UIPerfTest::PrintResultMeanAndError(const std::string& measurement, |
| 955 const std::string& modifier, | 33 const std::string& modifier, |
| 956 const std::string& trace, | 34 const std::string& trace, |
| 957 const std::string& mean_and_error, | 35 const std::string& mean_and_error, |
| 958 const std::string& units, | 36 const std::string& units, |
| 959 bool important) { | 37 bool important) { |
| 960 PrintResultsImpl(measurement, modifier, trace, mean_and_error, | 38 PrintResultsImpl(measurement, modifier, trace, mean_and_error, |
| 961 "{", "}", units, important); | 39 "{", "}", units, important); |
| 962 } | 40 } |
| 963 | 41 |
| 964 void UITestBase::PrintResultList(const std::string& measurement, | 42 void UIPerfTest::PrintResultList(const std::string& measurement, |
| 965 const std::string& modifier, | 43 const std::string& modifier, |
| 966 const std::string& trace, | 44 const std::string& trace, |
| 967 const std::string& values, | 45 const std::string& values, |
| 968 const std::string& units, | 46 const std::string& units, |
| 969 bool important) { | 47 bool important) { |
| 970 PrintResultsImpl(measurement, modifier, trace, values, | 48 PrintResultsImpl(measurement, modifier, trace, values, |
| 971 "[", "]", units, important); | 49 "[", "]", units, important); |
| 972 } | 50 } |
| 973 | 51 |
| 974 void UITestBase::PrintResultsImpl(const std::string& measurement, | 52 void UIPerfTest::PrintResultsImpl(const std::string& measurement, |
| 975 const std::string& modifier, | 53 const std::string& modifier, |
| 976 const std::string& trace, | 54 const std::string& trace, |
| 977 const std::string& values, | 55 const std::string& values, |
| 978 const std::string& prefix, | 56 const std::string& prefix, |
| 979 const std::string& suffix, | 57 const std::string& suffix, |
| 980 const std::string& units, | 58 const std::string& units, |
| 981 bool important) { | 59 bool important) { |
| 982 // <*>RESULT <graph_name>: <trace_name>= <value> <units> | 60 // <*>RESULT <graph_name>: <trace_name>= <value> <units> |
| 983 // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units> | 61 // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units> |
| 984 // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units> | 62 // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units> |
| 985 printf("%sRESULT %s%s: %s= %s%s%s %s\n", | 63 printf("%sRESULT %s%s: %s= %s%s%s %s\n", |
| 986 important ? "*" : "", measurement.c_str(), modifier.c_str(), | 64 important ? "*" : "", measurement.c_str(), modifier.c_str(), |
| 987 trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(), | 65 trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(), |
| 988 units.c_str()); | 66 units.c_str()); |
| 989 } | 67 } |
| 990 | 68 |
| 991 bool UITestBase::EvictFileFromSystemCacheWrapper(const FilePath& path) { | 69 void UIPerfTest::PrintIOPerfInfo(const char* test_name) { |
| 992 for (int i = 0; i < 10; i++) { | |
| 993 if (file_util::EvictFileFromSystemCache(path)) | |
| 994 return true; | |
| 995 PlatformThread::Sleep(sleep_timeout_ms() / 10); | |
| 996 } | |
| 997 return false; | |
| 998 } | |
| 999 | |
| 1000 // static | |
| 1001 void UITestBase::RewritePreferencesFile(const FilePath& user_data_dir) { | |
| 1002 const FilePath pref_template_path( | |
| 1003 user_data_dir.AppendASCII("Default").AppendASCII("PreferencesTemplate")); | |
| 1004 const FilePath pref_path( | |
| 1005 user_data_dir.AppendASCII("Default").AppendASCII("Preferences")); | |
| 1006 | |
| 1007 // Read in preferences template. | |
| 1008 std::string pref_string; | |
| 1009 EXPECT_TRUE(file_util::ReadFileToString(pref_template_path, &pref_string)); | |
| 1010 string16 format_string = ASCIIToUTF16(pref_string); | |
| 1011 | |
| 1012 // Make sure temp directory has the proper format for writing to prefs file. | |
| 1013 #if defined(OS_POSIX) | |
| 1014 std::wstring user_data_dir_w(ASCIIToWide(user_data_dir.value())); | |
| 1015 #elif defined(OS_WIN) | |
| 1016 std::wstring user_data_dir_w(user_data_dir.value()); | |
| 1017 // In Windows, the FilePath will write '\' for the path separators; change | |
| 1018 // these to a separator that won't trigger escapes. | |
| 1019 std::replace(user_data_dir_w.begin(), | |
| 1020 user_data_dir_w.end(), '\\', '/'); | |
| 1021 #endif | |
| 1022 | |
| 1023 // Rewrite prefs file. | |
| 1024 std::vector<string16> subst; | |
| 1025 subst.push_back(WideToUTF16(user_data_dir_w)); | |
| 1026 const std::string prefs_string = | |
| 1027 UTF16ToASCII(ReplaceStringPlaceholders(format_string, subst, NULL)); | |
| 1028 EXPECT_TRUE(file_util::WriteFile(pref_path, prefs_string.c_str(), | |
| 1029 prefs_string.size())); | |
| 1030 file_util::EvictFileFromSystemCache(pref_path); | |
| 1031 } | |
| 1032 | |
| 1033 FilePath UITestBase::user_data_dir() const { | |
| 1034 EXPECT_TRUE(temp_profile_dir_->IsValid()); | |
| 1035 return temp_profile_dir_->path(); | |
| 1036 } | |
| 1037 | |
| 1038 // static | |
| 1039 FilePath UITestBase::ComputeTypicalUserDataSource(ProfileType profile_type) { | |
| 1040 FilePath source_history_file; | |
| 1041 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, | |
| 1042 &source_history_file)); | |
| 1043 source_history_file = source_history_file.AppendASCII("profiles"); | |
| 1044 switch (profile_type) { | |
| 1045 case UITestBase::DEFAULT_THEME: | |
| 1046 source_history_file = source_history_file.AppendASCII("typical_history"); | |
| 1047 break; | |
| 1048 case UITestBase::COMPLEX_THEME: | |
| 1049 source_history_file = source_history_file.AppendASCII("complex_theme"); | |
| 1050 break; | |
| 1051 case UITestBase::NATIVE_THEME: | |
| 1052 source_history_file = source_history_file.AppendASCII("gtk_theme"); | |
| 1053 break; | |
| 1054 case UITestBase::CUSTOM_FRAME: | |
| 1055 source_history_file = source_history_file.AppendASCII("custom_frame"); | |
| 1056 break; | |
| 1057 case UITestBase::CUSTOM_FRAME_NATIVE_THEME: | |
| 1058 source_history_file = | |
| 1059 source_history_file.AppendASCII("custom_frame_gtk_theme"); | |
| 1060 break; | |
| 1061 default: | |
| 1062 NOTREACHED(); | |
| 1063 } | |
| 1064 return source_history_file; | |
| 1065 } | |
| 1066 | |
| 1067 void UITestBase::WaitForGeneratedFileAndCheck( | |
| 1068 const FilePath& generated_file, | |
| 1069 const FilePath& original_file, | |
| 1070 bool compare_files, | |
| 1071 bool need_equal, | |
| 1072 bool delete_generated_file) { | |
| 1073 // Check whether the target file has been generated. | |
| 1074 file_util::FileInfo previous, current; | |
| 1075 bool exist = false; | |
| 1076 const int kCycles = 20; | |
| 1077 for (int i = 0; i < kCycles; ++i) { | |
| 1078 if (exist) { | |
| 1079 file_util::GetFileInfo(generated_file, ¤t); | |
| 1080 if (current.size == previous.size) | |
| 1081 break; | |
| 1082 previous = current; | |
| 1083 } else if (file_util::PathExists(generated_file)) { | |
| 1084 file_util::GetFileInfo(generated_file, &previous); | |
| 1085 exist = true; | |
| 1086 } | |
| 1087 PlatformThread::Sleep(sleep_timeout_ms() / kCycles); | |
| 1088 } | |
| 1089 EXPECT_TRUE(exist); | |
| 1090 | |
| 1091 if (compare_files) { | |
| 1092 // Check whether the generated file is equal with original file according to | |
| 1093 // parameter: need_equal. | |
| 1094 int64 generated_file_size = 0; | |
| 1095 int64 original_file_size = 0; | |
| 1096 | |
| 1097 EXPECT_TRUE(file_util::GetFileSize(generated_file, &generated_file_size)); | |
| 1098 EXPECT_TRUE(file_util::GetFileSize(original_file, &original_file_size)); | |
| 1099 if (need_equal) { | |
| 1100 EXPECT_EQ(generated_file_size, original_file_size); | |
| 1101 EXPECT_TRUE(file_util::ContentsEqual(generated_file, original_file)); | |
| 1102 } else { | |
| 1103 EXPECT_NE(generated_file_size, original_file_size); | |
| 1104 EXPECT_FALSE(file_util::ContentsEqual(generated_file, original_file)); | |
| 1105 } | |
| 1106 } | |
| 1107 if (delete_generated_file) | |
| 1108 EXPECT_TRUE(file_util::DieFileDie(generated_file, false)); | |
| 1109 } | |
| 1110 | |
| 1111 bool UITestBase::LaunchBrowserHelper(const CommandLine& arguments, | |
| 1112 bool wait, | |
| 1113 base::ProcessHandle* process) { | |
| 1114 FilePath command = browser_directory_.Append( | |
| 1115 FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath)); | |
| 1116 CommandLine command_line(command); | |
| 1117 | |
| 1118 // Add any explicit command line flags passed to the process. | |
| 1119 CommandLine::StringType extra_chrome_flags = | |
| 1120 CommandLine::ForCurrentProcess()->GetSwitchValueNative( | |
| 1121 kExtraChromeFlagsSwitch); | |
| 1122 if (!extra_chrome_flags.empty()) { | |
| 1123 // Split by spaces and append to command line | |
| 1124 std::vector<CommandLine::StringType> flags; | |
| 1125 SplitString(extra_chrome_flags, ' ', &flags); | |
| 1126 for (size_t i = 0; i < flags.size(); ++i) | |
| 1127 command_line.AppendArgNative(flags[i]); | |
| 1128 } | |
| 1129 | |
| 1130 // No first-run dialogs, please. | |
| 1131 command_line.AppendSwitch(switches::kNoFirstRun); | |
| 1132 | |
| 1133 // No default browser check, it would create an info-bar (if we are not the | |
| 1134 // default browser) that could conflicts with some tests expectations. | |
| 1135 command_line.AppendSwitch(switches::kNoDefaultBrowserCheck); | |
| 1136 | |
| 1137 // This is a UI test. | |
| 1138 command_line.AppendSwitchASCII(switches::kTestType, kUITestType); | |
| 1139 | |
| 1140 // Tell the browser to use a temporary directory just for this test. | |
| 1141 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir()); | |
| 1142 | |
| 1143 // We need cookies on file:// for things like the page cycler. | |
| 1144 if (enable_file_cookies_) | |
| 1145 command_line.AppendSwitch(switches::kEnableFileCookies); | |
| 1146 | |
| 1147 if (dom_automation_enabled_) | |
| 1148 command_line.AppendSwitch(switches::kDomAutomationController); | |
| 1149 | |
| 1150 if (include_testing_id_) { | |
| 1151 command_line.AppendSwitchASCII(switches::kTestingChannelID, | |
| 1152 server_->channel_id()); | |
| 1153 } | |
| 1154 | |
| 1155 if (!show_error_dialogs_ && | |
| 1156 !CommandLine::ForCurrentProcess()->HasSwitch(kEnableErrorDialogs)) { | |
| 1157 command_line.AppendSwitch(switches::kNoErrorDialogs); | |
| 1158 } | |
| 1159 if (in_process_renderer_) | |
| 1160 command_line.AppendSwitch(switches::kSingleProcess); | |
| 1161 if (no_sandbox_) | |
| 1162 command_line.AppendSwitch(switches::kNoSandbox); | |
| 1163 if (full_memory_dump_) | |
| 1164 command_line.AppendSwitch(switches::kFullMemoryCrashReport); | |
| 1165 if (safe_plugins_) | |
| 1166 command_line.AppendSwitch(switches::kSafePlugins); | |
| 1167 if (enable_dcheck_) | |
| 1168 command_line.AppendSwitch(switches::kEnableDCHECK); | |
| 1169 if (silent_dump_on_dcheck_) | |
| 1170 command_line.AppendSwitch(switches::kSilentDumpOnDCHECK); | |
| 1171 if (disable_breakpad_) | |
| 1172 command_line.AppendSwitch(switches::kDisableBreakpad); | |
| 1173 if (!homepage_.empty()) | |
| 1174 command_line.AppendSwitchASCII(switches::kHomePage, homepage_); | |
| 1175 // Don't try to fetch web resources during UI testing. | |
| 1176 command_line.AppendSwitch(switches::kDisableWebResources); | |
| 1177 | |
| 1178 if (!js_flags_.empty()) | |
| 1179 command_line.AppendSwitchASCII(switches::kJavaScriptFlags, js_flags_); | |
| 1180 if (!log_level_.empty()) | |
| 1181 command_line.AppendSwitchASCII(switches::kLoggingLevel, log_level_); | |
| 1182 | |
| 1183 command_line.AppendSwitch(switches::kMetricsRecordingOnly); | |
| 1184 | |
| 1185 if (!CommandLine::ForCurrentProcess()->HasSwitch(kEnableErrorDialogs)) | |
| 1186 command_line.AppendSwitch(switches::kEnableLogging); | |
| 1187 | |
| 1188 if (dump_histograms_on_exit_) | |
| 1189 command_line.AppendSwitch(switches::kDumpHistogramsOnExit); | |
| 1190 | |
| 1191 #ifdef WAIT_FOR_DEBUGGER_ON_OPEN | |
| 1192 command_line.AppendSwitch(switches::kDebugOnStart); | |
| 1193 #endif | |
| 1194 | |
| 1195 if (!ui_test_name_.empty()) | |
| 1196 command_line.AppendSwitchASCII(switches::kTestName, ui_test_name_); | |
| 1197 | |
| 1198 // The tests assume that file:// URIs can freely access other file:// URIs. | |
| 1199 command_line.AppendSwitch(switches::kAllowFileAccessFromFiles); | |
| 1200 | |
| 1201 // Disable TabCloseableStateWatcher for tests. | |
| 1202 command_line.AppendSwitch(switches::kDisableTabCloseableStateWatcher); | |
| 1203 | |
| 1204 DebugFlags::ProcessDebugFlags( | |
| 1205 &command_line, ChildProcessInfo::UNKNOWN_PROCESS, false); | |
| 1206 command_line.AppendArguments(arguments, false); | |
| 1207 | |
| 1208 // TODO(phajdan.jr): Only run it for "main" browser launch. | |
| 1209 browser_launch_time_ = TimeTicks::Now(); | |
| 1210 | |
| 1211 #if defined(OS_WIN) | |
| 1212 bool started = base::LaunchApp(command_line, | |
| 1213 wait, | |
| 1214 !show_window_, | |
| 1215 process); | |
| 1216 #elif defined(OS_POSIX) | |
| 1217 // Sometimes one needs to run the browser under a special environment | |
| 1218 // (e.g. valgrind) without also running the test harness (e.g. python) | |
| 1219 // under the special environment. Provide a way to wrap the browser | |
| 1220 // commandline with a special prefix to invoke the special environment. | |
| 1221 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); | |
| 1222 if (browser_wrapper) { | |
| 1223 command_line.PrependWrapper(browser_wrapper); | |
| 1224 LOG(INFO) << "BROWSER_WRAPPER was set, prefixing command_line with " | |
| 1225 << browser_wrapper; | |
| 1226 } | |
| 1227 | |
| 1228 bool started = base::LaunchApp(command_line.argv(), | |
| 1229 server_->fds_to_map(), | |
| 1230 wait, | |
| 1231 process); | |
| 1232 #endif | |
| 1233 | |
| 1234 return started; | |
| 1235 } | |
| 1236 | |
| 1237 void UITestBase::UpdateHistoryDates() { | |
| 1238 // Migrate the times in the segment_usage table to yesterday so we get | |
| 1239 // actual thumbnails on the NTP. | |
| 1240 sql::Connection db; | |
| 1241 FilePath history = | |
| 1242 user_data_dir().AppendASCII("Default").AppendASCII("History"); | |
| 1243 // Not all test profiles have a history file. | |
| 1244 if (!file_util::PathExists(history)) | |
| 1245 return; | |
| 1246 | |
| 1247 ASSERT_TRUE(db.Open(history)); | |
| 1248 Time yesterday = Time::Now() - TimeDelta::FromDays(1); | |
| 1249 std::string yesterday_str = base::Int64ToString(yesterday.ToInternalValue()); | |
| 1250 std::string query = StringPrintf( | |
| 1251 "UPDATE segment_usage " | |
| 1252 "SET time_slot = %s " | |
| 1253 "WHERE id IN (SELECT id FROM segment_usage WHERE time_slot > 0);", | |
| 1254 yesterday_str.c_str()); | |
| 1255 ASSERT_TRUE(db.Execute(query.c_str())); | |
| 1256 db.Close(); | |
| 1257 file_util::EvictFileFromSystemCache(history); | |
| 1258 } | |
| 1259 | |
| 1260 void UITestBase::PrintIOPerfInfo(const char* test_name) { | |
| 1261 ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); | 70 ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); |
| 1262 | 71 |
| 1263 size_t read_op_b = 0; | 72 size_t read_op_b = 0; |
| 1264 size_t read_op_r = 0; | 73 size_t read_op_r = 0; |
| 1265 size_t write_op_b = 0; | 74 size_t write_op_b = 0; |
| 1266 size_t write_op_r = 0; | 75 size_t write_op_r = 0; |
| 1267 size_t other_op_b = 0; | 76 size_t other_op_b = 0; |
| 1268 size_t other_op_r = 0; | 77 size_t other_op_r = 0; |
| 1269 size_t total_op_b = 0; | 78 size_t total_op_b = 0; |
| 1270 size_t total_op_r = 0; | 79 size_t total_op_r = 0; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 PrintResult("write_op_r", "", "w_op_r" + t_name, write_op_r, "", false); | 165 PrintResult("write_op_r", "", "w_op_r" + t_name, write_op_r, "", false); |
| 1357 PrintResult("other_op_r", "", "o_op_r" + t_name, other_op_r, "", false); | 166 PrintResult("other_op_r", "", "o_op_r" + t_name, other_op_r, "", false); |
| 1358 PrintResult("total_op_r", "", "IO_op_r" + t_name, total_op_r, "", true); | 167 PrintResult("total_op_r", "", "IO_op_r" + t_name, total_op_r, "", true); |
| 1359 | 168 |
| 1360 PrintResult("read_byte_r", "", "r_r" + t_name, read_byte_r, "kb", false); | 169 PrintResult("read_byte_r", "", "r_r" + t_name, read_byte_r, "kb", false); |
| 1361 PrintResult("write_byte_r", "", "w_r" + t_name, write_byte_r, "kb", false); | 170 PrintResult("write_byte_r", "", "w_r" + t_name, write_byte_r, "kb", false); |
| 1362 PrintResult("other_byte_r", "", "o_r" + t_name, other_byte_r, "kb", false); | 171 PrintResult("other_byte_r", "", "o_r" + t_name, other_byte_r, "kb", false); |
| 1363 PrintResult("total_byte_r", "", "IO_r" + t_name, total_byte_r, "kb", true); | 172 PrintResult("total_byte_r", "", "IO_r" + t_name, total_byte_r, "kb", true); |
| 1364 } | 173 } |
| 1365 | 174 |
| 1366 void UITestBase::PrintMemoryUsageInfo(const char* test_name) { | 175 void UIPerfTest::PrintMemoryUsageInfo(const char* test_name) { |
| 1367 ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); | 176 ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); |
| 1368 | 177 |
| 1369 size_t browser_virtual_size = 0; | 178 size_t browser_virtual_size = 0; |
| 1370 size_t browser_working_set_size = 0; | 179 size_t browser_working_set_size = 0; |
| 1371 size_t renderer_virtual_size = 0; | 180 size_t renderer_virtual_size = 0; |
| 1372 size_t renderer_working_set_size = 0; | 181 size_t renderer_working_set_size = 0; |
| 1373 size_t total_virtual_size = 0; | 182 size_t total_virtual_size = 0; |
| 1374 size_t total_working_set_size = 0; | 183 size_t total_working_set_size = 0; |
| 1375 #if defined(OS_WIN) | 184 #if defined(OS_WIN) |
| 1376 size_t browser_peak_virtual_size = 0; | 185 size_t browser_peak_virtual_size = 0; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1488 total_working_set_size, "bytes", | 297 total_working_set_size, "bytes", |
| 1489 true /* important */); | 298 true /* important */); |
| 1490 #else | 299 #else |
| 1491 NOTIMPLEMENTED(); | 300 NOTIMPLEMENTED(); |
| 1492 #endif | 301 #endif |
| 1493 PrintResult("processes", "", "proc_" + trace_name, | 302 PrintResult("processes", "", "proc_" + trace_name, |
| 1494 chrome_processes.size(), "", | 303 chrome_processes.size(), "", |
| 1495 false /* not important */); | 304 false /* not important */); |
| 1496 } | 305 } |
| 1497 | 306 |
| 1498 void UITestBase::PrintSystemCommitCharge(const char* test_name, | 307 void UIPerfTest::PrintSystemCommitCharge(const char* test_name, |
| 1499 size_t charge, | 308 size_t charge, |
| 1500 bool important) { | 309 bool important) { |
| 1501 std::string trace_name(test_name); | 310 std::string trace_name(test_name); |
| 1502 PrintResult("commit_charge", "", "cc" + trace_name, charge, "kb", important); | 311 PrintResult("commit_charge", "", "cc" + trace_name, charge, "kb", important); |
| 1503 } | 312 } |
| 1504 | 313 |
| 1505 void UITestBase::UseReferenceBuild() { | 314 void UIPerfTest::UseReferenceBuild() { |
| 1506 FilePath dir; | 315 FilePath dir; |
| 1507 PathService::Get(chrome::DIR_TEST_TOOLS, &dir); | 316 PathService::Get(chrome::DIR_TEST_TOOLS, &dir); |
| 1508 dir = dir.AppendASCII("reference_build"); | 317 dir = dir.AppendASCII("reference_build"); |
| 1509 #if defined(OS_WIN) | 318 #if defined(OS_WIN) |
| 1510 dir = dir.AppendASCII("chrome"); | 319 dir = dir.AppendASCII("chrome"); |
| 1511 #elif defined(OS_LINUX) | 320 #elif defined(OS_LINUX) |
| 1512 dir = dir.AppendASCII("chrome_linux"); | 321 dir = dir.AppendASCII("chrome_linux"); |
| 1513 #elif defined(OS_MACOSX) | 322 #elif defined(OS_MACOSX) |
| 1514 dir = dir.AppendASCII("chrome_mac"); | 323 dir = dir.AppendASCII("chrome_mac"); |
| 1515 #endif | 324 #endif |
| 1516 SetBrowserDirectory(dir); | 325 SetBrowserDirectory(dir); |
| 1517 } | 326 } |
| 1518 | |
| 1519 void UITestBase::SetBrowserDirectory(const FilePath& dir) { | |
| 1520 browser_directory_ = dir; | |
| 1521 } | |
| 1522 | |
| 1523 // UITest methods | |
| 1524 | |
| 1525 void UITest::SetUp() { | |
| 1526 // Pass the test case name to chrome.exe on the command line to help with | |
| 1527 // parsing Purify output. | |
| 1528 const testing::TestInfo* const test_info = | |
| 1529 testing::UnitTest::GetInstance()->current_test_info(); | |
| 1530 if (test_info) { | |
| 1531 set_ui_test_name(test_info->test_case_name() + std::string(".") + | |
| 1532 test_info->name()); | |
| 1533 } | |
| 1534 UITestBase::SetUp(); | |
| 1535 PlatformTest::SetUp(); | |
| 1536 } | |
| 1537 | |
| 1538 void UITest::TearDown() { | |
| 1539 UITestBase::TearDown(); | |
| 1540 PlatformTest::TearDown(); | |
| 1541 } | |
| 1542 | |
| 1543 AutomationProxy* UITest::CreateAutomationProxy(int execution_timeout) { | |
| 1544 // Make the AutomationProxy disconnect the channel on the first error, | |
| 1545 // so that we avoid spending a lot of time in timeouts. The browser is likely | |
| 1546 // hosed if we hit those errors. | |
| 1547 return new AutomationProxy(execution_timeout, true); | |
| 1548 } | |
| 1549 | |
| OLD | NEW |