summaryrefslogtreecommitdiffstats
path: root/chrome/test/automated_ui_tests
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/test/automated_ui_tests
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test/automated_ui_tests')
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.cc887
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.h443
-rw-r--r--chrome/test/automated_ui_tests/automated_ui_tests.vcproj212
3 files changed, 1542 insertions, 0 deletions
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.cc b/chrome/test/automated_ui_tests/automated_ui_tests.cc
new file mode 100644
index 0000000..0129e81
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.cc
@@ -0,0 +1,887 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <fstream>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/view_ids.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/libxml_utils.h"
+#include "chrome/common/rand_util.h"
+#include "chrome/common/win_util.h"
+#include "chrome/test/automated_ui_tests/automated_ui_tests.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/views/view.h"
+#include "googleurl/src/gurl.h"
+
+namespace {
+
+const wchar_t* const kReproSwitch = L"key";
+
+const wchar_t* const kReproRepeatSwitch = L"num-reproductions";
+
+const wchar_t* const kInputFilePathSwitch = L"input";
+
+const wchar_t* const kOutputFilePathSwitch = L"output";
+
+const wchar_t* const kDebugModeSwitch = L"debug";
+
+const wchar_t* const kDefaultInputFilePath = L"C:\\automated_ui_tests.txt";
+
+const wchar_t* const kDefaultOutputFilePath
+ = L"C:\\automated_ui_tests_error_report.txt";
+
+const int kDebuggingTimeoutMsec = 5000;
+
+// How many commands to run when testing a dialog box.
+const int kTestDialogActionsToRun = 7;
+
+} // namespace
+
+// This subset of commands is used to test dialog boxes, which aren't likely
+// to respond to most other commands.
+std::string AutomatedUITest::test_dialog_possible_actions_[] = {
+ "PressTabKey",
+ "PressEnterKey",
+ "PressSpaceBar",
+ "DownArrow"
+};
+
+AutomatedUITest::AutomatedUITest()
+ : total_crashes_(0),
+ debug_logging_enabled_(false) {
+ show_window_ = true;
+ GetSystemTimeAsFileTime(&test_start_time_);
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kDebugModeSwitch))
+ debug_logging_enabled_ = true;
+}
+
+AutomatedUITest::~AutomatedUITest() {}
+
+void AutomatedUITest::RunReproduction() {
+ CommandLine parsed_command_line;
+ xml_writer_.StartWriting();
+ xml_writer_.StartElement("Report");
+ std::string action_string =
+ WideToASCII(parsed_command_line.GetSwitchValue(kReproSwitch));
+
+ int64 num_reproductions = 1;
+ if (parsed_command_line.HasSwitch(kReproRepeatSwitch)) {
+ std::wstring num_reproductions_string =
+ parsed_command_line.GetSwitchValue(kReproRepeatSwitch);
+ std::string test = WideToASCII(num_reproductions_string);
+ num_reproductions = StringToInt64(num_reproductions_string);
+ }
+ std::vector<std::string> actions;
+ SplitString(action_string, L',', &actions);
+ bool did_crash = false;
+ bool command_complete = false;
+
+ for (int64 i = 0; i < num_reproductions && !did_crash; ++i) {
+ bool did_teardown = false;
+ xml_writer_.StartElement("Executed");
+ for (size_t j = 0; j < actions.size(); ++j) {
+ DoAction(actions[j]);
+ if (DidCrash(true)) {
+ did_crash = true;
+ if (j >= (actions.size() - 1))
+ command_complete = true;
+ break;
+ }
+ if (LowerCaseEqualsASCII(actions[j], "teardown"))
+ did_teardown = true;
+ }
+
+ // Force proper teardown after each run, if it didn't already happen. But
+ // don't teardown after crashes.
+ if (!did_teardown && !did_crash)
+ DoAction("TearDown");
+
+ xml_writer_.EndElement(); // End "Executed" element.
+ }
+
+ if (did_crash) {
+ std::string crash_dump = WideToASCII(GetMostRecentCrashDump());
+ std::string result =
+ "*** Crash dump produced. See result file for more details. Dump = ";
+ result.append(crash_dump);
+ result.append(" ***\n");
+ printf("%s", result.c_str());
+ LogCrashResult(crash_dump, command_complete);
+ EXPECT_TRUE(false) << "Crash detected.";
+ } else {
+ printf("*** No crashes. See result file for more details. ***\n");
+ LogSuccessResult();
+ }
+
+ WriteReportToFile();
+}
+
+
+void AutomatedUITest::RunAutomatedUITest() {
+ ASSERT_TRUE(InitXMLReader()) << "Error initializing XMLReader";
+ xml_writer_.StartWriting();
+ xml_writer_.StartElement("Report");
+
+ while (init_reader_.Read()) {
+ init_reader_.SkipToElement();
+ std::string node_name = init_reader_.NodeName();
+ if (LowerCaseEqualsASCII(node_name, "command")) {
+ bool no_errors = true;
+ xml_writer_.StartElement("Executed");
+ std::string command_number;
+ if (init_reader_.NodeAttribute("number", &command_number)) {
+ xml_writer_.AddAttribute("command_number", command_number);
+ }
+ xml_writer_.StopIndenting();
+
+ // Starts the browser, logging it as an action.
+ DoAction("SetUp");
+
+ // Record the depth of the root of the command subtree, then advance to
+ // the first element in preperation for parsing.
+ int start_depth = init_reader_.Depth();
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ init_reader_.SkipToElement();
+
+ // Check for a crash right after startup.
+ if (DidCrash(true)) {
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), false);
+ // Try and start up again.
+ CloseBrowserAndServer();
+ LaunchBrowserAndServer();
+ if (DidCrash(true)) {
+ no_errors = false;
+ // We crashed again, so skip to the end of the this command.
+ while (init_reader_.Depth() != start_depth) {
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ }
+ } else {
+ // We didn't crash, so end the old element, logging a crash for that.
+ // Then start a new element to log this command.
+ xml_writer_.StartIndenting();
+ xml_writer_.EndElement();
+ xml_writer_.StartElement("Executed");
+ xml_writer_.AddAttribute("command_number", command_number);
+ xml_writer_.StopIndenting();
+ xml_writer_.StartElement("SetUp");
+ xml_writer_.EndElement();
+ }
+ }
+ // Parse the command, performing the specified actions and checking
+ // for a crash after each one.
+ while (init_reader_.Depth() != start_depth) {
+ node_name = init_reader_.NodeName();
+
+ DoAction(node_name);
+
+ // Advance to the next element
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ init_reader_.SkipToElement();
+ if (DidCrash(true)) {
+ no_errors = false;
+ // This was the last action if we've returned to the initial depth
+ // of the command subtree.
+ bool wasLastAction = init_reader_.Depth() == start_depth;
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), wasLastAction);
+ // Skip to the beginning of the next command.
+ while (init_reader_.Depth() != start_depth) {
+ ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
+ }
+ }
+ }
+
+ if (no_errors) {
+ // If there were no previous crashes, log our tear down and check for
+ // a crash, log success for the entire command if this doesn't crash.
+ DoAction("TearDown");
+ if (DidCrash(true))
+ LogCrashResult(WideToASCII(GetMostRecentCrashDump()), true);
+ else
+ LogSuccessResult();
+ } else {
+ // If there was a previous crash, just tear down without logging, so
+ // that we know what the last command was before we crashed.
+ CloseBrowserAndServer();
+ }
+
+ xml_writer_.StartIndenting();
+ xml_writer_.EndElement(); // End "Executed" element.
+ }
+ }
+ // The test is finished so write our report.
+ WriteReportToFile();
+}
+
+bool AutomatedUITest::DoAction(const std::string & action) {
+ bool did_complete_action = false;
+ xml_writer_.StartElement(action);
+ if (debug_logging_enabled_)
+ AppendToOutputFile(action);
+
+ if (LowerCaseEqualsASCII(action, "navigate")) {
+ did_complete_action = Navigate();
+ } else if (LowerCaseEqualsASCII(action, "newtab")) {
+ did_complete_action = NewTab();
+ } else if (LowerCaseEqualsASCII(action, "back")) {
+ did_complete_action = BackButton();
+ } else if (LowerCaseEqualsASCII(action, "forward")) {
+ did_complete_action = ForwardButton();
+ } else if (LowerCaseEqualsASCII(action, "closetab")) {
+ did_complete_action = CloseActiveTab();
+ } else if (LowerCaseEqualsASCII(action, "openwindow")) {
+ did_complete_action = OpenAndActivateNewBrowserWindow();
+ } else if (LowerCaseEqualsASCII(action, "reload")) {
+ did_complete_action = ReloadPage();
+ } else if (LowerCaseEqualsASCII(action, "star")) {
+ did_complete_action = StarPage();
+ } else if (LowerCaseEqualsASCII(action, "findinpage")) {
+ did_complete_action = FindInPage();
+ } else if (LowerCaseEqualsASCII(action, "selectnexttab")) {
+ did_complete_action = SelectNextTab();
+ } else if (LowerCaseEqualsASCII(action, "selectprevtab")) {
+ did_complete_action = SelectPreviousTab();
+ } else if (LowerCaseEqualsASCII(action, "zoomplus")) {
+ did_complete_action = ZoomPlus();
+ } else if (LowerCaseEqualsASCII(action, "zoomminus")) {
+ did_complete_action = ZoomMinus();
+ } else if (LowerCaseEqualsASCII(action, "history")) {
+ did_complete_action = ShowHistory();
+ } else if (LowerCaseEqualsASCII(action, "downloads")) {
+ did_complete_action = ShowDownloads();
+ } else if (LowerCaseEqualsASCII(action, "importsettings")) {
+ did_complete_action = ImportSettings();
+ } else if (LowerCaseEqualsASCII(action, "viewpasswords")) {
+ did_complete_action = ViewPasswords();
+ } else if (LowerCaseEqualsASCII(action, "clearbrowserdata")) {
+ did_complete_action = ClearBrowserData();
+ } else if (LowerCaseEqualsASCII(action, "taskmanager")) {
+ did_complete_action = TaskManager();
+ } else if (LowerCaseEqualsASCII(action, "goofftherecord")) {
+ did_complete_action = GoOffTheRecord();
+ } else if (LowerCaseEqualsASCII(action, "pressescapekey")) {
+ did_complete_action = PressEscapeKey();
+ } else if (LowerCaseEqualsASCII(action, "presstabkey")) {
+ did_complete_action = PressTabKey();
+ } else if (LowerCaseEqualsASCII(action, "pressenterkey")) {
+ did_complete_action = PressEnterKey();
+ } else if (LowerCaseEqualsASCII(action, "pressspacebar")) {
+ did_complete_action = PressSpaceBar();
+ } else if (LowerCaseEqualsASCII(action, "pagedown")) {
+ did_complete_action = PageDown();
+ } else if (LowerCaseEqualsASCII(action, "pageup")) {
+ did_complete_action = PageUp();
+ } else if (LowerCaseEqualsASCII(action, "dragtabright")) {
+ did_complete_action = DragActiveTab(true, false);
+ } else if (LowerCaseEqualsASCII(action, "dragtableft")) {
+ did_complete_action = DragActiveTab(false, false);
+ } else if (LowerCaseEqualsASCII(action, "dragtabout")) {
+ did_complete_action = DragActiveTab(false, true);
+ } else if (LowerCaseEqualsASCII(action, "uparrow")) {
+ did_complete_action = UpArrow();
+ } else if (LowerCaseEqualsASCII(action, "downarrow")) {
+ did_complete_action = DownArrow();
+ } else if (LowerCaseEqualsASCII(action, "testeditkeywords")) {
+ did_complete_action = TestEditKeywords();
+ } else if (LowerCaseEqualsASCII(action, "testtaskmanager")) {
+ did_complete_action = TestTaskManager();
+ } else if (LowerCaseEqualsASCII(action, "testviewpasswords")) {
+ did_complete_action = TestViewPasswords();
+ } else if (LowerCaseEqualsASCII(action, "testclearbrowserdata")) {
+ did_complete_action = TestClearBrowserData();
+ } else if (LowerCaseEqualsASCII(action, "testimportsettings")) {
+ did_complete_action = TestImportSettings();
+ } else if (LowerCaseEqualsASCII(action, "crash")) {
+ did_complete_action = ForceCrash();
+ } else if (LowerCaseEqualsASCII(action, "sleep")) {
+ // This is for debugging, it probably shouldn't be used real tests.
+ Sleep(kDebuggingTimeoutMsec);
+ did_complete_action = true;
+ } else if (LowerCaseEqualsASCII(action, "setup")) {
+ LaunchBrowserAndServer();
+ did_complete_action = true;
+ } else if (LowerCaseEqualsASCII(action, "teardown")) {
+ CloseBrowserAndServer();
+ did_complete_action = true;
+ }
+
+ if (!did_complete_action)
+ xml_writer_.AddAttribute("failed_to_complete", "yes");
+ xml_writer_.EndElement();
+
+ return did_complete_action;
+}
+
+bool AutomatedUITest::Navigate() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ bool did_timeout;
+ scoped_ptr<TabProxy> tab(
+ browser->GetActiveTabWithTimeout(kWaitForActionMaxMsec, &did_timeout));
+ // TODO(devint): This might be masking a bug. I can't think of many
+ // valid cases where we would get a browser window, but not be able
+ // to return an active tab. Yet this has happened and has triggered crashes.
+ // Investigate this.
+ if (tab.get() == NULL) {
+ AddErrorAttribute("active_tab_not_found");
+ return false;
+ }
+ std::string url = "about:blank";
+ if (init_reader_.NodeAttribute("url", &url)) {
+ xml_writer_.AddAttribute("url", url);
+ }
+ GURL test_url(url);
+ did_timeout = false;
+ tab->NavigateToURLWithTimeout(test_url, kMaxTestExecutionTime, &did_timeout);
+
+ if (did_timeout) {
+ AddWarningAttribute("timeout");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::NewTab() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int old_tab_count;
+ int new_tab_count;
+ bool is_timeout;
+ browser->GetTabCountWithTimeout(&old_tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ // Apply accelerator and wait for a new tab to open, if either
+ // fails, return false. Apply Accelerator takes care of logging its failure.
+ bool return_value = ApplyAccelerator(IDC_NEWTAB);
+ if (!browser->WaitForTabCountToChange(
+ old_tab_count, &new_tab_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("tab_count_failed_to_change");
+ return false;
+ }
+ return return_value;
+}
+
+bool AutomatedUITest::BackButton() {
+ return ApplyAccelerator(IDC_BACK);
+}
+
+bool AutomatedUITest::ForwardButton() {
+ return ApplyAccelerator(IDC_FORWARD);
+}
+
+bool AutomatedUITest::CloseActiveTab() {
+ bool return_value = false;
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int browser_windows_count;
+ int tab_count;
+ bool is_timeout;
+ browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ automation()->GetBrowserWindowCount(&browser_windows_count);
+ // Avoid quitting the application by not closing the last window.
+ if (tab_count > 1) {
+ int new_tab_count;
+ return_value = browser->ApplyAccelerator(IDC_CLOSETAB);
+ // Wait for the tab to close before we continue.
+ if (!browser->WaitForTabCountToChange(
+ tab_count, &new_tab_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("tab_count_failed_to_change");
+ return false;
+ }
+ } else if (tab_count == 1 && browser_windows_count > 1) {
+ int new_window_count;
+ return_value = browser->ApplyAccelerator(IDC_CLOSETAB);
+ // Wait for the window to close before we continue.
+ if (!automation()->WaitForWindowCountToChange(
+ browser_windows_count, &new_window_count, kWaitForActionMaxMsec)) {
+ AddWarningAttribute("window_count_failed_to_change");
+ return false;
+ }
+ } else {
+ AddInfoAttribute("would_have_exited_application");
+ return false;
+ }
+ return return_value;
+}
+
+bool AutomatedUITest::OpenAndActivateNewBrowserWindow() {
+ if (!automation()->OpenNewBrowserWindow(SW_SHOWNORMAL)) {
+ AddWarningAttribute("failed_to_open_new_browser_window");
+ return false;
+ }
+ int num_browser_windows;
+ automation()->GetBrowserWindowCount(&num_browser_windows);
+ // Get the most recently opened browser window and activate the tab
+ // in order to activate this browser window.
+ scoped_ptr<BrowserProxy> browser(
+ automation()->GetBrowserWindow(num_browser_windows - 1));
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ bool is_timeout;
+ if (!browser->ActivateTabWithTimeout(0, kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("failed_to_activate_tab");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::ReloadPage() {
+ return ApplyAccelerator(IDC_RELOAD);
+}
+
+bool AutomatedUITest::StarPage() {
+ return ApplyAccelerator(IDC_STAR);
+}
+
+bool AutomatedUITest::FindInPage() {
+ return ApplyAccelerator(IDC_FIND);
+}
+
+bool AutomatedUITest::SelectNextTab() {
+ return ApplyAccelerator(IDC_SELECT_NEXT_TAB);
+}
+
+bool AutomatedUITest::SelectPreviousTab() {
+ return ApplyAccelerator(IDC_SELECT_PREV_TAB);
+}
+
+bool AutomatedUITest::ZoomPlus() {
+ return ApplyAccelerator(IDC_ZOOM_PLUS);
+}
+
+bool AutomatedUITest::ZoomMinus() {
+ return ApplyAccelerator(IDC_ZOOM_MINUS);
+}
+
+bool AutomatedUITest::ShowHistory() {
+ return ApplyAccelerator(IDC_SHOW_HISTORY);
+}
+
+bool AutomatedUITest::ShowDownloads() {
+ return ApplyAccelerator(IDC_SHOW_DOWNLOADS);
+}
+
+bool AutomatedUITest::ImportSettings() {
+ return ApplyAccelerator(IDC_IMPORT_SETTINGS);
+}
+
+bool AutomatedUITest::ViewPasswords() {
+ return ApplyAccelerator(IDC_VIEW_PASSWORDS);
+}
+
+bool AutomatedUITest::ClearBrowserData() {
+ return ApplyAccelerator(IDC_CLEAR_BROWSING_DATA);
+}
+
+bool AutomatedUITest::TaskManager() {
+ return ApplyAccelerator(IDC_TASKMANAGER);
+}
+
+bool AutomatedUITest::GoOffTheRecord() {
+ return ApplyAccelerator(IDC_GOOFFTHERECORD);
+}
+
+bool AutomatedUITest::PressEscapeKey() {
+ return SimulateKeyPressInActiveWindow(VK_ESCAPE, 0);
+}
+
+bool AutomatedUITest::PressTabKey() {
+ return SimulateKeyPressInActiveWindow(VK_TAB, 0);
+}
+
+bool AutomatedUITest::PressEnterKey() {
+ return SimulateKeyPressInActiveWindow(VK_RETURN, 0);
+}
+
+bool AutomatedUITest::PressSpaceBar() {
+ return SimulateKeyPressInActiveWindow(VK_SPACE, 0);
+}
+
+bool AutomatedUITest::PageDown() {
+ return SimulateKeyPressInActiveWindow(VK_PRIOR, 0);
+}
+
+
+bool AutomatedUITest::PageUp() {
+ return SimulateKeyPressInActiveWindow(VK_NEXT, 0);
+}
+
+bool AutomatedUITest::UpArrow() {
+ return SimulateKeyPressInActiveWindow(VK_UP, 0);
+}
+
+bool AutomatedUITest::DownArrow() {
+ return SimulateKeyPressInActiveWindow(VK_DOWN, 0);
+}
+
+bool AutomatedUITest::TestEditKeywords() {
+ DoAction("EditKeywords");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestTaskManager() {
+ DoAction("TaskManager");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestViewPasswords() {
+ DoAction("ViewPasswords");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestClearBrowserData() {
+ DoAction("ClearBrowserData");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestImportSettings() {
+ DoAction("ImportSettings");
+ return TestDialog(kTestDialogActionsToRun);
+}
+
+bool AutomatedUITest::TestDialog(int num_actions) {
+ bool return_value = true;
+
+ for (int i = 0; i < num_actions; i++) {
+ int action_index = rand_util::RandInt(0, kNumTestDialogActions - 1);
+ return_value = return_value &&
+ DoAction(test_dialog_possible_actions_[action_index]);
+ if (DidCrash(false))
+ break;
+ }
+ return DoAction("PressEscapeKey") && return_value;
+}
+
+bool AutomatedUITest::ForceCrash() {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ scoped_ptr<TabProxy> tab(browser->GetActiveTab());
+ GURL test_url("about:crash");
+ bool did_timeout;
+ tab->NavigateToURLWithTimeout(test_url, kDebuggingTimeoutMsec, &did_timeout);
+ if (!did_timeout) {
+ AddInfoAttribute("expected_crash");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::DragActiveTab(bool drag_right, bool drag_out) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ scoped_ptr<WindowProxy> window(
+ GetAndActivateWindowForBrowser(browser.get()));
+ if (window.get() == NULL) {
+ AddErrorAttribute("active_window_not_found");
+ return false;
+ }
+ bool is_timeout;
+
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ int tab_count;
+ browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec,
+ &is_timeout);
+ // As far as we're concerned, if we can't get a view for a tab, it doesn't
+ // exist, so cap tab_count at the number of tab view ids there are.
+ tab_count = std::min(tab_count, VIEW_ID_TAB_LAST - VIEW_ID_TAB_0);
+
+ int tab_index;
+ if (!browser->GetActiveTabIndexWithTimeout(&tab_index,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("no_active_tab");
+ return false;
+ }
+
+ gfx::Rect dragged_tab_bounds;
+ if (!window->GetViewBoundsWithTimeout(VIEW_ID_TAB_0 + tab_index,
+ &dragged_tab_bounds, false,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("no_tab_view_found");
+ return false;
+ }
+
+ // Click on the center of the tab, and drag it to the left or the right.
+ POINT dragged_tab_point(dragged_tab_bounds.CenterPoint().ToPOINT());
+ POINT destination_point(dragged_tab_point);
+
+ int window_count;
+ if (drag_out) {
+ destination_point.y += 3*dragged_tab_bounds.height();
+ automation()->GetBrowserWindowCount(&window_count);
+ } else if (drag_right) {
+ if (tab_index >= (tab_count-1)) {
+ AddInfoAttribute("index_cant_be_moved");
+ return false;
+ }
+ destination_point.x += 2*dragged_tab_bounds.width()/3;
+ } else {
+ if (tab_index <= 0) {
+ AddInfoAttribute("index_cant_be_moved");
+ return false;
+ }
+ destination_point.x -= 2*dragged_tab_bounds.width()/3;
+ }
+
+ if (!browser->SimulateDragWithTimeout(dragged_tab_point,
+ destination_point,
+ ChromeViews::Event::EF_LEFT_BUTTON_DOWN,
+ kWaitForActionMaxMsec,
+ &is_timeout)) {
+ AddWarningAttribute("failed_to_simulate_drag");
+ return false;
+ }
+
+ // If we try to drag the tab out and the window we drag from contains more
+ // than just the dragged tab, we would expect the window count to increase
+ // because the dragged tab should open in a new window. If not, we probably
+ // just dragged into another tabstrip.
+ if (drag_out && tab_count > 1) {
+ int new_window_count;
+ automation()->GetBrowserWindowCount(&new_window_count);
+ if (new_window_count == window_count) {
+ AddInfoAttribute("no_new_browser_window");
+ return false;
+ }
+ }
+ return true;
+}
+
+WindowProxy* AutomatedUITest::GetAndActivateWindowForBrowser(
+ BrowserProxy* browser) {
+ WindowProxy* window = automation()->GetWindowForBrowser(browser);
+
+ bool did_timeout;
+ if (!browser->BringToFrontWithTimeout(kWaitForActionMaxMsec, &did_timeout)) {
+ AddWarningAttribute("failed_to_bring_window_to_front");
+ return NULL;
+ }
+ return window;
+}
+
+bool AutomatedUITest::ApplyAccelerator(int id) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ if (browser.get() == NULL) {
+ AddErrorAttribute("browser_window_not_found");
+ return false;
+ }
+ if (!browser->ApplyAccelerator(id)) {
+ AddWarningAttribute("failure_applying_accelerator");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::SimulateKeyPressInActiveWindow(wchar_t key, int flags) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow());
+ scoped_ptr<WindowProxy> window(
+ GetAndActivateWindowForBrowser(browser.get()));
+ if (window.get() == NULL) {
+ AddErrorAttribute("active_window_not_found");
+ return false;
+ }
+ if (!window->SimulateOSKeyPress(key, flags)) {
+ AddWarningAttribute("failure_simulating_key_press");
+ return false;
+ }
+ return true;
+}
+
+bool AutomatedUITest::InitXMLReader() {
+ std::wstring input_path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kInputFilePathSwitch))
+ input_path = parsed_command_line.GetSwitchValue(kInputFilePathSwitch);
+ else
+ input_path = kDefaultInputFilePath;
+
+ if (!file_util::ReadFileToString(input_path, &xml_init_file_))
+ return false;
+ return init_reader_.Load(xml_init_file_);
+}
+
+bool AutomatedUITest::WriteReportToFile() {
+ std::ofstream error_file;
+ std::wstring path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kOutputFilePathSwitch))
+ path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch);
+ else
+ path = kDefaultOutputFilePath;
+
+ if (!path.empty())
+ error_file.open(path.c_str(), std::ios::out);
+
+ // Closes all open elements and free the writer. This is required
+ // in order to retrieve the contents of the buffer.
+ xml_writer_.StopWriting();
+ error_file << xml_writer_.GetWrittenString();
+ error_file.close();
+ return true;
+}
+
+void AutomatedUITest::AppendToOutputFile(const std::string &append_string) {
+ std::ofstream error_file;
+ std::wstring path;
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kOutputFilePathSwitch))
+ path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch);
+ else
+ path = kDefaultOutputFilePath;
+
+ if (!path.empty())
+ error_file.open(path.c_str(), std::ios::out | std::ios_base::app);
+
+ error_file << append_string << " ";
+ error_file.close();
+}
+
+void AutomatedUITest::LogCrashResult(const std::string &crash_dump,
+ bool command_completed) {
+ xml_writer_.StartElement("result");
+ xml_writer_.StartElement("crash");
+ xml_writer_.AddAttribute("crash_dump", crash_dump);
+ if (command_completed)
+ xml_writer_.AddAttribute("command_completed", "yes");
+ else
+ xml_writer_.AddAttribute("command_completed", "no");
+ xml_writer_.EndElement();
+ xml_writer_.EndElement();
+}
+
+void AutomatedUITest::LogSuccessResult() {
+ xml_writer_.StartElement("result");
+ xml_writer_.StartElement("success");
+ xml_writer_.EndElement();
+ xml_writer_.EndElement();
+}
+
+void AutomatedUITest::AddInfoAttribute(const std::string &info) {
+ xml_writer_.AddAttribute("info", info);
+}
+
+void AutomatedUITest::AddWarningAttribute(const std::string &warning) {
+ xml_writer_.AddAttribute("warning", warning);
+}
+
+void AutomatedUITest::AddErrorAttribute(const std::string &error) {
+ xml_writer_.AddAttribute("error", error);
+}
+
+std::wstring AutomatedUITest::GetMostRecentCrashDump() {
+ std::wstring crash_dump_path;
+ int file_count = 0;
+ FILETIME most_recent_file_time;
+ std::wstring most_recent_file_name;
+ WIN32_FIND_DATA find_file_data;
+
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
+ // All files in the given directory.
+ std::wstring filename_spec = crash_dump_path + L"\\*";
+ HANDLE find_handle = FindFirstFile(filename_spec.c_str(), &find_file_data);
+ if (find_handle != INVALID_HANDLE_VALUE) {
+ most_recent_file_time = find_file_data.ftCreationTime;
+ most_recent_file_name = find_file_data.cFileName;
+ do {
+ // Don't count current or parent directories.
+ if ((wcscmp(find_file_data.cFileName, L"..") == 0) ||
+ (wcscmp(find_file_data.cFileName, L".") == 0))
+ continue;
+
+ long result = CompareFileTime(&find_file_data.ftCreationTime,
+ &most_recent_file_time);
+
+ // File was created on or after the current most recent file.
+ if ((result == 1) || (result == 0)) {
+ most_recent_file_time = find_file_data.ftCreationTime;
+ most_recent_file_name = find_file_data.cFileName;
+ }
+ } while (FindNextFile(find_handle, &find_file_data));
+ FindClose(find_handle);
+ }
+
+ if (most_recent_file_name.empty()) {
+ return L"";
+ } else {
+ file_util::AppendToPath(&crash_dump_path, most_recent_file_name);
+ return crash_dump_path;
+ }
+}
+
+bool AutomatedUITest::DidCrash(bool update_total_crashes) {
+ std::wstring crash_dump_path;
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
+ // Each crash creates two dump files, so we divide by two here.
+ int actual_crashes = file_util::CountFilesCreatedAfter(
+ crash_dump_path, test_start_time_) / 2;
+
+ // If there are more crash dumps than the total dumps which we have recorded
+ // then this is a new crash.
+ if (actual_crashes > total_crashes_) {
+ if (update_total_crashes)
+ total_crashes_ = actual_crashes;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+TEST_F(AutomatedUITest, TheOneAndOnlyTest) {
+ CommandLine parsed_command_line;
+ if (parsed_command_line.HasSwitch(kReproSwitch))
+ RunReproduction();
+ else
+ RunAutomatedUITest();
+}
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.h b/chrome/test/automated_ui_tests/automated_ui_tests.h
new file mode 100644
index 0000000..96475ee
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.h
@@ -0,0 +1,443 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
+#define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
+
+// This takes an input file of commands, which consist of a series of
+// actions, and runs every command, reporting the status of each one
+// to an output file once all the commands have been run.
+//
+// The input file should be an XML file that has a root of any name followed
+// by a series of elements named "command" with child elements representing
+// the various actions, in order, to be performed during each command. A
+// command element can optionally include an "number" attribute to identify it.
+//
+// Example:
+// <CommandList>
+// <command number="1"><NewTab/><Navigate/><OpenWindow/><Navigate/><Back/>
+// </command>
+// <command number="2"><NewTab/><Navigate/><Navigate/><Back/><Forward/>
+// </command>
+// <command number="3"><CloseTab/><OpenWindow/><NewTab/><Navigate/><CloseTab/>
+// </command>
+// </CommandList>
+//
+// When the test is finished it will output results to the output file,
+// overwriting any previous version of this file. The output file is an
+// XML file which reports on each command, indicating whether it successfully
+// ran and if there were any errors.
+//
+// Example: (actual output will probably contain more actions per command):
+// <Report>
+// <Executed command_number="1"><NewTab/><Navigate/><result><success/>
+// </result> </Executed>
+// <Executed command_number="2"><Back/><Forward/><result><success/></result>
+// </Executed>
+// <Executed command_number="3"><CloseTab/><result>
+// <crash crash_dump="C:\a_crash.txt" command_completed="no"/></result>
+// </Executed>
+// </Report>
+//
+// A "crash" result will have two attributes, crash_dump, which points
+// to the full path of crash dump associated with this crash, and
+// command_completed which indicates whether or not the last
+// action recorded was the final action of the command.
+//
+// Furthermore, each individual action may contain additional attributes
+// to log non-fatal failures. If the attribute 'failed_to_complete="yes"'
+// is present, then the action did not complete. If that attribute is present,
+// an info, warning, or error attribute will also be present, and will contain
+// a string describing the error. The presence of info means the failure was
+// expected, probably due to a state making the action impossible to perform
+// like trying to close the last remaining window. Warnings usually mean the
+// action couldn't complete for an unknown and unexpected reason, but that the
+// test state is probably fine. Errors are like warnings, but they mean the test
+// state is probably incorrect, and more failures are likely to be caused by
+// the same problem.
+//
+// Example of some failed actions:
+// <CloseTab failed_to_complete="yes" info="would_have_exited_application"/>
+// <Reload failed_to_complete="yes" warning="failed_to_apply_accelerator"/>
+// <Star failed_to_complete="yes" error="browser_window_not_found"/>
+//
+//
+// Switches
+// --input : Specifies the input file, must be an absolute directory.
+// Default is "C:\automated_ui_tests.txt"
+//
+// --output : Specifies the output file, must be an absolute directory.
+// Default is "C:\automated_ui_tests_error_report.txt"
+//
+//
+// Test reproduction options:
+//
+// If you're trying to reproduce the results from crash reports use the
+// following switches
+//
+// --key : Specifies, via a comma delimited list, what actions to run. Examples:
+// --key=SetUp,ZoomPlus,Forward,History,Navigate,Back,TearDown
+// --key=SetUp,ZoomPlus
+// Note, the second key doesn't include a TearDown, that will
+// automatically be added if the result doesn't crash.
+//
+// --num-reproductions : Specifies the number of reproductions to run, the
+// default is 1. Suggested use: run without this flag
+// to see if we reproduce a crash, then run with the flag
+// if there isn't a crash, to see if it might be a rare
+// race condition that causes the crash.
+//
+//
+// Debugging options:
+//
+// --debug : Will append each action that is performed to the output file, as
+// soon as the action is performed. If the program finishes, this file
+// will be overwritten with the normal results. This flag is used to
+// help debug the tests if they are crashing before they get a chance
+// to write their results to file.
+
+#include "chrome/test/ui/ui_test.h"
+
+// Size of the array of possible actions to use when testing a dialog.
+const int kNumTestDialogActions = 4;
+
+class AutomatedUITest : public UITest {
+ protected:
+ AutomatedUITest();
+ ~AutomatedUITest();
+
+ // Runs a reproduction of one set of actions, reporting whether they crash
+ // or not.
+ void RunReproduction();
+
+ // Runs automated UI tests which are read from the input file.
+ // Reports crashes to the output file.
+ void RunAutomatedUITest();
+
+ // Attempts to perform an action based on the input string. See below for
+ // possible actions. Returns true if the action completes, false otherwise.
+ bool DoAction(const std::string &action);
+
+ // Actions ------------------------------------------------------------------
+
+ // Navigates the activate tab to about:blank.
+ // XML element: <Navigate/>
+ // Optional Attributes: url="|address|" will navigate to |address|
+ bool Navigate();
+
+ // Opens a new tab in the active window using an accelerator.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <NewTab/>
+ bool NewTab();
+
+ // Activates back button in active window.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <Back/>
+ bool BackButton();
+
+ // Activates forward button in active window.
+ // Returns true if call to activate the accelerator is successful.
+ // XML element: <Forward/>
+ bool ForwardButton();
+
+ // Uses accelerator to close the active tab if it isn't the only tab.
+ // Returns false if active tab is the only tab, true otherwise.
+ // XML element: <CloseTab/>
+ bool CloseActiveTab();
+
+ // Opens a new browser window by calling automation()->OpenNewBrowserWindow
+ // Then activates the tab opened in the new window.
+ // Returns true if window is successfully created.
+ // XML element: <OpenWindow/>
+ bool OpenAndActivateNewBrowserWindow();
+
+ // Reload the active tab. Returns false on failure.
+ // XML element: <Reload/>
+ bool ReloadPage();
+
+ // Stars the current page. This opens a dialog that may or may not be
+ // dismissed.
+ // XML element: <Star/>
+ bool StarPage();
+
+ // Activates "find in page" on the current page.
+ // XML element: <FindInPage/>
+ bool FindInPage();
+
+ // Activates the next tab on the active browser window.
+ // XML element: <SelectNextTab/>
+ bool SelectNextTab();
+
+ // Activates the previous tab on the active browser window.
+ // XML element: <SelectPrevTab/>
+ bool SelectPreviousTab();
+
+ // Increases the text size on the current active tab.
+ // XML element: <ZoomPlus/>
+ bool ZoomPlus();
+
+ // Decreases the text size on the current active tab.
+ // XML element: <ZoomMinus/>
+ bool ZoomMinus();
+
+ // Opens the History page in the current active browser window.
+ // XML element: <History/>
+ bool ShowHistory();
+
+ // Opens the Downloads page in the current active browser window.
+ // XML element: <Downloads/>
+ bool ShowDownloads();
+
+ // Opens the Import Settings dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ImportSettings/>
+ bool ImportSettings();
+
+ // Opens the View Passwords dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ViewPasswords/>
+ bool ViewPasswords();
+
+ // Opens the Clear Browser Data dialog, this dialog is modal so a majority of
+ // the test can't be completed until it is dismissed.
+ // XML element: <ClearBrowserData/>
+ bool ClearBrowserData();
+
+ // Opens the Task Manager dialog. While it isn't modal, it takes focus from
+ // the current browser window, so most of the test can't continue until is
+ // dismissed.
+ // XML element: <TaskManager/>
+ bool TaskManager();
+
+ // Opens and focuses an OffTheRecord browser window.
+ // XML element: <GoOffTheRecord/>
+ bool GoOffTheRecord();
+
+ // Simulates an escape key press on the active window.
+ // XML element: <PressEscapeKey/>
+ bool PressEscapeKey();
+
+ // Simulates a tab key press on the active window.
+ // XML element: <PressTabKey/>
+ bool PressTabKey();
+
+ // Simulates an enter key press on the active window.
+ // XML element: <PressEnterKey/>
+ bool PressEnterKey();
+
+ // Simulates a space bar press on the active window.
+ // XML element: <PressSpaceBar/>
+ bool PressSpaceBar();
+
+ // Simulates a page down key press on the active window.
+ // XML element: <PageDown/>
+ bool PageDown();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <PageUp/>
+ bool PageUp();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <UpArrow/>
+ bool UpArrow();
+
+ // Simulates a page up key press on the active window.
+ // XML element: <DownArrow/>
+ bool DownArrow();
+
+ // Test Dialog Actions ******************************************************
+ // These are a special set of actions that perform multiple actions on a
+ // specified dialog. They run kTestDialogActionsToRun actions randomly
+ // chosen from test_dialog_possible_actions_ after opening the dialog. They
+ // then always end with a PressEscapeKey action, to attempt to close the
+ // dialog.
+ //
+ // The randomly performed actions are logged as child elements of the
+ // TestDialog action. For example (for kTestDialogActionsToRun = 4):
+ // <TestEditKeywords> <PressTabKey/><PressEnterKey/><DownArrow/>
+ // <DownArrow/><PressEscapeKey/> </TestEditKeywords>
+
+ // Opens Edit Keywords dialog and runs random actions on it.
+ // XML element: <TestEditKeywords/>
+ bool TestEditKeywords();
+
+ // Opens Task Manager and runs random actions on it.
+ // This has the possibility of killing both the browser and renderer
+ // processes, which will cause non-fatal errors for the remaining actions
+ // in this command.
+ // XML element: <TestTaskManager/>
+ bool TestTaskManager();
+
+ // Opens View Passwords dialog and runs random actions on it.
+ // XML element: <TestViewPasswords/>
+ bool TestViewPasswords();
+
+ // Opens Clear Browser Data dialog and runs random actions on it.
+ // XML element: <TestClearBrowserData/>
+ bool TestClearBrowserData();
+
+ // Opens Import Settings dialog and runs random actions on it.
+ // XML element: <TestImportSettings/>
+ bool TestImportSettings();
+
+ // End Test Dialog Actions **************************************************
+
+ // Runs a limited set of actions designed to test dialogs. Will run
+ // |num_actions| from the set defined in test_dialog_possible_actions_.
+ bool TestDialog(int num_actions);
+
+ // Navigates to about:crash.
+ // XML element: <Crash/>
+ bool ForceCrash();
+
+ // Drags the active tab. If |drag_out| is true, |drag_right| is ignored and
+ // the tab is dragged vertically to remove it from the tabstrip. Otherwise,
+ // If |drag_right| is true, if there is a tab to the right of the active tab,
+ // the active tab is dragged to that tabs position. If |drag_right| is false,
+ // if there is a tab to the left of the active tab, the active tab is dragged
+ // to that tabs position. Returns false if the tab isn't dragged, or if an
+ // attempt to drag out doesn't create a new window (likely because it was
+ // dragged in to another window).
+ // XML element (multiple elements use this):
+ // <DragTabRight/> - Calls DragActiveTab(true, false) (attempt to drag right)
+ // <DragTabLeft/> - Calls DragActiveTab(false, false) (attempt to drag left)
+ // <DragTabOut/> - Calls DragActiveTab(false, true) (attempt to drag tab out)
+ bool DragActiveTab(bool drag_right, bool drag_out);
+
+ // Utility functions --------------------------------------------------------
+
+ // Returns the WindowProxy associated with the given BrowserProxy
+ // (transferring ownership of the pointer to the caller) and brings that
+ // window to the top.
+ WindowProxy* GetAndActivateWindowForBrowser(BrowserProxy* browser);
+
+ // Applies the accelerator with the given ID to the current active window.
+ // Returns true if the call is successful.
+ // Returns false if the active window is not a browser window or if the
+ // message to apply the accelerator fails.
+ bool ApplyAccelerator(int id);
+
+ // Calls SimulateOSKeyPress on the active window. Simulates a key press at
+ // the OS level. |key| is the key pressed and |flags| specifies which
+ // modifiers keys are also pressed (as defined inchrome/views/event.h).
+ bool SimulateKeyPressInActiveWindow(wchar_t key, int flags);
+
+ // Opens init file, reads it into the reader, and closes the file.
+ // Returns false if there are any errors.
+ bool InitXMLReader();
+
+ // Closes the xml_writer and outputs the contents of its buffer to
+ // the output file.
+ bool WriteReportToFile();
+
+ // Appends the provided string to the output file.
+ void AppendToOutputFile(const std::string &append_string);
+
+ // Logs a crash to the xml_writer in the form of:
+ // <result><crash crash_dump="|crash_dump|" command_completed="yes/no"/>
+ // </result>
+ // crash_dump - Location of crash dump if applicable.
+ // command_completed - True if all actions in the command were completed
+ // before the crash occured.
+ void LogCrashResult(const std::string &crash_dump, bool command_completed);
+
+ // Logs a successful command to the xml_writer in the form of:
+ // <result><success/><result/>
+ void LogSuccessResult();
+
+ // Adds the attribute "reason=|reason|" to the current element.
+ // Used to log the reason for a given failure while performing an action.
+ void LogActionFailureReason(const std::string &reason);
+
+ // Adds the attribute 'info="|info|"' to the current element. Used when an
+ // action could not complete for a non-serious issue. Usually because the
+ // state of the test wouldn't allow for a particular action.
+ void AddInfoAttribute(const std::string &info);
+
+ // Adds the attribute "warning=|warning|" to the current element. Used when
+ // an action could not complete because of a potentially troublesome issue.
+ void AddWarningAttribute(const std::string &warning);
+
+ // Adds the attribute "error=|error|" to the current element. Used when an
+ // action could not complete due to an unexpected problem which might
+ // invalidate the results of the entire command (not just the action).
+ // This is usually used when the testing environment isn't acting as we'd
+ // expect. For example, no chrome windows are focused, or key presses aren't
+ // being registered.
+ void AddErrorAttribute(const std::string &error);
+
+ // Returns the full path of the crash dump. This is likely to be the
+ // .txt file, not the actual crash dump. Although they do share
+ // a common name.
+ std::wstring GetMostRecentCrashDump();
+
+ // Returns true if the test has produced any new crash logs.
+ // A "new" crash log is one that was produced since DidCrash was last called
+ // with |update_total_crashes| set to true.
+ bool DidCrash(bool update_total_crashes);
+
+ // Overridden so that UI Test doesn't set up when the tests start.
+ // We use DoAction("SetUp") to set up, because it logs it and makes
+ // it easier to check for crashes when we start the browser.
+ virtual void SetUp() {}
+
+ // Overridden so that UI Test doesn't close the browser (which is already
+ // closed) at the end of the test.
+ // We use DoAction("TearDown") to tear down, because it logs it and makes
+ // it easier to check for crashes when we close the browser.
+ virtual void TearDown() {}
+
+ private:
+ // Parses the init file.
+ XmlReader init_reader_;
+
+ // Builds the output file.
+ XmlWriter xml_writer_;
+
+ // Time the test was started. Used to find crash dumps.
+ FILETIME test_start_time_;
+
+ // Number of times the browser has crashed during this run.
+ // Used to check for new crashes.
+ int total_crashes_;
+
+ // Used to init the init_reader_. It must exist as long as the reader does.
+ std::string xml_init_file_;
+
+ // If true, appends the commands to the output file as they are executed.
+ // Used for debugging when automated_ui_tests.cc crashes before it outputs
+ // results.
+ bool debug_logging_enabled_;
+
+ static std::string test_dialog_possible_actions_[kNumTestDialogActions];
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutomatedUITest);
+};
+
+#endif // #define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__
diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.vcproj b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj
new file mode 100644
index 0000000..71914d1
--- /dev/null
+++ b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="automated_ui_tests"
+ ProjectGUID="{D2250C20-3A94-4FB9-AF73-11BC5B73884B}"
+ RootNamespace="page_cycler_tests"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Common"
+ >
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\tools\build\win\precompiled_wtl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\run_all_unittests.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\test_file_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\testing_browser_process.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ui\ui_test_suite.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MemoryUsage"
+ >
+ <File
+ RelativePath="..\perf\mem_usage.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\perf\mem_usage.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="AutomatedUITest"
+ >
+ <File
+ RelativePath=".\automated_ui_tests.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\automated_ui_tests.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>