summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authormarja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-08 19:53:40 +0000
committermarja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-08 19:53:40 +0000
commit604f893cf84613c0196657c234b2426b9201d9bd (patch)
treeee7a877216afa3709af2eac9d1ab3aadcaafad73 /tools
parentb01ee53f686955745f08f3cff14e7417c59f390a (diff)
downloadchromium_src-604f893cf84613c0196657c234b2426b9201d9bd.zip
chromium_src-604f893cf84613c0196657c234b2426b9201d9bd.tar.gz
chromium_src-604f893cf84613c0196657c234b2426b9201d9bd.tar.bz2
Chrome remote control multipage tests: Add interactions.
The page set .json description defines what kind of interactions (e.g., link clicks) are possible for a page. The corresponding Web Page Replay .wpr file must contain replies to the requests sent when the interaction is executed. This will be used in memory tests (see http://codereview.chromium.org/11273081/ ). The top_25_usage.json is a proof of concept page set description adding a couple of interactions. When it's more complete, the existing tests will be migrated to use it. Parts of the code are stolen from nduca@chromium.org (see http://codereview.chromium.org/11114020/ ). BUG=158323 Review URL: https://codereview.chromium.org/11369075 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166734 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/page_sets/top_25.json19
-rw-r--r--tools/telemetry/telemetry/click_to_navigate_interaction.py18
-rw-r--r--tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py25
-rw-r--r--tools/telemetry/telemetry/compound_interaction.py17
-rw-r--r--tools/telemetry/telemetry/compound_interaction_unittest.py42
-rw-r--r--tools/telemetry/telemetry/inspector_page.py78
-rw-r--r--tools/telemetry/telemetry/inspector_page_unittest.py27
-rw-r--r--tools/telemetry/telemetry/page_interaction.py37
-rw-r--r--tools/telemetry/unittest_data/page_with_link.html8
9 files changed, 240 insertions, 31 deletions
diff --git a/tools/perf/page_sets/top_25.json b/tools/perf/page_sets/top_25.json
index 2e23640..7ffa9f9 100644
--- a/tools/perf/page_sets/top_25.json
+++ b/tools/perf/page_sets/top_25.json
@@ -59,7 +59,24 @@
"url": "http://www.facebook.com/barackobama",
"why": "top social,Public profile",
"credentials": "facebook",
- "scroll_is_infinite": true
+ "scroll_is_infinite": true,
+ "stress_memory": {
+ "action": "compound",
+ "actions": [
+ {
+ "action": "click_to_navigate",
+ "selector": "a[href=\"http://www.facebook.com/WomenforObama\"]"
+ },
+ {
+ "action": "click_to_navigate",
+ "selector": "a[href=\"http://www.facebook.com/WomenforObama/info\"]"
+ },
+ {
+ "action": "click_to_navigate",
+ "selector": "a[href=\"http://www.facebook.com/?ref=tn_tnmn\"]"
+ }
+ ]
+ }
},
{
"name": "LinkedIn",
diff --git a/tools/telemetry/telemetry/click_to_navigate_interaction.py b/tools/telemetry/telemetry/click_to_navigate_interaction.py
new file mode 100644
index 0000000..0360fd8
--- /dev/null
+++ b/tools/telemetry/telemetry/click_to_navigate_interaction.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2012 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.
+from telemetry import page_interaction
+
+class ClickToNavigateInteraction(page_interaction.PageInteraction):
+ def __init__(self, attributes=None):
+ super(ClickToNavigateInteraction, self).__init__(attributes)
+
+ def PerformInteraction(self, page, tab):
+ assert self.selector
+ code = 'document.querySelector(\'' + self.selector + '\').click();'
+ def DoClick():
+ tab.runtime.Execute(code)
+ tab.page.PerformActionAndWaitForNavigate(DoClick)
+
+
+page_interaction.RegisterClass('click_to_navigate', ClickToNavigateInteraction)
diff --git a/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py b/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py
new file mode 100644
index 0000000..f631c2a
--- /dev/null
+++ b/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 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.
+import os
+
+from telemetry import click_to_navigate_interaction
+from telemetry import tab_test_case
+
+class ClickToNavigateInteractionTest(tab_test_case.TabTestCase):
+ def testClickToNavigateInteraction(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectory(unittest_data_dir)
+ self._tab.page.Navigate(
+ self._browser.http_server.UrlOf('page_with_link.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'),
+ '/page_with_link.html')
+
+ data = {'selector': 'a[id="clickme"]'}
+ i = click_to_navigate_interaction.ClickToNavigateInteraction(data)
+ i.PerformInteraction({}, self._tab)
+
+ self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'),
+ '/blank.html')
diff --git a/tools/telemetry/telemetry/compound_interaction.py b/tools/telemetry/telemetry/compound_interaction.py
new file mode 100644
index 0000000..2ff48b0
--- /dev/null
+++ b/tools/telemetry/telemetry/compound_interaction.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 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.
+from telemetry import page_interaction
+
+class CompoundInteraction(page_interaction.PageInteraction):
+ def __init__(self, attributes=None):
+ super(CompoundInteraction, self).__init__(attributes)
+
+ def PerformInteraction(self, page, tab):
+ for interaction_data in self.actions:
+ interaction = page_interaction.FindClassWithName(
+ interaction_data['action'])(interaction_data)
+ interaction.PerformInteraction(page, tab)
+
+
+page_interaction.RegisterClass('compound', CompoundInteraction)
diff --git a/tools/telemetry/telemetry/compound_interaction_unittest.py b/tools/telemetry/telemetry/compound_interaction_unittest.py
new file mode 100644
index 0000000..9b0c9115
--- /dev/null
+++ b/tools/telemetry/telemetry/compound_interaction_unittest.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2012 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.
+
+from telemetry import compound_interaction
+from telemetry import page_interaction
+from telemetry import tab_test_case
+
+class CompoundInteractionTest(tab_test_case.TabTestCase):
+ interaction1_called = False
+ interaction2_called = False
+
+ def __init__(self, *args):
+ super(CompoundInteractionTest, self).__init__(*args)
+
+ def testCompoundInteraction(self):
+
+ class MockInteraction1(page_interaction.PageInteraction):
+ def PerformInteraction(self, page, tab):
+ CompoundInteractionTest.interaction1_called = True
+
+ class MockInteraction2(page_interaction.PageInteraction):
+ def PerformInteraction(self, page, tab):
+ CompoundInteractionTest.interaction2_called = True
+
+ page_interaction.RegisterClass('mock1', MockInteraction1)
+ page_interaction.RegisterClass('mock2', MockInteraction2)
+
+ i = compound_interaction.CompoundInteraction({
+ 'action': 'compound',
+ 'actions': [
+ {
+ 'action': 'mock1'
+ },
+ {
+ 'action': 'mock2'
+ }
+ ]
+ })
+ i.PerformInteraction({}, self._tab)
+ self.assertTrue(CompoundInteractionTest.interaction1_called)
+ self.assertTrue(CompoundInteractionTest.interaction2_called)
diff --git a/tools/telemetry/telemetry/inspector_page.py b/tools/telemetry/telemetry/inspector_page.py
index a879dcf..b37d330 100644
--- a/tools/telemetry/telemetry/inspector_page.py
+++ b/tools/telemetry/telemetry/inspector_page.py
@@ -13,53 +13,71 @@ class InspectorPage(object):
'Page',
self._OnNotification,
self._OnClose)
- self._pending_navigate_url = None
+ self._navigation_pending = False
def _OnNotification(self, msg):
logging.debug('Notification: %s', json.dumps(msg, indent=2))
- if msg['method'] == 'Page.frameNavigated' and self._pending_navigate_url:
+ if msg['method'] == 'Page.frameNavigated' and self._navigation_pending:
url = msg['params']['frame']['url']
if not url == 'chrome://newtab/':
- # Marks the navigation as complete and unblocks the navigate call.
- self._pending_navigate_url = None
+ # Marks the navigation as complete and unblocks the
+ # PerformActionAndWaitForNavigate call.
+ self._navigation_pending = False
def _OnClose(self):
pass
- def Navigate(self, url, timeout=60):
- """Navigates to url"""
+ def PerformActionAndWaitForNavigate(self, action_function, timeout=60):
+ """Executes action_function, and waits for the navigation to complete.
+
+ action_function is expect to result in a navigation. This function returns
+ when the navigation is complete or when the timeout has been exceeded.
+ """
+
# Turn on notifications. We need them to get the Page.frameNavigated event.
request = {
- 'method': 'Page.enable'
- }
+ 'method': 'Page.enable'
+ }
res = self._inspector_backend.SyncRequest(request, timeout)
assert len(res['result'].keys()) == 0
- # Navigate the page. However, there seems to be a bug in chrome devtools
- # protocol where the request id for this event gets held on the browser side
- # pretty much indefinitely.
- #
- # So, instead of waiting for the event to actually complete, wait for the
- # Page.frameNavigated event.
- request = {
- 'method': 'Page.navigate',
- 'params': {
- 'url': url,
- }
- }
- res = self._inspector_backend.SendAndIgnoreResponse(request)
+ def DisablePageNotifications():
+ request = {
+ 'method': 'Page.disable'
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ assert len(res['result'].keys()) == 0
+
+ self._navigation_pending = True
+ try:
+ action_function()
+ except:
+ DisablePageNotifications()
+ raise
- self._pending_navigate_url = url
def IsNavigationDone(time_left):
self._inspector_backend.DispatchNotifications(time_left)
- return self._pending_navigate_url == None
-
+ return not self._navigation_pending
util.WaitFor(IsNavigationDone, timeout, pass_time_left_to_func=True)
- # Turn off notifications.
- request = {
- 'method': 'Page.disable'
- }
- res = self._inspector_backend.SyncRequest(request, timeout)
- assert len(res['result'].keys()) == 0
+ DisablePageNotifications()
+
+ def Navigate(self, url, timeout=60):
+ """Navigates to url"""
+
+ def DoNavigate():
+ # Navigate the page. However, there seems to be a bug in chrome devtools
+ # protocol where the request id for this event gets held on the browser
+ # side pretty much indefinitely.
+ #
+ # So, instead of waiting for the event to actually complete, wait for the
+ # Page.frameNavigated event.
+ request = {
+ 'method': 'Page.navigate',
+ 'params': {
+ 'url': url,
+ }
+ }
+ self._inspector_backend.SendAndIgnoreResponse(request)
+ self.PerformActionAndWaitForNavigate(DoNavigate, timeout)
diff --git a/tools/telemetry/telemetry/inspector_page_unittest.py b/tools/telemetry/telemetry/inspector_page_unittest.py
index fee527a..33c476e 100644
--- a/tools/telemetry/telemetry/inspector_page_unittest.py
+++ b/tools/telemetry/telemetry/inspector_page_unittest.py
@@ -1,9 +1,15 @@
# Copyright (c) 2012 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.
+import os
+
from telemetry import tab_test_case
class InspectorPageTest(tab_test_case.TabTestCase):
+ def __init__(self, *args):
+ super(InspectorPageTest, self).__init__(*args)
+ self._custom_action_called = False
+
def testPageNavigateToNormalUrl(self):
self._tab.page.Navigate('http://www.google.com')
self._tab.WaitForDocumentReadyStateToBeComplete()
@@ -17,3 +23,24 @@ class InspectorPageTest(tab_test_case.TabTestCase):
def testPageNavigateToImpossibleURL(self):
self._tab.page.Navigate('http://23f09f0f9fsdflajsfaldfkj2f3f.com')
self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testCustomActionToNavigate(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectory(unittest_data_dir)
+ self._tab.page.Navigate(
+ self._browser.http_server.UrlOf('page_with_link.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'),
+ '/page_with_link.html')
+
+ self._custom_action_called = False
+ def CustomAction():
+ self._custom_action_called = True
+ self._tab.runtime.Execute('document.getElementById("clickme").click();')
+
+ self._tab.page.PerformActionAndWaitForNavigate(CustomAction)
+
+ self.assertTrue(self._custom_action_called)
+ self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'),
+ '/blank.html')
diff --git a/tools/telemetry/telemetry/page_interaction.py b/tools/telemetry/telemetry/page_interaction.py
new file mode 100644
index 0000000..108db76
--- /dev/null
+++ b/tools/telemetry/telemetry/page_interaction.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 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.
+
+class PageInteractionNotSupported(Exception):
+ pass
+
+class PageInteractionFailed(Exception):
+ pass
+
+class PageInteraction(object):
+ """Represents an interaction that a user might try to perform to a page."""
+ def __init__(self, attributes=None):
+ if attributes:
+ for k, v in attributes.iteritems():
+ setattr(self, k, v)
+
+ def CustomizeBrowserOptions(self, options):
+ """Override to add test-specific options to the BrowserOptions object"""
+ pass
+
+ def PerformInteraction(self, page, tab):
+ raise NotImplementedError()
+
+ def CleanUp(self, page, tab):
+ pass
+
+_page_interaction_classes = {}
+def GetAllClasses():
+ return list(_page_interaction_classes.values())
+
+def FindClassWithName(name):
+ return _page_interaction_classes.get(name)
+
+def RegisterClass(name, interaction_class):
+ assert name not in _page_interaction_classes
+ _page_interaction_classes[name] = interaction_class
diff --git a/tools/telemetry/unittest_data/page_with_link.html b/tools/telemetry/unittest_data/page_with_link.html
new file mode 100644
index 0000000..dc3c008
--- /dev/null
+++ b/tools/telemetry/unittest_data/page_with_link.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+</head>
+<body>
+<a id="clickme" href="blank.html">Click me</a>
+</body>
+</html>