OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/test/ui/ui_test.h" | |
6 | |
7 #if defined(OS_POSIX) | |
8 #include <signal.h> | |
9 #include <sys/types.h> | |
10 #endif | |
11 | |
12 #include <set> | |
13 #include <vector> | |
14 | |
15 #include "base/base_switches.h" | |
16 #include "base/bind.h" | |
17 #include "base/command_line.h" | |
18 #include "base/environment.h" | |
19 #include "base/file_util.h" | |
20 #include "base/files/file_enumerator.h" | |
21 #include "base/files/file_path.h" | |
22 #include "base/files/scoped_temp_dir.h" | |
23 #include "base/json/json_file_value_serializer.h" | |
24 #include "base/logging.h" | |
25 #include "base/memory/scoped_ptr.h" | |
26 #include "base/path_service.h" | |
27 #include "base/strings/string_number_conversions.h" | |
28 #include "base/strings/string_split.h" | |
29 #include "base/strings/utf_string_conversions.h" | |
30 #include "base/test/test_file_util.h" | |
31 #include "base/test/test_timeouts.h" | |
32 #include "base/threading/platform_thread.h" | |
33 #include "base/time/time.h" | |
34 #include "chrome/app/chrome_command_ids.h" | |
35 #include "chrome/browser/profiles/profile_impl.h" | |
36 #include "chrome/common/automation_messages.h" | |
37 #include "chrome/common/chrome_constants.h" | |
38 #include "chrome/common/chrome_paths.h" | |
39 #include "chrome/common/chrome_switches.h" | |
40 #include "chrome/common/logging_chrome.h" | |
41 #include "chrome/common/net/url_fixer_upper.h" | |
42 #include "chrome/common/pref_names.h" | |
43 #include "chrome/common/url_constants.h" | |
44 #include "chrome/test/automation/automation_proxy.h" | |
45 #include "chrome/test/automation/browser_proxy.h" | |
46 #include "chrome/test/automation/proxy_launcher.h" | |
47 #include "chrome/test/automation/tab_proxy.h" | |
48 #include "chrome/test/automation/window_proxy.h" | |
49 #include "chrome/test/base/chrome_process_util.h" | |
50 #include "chrome/test/base/test_launcher_utils.h" | |
51 #include "chrome/test/base/test_switches.h" | |
52 #include "chrome/test/base/testing_profile.h" | |
53 #include "extensions/common/switches.h" | |
54 #include "net/base/net_util.h" | |
55 #include "ui/gl/gl_implementation.h" | |
56 #include "url/gurl.h" | |
57 | |
58 #if defined(OS_WIN) | |
59 #include "base/win/windows_version.h" | |
60 #endif | |
61 | |
62 using base::Time; | |
63 using base::TimeDelta; | |
64 using base::TimeTicks; | |
65 | |
66 const wchar_t UITestBase::kFailedNoCrashService[] = | |
67 #if defined(OS_WIN) | |
68 L"NOTE: This test is expected to fail if crash_service.exe is not " | |
69 L"running. Start it manually before running this test (see the build " | |
70 L"output directory)."; | |
71 #elif defined(OS_LINUX) | |
72 L"NOTE: This test is expected to fail if breakpad is not built in " | |
73 L"or if chromium is not running headless (try CHROME_HEADLESS=1)."; | |
74 #else | |
75 L"NOTE: Crash service not ported to this platform!"; | |
76 #endif | |
77 | |
78 UITestBase::UITestBase() | |
79 : launch_arguments_(CommandLine::NO_PROGRAM), | |
80 expected_errors_(0), | |
81 expected_crashes_(0), | |
82 homepage_(content::kAboutBlankURL), | |
83 wait_for_initial_loads_(true), | |
84 dom_automation_enabled_(false), | |
85 stats_collection_controller_enabled_(false), | |
86 show_window_(false), | |
87 clear_profile_(true), | |
88 include_testing_id_(true), | |
89 enable_file_cookies_(true) { | |
90 PathService::Get(chrome::DIR_APP, &browser_directory_); | |
91 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | |
92 } | |
93 | |
94 UITestBase::UITestBase(base::MessageLoop::Type msg_loop_type) | |
95 : launch_arguments_(CommandLine::NO_PROGRAM), | |
96 expected_errors_(0), | |
97 expected_crashes_(0), | |
98 wait_for_initial_loads_(true), | |
99 dom_automation_enabled_(false), | |
100 stats_collection_controller_enabled_(false), | |
101 show_window_(false), | |
102 clear_profile_(true), | |
103 include_testing_id_(true), | |
104 enable_file_cookies_(true) { | |
105 PathService::Get(chrome::DIR_APP, &browser_directory_); | |
106 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | |
107 } | |
108 | |
109 UITestBase::~UITestBase() {} | |
110 | |
111 void UITestBase::SetUp() { | |
112 // Tests that do a session restore (e.g. SessionRestoreUITest, StartupTest) | |
113 // call SetUp() multiple times because they restart the browser mid-test. | |
114 // We don't want to reset the ProxyLauncher's state in those cases. | |
115 if (!launcher_.get()) | |
116 launcher_.reset(CreateProxyLauncher()); | |
117 launcher_->AssertAppNotRunning("Please close any other instances " | |
118 "of the app before testing."); | |
119 | |
120 test_start_time_ = Time::NowFromSystemTime(); | |
121 | |
122 SetLaunchSwitches(); | |
123 ASSERT_TRUE(launcher_->InitializeConnection(DefaultLaunchState(), | |
124 wait_for_initial_loads_)); | |
125 } | |
126 | |
127 void UITestBase::TearDown() { | |
128 if (launcher_.get()) | |
129 launcher_->TerminateConnection(); | |
130 | |
131 CheckErrorsAndCrashes(); | |
132 } | |
133 | |
134 AutomationProxy* UITestBase::automation() const { | |
135 return launcher_->automation(); | |
136 } | |
137 | |
138 base::TimeDelta UITestBase::action_timeout() { | |
139 return automation()->action_timeout(); | |
140 } | |
141 | |
142 int UITestBase::action_timeout_ms() { | |
143 return action_timeout().InMilliseconds(); | |
144 } | |
145 | |
146 void UITestBase::set_action_timeout(base::TimeDelta timeout) { | |
147 automation()->set_action_timeout(timeout); | |
148 VLOG(1) << "Automation action timeout set to " | |
149 << timeout.InMilliseconds() << " ms"; | |
150 } | |
151 | |
152 void UITestBase::set_action_timeout_ms(int timeout) { | |
153 set_action_timeout(base::TimeDelta::FromMilliseconds(timeout)); | |
154 } | |
155 | |
156 ProxyLauncher* UITestBase::CreateProxyLauncher() { | |
157 return new AnonymousProxyLauncher(false); | |
158 } | |
159 | |
160 ProxyLauncher::LaunchState UITestBase::DefaultLaunchState() { | |
161 base::FilePath browser_executable = | |
162 browser_directory_.Append(GetExecutablePath()); | |
163 CommandLine command(browser_executable); | |
164 command.AppendArguments(launch_arguments_, false); | |
165 base::Closure setup_profile_callback = base::Bind(&UITestBase::SetUpProfile, | |
166 base::Unretained(this)); | |
167 ProxyLauncher::LaunchState state = | |
168 { clear_profile_, template_user_data_, setup_profile_callback, | |
169 command, include_testing_id_, show_window_ }; | |
170 return state; | |
171 } | |
172 | |
173 void UITestBase::SetLaunchSwitches() { | |
174 // All flags added here should also be added in ExtraChromeFlags() in | |
175 // chrome/test/pyautolib/pyauto.py as well to take effect for all tests | |
176 // on chromeos. | |
177 | |
178 // Propagate commandline settings from test_launcher_utils. | |
179 test_launcher_utils::PrepareBrowserCommandLineForTests(&launch_arguments_); | |
180 | |
181 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kWaitForDebugger)) | |
182 launch_arguments_.AppendSwitch(switches::kWaitForDebugger); | |
183 | |
184 // We need cookies on file:// for things like the page cycler. | |
185 if (enable_file_cookies_) | |
186 launch_arguments_.AppendSwitch(switches::kEnableFileCookies); | |
187 if (dom_automation_enabled_) | |
188 launch_arguments_.AppendSwitch(switches::kDomAutomationController); | |
189 if (stats_collection_controller_enabled_) | |
190 launch_arguments_.AppendSwitch(switches::kStatsCollectionController); | |
191 // Allow off-store extension installs. | |
192 launch_arguments_.AppendSwitchASCII( | |
193 extensions::switches::kEasyOffStoreExtensionInstall, "1"); | |
194 if (!homepage_.empty()) { | |
195 // Pass |homepage_| both as an arg (so that it opens on startup) and to the | |
196 // homepage switch (so that the homepage is set). | |
197 | |
198 if (!launch_arguments_.HasSwitch(switches::kHomePage)) | |
199 launch_arguments_.AppendSwitchASCII(switches::kHomePage, homepage_); | |
200 | |
201 if (launch_arguments_.GetArgs().empty() && | |
202 !launch_arguments_.HasSwitch(switches::kRestoreLastSession)) { | |
203 launch_arguments_.AppendArg(homepage_); | |
204 } | |
205 } | |
206 if (!test_name_.empty()) | |
207 launch_arguments_.AppendSwitchASCII(switches::kTestName, test_name_); | |
208 } | |
209 | |
210 void UITestBase::SetUpProfile() { | |
211 } | |
212 | |
213 void UITestBase::LaunchBrowser() { | |
214 LaunchBrowser(launch_arguments_, clear_profile_); | |
215 } | |
216 | |
217 void UITestBase::LaunchBrowserAndServer() { | |
218 ASSERT_TRUE(launcher_->LaunchBrowserAndServer(DefaultLaunchState(), | |
219 wait_for_initial_loads_)); | |
220 } | |
221 | |
222 void UITestBase::ConnectToRunningBrowser() { | |
223 ASSERT_TRUE(launcher_->ConnectToRunningBrowser(wait_for_initial_loads_)); | |
224 } | |
225 | |
226 void UITestBase::CloseBrowserAndServer() { | |
227 if (launcher_.get()) | |
228 launcher_->CloseBrowserAndServer(); | |
229 } | |
230 | |
231 void UITestBase::LaunchBrowser(const CommandLine& arguments, | |
232 bool clear_profile) { | |
233 ProxyLauncher::LaunchState state = DefaultLaunchState(); | |
234 state.clear_profile = clear_profile; | |
235 ASSERT_TRUE(launcher_->LaunchBrowser(state)); | |
236 } | |
237 | |
238 void UITestBase::QuitBrowser() { | |
239 launcher_->QuitBrowser(); | |
240 } | |
241 | |
242 scoped_refptr<TabProxy> UITestBase::GetActiveTab(int window_index) { | |
243 EXPECT_GE(window_index, 0); | |
244 int window_count = -1; | |
245 // We have to use EXPECT rather than ASSERT here because ASSERT_* only works | |
246 // in functions that return void. | |
247 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); | |
248 if (window_count == -1) | |
249 return NULL; | |
250 EXPECT_GT(window_count, window_index); | |
251 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
252 GetBrowserWindow(window_index)); | |
253 EXPECT_TRUE(window_proxy.get()); | |
254 if (!window_proxy.get()) | |
255 return NULL; | |
256 | |
257 int active_tab_index = -1; | |
258 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); | |
259 if (active_tab_index == -1) | |
260 return NULL; | |
261 | |
262 return window_proxy->GetTab(active_tab_index); | |
263 } | |
264 | |
265 scoped_refptr<TabProxy> UITestBase::GetActiveTab() { | |
266 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
267 GetBrowserWindow(0)); | |
268 EXPECT_TRUE(window_proxy.get()); | |
269 if (!window_proxy.get()) | |
270 return NULL; | |
271 | |
272 scoped_refptr<TabProxy> tab_proxy = window_proxy->GetActiveTab(); | |
273 EXPECT_TRUE(tab_proxy.get()); | |
274 return tab_proxy; | |
275 } | |
276 | |
277 void UITestBase::NavigateToURL(const GURL& url) { | |
278 NavigateToURL(url, 0, GetActiveTabIndex(0)); | |
279 } | |
280 | |
281 void UITestBase::NavigateToURL(const GURL& url, int window_index) { | |
282 NavigateToURL(url, window_index, GetActiveTabIndex(window_index)); | |
283 } | |
284 | |
285 void UITestBase::NavigateToURL(const GURL& url, int window_index, int | |
286 tab_index) { | |
287 NavigateToURLBlockUntilNavigationsComplete(url, 1, window_index, tab_index); | |
288 } | |
289 | |
290 void UITestBase::NavigateToURLBlockUntilNavigationsComplete( | |
291 const GURL& url, int number_of_navigations) { | |
292 scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); | |
293 ASSERT_TRUE(tab_proxy.get()); | |
294 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, | |
295 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( | |
296 url, number_of_navigations)) << url.spec(); | |
297 } | |
298 | |
299 void UITestBase::NavigateToURLBlockUntilNavigationsComplete( | |
300 const GURL& url, int number_of_navigations, int window_index, | |
301 int tab_index) { | |
302 scoped_refptr<BrowserProxy> window = | |
303 automation()->GetBrowserWindow(window_index); | |
304 ASSERT_TRUE(window.get()); | |
305 scoped_refptr<TabProxy> tab_proxy(window->GetTab(tab_index)); | |
306 ASSERT_TRUE(tab_proxy.get()); | |
307 EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, | |
308 tab_proxy->NavigateToURLBlockUntilNavigationsComplete( | |
309 url, number_of_navigations)) << url.spec(); | |
310 } | |
311 | |
312 GURL UITestBase::GetActiveTabURL(int window_index) { | |
313 scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); | |
314 EXPECT_TRUE(tab_proxy.get()); | |
315 if (!tab_proxy.get()) | |
316 return GURL(); | |
317 | |
318 GURL url; | |
319 bool success = tab_proxy->GetCurrentURL(&url); | |
320 EXPECT_TRUE(success); | |
321 if (!success) | |
322 return GURL(); | |
323 return url; | |
324 } | |
325 | |
326 std::wstring UITestBase::GetActiveTabTitle(int window_index) { | |
327 std::wstring title; | |
328 scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); | |
329 EXPECT_TRUE(tab_proxy.get()); | |
330 if (!tab_proxy.get()) | |
331 return title; | |
332 | |
333 EXPECT_TRUE(tab_proxy->GetTabTitle(&title)); | |
334 return title; | |
335 } | |
336 | |
337 int UITestBase::GetActiveTabIndex(int window_index) { | |
338 scoped_refptr<BrowserProxy> window_proxy(automation()-> | |
339 GetBrowserWindow(window_index)); | |
340 EXPECT_TRUE(window_proxy.get()); | |
341 if (!window_proxy.get()) | |
342 return -1; | |
343 | |
344 int active_tab_index = -1; | |
345 EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); | |
346 return active_tab_index; | |
347 } | |
348 | |
349 int UITestBase::GetTabCount() { | |
350 return GetTabCount(0); | |
351 } | |
352 | |
353 int UITestBase::GetTabCount(int window_index) { | |
354 scoped_refptr<BrowserProxy> window( | |
355 automation()->GetBrowserWindow(window_index)); | |
356 EXPECT_TRUE(window.get()); | |
357 if (!window.get()) | |
358 return 0; | |
359 | |
360 int result = 0; | |
361 EXPECT_TRUE(window->GetTabCount(&result)); | |
362 | |
363 return result; | |
364 } | |
365 | |
366 void UITestBase::WaitUntilTabCount(int tab_count) { | |
367 const int kMaxIntervals = 10; | |
368 const TimeDelta kDelay = TestTimeouts::action_timeout() / kMaxIntervals; | |
369 | |
370 for (int i = 0; i < kMaxIntervals; ++i) { | |
371 if (GetTabCount() == tab_count) | |
372 return; | |
373 | |
374 base::PlatformThread::Sleep(kDelay); | |
375 } | |
376 | |
377 ADD_FAILURE() << "Timeout reached in WaitUntilTabCount"; | |
378 } | |
379 | |
380 const base::FilePath::CharType* UITestBase::GetExecutablePath() { | |
381 if (launch_arguments_.HasSwitch(switches::kEnableChromiumBranding)) | |
382 return chrome::kBrowserProcessExecutablePathChromium; | |
383 return chrome::kBrowserProcessExecutablePath; | |
384 } | |
385 | |
386 bool UITestBase::CloseBrowser(BrowserProxy* browser, | |
387 bool* application_closed) const { | |
388 DCHECK(application_closed); | |
389 if (!browser->is_valid() || !browser->handle()) | |
390 return false; | |
391 | |
392 bool result = true; | |
393 | |
394 ChromeProcessList processes = GetRunningChromeProcesses( | |
395 browser_process_id()); | |
396 | |
397 bool succeeded = automation()->Send(new AutomationMsg_CloseBrowser( | |
398 browser->handle(), &result, application_closed)); | |
399 | |
400 if (!succeeded) | |
401 return false; | |
402 | |
403 if (*application_closed) { | |
404 int exit_code = -1; | |
405 EXPECT_TRUE(launcher_->WaitForBrowserProcessToQuit( | |
406 TestTimeouts::action_max_timeout(), &exit_code)); | |
407 EXPECT_EQ(0, exit_code); // Expect a clean shutown. | |
408 // Ensure no child processes are left dangling. | |
409 TerminateAllChromeProcesses(processes); | |
410 } | |
411 | |
412 return result; | |
413 } | |
414 | |
415 int UITestBase::GetCrashCount() const { | |
416 base::FilePath crash_dump_path; | |
417 PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); | |
418 | |
419 int files_found = 0; | |
420 base::FileEnumerator en(crash_dump_path, false, base::FileEnumerator::FILES); | |
421 while (!en.Next().empty()) { | |
422 if (en.GetInfo().GetLastModifiedTime() > test_start_time_) | |
423 files_found++; | |
424 } | |
425 | |
426 #if defined(OS_WIN) | |
427 // Each crash creates two dump files on Windows. | |
428 return files_found / 2; | |
429 #else | |
430 return files_found; | |
431 #endif | |
432 } | |
433 | |
434 std::string UITestBase::CheckErrorsAndCrashes() const { | |
435 // Make sure that we didn't encounter any assertion failures | |
436 logging::AssertionList assertions; | |
437 logging::GetFatalAssertions(&assertions); | |
438 | |
439 // If there were errors, get all the error strings for display. | |
440 std::wstring failures = | |
441 L"The following error(s) occurred in the application during this test:"; | |
442 if (assertions.size() > expected_errors_) { | |
443 logging::AssertionList::const_iterator iter = assertions.begin(); | |
444 for (; iter != assertions.end(); ++iter) { | |
445 failures += L"\n\n"; | |
446 failures += *iter; | |
447 } | |
448 } | |
449 EXPECT_EQ(expected_errors_, assertions.size()) << failures; | |
450 | |
451 int actual_crashes = GetCrashCount(); | |
452 | |
453 std::wstring error_msg = | |
454 L"Encountered an unexpected crash in the program during this test."; | |
455 if (expected_crashes_ > 0 && actual_crashes == 0) { | |
456 error_msg += L" "; | |
457 error_msg += kFailedNoCrashService; | |
458 } | |
459 EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg; | |
460 | |
461 std::wstring wide_result; | |
462 if (expected_errors_ != assertions.size()) { | |
463 wide_result += failures; | |
464 wide_result += L"\n\n"; | |
465 } | |
466 if (expected_crashes_ != actual_crashes) | |
467 wide_result += error_msg; | |
468 | |
469 return std::string(wide_result.begin(), wide_result.end()); | |
470 } | |
471 | |
472 void UITestBase::SetBrowserDirectory(const base::FilePath& dir) { | |
473 browser_directory_ = dir; | |
474 } | |
475 | |
476 void UITestBase::AppendBrowserLaunchSwitch(const char* name) { | |
477 launch_arguments_.AppendSwitch(name); | |
478 } | |
479 | |
480 void UITestBase::AppendBrowserLaunchSwitch(const char* name, | |
481 const char* value) { | |
482 launch_arguments_.AppendSwitchASCII(name, value); | |
483 } | |
484 | |
485 bool UITestBase::BeginTracing(const std::string& category_patterns) { | |
486 return automation()->BeginTracing(category_patterns); | |
487 } | |
488 | |
489 std::string UITestBase::EndTracing() { | |
490 std::string json_trace_output; | |
491 if (!automation()->EndTracing(&json_trace_output)) | |
492 return std::string(); | |
493 return json_trace_output; | |
494 } | |
495 | |
496 // UITest methods | |
497 | |
498 void UITest::SetUp() { | |
499 // Pass the test case name to chrome.exe on the command line to help with | |
500 // parsing Purify output. | |
501 const testing::TestInfo* const test_info = | |
502 testing::UnitTest::GetInstance()->current_test_info(); | |
503 if (test_info) { | |
504 set_test_name(test_info->test_case_name() + std::string(".") + | |
505 test_info->name()); | |
506 } | |
507 | |
508 UITestBase::SetUp(); | |
509 PlatformTest::SetUp(); | |
510 } | |
511 | |
512 void UITest::TearDown() { | |
513 UITestBase::TearDown(); | |
514 PlatformTest::TearDown(); | |
515 } | |
516 | |
517 ProxyLauncher* UITest::CreateProxyLauncher() { | |
518 // Make the AutomationProxy disconnect the channel on the first error, | |
519 // so that we avoid spending a lot of time in timeouts. The browser is likely | |
520 // hosed if we hit those errors. | |
521 return new AnonymousProxyLauncher(true); | |
522 } | |
523 | |
524 bool UITest::GetBrowserProcessCount(int* count) { | |
525 *count = 0; | |
526 if (!automation()->WaitForProcessLauncherThreadToGoIdle()) | |
527 return false; | |
528 *count = GetRunningChromeProcesses(browser_process_id()).size(); | |
529 return true; | |
530 } | |
531 | |
532 static base::DictionaryValue* LoadDictionaryValueFromPath( | |
533 const base::FilePath& path) { | |
534 if (path.empty()) | |
535 return NULL; | |
536 | |
537 JSONFileValueSerializer serializer(path); | |
538 scoped_ptr<base::Value> root_value(serializer.Deserialize(NULL, NULL)); | |
539 if (!root_value.get() || | |
540 root_value->GetType() != base::Value::TYPE_DICTIONARY) { | |
541 return NULL; | |
542 } | |
543 | |
544 return static_cast<base::DictionaryValue*>(root_value.release()); | |
545 } | |
546 | |
547 base::DictionaryValue* UITest::GetLocalState() { | |
548 base::FilePath local_state_path; | |
549 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); | |
550 return LoadDictionaryValueFromPath(local_state_path); | |
551 } | |
552 | |
553 base::DictionaryValue* UITest::GetDefaultProfilePreferences() { | |
554 base::FilePath path; | |
555 PathService::Get(chrome::DIR_USER_DATA, &path); | |
556 path = path.AppendASCII(TestingProfile::kTestUserProfileDir); | |
557 return LoadDictionaryValueFromPath(path.Append(chrome::kPreferencesFilename)); | |
558 } | |
559 | |
560 void UITest::WaitForFinish(const std::string &name, | |
561 const std::string &id, | |
562 const GURL &url, | |
563 const std::string& test_complete_cookie, | |
564 const std::string& expected_cookie_value, | |
565 const base::TimeDelta wait_time) { | |
566 // The webpage being tested has javascript which sets a cookie | |
567 // which signals completion of the test. The cookie name is | |
568 // a concatenation of the test name and the test id. This allows | |
569 // us to run multiple tests within a single webpage and test | |
570 // that they all c | |
571 std::string cookie_name = name; | |
572 cookie_name.append("."); | |
573 cookie_name.append(id); | |
574 cookie_name.append("."); | |
575 cookie_name.append(test_complete_cookie); | |
576 | |
577 scoped_refptr<TabProxy> tab(GetActiveTab()); | |
578 ASSERT_TRUE(tab.get()); | |
579 std::string cookie_value = WaitUntilCookieNonEmpty(tab.get(), url, | |
580 cookie_name.c_str(), | |
581 wait_time); | |
582 EXPECT_EQ(expected_cookie_value, cookie_value); | |
583 } | |
584 | |
585 bool UITest::WaitUntilJavaScriptCondition(TabProxy* tab, | |
586 const std::wstring& frame_xpath, | |
587 const std::wstring& jscript, | |
588 base::TimeDelta timeout) { | |
589 const TimeDelta kDelay = TimeDelta::FromMilliseconds(250); | |
590 const int kMaxDelays = timeout / kDelay; | |
591 | |
592 // Wait until the test signals it has completed. | |
593 for (int i = 0; i < kMaxDelays; ++i) { | |
594 bool done_value = false; | |
595 bool success = tab->ExecuteAndExtractBool(frame_xpath, jscript, | |
596 &done_value); | |
597 EXPECT_TRUE(success); | |
598 if (!success) | |
599 return false; | |
600 if (done_value) | |
601 return true; | |
602 | |
603 base::PlatformThread::Sleep(kDelay); | |
604 } | |
605 | |
606 ADD_FAILURE() << "Timeout reached in WaitUntilJavaScriptCondition"; | |
607 return false; | |
608 } | |
609 | |
610 bool UITest::WaitUntilCookieValue(TabProxy* tab, | |
611 const GURL& url, | |
612 const char* cookie_name, | |
613 base::TimeDelta timeout, | |
614 const char* expected_value) { | |
615 const TimeDelta kDelay = TimeDelta::FromMilliseconds(250); | |
616 const int kMaxDelays = timeout / kDelay; | |
617 | |
618 std::string cookie_value; | |
619 for (int i = 0; i < kMaxDelays; ++i) { | |
620 EXPECT_TRUE(tab->GetCookieByName(url, cookie_name, &cookie_value)); | |
621 if (cookie_value == expected_value) | |
622 return true; | |
623 | |
624 base::PlatformThread::Sleep(kDelay); | |
625 } | |
626 | |
627 ADD_FAILURE() << "Timeout reached in WaitUntilCookieValue"; | |
628 return false; | |
629 } | |
630 | |
631 std::string UITest::WaitUntilCookieNonEmpty(TabProxy* tab, | |
632 const GURL& url, | |
633 const char* cookie_name, | |
634 base::TimeDelta timeout) { | |
635 const TimeDelta kDelay = TimeDelta::FromMilliseconds(250); | |
636 const int kMaxDelays = timeout / kDelay; | |
637 | |
638 for (int i = 0; i < kMaxDelays; ++i) { | |
639 std::string cookie_value; | |
640 EXPECT_TRUE(tab->GetCookieByName(url, cookie_name, &cookie_value)); | |
641 if (!cookie_value.empty()) | |
642 return cookie_value; | |
643 | |
644 base::PlatformThread::Sleep(kDelay); | |
645 } | |
646 | |
647 ADD_FAILURE() << "Timeout reached in WaitUntilCookieNonEmpty"; | |
648 return std::string(); | |
649 } | |
650 | |
651 bool UITest::WaitForFindWindowVisibilityChange(BrowserProxy* browser, | |
652 bool wait_for_open) { | |
653 const int kCycles = 10; | |
654 const TimeDelta kDelay = TestTimeouts::action_timeout() / kCycles; | |
655 for (int i = 0; i < kCycles; i++) { | |
656 bool visible = false; | |
657 if (!browser->IsFindWindowFullyVisible(&visible)) | |
658 return false; // Some error. | |
659 if (visible == wait_for_open) | |
660 return true; // Find window visibility change complete. | |
661 | |
662 // Give it a chance to catch up. | |
663 base::PlatformThread::Sleep(kDelay); | |
664 } | |
665 | |
666 ADD_FAILURE() << "Timeout reached in WaitForFindWindowVisibilityChange"; | |
667 return false; | |
668 } | |
669 | |
670 void UITest::TerminateBrowser() { | |
671 launcher_->TerminateBrowser(); | |
672 | |
673 // Make sure the UMA metrics say we didn't crash. | |
674 scoped_ptr<base::DictionaryValue> local_prefs(GetLocalState()); | |
675 bool exited_cleanly; | |
676 ASSERT_TRUE(local_prefs.get()); | |
677 ASSERT_TRUE(local_prefs->GetBoolean(prefs::kStabilityExitedCleanly, | |
678 &exited_cleanly)); | |
679 ASSERT_TRUE(exited_cleanly); | |
680 | |
681 // And that session end was successful. | |
682 bool session_end_completed; | |
683 ASSERT_TRUE(local_prefs->GetBoolean(prefs::kStabilitySessionEndCompleted, | |
684 &session_end_completed)); | |
685 ASSERT_TRUE(session_end_completed); | |
686 | |
687 // Make sure session restore says we didn't crash. | |
688 scoped_ptr<base::DictionaryValue> profile_prefs( | |
689 GetDefaultProfilePreferences()); | |
690 ASSERT_TRUE(profile_prefs.get()); | |
691 std::string exit_type; | |
692 ASSERT_TRUE(profile_prefs->GetString(prefs::kSessionExitedCleanly, | |
693 &exit_type)); | |
694 EXPECT_EQ(ProfileImpl::kPrefExitTypeNormal, exit_type); | |
695 } | |
OLD | NEW |