Chromium Code Reviews| 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_test.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <signal.h> | 8 #include <signal.h> |
| 9 #include <sys/types.h> | 9 #include <sys/types.h> |
| 10 #endif | 10 #endif |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 | 54 |
| 55 #if defined(OS_WIN) | 55 #if defined(OS_WIN) |
| 56 #include "base/win/windows_version.h" | 56 #include "base/win/windows_version.h" |
| 57 #endif | 57 #endif |
| 58 | 58 |
| 59 | 59 |
| 60 using base::Time; | 60 using base::Time; |
| 61 using base::TimeDelta; | 61 using base::TimeDelta; |
| 62 using base::TimeTicks; | 62 using base::TimeTicks; |
| 63 | 63 |
| 64 // Passed as value of kTestType. | |
| 65 static const char kUITestType[] = "ui"; | |
| 66 | |
| 67 const wchar_t UITestBase::kFailedNoCrashService[] = | 64 const wchar_t UITestBase::kFailedNoCrashService[] = |
| 68 #if defined(OS_WIN) | 65 #if defined(OS_WIN) |
| 69 L"NOTE: This test is expected to fail if crash_service.exe is not " | 66 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 " | 67 L"running. Start it manually before running this test (see the build " |
| 71 L"output directory)."; | 68 L"output directory)."; |
| 72 #elif defined(OS_LINUX) | 69 #elif defined(OS_LINUX) |
| 73 L"NOTE: This test is expected to fail if breakpad is not built in " | 70 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)."; | 71 L"or if chromium is not running headless (try CHROME_HEADLESS=1)."; |
| 75 #else | 72 #else |
| 76 L"NOTE: Crash service not ported to this platform!"; | 73 L"NOTE: Crash service not ported to this platform!"; |
| 77 #endif | 74 #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 std::string UITestBase::js_flags_ = ""; | |
| 88 std::string UITestBase::log_level_ = ""; | |
| 89 | 75 |
| 90 // Uncomment this line to have the spawned process wait for the debugger to | 76 // Uncomment this line to have the spawned process wait for the debugger to |
| 91 // attach. This only works on Windows. On posix systems, you can set the | 77 // attach. This only works on Windows. On posix systems, you can set the |
| 92 // BROWSER_WRAPPER env variable to wrap the browser process. | 78 // BROWSER_WRAPPER env variable to wrap the browser process. |
| 93 // #define WAIT_FOR_DEBUGGER_ON_OPEN 1 | 79 // #define WAIT_FOR_DEBUGGER_ON_OPEN 1 |
| 94 | 80 |
| 95 UITestBase::UITestBase() | 81 UITestBase::UITestBase() |
| 96 : launch_arguments_(CommandLine::NO_PROGRAM), | 82 : launch_arguments_(CommandLine::NO_PROGRAM), |
| 97 expected_errors_(0), | 83 expected_errors_(0), |
| 98 expected_crashes_(0), | 84 expected_crashes_(0), |
| 99 homepage_(chrome::kAboutBlankURL), | |
| 100 wait_for_initial_loads_(true), | 85 wait_for_initial_loads_(true), |
| 101 dom_automation_enabled_(false), | 86 dom_automation_enabled_(false), |
| 102 process_(base::kNullProcessHandle), | 87 process_(base::kNullProcessHandle), |
| 103 process_id_(-1), | 88 process_id_(-1), |
| 104 show_window_(false), | 89 show_window_(false), |
| 105 clear_profile_(true), | 90 clear_profile_(true), |
| 106 include_testing_id_(true), | 91 include_testing_id_(true), |
| 107 enable_file_cookies_(true), | 92 enable_file_cookies_(true), |
| 108 profile_type_(UITestBase::DEFAULT_THEME), | 93 profile_type_(ProxyLauncher::DEFAULT_THEME), |
| 109 shutdown_type_(UITestBase::WINDOW_CLOSE), | 94 shutdown_type_(ProxyLauncher::WINDOW_CLOSE) { |
| 110 temp_profile_dir_(new ScopedTempDir()) { | |
| 111 PathService::Get(chrome::DIR_APP, &browser_directory_); | 95 PathService::Get(chrome::DIR_APP, &browser_directory_); |
| 112 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | 96 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); |
| 97 launcher_.reset(CreateProxyLauncher()); | |
|
Paweł Hajdan Jr.
2011/01/05 21:47:59
I wonder if we should do it in SetUp... that might
dtu
2011/01/06 01:41:13
It was originally in SetUp(). I moved it out of Se
Paweł Hajdan Jr.
2011/01/06 20:37:14
I see. How about removing knowledge about homepage
dtu
2011/01/08 01:54:51
Done.
| |
| 113 } | 98 } |
| 114 | 99 |
| 115 UITestBase::UITestBase(MessageLoop::Type msg_loop_type) | 100 UITestBase::UITestBase(MessageLoop::Type msg_loop_type) |
| 116 : launch_arguments_(CommandLine::NO_PROGRAM), | 101 : launch_arguments_(CommandLine::NO_PROGRAM), |
| 117 expected_errors_(0), | 102 expected_errors_(0), |
| 118 expected_crashes_(0), | 103 expected_crashes_(0), |
| 119 homepage_(chrome::kAboutBlankURL), | |
| 120 wait_for_initial_loads_(true), | 104 wait_for_initial_loads_(true), |
| 121 dom_automation_enabled_(false), | 105 dom_automation_enabled_(false), |
| 122 process_(base::kNullProcessHandle), | 106 process_(base::kNullProcessHandle), |
| 123 process_id_(-1), | 107 process_id_(-1), |
| 124 show_window_(false), | 108 show_window_(false), |
| 125 clear_profile_(true), | 109 clear_profile_(true), |
| 126 include_testing_id_(true), | 110 include_testing_id_(true), |
| 127 enable_file_cookies_(true), | 111 enable_file_cookies_(true), |
| 128 profile_type_(UITestBase::DEFAULT_THEME), | 112 profile_type_(ProxyLauncher::DEFAULT_THEME), |
| 129 shutdown_type_(UITestBase::WINDOW_CLOSE) { | 113 shutdown_type_(ProxyLauncher::WINDOW_CLOSE) { |
| 130 PathService::Get(chrome::DIR_APP, &browser_directory_); | 114 PathService::Get(chrome::DIR_APP, &browser_directory_); |
| 131 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | 115 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); |
| 116 launcher_.reset(CreateProxyLauncher()); | |
| 132 } | 117 } |
| 133 | 118 |
| 134 UITestBase::~UITestBase() { | 119 UITestBase::~UITestBase() { |
| 135 } | 120 } |
| 136 | 121 |
| 137 void UITestBase::SetUp() { | 122 void UITestBase::SetUp() { |
| 138 AssertAppNotRunning(L"Please close any other instances " | |
| 139 L"of the app before testing."); | |
| 140 | |
| 141 JavaScriptExecutionController::set_timeout( | 123 JavaScriptExecutionController::set_timeout( |
| 142 TestTimeouts::action_max_timeout_ms()); | 124 TestTimeouts::action_max_timeout_ms()); |
| 143 test_start_time_ = Time::NowFromSystemTime(); | 125 test_start_time_ = Time::NowFromSystemTime(); |
| 144 | 126 |
| 145 launcher_.reset(CreateProxyLauncher()); | 127 launcher_->SetUp(process_id_); |
| 146 launcher_->InitializeConnection(this); | 128 |
| 129 SetLaunchSwitches(); | |
| 130 | |
| 131 launcher_->InitializeConnection(launch_arguments_, include_testing_id_, | |
|
Paweł Hajdan Jr.
2011/01/05 21:47:59
Another idea is to push data to launcher_ in place
| |
| 132 clear_profile_, template_user_data_, | |
| 133 profile_type_, browser_directory_, | |
| 134 show_window_, wait_for_initial_loads_, | |
| 135 &browser_launch_time_, &process_, | |
| 136 &process_id_); | |
| 147 } | 137 } |
| 148 | 138 |
| 149 void UITestBase::TearDown() { | 139 void UITestBase::TearDown() { |
| 150 CloseBrowserAndServer(); | 140 CloseBrowserAndServer(); |
| 151 | 141 |
| 152 // Make sure that we didn't encounter any assertion failures | 142 // Make sure that we didn't encounter any assertion failures |
| 153 logging::AssertionList assertions; | 143 logging::AssertionList assertions; |
| 154 logging::GetFatalAssertions(&assertions); | 144 logging::GetFatalAssertions(&assertions); |
| 155 | 145 |
| 156 // If there were errors, get all the error strings for display. | 146 // If there were errors, get all the error strings for display. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 171 L"Encountered an unexpected crash in the program during this test."; | 161 L"Encountered an unexpected crash in the program during this test."; |
| 172 if (expected_crashes_ > 0 && actual_crashes == 0) { | 162 if (expected_crashes_ > 0 && actual_crashes == 0) { |
| 173 error_msg += L" "; | 163 error_msg += L" "; |
| 174 error_msg += kFailedNoCrashService; | 164 error_msg += kFailedNoCrashService; |
| 175 } | 165 } |
| 176 EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg; | 166 EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg; |
| 177 } | 167 } |
| 178 | 168 |
| 179 // TODO(phajdan.jr): get rid of set_command_execution_timeout_ms. | 169 // TODO(phajdan.jr): get rid of set_command_execution_timeout_ms. |
| 180 void UITestBase::set_command_execution_timeout_ms(int timeout) { | 170 void UITestBase::set_command_execution_timeout_ms(int timeout) { |
| 181 automation_proxy_->set_command_execution_timeout_ms(timeout); | 171 automation()->set_command_execution_timeout_ms(timeout); |
| 182 VLOG(1) << "Automation command execution timeout set to " << timeout << " ms"; | 172 VLOG(1) << "Automation command execution timeout set to " << timeout << " ms"; |
| 183 } | 173 } |
| 184 | 174 |
| 185 ProxyLauncher* UITestBase::CreateProxyLauncher() { | 175 ProxyLauncher* UITestBase::CreateProxyLauncher() { |
| 186 return new AnonymousProxyLauncher(false); | 176 return new AnonymousProxyLauncher(false); |
| 187 } | 177 } |
| 188 | 178 |
| 179 void UITestBase::SetLaunchSwitches() { | |
| 180 // We need cookies on file:// for things like the page cycler. | |
| 181 if (enable_file_cookies_) | |
| 182 SetLaunchSwitch(switches::kEnableFileCookies); | |
| 183 if (dom_automation_enabled_) | |
| 184 SetLaunchSwitch(switches::kDomAutomationController); | |
| 185 } | |
| 186 | |
| 187 void UITestBase::SetLaunchSwitch(const std::string& switch_string) { | |
| 188 if (!launch_arguments_.HasSwitch(switch_string)) | |
|
Paweł Hajdan Jr.
2011/01/05 21:47:59
Do we need this check? It seems it would be simple
dtu
2011/01/06 01:41:13
Yes, I believe this check is optional. Done.
| |
| 189 launch_arguments_.AppendSwitch(switch_string); | |
| 190 } | |
| 191 | |
| 189 void UITestBase::LaunchBrowser() { | 192 void UITestBase::LaunchBrowser() { |
| 190 LaunchBrowser(launch_arguments_, clear_profile_); | 193 LaunchBrowser(launch_arguments_, clear_profile_); |
| 191 } | 194 } |
| 192 | 195 |
| 193 void UITestBase::LaunchBrowserAndServer() { | 196 void UITestBase::LaunchBrowserAndServer() { |
| 194 // Set up IPC testing interface as a server. | 197 launcher_->LaunchBrowserAndServer(launch_arguments_, include_testing_id_, |
| 195 automation_proxy_.reset(launcher_->CreateAutomationProxy( | 198 clear_profile_, template_user_data_, |
| 196 TestTimeouts::command_execution_timeout_ms())); | 199 profile_type_, browser_directory_, |
| 197 | 200 show_window_, wait_for_initial_loads_, |
| 198 LaunchBrowser(launch_arguments_, clear_profile_); | 201 &browser_launch_time_, &process_, |
| 199 WaitForBrowserLaunch(); | 202 &process_id_); |
| 200 } | 203 } |
| 201 | 204 |
| 202 void UITestBase::ConnectToRunningBrowser() { | 205 void UITestBase::ConnectToRunningBrowser() { |
| 203 // Set up IPC testing interface as a client. | 206 launcher_->ConnectToRunningBrowser(wait_for_initial_loads_); |
| 204 automation_proxy_.reset(launcher_->CreateAutomationProxy( | |
| 205 TestTimeouts::command_execution_timeout_ms())); | |
| 206 WaitForBrowserLaunch(); | |
| 207 } | |
| 208 | |
| 209 void UITestBase::WaitForBrowserLaunch() { | |
| 210 ASSERT_EQ(AUTOMATION_SUCCESS, automation_proxy_->WaitForAppLaunch()) | |
| 211 << "Error while awaiting automation ping from browser process"; | |
| 212 if (wait_for_initial_loads_) | |
| 213 ASSERT_TRUE(automation_proxy_->WaitForInitialLoads()); | |
| 214 else | |
| 215 base::PlatformThread::Sleep(sleep_timeout_ms()); | |
| 216 | |
| 217 EXPECT_TRUE(automation()->SetFilteredInet(ShouldFilterInet())); | |
| 218 } | 207 } |
| 219 | 208 |
| 220 void UITestBase::CloseBrowserAndServer() { | 209 void UITestBase::CloseBrowserAndServer() { |
| 221 QuitBrowser(); | 210 launcher_->CloseBrowserAndServer(shutdown_type_, &browser_quit_time_, |
| 222 CleanupAppProcesses(); | 211 &process_, &process_id_); |
| 223 | |
| 224 // Suppress spammy failures that seem to be occurring when running | |
| 225 // the UI tests in single-process mode. | |
| 226 // TODO(jhughes): figure out why this is necessary at all, and fix it | |
| 227 if (!in_process_renderer_) | |
| 228 AssertAppNotRunning(StringPrintf( | |
| 229 L"Unable to quit all browser processes. Original PID %d", process_id_)); | |
| 230 | |
| 231 automation_proxy_.reset(); // Shut down IPC testing interface. | |
| 232 } | 212 } |
| 233 | 213 |
| 234 void UITestBase::LaunchBrowser(const CommandLine& arguments, | 214 void UITestBase::LaunchBrowser(const CommandLine& arguments, |
| 235 bool clear_profile) { | 215 bool clear_profile) { |
| 236 if (clear_profile || !temp_profile_dir_->IsValid()) { | 216 launcher_->LaunchBrowser(arguments, include_testing_id_, clear_profile, |
| 237 temp_profile_dir_.reset(new ScopedTempDir()); | 217 template_user_data_, profile_type_, |
| 238 ASSERT_TRUE(temp_profile_dir_->CreateUniqueTempDir()); | 218 browser_directory_, show_window_, |
| 239 | 219 &browser_launch_time_, &process_, &process_id_); |
| 240 ASSERT_TRUE( | |
| 241 test_launcher_utils::OverrideUserDataDir(temp_profile_dir_->path())); | |
| 242 } | |
| 243 | |
| 244 if (!template_user_data_.empty()) { | |
| 245 // Recursively copy the template directory to the user_data_dir. | |
| 246 ASSERT_TRUE(file_util::CopyRecursiveDirNoCache( | |
| 247 template_user_data_, | |
| 248 user_data_dir())); | |
| 249 // If we're using the complex theme data, we need to write the | |
| 250 // user_data_dir_ to our preferences file. | |
| 251 if (profile_type_ == UITestBase::COMPLEX_THEME) { | |
| 252 RewritePreferencesFile(user_data_dir()); | |
| 253 } | |
| 254 | |
| 255 // Update the history file to include recent dates. | |
| 256 UpdateHistoryDates(); | |
| 257 } | |
| 258 | |
| 259 ASSERT_TRUE(LaunchBrowserHelper(arguments, false, &process_)); | |
| 260 process_id_ = base::GetProcId(process_); | |
| 261 } | 220 } |
| 262 | 221 |
| 263 #if !defined(OS_MACOSX) | 222 #if !defined(OS_MACOSX) |
| 264 bool UITestBase::LaunchAnotherBrowserBlockUntilClosed( | 223 bool UITestBase::LaunchAnotherBrowserBlockUntilClosed( |
| 265 const CommandLine& cmdline) { | 224 const CommandLine& cmdline) { |
| 266 return LaunchBrowserHelper(cmdline, true, NULL); | 225 return launcher_->LaunchAnotherBrowserBlockUntilClosed( |
| 226 cmdline, include_testing_id_, browser_directory_, | |
| 227 show_window_, &browser_launch_time_); | |
| 267 } | 228 } |
| 268 #endif | 229 #endif |
| 269 | 230 |
| 270 void UITestBase::QuitBrowser() { | 231 void UITestBase::QuitBrowser() { |
| 271 if (SESSION_ENDING == shutdown_type_) { | 232 launcher_->QuitBrowser(shutdown_type_, &browser_quit_time_, |
| 272 TerminateBrowser(); | 233 &process_, &process_id_); |
| 273 return; | |
| 274 } | |
| 275 | |
| 276 // There's nothing to do here if the browser is not running. | |
| 277 // WARNING: There is a race condition here where the browser may shut down | |
| 278 // after this check but before some later automation call. Your test should | |
| 279 // use WaitForBrowserProcessToQuit() if it intentionally | |
| 280 // causes the browser to shut down. | |
| 281 if (IsBrowserRunning()) { | |
| 282 TimeTicks quit_start = TimeTicks::Now(); | |
| 283 EXPECT_TRUE(automation()->SetFilteredInet(false)); | |
| 284 | |
| 285 if (WINDOW_CLOSE == shutdown_type_) { | |
| 286 int window_count = 0; | |
| 287 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
| 288 | |
| 289 // Synchronously close all but the last browser window. Closing them | |
| 290 // one-by-one may help with stability. | |
| 291 while (window_count > 1) { | |
| 292 scoped_refptr<BrowserProxy> browser_proxy = | |
| 293 automation()->GetBrowserWindow(0); | |
| 294 EXPECT_TRUE(browser_proxy.get()); | |
| 295 if (browser_proxy.get()) { | |
| 296 EXPECT_TRUE(browser_proxy->RunCommand(IDC_CLOSE_WINDOW)); | |
| 297 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
| 298 } else { | |
| 299 break; | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 // Close the last window asynchronously, because the browser may | |
| 304 // shutdown faster than it will be able to send a synchronous response | |
| 305 // to our message. | |
| 306 scoped_refptr<BrowserProxy> browser_proxy = | |
| 307 automation()->GetBrowserWindow(0); | |
| 308 EXPECT_TRUE(browser_proxy.get()); | |
| 309 if (browser_proxy.get()) { | |
| 310 EXPECT_TRUE(browser_proxy->ApplyAccelerator(IDC_CLOSE_WINDOW)); | |
| 311 browser_proxy = NULL; | |
| 312 } | |
| 313 } else if (USER_QUIT == shutdown_type_) { | |
| 314 scoped_refptr<BrowserProxy> browser_proxy = | |
| 315 automation()->GetBrowserWindow(0); | |
| 316 EXPECT_TRUE(browser_proxy.get()); | |
| 317 if (browser_proxy.get()) { | |
| 318 EXPECT_TRUE(browser_proxy->RunCommandAsync(IDC_EXIT)); | |
| 319 } | |
| 320 } else { | |
| 321 NOTREACHED() << "Invalid shutdown type " << shutdown_type_; | |
| 322 } | |
| 323 | |
| 324 // Now, drop the automation IPC channel so that the automation provider in | |
| 325 // the browser notices and drops its reference to the browser process. | |
| 326 automation()->Disconnect(); | |
| 327 | |
| 328 // Wait for the browser process to quit. It should quit once all tabs have | |
| 329 // been closed. | |
| 330 if (!WaitForBrowserProcessToQuit()) { | |
| 331 // We need to force the browser to quit because it didn't quit fast | |
| 332 // enough. Take no chance and kill every chrome processes. | |
| 333 CleanupAppProcesses(); | |
| 334 } | |
| 335 browser_quit_time_ = TimeTicks::Now() - quit_start; | |
| 336 } | |
| 337 | |
| 338 // Don't forget to close the handle | |
| 339 base::CloseProcessHandle(process_); | |
| 340 process_ = base::kNullProcessHandle; | |
| 341 process_id_ = -1; | |
| 342 } | 234 } |
| 343 | 235 |
| 344 void UITestBase::TerminateBrowser() { | 236 void UITestBase::TerminateBrowser() { |
| 345 if (IsBrowserRunning()) { | 237 launcher_->TerminateBrowser(&browser_quit_time_, &process_, &process_id_); |
| 346 TimeTicks quit_start = TimeTicks::Now(); | |
| 347 EXPECT_TRUE(automation()->SetFilteredInet(false)); | |
| 348 #if defined(OS_WIN) | |
| 349 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); | |
| 350 ASSERT_TRUE(browser.get()); | |
| 351 ASSERT_TRUE(browser->TerminateSession()); | |
| 352 #endif // defined(OS_WIN) | |
| 353 | |
| 354 // Now, drop the automation IPC channel so that the automation provider in | |
| 355 // the browser notices and drops its reference to the browser process. | |
| 356 automation()->Disconnect(); | |
| 357 | |
| 358 #if defined(OS_POSIX) | |
| 359 EXPECT_EQ(kill(process_, SIGTERM), 0); | |
| 360 #endif // OS_POSIX | |
| 361 | |
| 362 if (!WaitForBrowserProcessToQuit()) { | |
| 363 // We need to force the browser to quit because it didn't quit fast | |
| 364 // enough. Take no chance and kill every chrome processes. | |
| 365 CleanupAppProcesses(); | |
| 366 } | |
| 367 browser_quit_time_ = TimeTicks::Now() - quit_start; | |
| 368 } | |
| 369 | |
| 370 // Don't forget to close the handle | |
| 371 base::CloseProcessHandle(process_); | |
| 372 process_ = base::kNullProcessHandle; | |
| 373 process_id_ = -1; | |
| 374 } | |
| 375 | |
| 376 void UITestBase::AssertAppNotRunning(const std::wstring& error_message) { | |
| 377 std::wstring final_error_message(error_message); | |
| 378 | |
| 379 ChromeProcessList processes = GetRunningChromeProcesses(process_id_); | |
| 380 if (!processes.empty()) { | |
| 381 final_error_message += L" Leftover PIDs: ["; | |
| 382 for (ChromeProcessList::const_iterator it = processes.begin(); | |
| 383 it != processes.end(); ++it) { | |
| 384 final_error_message += StringPrintf(L" %d", *it); | |
| 385 } | |
| 386 final_error_message += L" ]"; | |
| 387 } | |
| 388 ASSERT_TRUE(processes.empty()) << final_error_message; | |
| 389 } | 238 } |
| 390 | 239 |
| 391 void UITestBase::CleanupAppProcesses() { | 240 void UITestBase::CleanupAppProcesses() { |
| 392 TerminateAllChromeProcesses(process_id_); | 241 TerminateAllChromeProcesses(process_id_); |
| 393 } | 242 } |
| 394 | 243 |
| 395 scoped_refptr<TabProxy> UITestBase::GetActiveTab(int window_index) { | 244 scoped_refptr<TabProxy> UITestBase::GetActiveTab(int window_index) { |
| 396 EXPECT_GE(window_index, 0); | 245 EXPECT_GE(window_index, 0); |
| 397 int window_count = -1; | 246 int window_count = -1; |
| 398 // We have to use EXPECT rather than ASSERT here because ASSERT_* only works | 247 // We have to use EXPECT rather than ASSERT here because ASSERT_* only works |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 automation()->GetBrowserWindow(window_index); | 307 automation()->GetBrowserWindow(window_index); |
| 459 ASSERT_TRUE(window.get()); | 308 ASSERT_TRUE(window.get()); |
| 460 scoped_refptr<TabProxy> tab_proxy(window->GetTab(tab_index)); | 309 scoped_refptr<TabProxy> tab_proxy(window->GetTab(tab_index)); |
| 461 ASSERT_TRUE(tab_proxy.get()); | 310 ASSERT_TRUE(tab_proxy.get()); |
| 462 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, | 311 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, |
| 463 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( | 312 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( |
| 464 url, number_of_navigations)) << url.spec(); | 313 url, number_of_navigations)) << url.spec(); |
| 465 } | 314 } |
| 466 | 315 |
| 467 bool UITestBase::WaitForBrowserProcessToQuit() { | 316 bool UITestBase::WaitForBrowserProcessToQuit() { |
| 468 // Wait for the browser process to quit. | 317 return launcher_->WaitForBrowserProcessToQuit(process_); |
| 469 int timeout = TestTimeouts::wait_for_terminate_timeout_ms(); | |
| 470 #ifdef WAIT_FOR_DEBUGGER_ON_OPEN | |
| 471 timeout = 500000; | |
| 472 #endif | |
| 473 return base::WaitForSingleProcess(process_, timeout); | |
| 474 } | 318 } |
| 475 | 319 |
| 476 bool UITestBase::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, | 320 bool UITestBase::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, |
| 477 bool wait_for_open) { | 321 bool wait_for_open) { |
| 478 const int kCycles = 10; | 322 const int kCycles = 10; |
| 479 for (int i = 0; i < kCycles; i++) { | 323 for (int i = 0; i < kCycles; i++) { |
| 480 bool visible = false; | 324 bool visible = false; |
| 481 bool animating = true; | 325 bool animating = true; |
| 482 if (!browser->GetBookmarkBarVisibility(&visible, &animating)) | 326 if (!browser->GetBookmarkBarVisibility(&visible, &animating)) |
| 483 return false; // Some error. | 327 return false; // Some error. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 EXPECT_TRUE(window_proxy.get()); | 370 EXPECT_TRUE(window_proxy.get()); |
| 527 if (!window_proxy.get()) | 371 if (!window_proxy.get()) |
| 528 return -1; | 372 return -1; |
| 529 | 373 |
| 530 int active_tab_index = -1; | 374 int active_tab_index = -1; |
| 531 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); | 375 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); |
| 532 return active_tab_index; | 376 return active_tab_index; |
| 533 } | 377 } |
| 534 | 378 |
| 535 bool UITestBase::IsBrowserRunning() { | 379 bool UITestBase::IsBrowserRunning() { |
| 536 return CrashAwareSleep(0); | 380 return launcher_->IsBrowserRunning(process_); |
| 537 } | 381 } |
| 538 | 382 |
| 539 bool UITestBase::CrashAwareSleep(int time_out_ms) { | 383 bool UITestBase::CrashAwareSleep(int time_out_ms) { |
| 540 return base::CrashAwareSleep(process_, time_out_ms); | 384 return launcher_->CrashAwareSleep(process_, time_out_ms); |
| 541 } | 385 } |
| 542 | 386 |
| 543 int UITestBase::GetTabCount() { | 387 int UITestBase::GetTabCount() { |
| 544 return GetTabCount(0); | 388 return GetTabCount(0); |
| 545 } | 389 } |
| 546 | 390 |
| 547 int UITestBase::GetTabCount(int window_index) { | 391 int UITestBase::GetTabCount(int window_index) { |
| 548 scoped_refptr<BrowserProxy> window( | 392 scoped_refptr<BrowserProxy> window( |
| 549 automation()->GetBrowserWindow(window_index)); | 393 automation()->GetBrowserWindow(window_index)); |
| 550 EXPECT_TRUE(window.get()); | 394 EXPECT_TRUE(window.get()); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 578 EXPECT_TRUE(tab_proxy.get()); | 422 EXPECT_TRUE(tab_proxy.get()); |
| 579 if (!tab_proxy.get()) | 423 if (!tab_proxy.get()) |
| 580 return FilePath(); | 424 return FilePath(); |
| 581 | 425 |
| 582 FilePath download_directory; | 426 FilePath download_directory; |
| 583 EXPECT_TRUE(tab_proxy->GetDownloadDirectory(&download_directory)); | 427 EXPECT_TRUE(tab_proxy->GetDownloadDirectory(&download_directory)); |
| 584 return download_directory; | 428 return download_directory; |
| 585 } | 429 } |
| 586 | 430 |
| 587 void UITestBase::CloseBrowserAsync(BrowserProxy* browser) const { | 431 void UITestBase::CloseBrowserAsync(BrowserProxy* browser) const { |
| 588 ASSERT_TRUE(automation_proxy_->Send( | 432 ASSERT_TRUE(automation()->Send( |
| 589 new AutomationMsg_CloseBrowserRequestAsync(browser->handle()))); | 433 new AutomationMsg_CloseBrowserRequestAsync(browser->handle()))); |
| 590 } | 434 } |
| 591 | 435 |
| 592 bool UITestBase::CloseBrowser(BrowserProxy* browser, | 436 bool UITestBase::CloseBrowser(BrowserProxy* browser, |
| 593 bool* application_closed) const { | 437 bool* application_closed) const { |
| 594 DCHECK(application_closed); | 438 DCHECK(application_closed); |
| 595 if (!browser->is_valid() || !browser->handle()) | 439 if (!browser->is_valid() || !browser->handle()) |
| 596 return false; | 440 return false; |
| 597 | 441 |
| 598 bool result = true; | 442 bool result = true; |
| 599 | 443 |
| 600 bool succeeded = automation_proxy_->Send(new AutomationMsg_CloseBrowser( | 444 bool succeeded = automation()->Send(new AutomationMsg_CloseBrowser( |
| 601 browser->handle(), &result, application_closed)); | 445 browser->handle(), &result, application_closed)); |
| 602 | 446 |
| 603 if (!succeeded) | 447 if (!succeeded) |
| 604 return false; | 448 return false; |
| 605 | 449 |
| 606 if (*application_closed) { | 450 if (*application_closed) { |
| 607 // Let's wait until the process dies (if it is not gone already). | 451 // Let's wait until the process dies (if it is not gone already). |
| 608 bool success = base::WaitForSingleProcess(process_, base::kNoTimeout); | 452 bool success = base::WaitForSingleProcess(process_, base::kNoTimeout); |
| 609 EXPECT_TRUE(success); | 453 EXPECT_TRUE(success); |
| 610 } | 454 } |
| 611 | 455 |
| 612 return result; | 456 return result; |
| 613 } | 457 } |
| 614 | 458 |
| 615 // static | 459 // static |
| 616 void UITestBase::RewritePreferencesFile(const FilePath& user_data_dir) { | 460 FilePath UITestBase::ComputeTypicalUserDataSource( |
| 617 const FilePath pref_template_path( | 461 ProxyLauncher::ProfileType profile_type) { |
| 618 user_data_dir.AppendASCII("Default").AppendASCII("PreferencesTemplate")); | |
| 619 const FilePath pref_path( | |
| 620 user_data_dir.AppendASCII("Default").AppendASCII("Preferences")); | |
| 621 | |
| 622 // Read in preferences template. | |
| 623 std::string pref_string; | |
| 624 EXPECT_TRUE(file_util::ReadFileToString(pref_template_path, &pref_string)); | |
| 625 string16 format_string = ASCIIToUTF16(pref_string); | |
| 626 | |
| 627 // Make sure temp directory has the proper format for writing to prefs file. | |
| 628 #if defined(OS_POSIX) | |
| 629 std::wstring user_data_dir_w(ASCIIToWide(user_data_dir.value())); | |
| 630 #elif defined(OS_WIN) | |
| 631 std::wstring user_data_dir_w(user_data_dir.value()); | |
| 632 // In Windows, the FilePath will write '\' for the path separators; change | |
| 633 // these to a separator that won't trigger escapes. | |
| 634 std::replace(user_data_dir_w.begin(), | |
| 635 user_data_dir_w.end(), '\\', '/'); | |
| 636 #endif | |
| 637 | |
| 638 // Rewrite prefs file. | |
| 639 std::vector<string16> subst; | |
| 640 subst.push_back(WideToUTF16(user_data_dir_w)); | |
| 641 const std::string prefs_string = | |
| 642 UTF16ToASCII(ReplaceStringPlaceholders(format_string, subst, NULL)); | |
| 643 EXPECT_TRUE(file_util::WriteFile(pref_path, prefs_string.c_str(), | |
| 644 prefs_string.size())); | |
| 645 file_util::EvictFileFromSystemCache(pref_path); | |
| 646 } | |
| 647 | |
| 648 FilePath UITestBase::user_data_dir() const { | |
| 649 EXPECT_TRUE(temp_profile_dir_->IsValid()); | |
| 650 return temp_profile_dir_->path(); | |
| 651 } | |
| 652 | |
| 653 // static | |
| 654 FilePath UITestBase::ComputeTypicalUserDataSource(ProfileType profile_type) { | |
| 655 FilePath source_history_file; | 462 FilePath source_history_file; |
| 656 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, | 463 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, |
| 657 &source_history_file)); | 464 &source_history_file)); |
| 658 source_history_file = source_history_file.AppendASCII("profiles"); | 465 source_history_file = source_history_file.AppendASCII("profiles"); |
| 659 switch (profile_type) { | 466 switch (profile_type) { |
| 660 case UITestBase::DEFAULT_THEME: | 467 case ProxyLauncher::DEFAULT_THEME: |
| 661 source_history_file = source_history_file.AppendASCII("typical_history"); | 468 source_history_file = source_history_file.AppendASCII("typical_history"); |
| 662 break; | 469 break; |
| 663 case UITestBase::COMPLEX_THEME: | 470 case ProxyLauncher::COMPLEX_THEME: |
| 664 source_history_file = source_history_file.AppendASCII("complex_theme"); | 471 source_history_file = source_history_file.AppendASCII("complex_theme"); |
| 665 break; | 472 break; |
| 666 case UITestBase::NATIVE_THEME: | 473 case ProxyLauncher::NATIVE_THEME: |
| 667 source_history_file = source_history_file.AppendASCII("gtk_theme"); | 474 source_history_file = source_history_file.AppendASCII("gtk_theme"); |
| 668 break; | 475 break; |
| 669 case UITestBase::CUSTOM_FRAME: | 476 case ProxyLauncher::CUSTOM_FRAME: |
| 670 source_history_file = source_history_file.AppendASCII("custom_frame"); | 477 source_history_file = source_history_file.AppendASCII("custom_frame"); |
| 671 break; | 478 break; |
| 672 case UITestBase::CUSTOM_FRAME_NATIVE_THEME: | 479 case ProxyLauncher::CUSTOM_FRAME_NATIVE_THEME: |
| 673 source_history_file = | 480 source_history_file = |
| 674 source_history_file.AppendASCII("custom_frame_gtk_theme"); | 481 source_history_file.AppendASCII("custom_frame_gtk_theme"); |
| 675 break; | 482 break; |
| 676 default: | 483 default: |
| 677 NOTREACHED(); | 484 NOTREACHED(); |
| 678 } | 485 } |
| 679 return source_history_file; | 486 return source_history_file; |
| 680 } | 487 } |
| 681 | 488 |
| 682 void UITestBase::PrepareTestCommandline(CommandLine* command_line) { | |
| 683 // Propagate commandline settings from test_launcher_utils. | |
| 684 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line); | |
| 685 | |
| 686 // Add any explicit command line flags passed to the process. | |
| 687 CommandLine::StringType extra_chrome_flags = | |
| 688 CommandLine::ForCurrentProcess()->GetSwitchValueNative( | |
| 689 switches::kExtraChromeFlags); | |
| 690 if (!extra_chrome_flags.empty()) { | |
| 691 // Split by spaces and append to command line | |
| 692 std::vector<CommandLine::StringType> flags; | |
| 693 base::SplitString(extra_chrome_flags, ' ', &flags); | |
| 694 for (size_t i = 0; i < flags.size(); ++i) | |
| 695 command_line->AppendArgNative(flags[i]); | |
| 696 } | |
| 697 | |
| 698 // No default browser check, it would create an info-bar (if we are not the | |
| 699 // default browser) that could conflicts with some tests expectations. | |
| 700 command_line->AppendSwitch(switches::kNoDefaultBrowserCheck); | |
| 701 | |
| 702 // This is a UI test. | |
| 703 command_line->AppendSwitchASCII(switches::kTestType, kUITestType); | |
| 704 | |
| 705 // Tell the browser to use a temporary directory just for this test. | |
| 706 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir()); | |
| 707 | |
| 708 // We need cookies on file:// for things like the page cycler. | |
| 709 if (enable_file_cookies_) | |
| 710 command_line->AppendSwitch(switches::kEnableFileCookies); | |
| 711 | |
| 712 if (dom_automation_enabled_) | |
| 713 command_line->AppendSwitch(switches::kDomAutomationController); | |
| 714 | |
| 715 if (include_testing_id_) | |
| 716 command_line->AppendSwitchASCII(switches::kTestingChannelID, | |
| 717 launcher_->PrefixedChannelID()); | |
| 718 | |
| 719 if (!show_error_dialogs_ && | |
| 720 !CommandLine::ForCurrentProcess()->HasSwitch( | |
| 721 switches::kEnableErrorDialogs)) { | |
| 722 command_line->AppendSwitch(switches::kNoErrorDialogs); | |
| 723 } | |
| 724 if (in_process_renderer_) | |
| 725 command_line->AppendSwitch(switches::kSingleProcess); | |
| 726 if (no_sandbox_) | |
| 727 command_line->AppendSwitch(switches::kNoSandbox); | |
| 728 if (full_memory_dump_) | |
| 729 command_line->AppendSwitch(switches::kFullMemoryCrashReport); | |
| 730 if (safe_plugins_) | |
| 731 command_line->AppendSwitch(switches::kSafePlugins); | |
| 732 if (enable_dcheck_) | |
| 733 command_line->AppendSwitch(switches::kEnableDCHECK); | |
| 734 if (silent_dump_on_dcheck_) | |
| 735 command_line->AppendSwitch(switches::kSilentDumpOnDCHECK); | |
| 736 if (disable_breakpad_) | |
| 737 command_line->AppendSwitch(switches::kDisableBreakpad); | |
| 738 if (!homepage_.empty()) | |
| 739 command_line->AppendSwitchASCII(switches::kHomePage, homepage_); | |
| 740 | |
| 741 if (!js_flags_.empty()) | |
| 742 command_line->AppendSwitchASCII(switches::kJavaScriptFlags, js_flags_); | |
| 743 if (!log_level_.empty()) | |
| 744 command_line->AppendSwitchASCII(switches::kLoggingLevel, log_level_); | |
| 745 | |
| 746 command_line->AppendSwitch(switches::kMetricsRecordingOnly); | |
| 747 | |
| 748 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 749 switches::kEnableErrorDialogs)) | |
| 750 command_line->AppendSwitch(switches::kEnableLogging); | |
| 751 | |
| 752 if (dump_histograms_on_exit_) | |
| 753 command_line->AppendSwitch(switches::kDumpHistogramsOnExit); | |
| 754 | |
| 755 #ifdef WAIT_FOR_DEBUGGER_ON_OPEN | |
| 756 command_line->AppendSwitch(switches::kDebugOnStart); | |
| 757 #endif | |
| 758 | |
| 759 if (!ui_test_name_.empty()) | |
| 760 command_line->AppendSwitchASCII(switches::kTestName, ui_test_name_); | |
| 761 | |
| 762 // The tests assume that file:// URIs can freely access other file:// URIs. | |
| 763 command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); | |
| 764 | |
| 765 // Disable TabCloseableStateWatcher for tests. | |
| 766 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher); | |
| 767 | |
| 768 // Allow file:// access on ChromeOS. | |
| 769 command_line->AppendSwitch(switches::kAllowFileAccess); | |
| 770 } | |
| 771 | |
| 772 bool UITestBase::LaunchBrowserHelper(const CommandLine& arguments, | |
| 773 bool wait, | |
| 774 base::ProcessHandle* process) { | |
| 775 FilePath command = browser_directory_.Append( | |
| 776 chrome::kBrowserProcessExecutablePath); | |
| 777 | |
| 778 CommandLine command_line(command); | |
| 779 | |
| 780 // Add command line arguments that should be applied to all UI tests. | |
| 781 PrepareTestCommandline(&command_line); | |
| 782 DebugFlags::ProcessDebugFlags( | |
| 783 &command_line, ChildProcessInfo::UNKNOWN_PROCESS, false); | |
| 784 command_line.AppendArguments(arguments, false); | |
| 785 | |
| 786 // TODO(phajdan.jr): Only run it for "main" browser launch. | |
| 787 browser_launch_time_ = TimeTicks::Now(); | |
| 788 | |
| 789 #if defined(OS_WIN) | |
| 790 bool started = base::LaunchApp(command_line, | |
| 791 wait, | |
| 792 !show_window_, | |
| 793 process); | |
| 794 #elif defined(OS_POSIX) | |
| 795 // Sometimes one needs to run the browser under a special environment | |
| 796 // (e.g. valgrind) without also running the test harness (e.g. python) | |
| 797 // under the special environment. Provide a way to wrap the browser | |
| 798 // commandline with a special prefix to invoke the special environment. | |
| 799 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); | |
| 800 if (browser_wrapper) { | |
| 801 command_line.PrependWrapper(browser_wrapper); | |
| 802 VLOG(1) << "BROWSER_WRAPPER was set, prefixing command_line with " | |
| 803 << browser_wrapper; | |
| 804 } | |
| 805 | |
| 806 base::file_handle_mapping_vector fds; | |
| 807 if (automation_proxy_.get()) | |
| 808 fds = automation_proxy_->fds_to_map(); | |
| 809 | |
| 810 bool started = base::LaunchApp(command_line.argv(), fds, wait, process); | |
| 811 #endif | |
| 812 | |
| 813 return started; | |
| 814 } | |
| 815 | |
| 816 void UITestBase::UpdateHistoryDates() { | |
| 817 // Migrate the times in the segment_usage table to yesterday so we get | |
| 818 // actual thumbnails on the NTP. | |
| 819 sql::Connection db; | |
| 820 FilePath history = | |
| 821 user_data_dir().AppendASCII("Default").AppendASCII("History"); | |
| 822 // Not all test profiles have a history file. | |
| 823 if (!file_util::PathExists(history)) | |
| 824 return; | |
| 825 | |
| 826 ASSERT_TRUE(db.Open(history)); | |
| 827 Time yesterday = Time::Now() - TimeDelta::FromDays(1); | |
| 828 std::string yesterday_str = base::Int64ToString(yesterday.ToInternalValue()); | |
| 829 std::string query = StringPrintf( | |
| 830 "UPDATE segment_usage " | |
| 831 "SET time_slot = %s " | |
| 832 "WHERE id IN (SELECT id FROM segment_usage WHERE time_slot > 0);", | |
| 833 yesterday_str.c_str()); | |
| 834 ASSERT_TRUE(db.Execute(query.c_str())); | |
| 835 db.Close(); | |
| 836 file_util::EvictFileFromSystemCache(history); | |
| 837 } | |
| 838 | |
| 839 int UITestBase::GetCrashCount() { | 489 int UITestBase::GetCrashCount() { |
| 840 FilePath crash_dump_path; | 490 FilePath crash_dump_path; |
| 841 PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); | 491 PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); |
| 842 int actual_crashes = file_util::CountFilesCreatedAfter( | 492 int actual_crashes = file_util::CountFilesCreatedAfter( |
| 843 crash_dump_path, test_start_time_); | 493 crash_dump_path, test_start_time_); |
| 844 | 494 |
| 845 #if defined(OS_WIN) | 495 #if defined(OS_WIN) |
| 846 // Each crash creates two dump files, so we divide by two here. | 496 // Each crash creates two dump files, so we divide by two here. |
| 847 actual_crashes /= 2; | 497 actual_crashes /= 2; |
| 848 #endif | 498 #endif |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1208 incorrect_state_count++; | 858 incorrect_state_count++; |
| 1209 } | 859 } |
| 1210 | 860 |
| 1211 LOG(INFO) << "Elapsed time: " << (base::Time::Now() - start).InSecondsF() | 861 LOG(INFO) << "Elapsed time: " << (base::Time::Now() - start).InSecondsF() |
| 1212 << " seconds" | 862 << " seconds" |
| 1213 << " call failed " << fail_count << " times" | 863 << " call failed " << fail_count << " times" |
| 1214 << " state was incorrect " << incorrect_state_count << " times"; | 864 << " state was incorrect " << incorrect_state_count << " times"; |
| 1215 ADD_FAILURE() << "Timeout reached in " << __FUNCTION__; | 865 ADD_FAILURE() << "Timeout reached in " << __FUNCTION__; |
| 1216 return false; | 866 return false; |
| 1217 } | 867 } |
| OLD | NEW |