summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xchrome/chrome.gyp1
-rw-r--r--chrome/test/automation/automation_proxy.h2
-rw-r--r--chrome/test/automation/automation_proxy_uitest.cc285
-rw-r--r--chrome/test/automation/automation_proxy_uitest.h11
-rw-r--r--chrome/test/ui_test_utils.cc23
-rw-r--r--chrome/test/ui_test_utils.h29
6 files changed, 252 insertions, 99 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index de12db9..e3b1e4b 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -4188,6 +4188,7 @@
'../net/net.gyp:net',
'../build/temp_gyp/googleurl.gyp:googleurl',
'../skia/skia.gyp:skia',
+ '../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../third_party/icu/icu.gyp:icui18n',
'../third_party/icu/icu.gyp:icuuc',
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
index aa22ee9..5c2d8ab 100644
--- a/chrome/test/automation/automation_proxy.h
+++ b/chrome/test/automation/automation_proxy.h
@@ -214,7 +214,7 @@ class AutomationProxy : public IPC::Channel::Listener,
// Wrapper over AutomationHandleTracker::InvalidateHandle. Receives the
// message from AutomationProxy, unpacks the messages and routes that call to
// the tracker.
- void InvalidateHandle(const IPC::Message& message);
+ virtual void InvalidateHandle(const IPC::Message& message);
// Creates a tab that can hosted in an external process. The function
// returns a TabProxy representing the tab as well as a window handle
diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc
index 6187dfb..f9daa7c7 100644
--- a/chrome/test/automation/automation_proxy_uitest.cc
+++ b/chrome/test/automation/automation_proxy_uitest.cc
@@ -8,6 +8,7 @@
#include "app/l10n_util.h"
#include "app/message_box_flags.h"
#include "base/command_line.h"
+#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/gfx/rect.h"
#include "base/string_util.h"
@@ -24,11 +25,18 @@
#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_test_utils.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/url_request/url_request_unittest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
+#include "testing/gmock_mutant.h"
#include "views/event.h"
+using ui_test_utils::TimedMessageLoopRunner;
+using testing::CreateFunctor;
+
#if defined(OS_MACOSX)
#define MAYBE_WindowGetViewBounds DISABLED_WindowGetViewBounds
#else
@@ -846,101 +854,181 @@ void AutomationProxyForExternalTab::OnForwardMessageToExternalHost(
QuitLoop();
}
-GURL simple_data_url = GURL(std::string(
+const char simple_data_url[] =
"data:text/html,<html><head><title>External tab test</title></head>"
"<body>A simple page for testing a floating/invisible tab<br></div>"
- "</body></html>"));
-
-// Create with specifying a url
-TEST_F(ExternalTabTestType, CreateExternalTab1) {
- AutomationProxyForExternalTab* proxy =
- static_cast<AutomationProxyForExternalTab*>(automation());
- HWND external_tab_container = NULL;
- HWND tab_wnd = NULL;
- scoped_refptr<TabProxy> tab(proxy->CreateTabWithHostWindow(false,
- simple_data_url, &external_tab_container, &tab_wnd));
+ "</body></html>";
+
+// We have to derive from AutomationProxy in order to hook up
+// OnMessageReceived callbacks.
+class ExternalTabUITestMockClient : public AutomationProxy {
+ public:
+ explicit ExternalTabUITestMockClient(int execution_timeout)
+ : AutomationProxy(execution_timeout),
+ host_window_(NULL) {
+ }
- EXPECT_TRUE(tab->is_valid());
- if (tab != NULL) {
- EXPECT_TRUE(proxy->WaitForNavigation(action_max_timeout_ms()));
+ MOCK_METHOD2(OnDidNavigate, void(int tab_handle,
+ const IPC::NavigationInfo& nav_info));
+ MOCK_METHOD4(OnForwardMessageToExternalHost, void(int handle,
+ const std::string& message, const std::string& origin,
+ const std::string& target));
+ MOCK_METHOD1(HandleClosed, void(int handle));
- proxy->DestroyHostWindow();
- proxy->WaitForTabCleanup(tab, action_max_timeout_ms());
+ scoped_refptr<TabProxy> CreateTabWithHostWindow(
+ bool is_incognito, const GURL& initial_url);
+ void DestroyHostWindow();
- EXPECT_FALSE(tab->is_valid());
- EXPECT_EQ(FALSE, ::IsWindow(external_tab_container));
- EXPECT_EQ(FALSE, ::IsWindow(tab_wnd));
+ protected:
+ HWND host_window_;
+
+ // Simple dispatcher to above OnXXX methods.
+ virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void InvalidateHandle(const IPC::Message& message) {
+ void* iter = NULL;
+ int handle;
+ ASSERT_TRUE(message.ReadInt(&iter, &handle));
+
+ // Call base class
+ AutomationProxy::InvalidateHandle(message);
+ HandleClosed(handle);
}
+};
+
+void ExternalTabUITestMockClient::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(ExternalTabUITestMockClient, msg)
+ IPC_MESSAGE_HANDLER(AutomationMsg_DidNavigate, OnDidNavigate)
+ IPC_MESSAGE_HANDLER(AutomationMsg_ForwardMessageToExternalHost,
+ OnForwardMessageToExternalHost)
+ IPC_END_MESSAGE_MAP()
}
-// Create with empty url and then navigate
-TEST_F(ExternalTabTestType, CreateExternalTab2) {
- AutomationProxyForExternalTab* proxy =
- static_cast<AutomationProxyForExternalTab*>(automation());
- HWND external_tab_container = NULL;
+scoped_refptr<TabProxy> ExternalTabUITestMockClient::CreateTabWithHostWindow(
+ bool is_incognito, const GURL& initial_url) {
+
+ DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
+ host_window_ = CreateWindowW(L"Static", NULL, style,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL);
+
+ EXPECT_THAT(host_window_, testing::Truly(::IsWindow));
+
+ RECT client_area = {0};
+ ::GetClientRect(host_window_, &client_area);
+
+ const IPC::ExternalTabSettings settings = {
+ host_window_,
+ gfx::Rect(client_area),
+ WS_CHILD | WS_VISIBLE,
+ is_incognito,
+ false,
+ false,
+ initial_url
+ };
+
+ HWND container_wnd = NULL;
HWND tab_wnd = NULL;
- scoped_refptr<TabProxy> tab(proxy->CreateTabWithHostWindow(false,
- GURL(), &external_tab_container, &tab_wnd));
+ scoped_refptr<TabProxy> tab(CreateExternalTab(settings, &container_wnd,
+ &tab_wnd));
- // Enter a message loop to allow the tab to be created
- proxy->WaitForNavigation(2000);
- EXPECT_TRUE(tab->is_valid());
+ EXPECT_TRUE(tab != NULL);
+ EXPECT_NE(FALSE, ::IsWindow(container_wnd));
+ EXPECT_NE(FALSE, ::IsWindow(tab_wnd));
+ return tab;
+}
- if (tab != NULL) {
- // Wait for navigation
- tab->NavigateInExternalTab(simple_data_url, GURL());
- EXPECT_TRUE(proxy->WaitForNavigation(action_max_timeout_ms()));
+void ExternalTabUITestMockClient::DestroyHostWindow() {
+ ::DestroyWindow(host_window_);
+}
- // Now destroy the external tab
- proxy->DestroyHostWindow();
- proxy->WaitForTabCleanup(tab, action_max_timeout_ms());
+// Handy macro
+#define QUIT_LOOP(loop) testing::InvokeWithoutArgs(\
+ CreateFunctor(loop, &TimedMessageLoopRunner::Quit))
+#define QUIT_LOOP_SOON(loop, ms) testing::InvokeWithoutArgs(\
+ CreateFunctor(loop, &TimedMessageLoopRunner::QuitAfter, ms))
- EXPECT_FALSE(tab->is_valid());
- EXPECT_EQ(FALSE, ::IsWindow(external_tab_container));
- EXPECT_EQ(FALSE, ::IsWindow(tab_wnd));
- }
+template <typename T> T** ReceivePointer(scoped_ptr<T>& p) { // NOLINT
+ return reinterpret_cast<T**>(&p);
}
-// Freezes randomly causing the entire ui test to hang
-// http://code.google.com/p/chromium/issues/detail?id=24664
-TEST_F(ExternalTabTestType, DISABLED_IncognitoMode) {
- AutomationProxyForExternalTab* proxy =
- static_cast<AutomationProxyForExternalTab*>(automation());
- HWND external_tab_container = NULL;
- HWND tab_wnd = NULL;
+template <typename T> T** ReceivePointer(scoped_refptr<T>& p) { // NOLINT
+ return reinterpret_cast<T**>(&p);
+}
- // Create incognito tab
- GURL url("http://anatomyofmelancholy.net");
- scoped_refptr<TabProxy> tab(proxy->CreateTabWithHostWindow(true, url,
- &external_tab_container, &tab_wnd));
- EXPECT_TRUE(proxy->WaitForNavigation(action_max_timeout_ms()));
+AutomationProxy* ExternalTabUITest::CreateAutomationProxy(int exec_timeout) {
+ mock_ = new ExternalTabUITestMockClient(exec_timeout);
+ return mock_;
+}
+// Create with specifying a url
+TEST_F(ExternalTabUITest, CreateExternalTab1) {
+ scoped_refptr<TabProxy> tab;
+ TimedMessageLoopRunner loop(MessageLoop::current());
+ ASSERT_THAT(mock_, testing::NotNull());
+
+ EXPECT_CALL(*mock_, OnDidNavigate(testing::_, testing::_))
+ .Times(1)
+ .WillOnce(testing::InvokeWithoutArgs(mock_,
+ &ExternalTabUITestMockClient::DestroyHostWindow));
+
+ EXPECT_CALL(*mock_, HandleClosed(1))
+ .Times(1)
+ .WillOnce(QUIT_LOOP(&loop));
+
+ tab = mock_->CreateTabWithHostWindow(false, GURL(simple_data_url));
+ loop.RunFor(2 * action_max_timeout_ms());
+}
+
+// Create with empty url and then navigate
+TEST_F(ExternalTabUITest, CreateExternalTab2) {
+ scoped_refptr<TabProxy> tab;
+ TimedMessageLoopRunner loop(MessageLoop::current());
+ ASSERT_THAT(mock_, testing::NotNull());
+
+ EXPECT_CALL(*mock_, OnDidNavigate(testing::_, testing::_))
+ .Times(1)
+ .WillOnce(testing::InvokeWithoutArgs(mock_,
+ &ExternalTabUITestMockClient::DestroyHostWindow));
+
+ EXPECT_CALL(*mock_, HandleClosed(1))
+ .Times(1)
+ .WillOnce(QUIT_LOOP(&loop));
+
+ tab = mock_->CreateTabWithHostWindow(false, GURL());
+ tab->NavigateInExternalTab(GURL(simple_data_url), GURL());
+ loop.RunFor(2 * action_max_timeout_ms());
+}
+
+TEST_F(ExternalTabUITest, IncognitoMode) {
+ scoped_refptr<TabProxy> tab;
+ TimedMessageLoopRunner loop(MessageLoop::current());
+ ASSERT_THAT(mock_, testing::NotNull());
+
+
+ GURL url("http://anatomyofmelancholy.net");
+ tab = mock_->CreateTabWithHostWindow(true, GURL());
std::string value_result;
EXPECT_TRUE(tab->SetCookie(url, "robert=burton; "
- "expires=Thu, 13 Oct 2011 05:04:03 UTC;"));
+ "expires=Thu, 13 Oct 2011 05:04:03 UTC;"));
EXPECT_TRUE(tab->GetCookieByName(url, "robert", &value_result));
EXPECT_EQ("burton", value_result);
- proxy->DestroyHostWindow();
+ mock_->DestroyHostWindow();
CloseBrowserAndServer();
tab = NULL;
value_result.clear();
clear_profile_ = false;
- external_tab_container = NULL;
- tab_wnd = NULL;
LaunchBrowserAndServer();
- tab = proxy->CreateTabWithHostWindow(false, url, &external_tab_container,
- &tab_wnd);
+ tab = mock_->CreateTabWithHostWindow(false, GURL());
EXPECT_TRUE(tab->GetCookieByName(url, "robert", &value_result));
EXPECT_EQ("", value_result);
}
-TEST_F(ExternalTabTestType, DISABLED_ExternalTabPostMessage) {
- AutomationProxyForExternalTab* proxy =
- static_cast<AutomationProxyForExternalTab*>(automation());
- HWND external_tab_container = NULL;
- HWND tab_wnd = NULL;
+TEST_F(ExternalTabUITest, TabPostMessage) {
+ scoped_refptr<TabProxy> tab;
+ TimedMessageLoopRunner loop(MessageLoop::current());
+ ASSERT_THAT(mock_, testing::NotNull());
+
std::string content =
"data:text/html,<html><head><script>"
"function onload() {"
@@ -952,56 +1040,57 @@ TEST_F(ExternalTabTestType, DISABLED_ExternalTabPostMessage) {
"</script></head>"
"<body onload='onload()'>external tab test<br></div>"
"</body></html>";
- scoped_refptr<TabProxy> tab(proxy->CreateTabWithHostWindow(false,
- GURL(content), &external_tab_container, &tab_wnd));
- if (tab != NULL) {
- // Wait for navigation
- EXPECT_TRUE(proxy->WaitForNavigation(action_max_timeout_ms()));
+ EXPECT_CALL(*mock_, OnDidNavigate(testing::_, testing::_))
+ .Times(1)
+ .WillOnce(testing::InvokeWithoutArgs(CreateFunctor(
+ ReceivePointer(tab),
+ &TabProxy::HandleMessageFromExternalHost,
+ std::string("Hello from gtest"),
+ std::string("null"), std::string("*"))));
- tab->HandleMessageFromExternalHost("Hello from gtest", "null", "*");
- EXPECT_TRUE(proxy->WaitForMessage(5000));
+ EXPECT_CALL(*mock_, OnForwardMessageToExternalHost(testing::_,
+ testing::StrEq("Hello from gtest"), testing::_, testing::_))
+ .Times(1)
+ .WillOnce(QUIT_LOOP_SOON(&loop, 50));
- EXPECT_NE(0, proxy->messages_received());
- if (proxy->messages_received()) {
- EXPECT_EQ("Hello from gtest", proxy->message());
- }
- }
+ tab = mock_->CreateTabWithHostWindow(false, GURL(content));
+ loop.RunFor(2 * action_max_timeout_ms());
}
-TEST_F(ExternalTabTestType, DISABLED_ExternalTabPostMessageTarget) {
+TEST_F(ExternalTabUITest, PostMessageTarget) {
const wchar_t kDocRoot[] = L"chrome/test/data/external_tab";
scoped_refptr<HTTPTestServer> server(
HTTPTestServer::CreateServer(kDocRoot, NULL));
+ ASSERT_THAT(server.get(), testing::NotNull());
- const char kTestUrl[] = "http://localhost:1337/files/post_message.html";
+ scoped_refptr<TabProxy> tab;
+ TimedMessageLoopRunner loop(MessageLoop::current());
+ ASSERT_THAT(mock_, testing::NotNull());
- AutomationProxyForExternalTab* proxy =
- static_cast<AutomationProxyForExternalTab*>(automation());
- HWND external_tab_container = NULL;
- HWND tab_wnd = NULL;
- scoped_refptr<TabProxy> tab(proxy->CreateTabWithHostWindow(false,
- GURL(kTestUrl), &external_tab_container, &tab_wnd));
+ std::string kTestMessage("Hello from gtest");
+ std::string kTestOrigin("http://www.external.tab");
- if (tab != NULL) {
- EXPECT_TRUE(proxy->WaitForNavigation(action_max_timeout_ms()));
+ EXPECT_CALL(*mock_, OnDidNavigate(1, testing::_))
+ .Times(1)
+ .WillOnce(testing::InvokeWithoutArgs(CreateFunctor(
+ ReceivePointer(tab),
+ &TabProxy::HandleMessageFromExternalHost,
+ kTestMessage, kTestOrigin, std::string("http://localhost:1337/"))));
- // Post a message to the page, specifying a target.
- // If the page receives it, it will post the same message right back to us.
- const char kTestMessage[] = "Hello from gtest";
- const char kTestOrigin[] = "http://www.external.tab";
- tab->HandleMessageFromExternalHost(kTestMessage, kTestOrigin,
- "http://localhost:1337/");
+ EXPECT_CALL(*mock_, OnForwardMessageToExternalHost(1,
+ testing::StrEq(kTestMessage),
+ testing::_,
+ testing::StrEq(GURL(kTestOrigin).GetOrigin().spec())))
+ .Times(1)
+ .WillOnce(QUIT_LOOP_SOON(&loop, 50));
- EXPECT_TRUE(proxy->WaitForMessage(5000));
- EXPECT_NE(0, proxy->messages_received());
- if (proxy->messages_received()) {
- EXPECT_EQ(kTestMessage, proxy->message());
- EXPECT_EQ(GURL(kTestOrigin).GetOrigin(), GURL(proxy->target()));
- }
- }
+ tab = mock_->CreateTabWithHostWindow(false,
+ GURL("http://localhost:1337/files/post_message.html"));
+
+ loop.RunFor(2 * action_max_timeout_ms());
}
#endif // defined(OS_WIN)
diff --git a/chrome/test/automation/automation_proxy_uitest.h b/chrome/test/automation/automation_proxy_uitest.h
index 782d7e3..3affb89 100644
--- a/chrome/test/automation/automation_proxy_uitest.h
+++ b/chrome/test/automation/automation_proxy_uitest.h
@@ -16,6 +16,17 @@
#include "googleurl/src/gurl.h"
class TabProxy;
+class ExternalTabUITestMockClient;
+
+class ExternalTabUITest : public UITest {
+ public:
+ // Override UITest's CreateAutomationProxy to provide the unit test
+ // with our special implementation of AutomationProxy.
+ // This function is called from within UITest::LaunchBrowserAndServer.
+ virtual AutomationProxy* CreateAutomationProxy(int execution_timeout);
+ protected:
+ ExternalTabUITestMockClient* mock_;
+};
// Base class for automation proxy testing.
class AutomationProxyVisibleTest : public UITest {
diff --git a/chrome/test/ui_test_utils.cc b/chrome/test/ui_test_utils.cc
index c9348b3..59663b2 100644
--- a/chrome/test/ui_test_utils.cc
+++ b/chrome/test/ui_test_utils.cc
@@ -503,4 +503,27 @@ void RegisterAndWait(NotificationType::Type type,
RunMessageLoop();
}
+TimedMessageLoopRunner::TimedMessageLoopRunner()
+ : loop_(new MessageLoopForUI()),
+ owned_(true) {
+}
+
+TimedMessageLoopRunner::~TimedMessageLoopRunner() {
+ if (owned_)
+ delete loop_;
+}
+
+void TimedMessageLoopRunner::RunFor(int ms) {
+ QuitAfter(ms);
+ loop_->Run();
+}
+
+void TimedMessageLoopRunner::Quit() {
+ loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+}
+
+void TimedMessageLoopRunner::QuitAfter(int ms) {
+ loop_->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, ms);
+}
+
} // namespace ui_test_utils
diff --git a/chrome/test/ui_test_utils.h b/chrome/test/ui_test_utils.h
index ae0d44e..c7cab8c 100644
--- a/chrome/test/ui_test_utils.h
+++ b/chrome/test/ui_test_utils.h
@@ -17,6 +17,7 @@ class AppModalDialog;
class Browser;
class DownloadManager;
class GURL;
+class MessageLoop;
class NavigationController;
class RenderViewHost;
class TabContents;
@@ -135,6 +136,34 @@ void RegisterAndWait(NotificationType::Type type,
NotificationObserver* observer,
int64 timeout_ms);
+// Run a message loop only for the specified amount of time.
+class TimedMessageLoopRunner {
+ public:
+ // Create new MessageLoopForUI and attach to it.
+ TimedMessageLoopRunner();
+
+ // Attach to an existing message loop.
+ explicit TimedMessageLoopRunner(MessageLoop* loop)
+ : loop_(loop), owned_(false) {}
+
+ ~TimedMessageLoopRunner();
+
+ // Run the message loop for ms milliseconds.
+ void RunFor(int ms);
+
+ // Post Quit task to the message loop.
+ void Quit();
+
+ // Post delayed Quit task to the message loop.
+ void QuitAfter(int ms);
+
+ private:
+ MessageLoop* loop_;
+ bool owned_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimedMessageLoopRunner);
+};
+
} // namespace ui_test_utils
#endif // CHROME_TEST_UI_TEST_UTILS_H_