summaryrefslogtreecommitdiffstats
path: root/remoting/test
diff options
context:
space:
mode:
authorweitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-18 00:00:10 +0000
committerweitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-18 00:00:10 +0000
commit520d6b417cf4ac872850098889d3b7bf5e16fc97 (patch)
tree52ba10ba159030ce12db00857e297ecd708a22c5 /remoting/test
parent2521cf2c4941e6933c2c494ab5441e95648217c5 (diff)
downloadchromium_src-520d6b417cf4ac872850098889d3b7bf5e16fc97.zip
chromium_src-520d6b417cf4ac872850098889d3b7bf5e16fc97.tar.gz
chromium_src-520d6b417cf4ac872850098889d3b7bf5e16fc97.tar.bz2
Refactoring the synchronization code in the chromoting browser_tests
BUG=134210 Details: 1. Implement Wait* routines using nested message loop. 2. Replace all the busy wait code with the Wait* routines. 3. Refactor NavigateToURLAndWaitForPageLoad: Use a callback to check the currently loaded page in WindowsNotificationObserver. 4. Some other minor refactorings. 5. Move Me2MeBrowserTest in a separate test class. The class is empty right now but me2me specific test routines will be added to it in subsequent CLs. Review URL: https://chromiumcodereview.appspot.com/23934004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/test')
-rw-r--r--remoting/test/me2me_browsertest.cc7
-rw-r--r--remoting/test/remote_desktop_browsertest.cc125
-rw-r--r--remoting/test/remote_desktop_browsertest.h45
-rw-r--r--remoting/test/waiter.cc81
-rw-r--r--remoting/test/waiter.h74
5 files changed, 262 insertions, 70 deletions
diff --git a/remoting/test/me2me_browsertest.cc b/remoting/test/me2me_browsertest.cc
index 115bd93..bd1f7a2 100644
--- a/remoting/test/me2me_browsertest.cc
+++ b/remoting/test/me2me_browsertest.cc
@@ -6,7 +6,10 @@
namespace remoting {
-IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest,
+class Me2MeBrowserTest : public RemoteDesktopBrowserTest {
+};
+
+IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest,
MANUAL_Me2Me_Connect_Localhost) {
VerifyInternetAccess();
@@ -21,8 +24,6 @@ IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest,
ConnectToLocalHost();
- EnterPin(me2me_pin());
-
Cleanup();
}
diff --git a/remoting/test/remote_desktop_browsertest.cc b/remoting/test/remote_desktop_browsertest.cc
index d389788..d7303e4 100644
--- a/remoting/test/remote_desktop_browsertest.cc
+++ b/remoting/test/remote_desktop_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/test/test_utils.h"
+#include "remoting/test/waiter.h"
using extensions::Extension;
@@ -40,7 +41,7 @@ void RemoteDesktopBrowserTest::TearDownInProcessBrowserTestFixture() {
void RemoteDesktopBrowserTest::VerifyInternetAccess() {
GURL google_url("http://www.google.com");
- NavigateToURLAndWait(google_url);
+ NavigateToURLAndWaitForPageLoad(google_url);
EXPECT_EQ(GetCurrentURL().host(), "www.google.com");
}
@@ -111,7 +112,7 @@ void RemoteDesktopBrowserTest::LaunchChromotingApp() {
ASSERT_FALSE(ChromotingID().empty());
const GURL chromoting_main = Chromoting_Main_URL();
- NavigateToURLAndWait(chromoting_main);
+ NavigateToURLAndWaitForPageLoad(chromoting_main);
EXPECT_EQ(GetCurrentURL(), chromoting_main);
}
@@ -126,7 +127,8 @@ void RemoteDesktopBrowserTest::Authorize() {
ASSERT_FALSE(ExecuteScriptAndExtractBool(
"remoting.OAuth2.prototype.isAuthenticated()"));
- ExecuteScriptAndWait("remoting.OAuth2.prototype.doAuthRedirect();");
+ ExecuteScriptAndWaitForAnyPageLoad(
+ "remoting.OAuth2.prototype.doAuthRedirect();");
// Verify the active tab is at the "Google Accounts" login page.
EXPECT_EQ(GetCurrentURL().host(), "accounts.google.com");
@@ -144,14 +146,14 @@ void RemoteDesktopBrowserTest::Authenticate() {
ASSERT_TRUE(HtmlElementExists("Passwd"));
// Now log in using the username and password passed in from the command line.
- ExecuteScriptAndWait(
+ ExecuteScriptAndWaitForAnyPageLoad(
"document.getElementById(\"Email\").value = \"" + username_ + "\";" +
"document.getElementById(\"Passwd\").value = \"" + password_ +"\";" +
"document.forms[\"gaia_loginform\"].submit();");
EXPECT_EQ(GetCurrentURL().host(), "accounts.google.com");
- // TODO: Is there a better way to verify we are on the
+ // TODO(weitaosu): Is there a better way to verify we are on the
// "Request for Permission" page?
EXPECT_TRUE(HtmlElementExists("submit_approve_access"));
}
@@ -168,7 +170,7 @@ void RemoteDesktopBrowserTest::Approve() {
ASSERT_TRUE(HtmlElementExists("submit_approve_access"));
const GURL chromoting_main = Chromoting_Main_URL();
- ExecuteScriptAndWaitUntil(
+ ExecuteScriptAndWaitForPageLoad(
"lso.approveButtonAction();"
"document.forms[\"connect-approve\"].submit();",
chromoting_main);
@@ -198,6 +200,19 @@ void RemoteDesktopBrowserTest::StartMe2Me() {
EXPECT_TRUE(HtmlElementVisible("me2me-content"));
EXPECT_FALSE(HtmlElementVisible("me2me-first-run"));
+
+ // Wait until localHost is initialized. This can take a while.
+ ConditionalTimeoutWaiter waiter(
+ base::TimeDelta::FromSeconds(5),
+ base::TimeDelta::FromSeconds(1),
+ base::Bind(&RemoteDesktopBrowserTest::IsLocalHostReady, this));
+ EXPECT_TRUE(waiter.Wait());
+
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ "remoting.hostList.localHost_.hostName && "
+ "remoting.hostList.localHost_.hostId && "
+ "remoting.hostList.localHost_.status && "
+ "remoting.hostList.localHost_.status == 'ONLINE'"));
}
void RemoteDesktopBrowserTest::SimulateKeyPressWithCode(
@@ -224,7 +239,7 @@ void RemoteDesktopBrowserTest::SimulateKeyPressWithCode(
}
void RemoteDesktopBrowserTest::Install() {
- // TODO: add support for installing unpacked extension (the v2 app needs it).
+ // TODO(weitaosu): add support for unpacked extension (the v2 app needs it).
if (!NoInstall()) {
VerifyChromotingLoaded(false);
InstallChromotingApp();
@@ -234,7 +249,8 @@ void RemoteDesktopBrowserTest::Install() {
}
void RemoteDesktopBrowserTest::Cleanup() {
- // TODO: Remove this hack by blocking on the appropriate notification.
+ // TODO(weitaosu): Remove this hack by blocking on the appropriate
+ // notification.
// The browser may still be loading images embedded in the webapp. If we
// uinstall it now those load will fail. Navigating away to avoid the load
// failures.
@@ -253,21 +269,20 @@ void RemoteDesktopBrowserTest::Auth() {
}
void RemoteDesktopBrowserTest::ConnectToLocalHost() {
- // Wait until remoting.hostList.localHost_ is initialized.
- // This can take a while.
- // TODO: Instead of polling, can we register a callback to
- // remoting.hostList.setLocalHost_?
- while (ExecuteScriptAndExtractBool(
- "remoting.hostList.localHost_ == null")) {
- }
-
+ // Verify that the local host is online.
ASSERT_TRUE(ExecuteScriptAndExtractBool(
"remoting.hostList.localHost_.hostName && "
"remoting.hostList.localHost_.hostId && "
"remoting.hostList.localHost_.status && "
"remoting.hostList.localHost_.status == 'ONLINE'"));
+ // Connect.
ClickOnControl("this-host-connect");
+
+ // Enter the pin # passed in from the command line.
+ EnterPin(me2me_pin());
+
+ WaitForConnection();
}
void RemoteDesktopBrowserTest::EnableDNSLookupForThisTest(
@@ -329,7 +344,8 @@ void RemoteDesktopBrowserTest::ExecuteScript(const std::string& script) {
browser()->tab_strip_model()->GetActiveWebContents(), script));
}
-void RemoteDesktopBrowserTest::ExecuteScriptAndWait(const std::string& script) {
+void RemoteDesktopBrowserTest::ExecuteScriptAndWaitForAnyPageLoad(
+ const std::string& script) {
content::WindowedNotificationObserver observer(
content::NOTIFICATION_LOAD_STOP,
content::Source<content::NavigationController>(
@@ -341,27 +357,16 @@ void RemoteDesktopBrowserTest::ExecuteScriptAndWait(const std::string& script) {
observer.Wait();
}
-void RemoteDesktopBrowserTest::ExecuteScriptAndWaitUntil(
+void RemoteDesktopBrowserTest::ExecuteScriptAndWaitForPageLoad(
const std::string& script,
const GURL& target) {
content::WindowedNotificationObserver observer(
content::NOTIFICATION_LOAD_STOP,
- content::Source<content::NavigationController>(
- &browser()->tab_strip_model()->GetActiveWebContents()->
- GetController()));
+ base::Bind(&RemoteDesktopBrowserTest::IsURLLoaded, this, target));
ExecuteScript(script);
observer.Wait();
-
- // TODO: is there a better way to wait for all the redirections to complete?
- while (GetCurrentURL() != target) {
- content::WindowedNotificationObserver(
- content::NOTIFICATION_LOAD_STOP,
- content::Source<content::NavigationController>(
- &browser()->tab_strip_model()->GetActiveWebContents()->
- GetController())).Wait();
- }
}
bool RemoteDesktopBrowserTest::ExecuteScriptAndExtractBool(
@@ -398,7 +403,8 @@ std::string RemoteDesktopBrowserTest::ExecuteScriptAndExtractString(
}
// Helper to navigate to a given url.
-void RemoteDesktopBrowserTest::NavigateToURLAndWait(const GURL& url) {
+void RemoteDesktopBrowserTest::NavigateToURLAndWaitForPageLoad(
+ const GURL& url) {
content::WindowedNotificationObserver observer(
content::NOTIFICATION_LOAD_STOP,
content::Source<content::NavigationController>(
@@ -419,33 +425,62 @@ void RemoteDesktopBrowserTest::ClickOnControl(const std::string& name) {
void RemoteDesktopBrowserTest::EnterPin(const std::string& pin) {
// Wait for the pin-form to be displayed. This can take a while.
// We also need to dismiss the host-needs-update dialog if it comes up.
- // TODO 1: Instead of polling, can we register a callback to be called
- // when the pin-form is ready?
- // TODO 2: Instead of blindly dismiss the host-needs-update dialog,
+ // TODO(weitaosu) 1: Instead of polling, can we register a callback to be
+ // called when the pin-form is ready?
+ // TODO(weitaosu) 2: Instead of blindly dismiss the host-needs-update dialog,
// we should verify that it only pops up at the right circumstance. That
// probably belongs in a separate test case though.
- do {
- if (HtmlElementVisible("host-needs-update-connect-button")) {
- ClickOnControl("host-needs-update-connect-button");
- }
- } while (!HtmlElementVisible("pin-form"));
+ ConditionalTimeoutWaiter waiter(
+ base::TimeDelta::FromSeconds(3),
+ base::TimeDelta::FromSeconds(1),
+ base::Bind(&RemoteDesktopBrowserTest::IsPinFormVisible, this));
+ EXPECT_TRUE(waiter.Wait());
ExecuteScript(
"document.getElementById(\"pin-entry\").value = \"" + pin + "\";");
ClickOnControl("pin-connect-button");
-
- WaitForConnection();
}
void RemoteDesktopBrowserTest::WaitForConnection() {
// Wait until the client has connected to the server.
// This can take a while.
- // TODO: Instead of polling, can we register a callback to
+ // TODO(weitaosu): Instead of polling, can we register a callback to
// remoting.clientSession.onStageChange_?
- while (ExecuteScriptAndExtractBool(
- "remoting.clientSession == null")) {
- }
+ ConditionalTimeoutWaiter waiter(
+ base::TimeDelta::FromSeconds(8),
+ base::TimeDelta::FromSeconds(1),
+ base::Bind(&RemoteDesktopBrowserTest::IsSessionConnected, this));
+ EXPECT_TRUE(waiter.Wait());
+
+ // The client is not yet ready to take input when the session state becomes
+ // CONNECTED. Wait for 3 seconds for the client to become ready.
+ // TODO(weitaosu): Find a way to detect when the client is truly ready.
+ TimeoutWaiter(base::TimeDelta::FromSeconds(3)).Wait();
+}
+
+bool RemoteDesktopBrowserTest::IsLocalHostReady() {
+ // TODO(weitaosu): Instead of polling, can we register a callback to
+ // remoting.hostList.setLocalHost_?
+ return ExecuteScriptAndExtractBool("remoting.hostList.localHost_ != null");
+}
+
+bool RemoteDesktopBrowserTest::IsSessionConnected() {
+ return ExecuteScriptAndExtractBool(
+ "remoting.clientSession != null && "
+ "remoting.clientSession.getState() == "
+ "remoting.ClientSession.State.CONNECTED");
+}
+
+bool RemoteDesktopBrowserTest::IsPinFormVisible() {
+ if (HtmlElementVisible("host-needs-update-connect-button"))
+ ClickOnControl("host-needs-update-connect-button");
+
+ return HtmlElementVisible("pin-form");
+}
+
+bool RemoteDesktopBrowserTest::IsURLLoaded(const GURL& url) {
+ return GetCurrentURL() == url;
}
} // namespace remoting
diff --git a/remoting/test/remote_desktop_browsertest.h b/remoting/test/remote_desktop_browsertest.h
index a9922b8..81e73e9 100644
--- a/remoting/test/remote_desktop_browsertest.h
+++ b/remoting/test/remote_desktop_browsertest.h
@@ -49,10 +49,7 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
// InProcessBrowserTest Overrides
virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
-
- /* */
- /* The following helpers each perform a simple task. */
- /* */
+ // The following helpers each perform a simple task.
// Verify the test has access to the internet (specifically google.com)
void VerifyInternetAccess();
@@ -91,10 +88,7 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
bool alt,
bool command);
-
- /* */
- /* The following helpers each perform a composite task. */
- /* */
+ // The following helpers each perform a composite task.
// Install the chromoting extension
void Install();
@@ -127,10 +121,7 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
void ParseCommandLine();
-
- /* */
- /* Accessor methods. */
- /* */
+ // Accessor methods.
// Helper to get the path to the crx file of the webapp to be tested.
base::FilePath WebAppCrxPath() { return webapp_crx_; }
@@ -156,22 +147,20 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
return browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
}
-
- /* */
- /* Helpers to execute javascript code on a web page. */
- /* */
+ // Helpers to execute javascript code on a web page.
// Helper to execute a javascript code snippet on the current page.
void ExecuteScript(const std::string& script);
// Helper to execute a javascript code snippet on the current page and
// wait for page load to complete.
- void ExecuteScriptAndWait(const std::string& script);
+ void ExecuteScriptAndWaitForAnyPageLoad(const std::string& script);
// Helper to execute a javascript code snippet on the current page and
// wait until the target url is loaded. This is used when the target page
// is loaded after multiple redirections.
- void ExecuteScriptAndWaitUntil(const std::string& script, const GURL& target);
+ void ExecuteScriptAndWaitForPageLoad(const std::string& script,
+ const GURL& target);
// Helper to execute a javascript code snippet on the current page and
// extract the boolean result.
@@ -186,7 +175,7 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
std::string ExecuteScriptAndExtractString(const std::string& script);
// Helper to navigate to a given url.
- void NavigateToURLAndWait(const GURL& url);
+ void NavigateToURLAndWaitForPageLoad(const GURL& url);
// Helper to check whether an html element with the given name exists on
// the current page.
@@ -204,10 +193,22 @@ class RemoteDesktopBrowserTest : public ExtensionBrowserTest {
// Wait for the me2me connection to be established.
void WaitForConnection();
+ // Checking whether the localHost has been initialized.
+ bool IsLocalHostReady();
+
+ // Callback used by EnterPin to check whether the pin form is visible
+ // and to dismiss the host-needs-update dialog.
+ bool IsPinFormVisible();
+
+ // Callback used by WaitForConnection to check whether the connection
+ // has been established.
+ bool IsSessionConnected();
+
+ // Callback used by ExecuteScriptAndWaitForPageLoad to check whether
+ // the given page is currently loaded.
+ bool IsURLLoaded(const GURL& url);
- /* */
- /* Fields */
- /* */
+ // Fields
// This test needs to make live DNS requests for access to
// GAIA and sync server URLs under google.com. We use a scoped version
diff --git a/remoting/test/waiter.cc b/remoting/test/waiter.cc
new file mode 100644
index 0000000..adc21c0
--- /dev/null
+++ b/remoting/test/waiter.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/test/waiter.h"
+
+#include "content/public/test/test_utils.h"
+
+namespace remoting {
+
+TimeoutWaiter::TimeoutWaiter(base::TimeDelta timeout)
+ : timeout_(timeout) {
+ DCHECK(timeout > base::TimeDelta::FromSeconds(0));
+}
+
+TimeoutWaiter::~TimeoutWaiter() {}
+
+bool TimeoutWaiter::Wait() {
+ DCHECK(!timeout_timer_.IsRunning());
+
+ timeout_timer_.Start(
+ FROM_HERE,
+ timeout_,
+ base::Bind(&TimeoutWaiter::CancelWaitCallback, base::Unretained(this)));
+
+ message_loop_runner_ = new content::MessageLoopRunner;
+ message_loop_runner_->Run();
+
+ return true;
+}
+
+void TimeoutWaiter::CancelWait() {
+ message_loop_runner_->Quit();
+}
+
+void TimeoutWaiter::CancelWaitCallback() {
+ CancelWait();
+}
+
+ConditionalTimeoutWaiter::ConditionalTimeoutWaiter(base::TimeDelta timeout,
+ base::TimeDelta interval,
+ const Predicate& callback)
+ : TimeoutWaiter(timeout),
+ interval_(interval),
+ callback_(callback),
+ success_(false) {
+ DCHECK(timeout > interval);
+}
+
+ConditionalTimeoutWaiter::~ConditionalTimeoutWaiter() {}
+
+bool ConditionalTimeoutWaiter::Wait() {
+ DCHECK(!condition_timer_.IsRunning());
+
+ condition_timer_.Start(
+ FROM_HERE,
+ interval_,
+ base::Bind(&ConditionalTimeoutWaiter::CancelWaitCallback,
+ base::Unretained(this)));
+
+ // Also call the base class Wait() to start the timeout timer.
+ TimeoutWaiter::Wait();
+
+ return success_;
+}
+
+void ConditionalTimeoutWaiter::CancelWait() {
+ condition_timer_.Stop();
+
+ // Also call the base class CancelWait() to stop the timeout timer.
+ TimeoutWaiter::CancelWait();
+}
+
+void ConditionalTimeoutWaiter::CancelWaitCallback() {
+ if (callback_.Run()) {
+ CancelWait();
+ success_ = true;
+ }
+}
+
+} // namespace remoting
diff --git a/remoting/test/waiter.h b/remoting/test/waiter.h
new file mode 100644
index 0000000..71e64a8
--- /dev/null
+++ b/remoting/test/waiter.h
@@ -0,0 +1,74 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_TEST_WAITER_H_
+#define REMOTING_TEST_WAITER_H_
+
+#include "base/timer/timer.h"
+
+namespace content {
+class MessageLoopRunner;
+}
+
+namespace remoting {
+
+// Block the execution of the test code for the specified number of
+// milliseconds while keeping the message loop running. The browser instance
+// will be responsive during the wait and test actions initiated before
+// the wait will keep running.
+class TimeoutWaiter {
+ public:
+ TimeoutWaiter(base::TimeDelta timeout);
+ virtual ~TimeoutWaiter();
+
+ // Returns true in case of success.
+ // For TimeoutWaiter it should always be true.
+ virtual bool Wait();
+
+ protected:
+ virtual void CancelWait();
+
+ private:
+ // Callback used to cancel the TimeoutWaiter::Wait.
+ void CancelWaitCallback();
+
+ base::OneShotTimer<TimeoutWaiter> timeout_timer_;
+ base::TimeDelta timeout_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimeoutWaiter);
+};
+
+// With a message loop running, keep calling callback in the specified
+// interval until true is returned.
+class ConditionalTimeoutWaiter : public TimeoutWaiter {
+ public:
+ typedef base::Callback<bool(void)> Predicate;
+
+ ConditionalTimeoutWaiter(base::TimeDelta timeout,
+ base::TimeDelta interval,
+ const Predicate& callback);
+ virtual ~ConditionalTimeoutWaiter();
+
+ // Returns true if |callback_| returned true and false in case of timeout.
+ virtual bool Wait() OVERRIDE;
+
+ protected:
+ virtual void CancelWait() OVERRIDE;
+
+ private:
+ // Callback used to cancel the ConditionalTimeoutWaiter::Wait.
+ void CancelWaitCallback();
+
+ base::TimeDelta interval_;
+ Predicate callback_;
+ base::RepeatingTimer<ConditionalTimeoutWaiter> condition_timer_;
+ bool success_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConditionalTimeoutWaiter);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_TEST_WAITER_H_