summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-04 15:07:36 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-04 15:07:36 +0000
commit8b46deaa1f0ab3794fa08f08f314c481584e591a (patch)
treea60786693fa569a34572fc7767929eb2b44a1bf1 /tools
parent218c1f36a7bc72ef661faf5047a40cc81369ac72 (diff)
downloadchromium_src-8b46deaa1f0ab3794fa08f08f314c481584e591a.zip
chromium_src-8b46deaa1f0ab3794fa08f08f314c481584e591a.tar.gz
chromium_src-8b46deaa1f0ab3794fa08f08f314c481584e591a.tar.bz2
Polish to chrome_remote_control to reduce flake and improve modularity.
- Make android work - Overhaul tools/gpu to be more component-y - Fix error where pexpect missing breaks all browser discovery - Use page.navigate and get rid of the strange timeout logic in InspectorBackend - Make browser selection explicit. You have to select browsers explicitly. - Add --repeat-count to run_tests - Move sleep-after-each-load to gpu_tools.url_test - Make timeouts explicit - Fix handling of optparse defaults and counters - Add is_content_shell property on backends - Set up content-shell command line on android - Override user-data-dir only for non-content-shell backends - If browser fails to die on sigterm, send it a sigkill - Move gpu tools browser creation to toplevel test - Make non-jsonizable evaluate test independent of window for perf reasons - Add runtime.execute to avoid hacks of runtime.evaluate TBR=dtu@chromium.org Review URL: https://chromiumcodereview.appspot.com/10912078 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154754 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/adb_commands.py (renamed from tools/chrome_remote_control/chrome_remote_control/android_commands.py)22
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py31
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py17
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py31
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser.py4
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser_backend.py9
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser_finder.py45
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser_options.py36
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser_options_unittest.py47
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/browser_unittest.py25
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/desktop_browser_backend.py35
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder.py29
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder_unittest.py1
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/inspector_backend.py46
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/run_tests.py68
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab.py35
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab_page.py67
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab_page_unittest.py43
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab_runtime.py8
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab_runtime_unittest.py21
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/tab_unittest.py10
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/util.py19
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/util_unittest.py17
-rw-r--r--tools/chrome_remote_control/chrome_remote_control/websocket.py2
-rwxr-xr-xtools/chrome_remote_control/examples/rendering_microbenchmark_test.py7
-rw-r--r--tools/chrome_remote_control/examples/top1k4
-rwxr-xr-xtools/chrome_remote_control/run_tests15
-rw-r--r--tools/gpu/data/urls.txt218
-rw-r--r--tools/gpu/gpu_tools/__init__.py16
-rw-r--r--tools/gpu/gpu_tools/file_server.py (renamed from tools/gpu/pylib/file_server.py)22
-rw-r--r--tools/gpu/gpu_tools/page_scroller.py50
-rw-r--r--tools/gpu/gpu_tools/page_scroller_unittest.py39
-rw-r--r--tools/gpu/gpu_tools/page_set.py37
-rw-r--r--tools/gpu/gpu_tools/page_set_unittest.py27
-rw-r--r--tools/gpu/gpu_tools/scroll.js (renamed from tools/gpu/pylib/scroll.js)0
-rw-r--r--tools/gpu/gpu_tools/scroll.py (renamed from tools/gpu/pylib/scroll.py)4
-rw-r--r--tools/gpu/gpu_tools/scroll_results.py (renamed from tools/gpu/pylib/scroll_results.py)0
-rw-r--r--tools/gpu/gpu_tools/url_test.py44
-rw-r--r--tools/gpu/page_sets/Q32012.json223
-rw-r--r--tools/gpu/page_sets/__init__.py15
-rw-r--r--tools/gpu/page_sets/page_sets_unittest.py17
-rw-r--r--tools/gpu/pylib/browser.py15
-rw-r--r--tools/gpu/pylib/url_test.py48
-rwxr-xr-xtools/gpu/run_gpu_tools_unittests27
-rwxr-xr-x[-rw-r--r--]tools/gpu/run_page_scroller (renamed from tools/gpu/pylib/__init__.py)8
-rwxr-xr-xtools/gpu/run_scroll_test.py34
-rwxr-xr-xtools/gpu/scroll_test_unittest.py30
-rw-r--r--tools/gpu/unittest_data/scrollable_page.html (renamed from tools/gpu/data/scrollable_page.html)0
48 files changed, 1017 insertions, 551 deletions
diff --git a/tools/chrome_remote_control/chrome_remote_control/android_commands.py b/tools/chrome_remote_control/chrome_remote_control/adb_commands.py
index db67a43..908a5a3 100644
--- a/tools/chrome_remote_control/chrome_remote_control/android_commands.py
+++ b/tools/chrome_remote_control/chrome_remote_control/adb_commands.py
@@ -14,11 +14,18 @@ import sys
# Get build/android scripts into our path.
sys.path.append(
- os.path.join(os.path.dirname(__file__),
- "../../../build/android"))
-from pylib import android_commands as real_android_commands
-from pylib import cmd_helper as real_cmd_helper
-
+ os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ "../../../build/android")))
+try:
+ from pylib import android_commands as real_android_commands
+ from pylib import cmd_helper as real_cmd_helper
+except:
+ import traceback; traceback.print_exc()
+ real_android_commands = None
+
+def IsAndroidSupported():
+ return real_android_commands
def GetAttachedDevices():
"""Returns a list of attached, online android devices.
@@ -27,7 +34,7 @@ def GetAttachedDevices():
the returned list."""
return real_android_commands.GetAttachedDevices()
-class AndroidCommands(object):
+class ADBCommands(object):
"""A thin wrapper around ADB"""
def __init__(self, device):
@@ -98,3 +105,6 @@ class AndroidCommands(object):
action,
category, data,
extras, trace_file_name)
+
+ def Push(self, local, remote):
+ return self._adb.Adb().Push(local, remote)
diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py
index 5f0e25d2..58249cb 100644
--- a/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py
+++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py
@@ -18,9 +18,9 @@ class AndroidBrowserBackend(browser_backend.BrowserBackend):
"""The backend for controlling a browser instance running on Android.
"""
def __init__(self, type, options, adb,
- package, cmdline_file, activity,
+ package, is_content_shell, cmdline_file, activity,
devtools_remote_port):
- super(AndroidBrowserBackend, self).__init__()
+ super(AndroidBrowserBackend, self).__init__(is_content_shell)
# Initialize fields so that an explosion during init doesn't break in Close.
self._options = options
self._adb = adb
@@ -30,18 +30,33 @@ class AndroidBrowserBackend(browser_backend.BrowserBackend):
self._port = 9222
self._devtools_remote_port = devtools_remote_port
- args = [type,
- "--disable-fre",
- "--remote-debugging-port=%i" % 9222]
- if not options.dont_override_profile:
- logging.warning("Overriding of profile is not yet supported on android.")
- args.extend(options.extra_browser_args)
+ # Beginnings of a basic command line.
+ if is_content_shell:
+ pseudo_exec_name = "content_shell"
+ else:
+ pseudo_exec_name = "chrome"
+ args = [pseudo_exec_name,
+ "--disable-fre", "--no-first-run"]
# Kill old broser.
self._adb.KillAll(self._package)
self._adb.KillAll('forawrder')
self._adb.Forward('tcp:9222', self._devtools_remote_port)
+ # Set up temporary dir if needed. As far as we can tell, content_shell
+ # doesn't have persisted data, so --user-data-dir isn't needed.
+ if not is_content_shell and not options.dont_override_profile:
+ self._tmpdir = "/sdcard/chrome_remote_control_data"
+ self._adb.RunShellCommand('rm -r %s' % self._tmpdir)
+ args.append("--user-data-dir=%s" % self._tmpdir)
+
+ # Set up the command line.
+ args.extend(options.extra_browser_args)
+ with tempfile.NamedTemporaryFile() as f:
+ f.write(" ".join(args))
+ f.flush()
+ self._adb.Push(f.name, cmdline_file)
+
# Start it up!
self._adb.StartActivity(self._package,
self._activity,
diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py
index 6c24202..8889883 100644
--- a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py
+++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py
@@ -6,8 +6,8 @@ import sys as real_sys
import subprocess as real_subprocess
import logging
-import android_browser_backend
-import android_commands as real_android_commands
+import chrome_remote_control.android_browser_backend as android_browser_backend
+import chrome_remote_control.adb_commands as real_adb_commands
import browser
import possible_browser
@@ -15,7 +15,6 @@ import possible_browser
"""Finds android browsers that can be controlled by chrome_remote_control."""
ALL_BROWSER_TYPES = 'android-content-shell'
-DEFAULT_BROWSER_TYPES_TO_RUN = 'android-content-shell'
# Commmand line
# content-shell: /data/local/tmp/content-shell-command-line
@@ -40,7 +39,7 @@ CHROME_DEVTOOLS_REMOTE_PORT = 'localabstract:chrome_devtools-remote'
CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell'
CONTENT_SHELL_ACTIVITY = '.ContentShellActivity'
-CONTENT_SHELL_COMMAND_LINE = '/data/local/chrome-command-line'
+CONTENT_SHELL_COMMAND_LINE = '/data/local/tmp/content-shell-command-line'
CONTENT_SHELL_DEVTOOLS_REMOTE_PORT = (
'localabstract:content_shell_devtools_remote')
@@ -67,8 +66,10 @@ class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
def FindAllAvailableBrowsers(options,
subprocess = real_subprocess,
- android_commands = real_android_commands):
+ adb_commands = real_adb_commands):
"""Finds all the desktop browsers available on this machine."""
+ if not adb_commands.IsAndroidSupported():
+ return []
browsers = []
# See if adb even works.
@@ -82,7 +83,7 @@ def FindAllAvailableBrowsers(options,
device = None
if not options.android_device:
- devices = android_commands.GetAttachedDevices()
+ devices = adb_commands.GetAttachedDevices()
else:
devices = []
@@ -97,13 +98,13 @@ def FindAllAvailableBrowsers(options,
device = devices[0]
- adb = android_commands.AndroidCommands(device=device)
+ adb = adb_commands.ADBCommands(device=device)
packages = adb.RunShellCommand('pm list packages')
if 'package:' + CONTENT_SHELL_PACKAGE in packages:
b = PossibleAndroidBrowser('android-content-shell',
options, adb,
- CONTENT_SHELL_PACKAGE,
+ CONTENT_SHELL_PACKAGE, True,
CONTENT_SHELL_COMMAND_LINE,
CONTENT_SHELL_ACTIVITY,
CONTENT_SHELL_DEVTOOLS_REMOTE_PORT)
diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py
index bcef902..be0c6e3 100644
--- a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py
@@ -19,7 +19,7 @@ class StubSubprocess(object):
raise Exception('Should not be reached.')
return self.call_hook(*args, **kwargs)
-class StubAndroidCommands(object):
+class StubADBCommands(object):
def __init__(self, module, device):
self._module = module
self._device = device
@@ -31,14 +31,17 @@ class StubAndroidCommands(object):
handler = self._module.shell_command_handlers[args[0]]
return handler(args)
-class StubAndroidCommandsModule(object):
+class StubADBCommandsModule(object):
def __init__(self):
self.attached_devices = []
self.shell_command_handlers = {}
- def StubAndroidCommandsConstructor(device=None):
- return StubAndroidCommands(self, device)
- self.AndroidCommands = StubAndroidCommandsConstructor
+ def StubADBCommandsConstructor(device=None):
+ return StubADBCommands(self, device)
+ self.ADBCommands = StubADBCommandsConstructor
+
+ def IsAndroidSupported(self):
+ return True
def GetAttachedDevices(self):
return self.attached_devices
@@ -60,9 +63,9 @@ class AndroidBrowserFinderTest(unittest.TestCase):
subprocess_stub = StubSubprocess()
subprocess_stub.call_hook = lambda *args, **kargs: 0
- android_commands_module_stub = StubAndroidCommandsModule()
+ adb_commands_module_stub = StubADBCommandsModule()
browsers = android_browser_finder.FindAllAvailableBrowsers(
- options, subprocess_stub, android_commands_module_stub)
+ options, subprocess_stub, adb_commands_module_stub)
self.assertEquals(0, len(browsers))
def test_adb_two_devices(self):
@@ -70,8 +73,8 @@ class AndroidBrowserFinderTest(unittest.TestCase):
subprocess_stub = StubSubprocess()
subprocess_stub.call_hook = lambda *args, **kargs: 0
- android_commands_module_stub = StubAndroidCommandsModule()
- android_commands_module_stub.attached_devices = ['015d14fec128220c',
+ adb_commands_module_stub = StubADBCommandsModule()
+ adb_commands_module_stub.attached_devices = ['015d14fec128220c',
'015d14fec128220d']
warnings = []
@@ -86,7 +89,7 @@ class AndroidBrowserFinderTest(unittest.TestCase):
logger.addFilter(temp_filter)
browsers = android_browser_finder.FindAllAvailableBrowsers(
- options, subprocess_stub, android_commands_module_stub)
+ options, subprocess_stub, adb_commands_module_stub)
finally:
logger.removeFilter(temp_filter)
self.assertEquals(1, len(warnings))
@@ -97,8 +100,8 @@ class AndroidBrowserFinderTest(unittest.TestCase):
subprocess_stub = StubSubprocess()
subprocess_stub.call_hook = lambda *args, **kargs: 0
- android_commands_module_stub = StubAndroidCommandsModule()
- android_commands_module_stub.attached_devices = ['015d14fec128220c']
+ adb_commands_module_stub = StubADBCommandsModule()
+ adb_commands_module_stub.attached_devices = ['015d14fec128220c']
def OnPM(args):
assert args[0] == 'pm'
@@ -107,8 +110,8 @@ class AndroidBrowserFinderTest(unittest.TestCase):
return ['package:org.chromium.content_shell',
'package.com.google.android.setupwizard']
- android_commands_module_stub.shell_command_handlers['pm'] = OnPM
+ adb_commands_module_stub.shell_command_handlers['pm'] = OnPM
browsers = android_browser_finder.FindAllAvailableBrowsers(
- options, subprocess_stub, android_commands_module_stub)
+ options, subprocess_stub, adb_commands_module_stub)
self.assertEquals(1, len(browsers))
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser.py b/tools/chrome_remote_control/chrome_remote_control/browser.py
index 925cec9..eb033ed 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser.py
@@ -13,11 +13,11 @@ import browser_finder
class Browser(object):
"""A running browser instance that can be controled in a limited way.
- To create a browser instance, use browser_finder.FindBestPossibleBrowser.
+ To create a browser instance, use browser_finder.FindBrowser.
Be sure to clean up after yourself by calling Close() when you are done with
the browser. Or better yet:
- browser_to_create = FindBestPossibleBrowser(options)
+ browser_to_create = FindBrowser(options)
with browser_to_create.Create() as browser:
... do all your operations on browser here
"""
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_backend.py b/tools/chrome_remote_control/chrome_remote_control/browser_backend.py
index bfe01a9..e041690 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser_backend.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser_backend.py
@@ -15,8 +15,8 @@ class BrowserGoneException(Exception):
class BrowserBackend(object):
"""A base class for broser backends. Provides basic functionality
once a remote-debugger port has been established."""
- def __init__(self):
- pass
+ def __init__(self, is_content_shell):
+ self.is_content_shell = is_content_shell
def __del__(self):
self.Close()
@@ -31,7 +31,10 @@ class BrowserBackend(object):
return False
else:
return True
- util.WaitFor(IsBrowserUp)
+ try:
+ util.WaitFor(IsBrowserUp, timeout=15)
+ except util.TimeoutException:
+ raise BrowserGoneException()
def _ListTabs(self, timeout=None):
if timeout:
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_finder.py b/tools/chrome_remote_control/chrome_remote_control/browser_finder.py
index e22635d..9588c35 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser_finder.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser_finder.py
@@ -1,6 +1,8 @@
# 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 logging
+
import android_browser_finder
import desktop_browser_finder
@@ -10,19 +12,42 @@ ALL_BROWSER_TYPES = (
desktop_browser_finder.ALL_BROWSER_TYPES + "," +
android_browser_finder.ALL_BROWSER_TYPES)
-DEFAULT_BROWSER_TYPES_TO_RUN = (
- desktop_browser_finder.DEFAULT_BROWSER_TYPES_TO_RUN + "," +
- android_browser_finder.DEFAULT_BROWSER_TYPES_TO_RUN)
+class BrowserTypeRequiredException(Exception):
+ pass
-def FindBestPossibleBrowser(options):
+def FindBrowser(options):
"""Finds the best PossibleBrowser object to run given the provided
BrowserOptions object. The returned possiblity object can then be used to
connect to and control the located browser."""
+ if options.browser_type == 'exact' and options.browser_executable == None:
+ raise Exception("browser_type=exact requires browser_executable be set.")
- browsers = FindAllPossibleBrowsers(options)
- if len(browsers):
- return browsers[0]
- return None
+ if options.browser_type != 'exact' and options.browser_executable != None:
+ raise Exception("browser_executable requires browser_executable=exact.")
+
+ if options.browser_type == None:
+ raise BrowserTypeRequiredException("browser_type must be specified")
+
+ browsers = []
+ browsers.extend(desktop_browser_finder.FindAllAvailableBrowsers(options))
+ browsers.extend(android_browser_finder.FindAllAvailableBrowsers(options))
+
+ if options.browser_type == 'any':
+ if len(browsers) >= 1:
+ return browsers[0]
+ else:
+ return None
+
+ matching_browsers = [b for b in browsers if b.type == options.browser_type]
+
+ if len(matching_browsers) == 1:
+ return matching_browsers[0]
+ elif len(matching_browsers) > 1:
+ logging.warning('Multiple browsers of the same type found: %s' % (
+ repr(matching_browsers)))
+ return matching_browsers[0]
+ else:
+ return None
def GetAllAvailableBrowserTypes(options):
"""Returns an array of browser types supported on this system."""
@@ -36,10 +61,6 @@ def FindAllPossibleBrowsers(options):
"""Finds all browsers that can be created given the options. Returns an array
of PossibleBrowser objects, sorted and filtered by
options.browser_types_to_use."""
- browsers = []
- browsers.extend(desktop_browser_finder.FindAllAvailableBrowsers(options))
- browsers.extend(android_browser_finder.FindAllAvailableBrowsers(options))
-
selected_browsers = [browser
for browser in browsers
if browser.type in options.browser_types_to_use]
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_options.py b/tools/chrome_remote_control/chrome_remote_control/browser_options.py
index 55c90ba..db4fc15 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser_options.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser_options.py
@@ -2,34 +2,37 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import optparse
+import sys
+
import browser_finder
-class BrowserOptions(object):
+class BrowserOptions(optparse.Values):
"""Options to be used for disocvering and launching browsers."""
def __init__(self):
+ optparse.Values.__init__(self)
self.dont_override_profile = False
self.hide_stdout = True
self.browser_executable = None
- self._browser_types_to_use = (
- browser_finder.DEFAULT_BROWSER_TYPES_TO_RUN.split(","))
+ self._browser_type = None
self.chrome_root = None
self.android_device = None
self.extra_browser_args = []
def CreateParser(self, *args, **kwargs):
parser = optparse.OptionParser(*args, **kwargs)
+ parser.add_option('--browser',
+ dest='browser_type',
+ default=None,
+ help='Browser type to run, '
+ 'in order of priority. Supported values: %s' %
+ browser_finder.ALL_BROWSER_TYPES)
parser.add_option('--dont-override-profile', action='store_true',
dest='dont_override_profile',
help='Uses the regular user profile instead of a clean one')
parser.add_option('--browser-executable',
dest='browser_executable',
help='The exact browser to run.')
- parser.add_option('--browser-types-to-use',
- dest='browser_types_to_use',
- help='Comma-separated list of browsers to run, '
- 'in order of priority. Possible values: %s' %
- browser_finder.DEFAULT_BROWSER_TYPES_TO_RUN)
parser.add_option('--chrome-root',
dest='chrome_root',
help='Where to look for chrome builds.'
@@ -40,18 +43,21 @@ class BrowserOptions(object):
'If not specified, only 0 or 1 connected devcies are supported.')
real_parse = parser.parse_args
def ParseArgs(args=None):
+ defaults = parser.get_default_values()
+ for k, v in defaults.__dict__.items():
+ if k in self.__dict__:
+ continue
+ self.__dict__[k] = v
ret = real_parse(args, self)
+ if self.browser_executable and not self.browser_type:
+ self.browser_type = 'exact'
+ if not self.browser_executable and not self.browser_type:
+ sys.stderr.write("Must provide --browser=<type>\n")
+ sys.exit(1)
return ret
parser.parse_args = ParseArgs
return parser
- def __getattr__(self, name):
- return None
-
- def __setattr__(self, name, value):
- object.__setattr__(self, name, value)
- return value
-
@property
def browser_types_to_use(self):
return self._browser_types_to_use
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_options_unittest.py b/tools/chrome_remote_control/chrome_remote_control/browser_options_unittest.py
index 520122e..d8e3d62 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser_options_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser_options_unittest.py
@@ -6,20 +6,47 @@ import unittest
import browser_options
class BrowserOptionsTest(unittest.TestCase):
- def testDirectMutability(self):
+ def testDefaults(self):
options = browser_options.BrowserOptions()
- # Should be possible to add new fields to the options object.
- options.x = 3
- self.assertEquals(3, options.x)
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.x, 3)
+
+ def testDefaultsPlusOverride(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any', '-x', 10])
+ self.assertEquals(options.x, 10)
+
+ def testDefaultsDontClobberPresetValue(self):
+ options = browser_options.BrowserOptions()
+ setattr(options, 'x', 7)
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.x, 7)
+
+ def testCount0(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-v', action='count', dest='v')
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.v, None)
- # Unset fields on the options object should default to None.
- self.assertEquals(None, options.y)
+ def testCount2(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-v', action='count', dest='v')
+ parser.parse_args(['--browser', 'any', '-vv'])
+ self.assertEquals(options.v, 2)
def testOptparseMutabilityWhenSpecified(self):
options = browser_options.BrowserOptions()
parser = options.CreateParser()
- parser.add_option("-v", dest="verbosity", action="store_true")
- options_ret, args = parser.parse_args(["-v"])
+ parser.add_option('-v', dest='verbosity', action='store_true')
+ options_ret, args = parser.parse_args(['--browser', 'any', '-v'])
self.assertEquals(options_ret, options)
self.assertTrue(options.verbosity)
@@ -27,7 +54,7 @@ class BrowserOptionsTest(unittest.TestCase):
options = browser_options.BrowserOptions()
parser = options.CreateParser()
- parser.add_option("-v", dest="verbosity", action="store_true")
- options_ret, args = parser.parse_args([])
+ parser.add_option('-v', dest='verbosity', action='store_true')
+ options_ret, args = parser.parse_args(['--browser', 'any'])
self.assertEquals(options_ret, options)
self.assertFalse(options.verbosity)
diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py b/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py
index c193059..0c4b8d2 100644
--- a/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py
@@ -10,7 +10,7 @@ class BrowserTest(unittest.TestCase):
def testBasic(self):
options = browser_options.options_for_unittests
options.browser_to_use = browser_finder.ALL_BROWSER_TYPES
- browser_to_create = browser_finder.FindBestPossibleBrowser(options)
+ browser_to_create = browser_finder.FindBrowser(options)
if not browser_to_create:
raise Exception('No browser found, cannot continue test.')
with browser_to_create.Create() as b:
@@ -18,3 +18,26 @@ class BrowserTest(unittest.TestCase):
# Different browsers boot up to different things
assert b.GetNthTabUrl(0)
+
+ def testCommandLineOverriding(self):
+ # This test starts the browser with --enable-benchmarking, which should
+ # create a chrome.Interval namespace. This tests whether the command line is
+ # being set.
+ options = browser_options.options_for_unittests
+ options.browser_to_use = browser_finder.ALL_BROWSER_TYPES
+ testJS = ("window.chrome.gpuBenchmarking !== undefined ||" +
+ "chrome.Interval !== undefined")
+
+ flag1 = "--enable-benchmarking"
+ flag2 = "--enable-gpu-benchmarking"
+ options.extra_browser_args.append(flag1)
+ options.extra_browser_args.append(flag2)
+
+ try:
+ browser_to_create = browser_finder.FindBrowser(options)
+ with browser_to_create.Create() as b:
+ with b.ConnectToNthTab(0) as t:
+ self.assertTrue(t.runtime.Evaluate(testJS))
+ finally:
+ options.extra_browser_args.remove(flag2)
+ options.extra_browser_args.remove(flag1)
diff --git a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_backend.py b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_backend.py
index d52f0c0..712dc07 100644
--- a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_backend.py
+++ b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_backend.py
@@ -11,6 +11,7 @@ import browser_backend
import browser_finder
import inspector_backend
import tab
+import util
DEFAULT_PORT = 9273
@@ -18,8 +19,8 @@ class DesktopBrowserBackend(browser_backend.BrowserBackend):
"""The backend for controlling a locally-executed browser instance, on Linux,
Mac or Windows.
"""
- def __init__(self, options, executable):
- super(DesktopBrowserBackend, self).__init__()
+ def __init__(self, options, executable, is_content_shell):
+ super(DesktopBrowserBackend, self).__init__(is_content_shell)
# Initialize fields so that an explosion during init doesn't break in Close.
self._proc = None
@@ -30,12 +31,12 @@ class DesktopBrowserBackend(browser_backend.BrowserBackend):
if not self._executable:
raise Exception("Cannot create browser, no executable found!")
- self._tmpdir = tempfile.mkdtemp()
self._port = DEFAULT_PORT
args = [self._executable,
"--no-first-run",
"--remote-debugging-port=%i" % self._port]
if not options.dont_override_profile:
+ self._tmpdir = tempfile.mkdtemp()
args.append("--user-data-dir=%s" % self._tmpdir)
args.extend(options.extra_browser_args)
if options.hide_stdout:
@@ -60,12 +61,34 @@ class DesktopBrowserBackend(browser_backend.BrowserBackend):
def Close(self):
if self._proc:
+
+ def IsClosed():
+ if not self._proc:
+ return True
+ return self._proc.poll() != None
+
+ # Try to politely shutdown, first.
self._proc.terminate()
- self._proc.wait()
- self._proc = None
+ try:
+ util.WaitFor(IsClosed, timeout=1)
+ self._proc = None
+ except util.TimeoutException:
+ pass
- if os.path.exists(self._tmpdir):
+ # Kill it.
+ if not IsClosed():
+ self._proc.kill()
+ try:
+ util.WaitFor(IsClosed, timeout=5)
+ self._proc = None
+ except util.TimeoutException:
+ self._proc = None
+ raise Exception("Could not shutdown the browser.")
+
+ if self._tmpdir and os.path.exists(self._tmpdir):
shutil.rmtree(self._tmpdir, ignore_errors=True)
+ self._tmpdir = None
if self._devnull:
self._devnull.close()
+ self._devnull = None
diff --git a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder.py b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder.py
index 76cbbc3..b4ca1a2 100644
--- a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder.py
+++ b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder.py
@@ -13,21 +13,21 @@ import possible_browser
"""Finds desktop browsers that can be controlled by chrome_remote_control."""
ALL_BROWSER_TYPES = "exact,release,debug,canary,system"
-DEFAULT_BROWSER_TYPES_TO_RUN = "exact,release,canary,system"
class PossibleDesktopBrowser(possible_browser.PossibleBrowser):
"""A desktop browser that can be controlled."""
- def __init__(self, type, options, executable):
+ def __init__(self, type, options, executable, is_content_shell):
super(PossibleDesktopBrowser, self).__init__(type, options)
self._local_executable = executable
+ self._is_content_shell = is_content_shell
def __repr__(self):
return "PossibleDesktopBrowser(type=%s)" % self.type
def Create(self):
backend = desktop_browser_backend.DesktopBrowserBackend(
- self._options, self._local_executable)
+ self._options, self._local_executable, self._is_content_shell)
return browser.Browser(backend)
def FindAllAvailableBrowsers(options,
@@ -46,7 +46,7 @@ def FindAllAvailableBrowsers(options,
if options.browser_executable:
if os.path.exists(options.browser_executable):
browsers.append(PossibleDesktopBrowser("exact", options,
- options.browser_executable))
+ options.browser_executable, False))
# Look for a browser in the standard chrome build locations.
if options.chrome_root:
@@ -70,11 +70,13 @@ def FindAllAvailableBrowsers(options,
debug_app = os.path.join(chrome_root, build_dir, "Debug", app_name)
if os.path.exists(debug_app):
- browsers.append(PossibleDesktopBrowser("debug", options, debug_app))
+ browsers.append(PossibleDesktopBrowser("debug", options,
+ debug_app, False))
release_app = os.path.join(chrome_root, build_dir, "Release", app_name)
if os.path.exists(release_app):
- browsers.append(PossibleDesktopBrowser("release", options, release_app))
+ browsers.append(PossibleDesktopBrowser("release", options,
+ release_app, False))
# Mac-specific options.
if sys.platform == 'darwin':
@@ -82,10 +84,12 @@ def FindAllAvailableBrowsers(options,
"Contents/MacOS/Google Chrome Canary")
mac_system = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
if os.path.exists(mac_canary):
- browsers.append(PossibleDesktopBrowser("canary", options, mac_canary))
+ browsers.append(PossibleDesktopBrowser("canary", options,
+ mac_canary, False))
if os.path.exists(mac_system):
- browsers.append(PossibleDesktopBrowser("system", options, mac_system))
+ browsers.append(PossibleDesktopBrowser("system", options,
+ mac_system, False))
# Linux specific options.
if sys.platform.startswith('linux'):
@@ -99,7 +103,8 @@ def FindAllAvailableBrowsers(options,
pass
if found:
browsers.append(
- PossibleDesktopBrowser("system", options, 'google-chrome'))
+ PossibleDesktopBrowser("system", options,
+ 'google-chrome', False))
# Win32-specific options.
if sys.platform.startswith('win') and os.getenv('LOCALAPPDATA'):
@@ -109,10 +114,12 @@ def FindAllAvailableBrowsers(options,
win_system = os.path.join(local_app_data,
'Google\\Chrome\\Application\\chrome.exe')
if os.path.exists(win_canary):
- browsers.append(PossibleDesktopBrowser("canary", options, win_canary))
+ browsers.append(PossibleDesktopBrowser("canary", options,
+ win_canary, False))
if os.path.exists(win_system):
- browsers.append(PossibleDesktopBrowser("system", options, win_system))
+ browsers.append(PossibleDesktopBrowser("system", options,
+ win_system, False))
if len(browsers) and not has_display:
logging.warning('Found (%s), but you have a DISPLAY environment set.' %
diff --git a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder_unittest.py b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder_unittest.py
index 9eed53f..8cb8ea8 100644
--- a/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/desktop_browser_finder_unittest.py
@@ -145,7 +145,6 @@ class LinuxFindTest(FindTestBase):
self.assertEquals([], self.DoFindAllTypes())
def testFindUsingRelease(self):
- self._options.browser_types_to_use.append("debug")
self.assertTrue("release" in self.DoFindAllTypes())
class WinFindTest(FindTestBase):
diff --git a/tools/chrome_remote_control/chrome_remote_control/inspector_backend.py b/tools/chrome_remote_control/chrome_remote_control/inspector_backend.py
index e7889e5..ea85910 100644
--- a/tools/chrome_remote_control/chrome_remote_control/inspector_backend.py
+++ b/tools/chrome_remote_control/chrome_remote_control/inspector_backend.py
@@ -2,9 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
+import logging
+import socket
import time
import websocket
-import socket
class InspectorException(Exception):
pass
@@ -15,7 +16,6 @@ class InspectorBackend(object):
self._descriptor = descriptor
self._socket = websocket.create_connection(
descriptor["webSocketDebuggerUrl"]);
- self._socket.settimeout(0.5)
self._next_request_id = 0
self._domain_handlers = {}
@@ -28,19 +28,44 @@ class InspectorBackend(object):
self._socket = None
self._backend = None
- def SyncRequest(self, req):
+ def DispatchNotifications(self):
+ try:
+ data = self._socket.recv()
+ except socket.error:
+ return None
+
+ res = json.loads(data)
+ logging.debug("got [%s]", data)
+ if "method" not in res:
+ return
+
+ mname = res["method"]
+ dot_pos = mname.find(".")
+ domain_name = mname[:dot_pos]
+ if domain_name in self._domain_handlers:
+ try:
+ self._domain_handlers[domain_name][0](res)
+ except:
+ import traceback
+ traceback.print_exc()
+
+ def SendAndIgnoreResponse(self, req):
+ req["id"] = self._next_request_id
+ self._next_request_id += 1
+ self._socket.send(json.dumps(req))
+
+ def SyncRequest(self, req, timeout=60):
+ # TODO(nduca): Listen to the timeout argument
+ # self._socket.settimeout(timeout)
req["id"] = self._next_request_id
self._next_request_id += 1
self._socket.send(json.dumps(req))
+
while True:
- try:
- data = self._socket.recv()
- except socket.error:
- req["id"] = self._next_request_id
- self._next_request_id += 1
- self._socket.send(json.dumps(req))
- continue
+ data = self._socket.recv()
+
res = json.loads(data)
+ logging.debug("got [%s]", data)
if "method" in res:
mname = res["method"]
dot_pos = mname.find(".")
@@ -54,6 +79,7 @@ class InspectorBackend(object):
continue
if res["id"] != req["id"]:
+ logging.debug("Dropped reply: %s", json.dumps(res))
continue
return res
diff --git a/tools/chrome_remote_control/chrome_remote_control/run_tests.py b/tools/chrome_remote_control/chrome_remote_control/run_tests.py
index 7f68ee9..40505dd 100644
--- a/tools/chrome_remote_control/chrome_remote_control/run_tests.py
+++ b/tools/chrome_remote_control/chrome_remote_control/run_tests.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import fnmatch
+import logging
import os
import sys
import traceback
@@ -15,7 +16,6 @@ def Discover(start_dir, pattern = "test*.py", top_level_dir = None):
pattern,
top_level_dir)
- # TODO(nduca): Do something with top_level_dir non-None
modules = []
for (dirpath, dirnames, filenames) in os.walk(start_dir):
for filename in filenames:
@@ -28,7 +28,9 @@ def Discover(start_dir, pattern = "test*.py", top_level_dir = None):
if filename.startswith('.') or filename.startswith('_'):
continue
name,ext = os.path.splitext(filename)
- fqn = dirpath.replace('/', '.') + '.' + name
+
+ relpath = os.path.relpath(dirpath, top_level_dir)
+ fqn = relpath.replace('/', '.') + '.' + name
# load the module
try:
@@ -67,43 +69,53 @@ def FilterSuite(suite, predicate):
return new_suite
-def DiscoverAndRunTests(args):
- dir_name = os.path.join(os.path.dirname(__file__), "..")
- olddir = os.getcwd()
- try:
- os.chdir(dir_name)
- suite = Discover("chrome_remote_control", "*_unittest.py", ".")
+def DiscoverAndRunTests(dir_name, args, top_level_dir):
+ suite = Discover(dir_name, "*_unittest.py", top_level_dir)
- def IsTestSelected(test):
- if len(args) == 0:
+ def IsTestSelected(test):
+ if len(args) == 0:
+ return True
+ for name in args:
+ if str(test).find(name) != -1:
return True
- for name in args:
- if str(test).find(name) != -1:
- return True
- return False
+ return False
- filtered_suite = FilterSuite(suite, IsTestSelected)
- runner = unittest.TextTestRunner(verbosity = 2)
- test_result = runner.run(filtered_suite)
- return len(test_result.errors) + len(test_result.failures)
+ filtered_suite = FilterSuite(suite, IsTestSelected)
+ runner = unittest.TextTestRunner(verbosity = 2)
+ test_result = runner.run(filtered_suite)
+ return len(test_result.errors) + len(test_result.failures)
- finally:
- os.chdir(olddir)
- return 1
-
-def Main(args):
+def Main(args, start_dir, top_level_dir):
"""Unit test suite that collects all test cases for chrome_remote_control."""
default_options = browser_options.BrowserOptions()
+ default_options.browser_type = 'any'
+
parser = default_options.CreateParser("run_tests [options] [test names]")
+ parser.add_option(
+ '-v', '--verbose', action='count', dest="verbosity",
+ help='Increase verbosity level (repeat as needed)')
+ parser.add_option('--repeat-count', dest='run_test_repeat_count',
+ type='int', default=1,
+ help="Repeats each a provided number of times.")
+
_, args = parser.parse_args(args)
+ if default_options.verbosity >= 2:
+ logging.basicConfig(level=logging.DEBUG)
+ elif default_options.verbosity:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.WARNING)
+
browser_options.options_for_unittests = default_options
+ olddir = os.getcwd()
+ num_errors = 0
try:
- DiscoverAndRunTests(args)
+ os.chdir(top_level_dir)
+ for i in range(default_options.run_test_repeat_count):
+ num_errors += DiscoverAndRunTests(start_dir, args, top_level_dir)
finally:
+ os.chdir(olddir)
browser_options.options_for_unittests = None
-
-
-if __name__ == "__main__":
- sys.exit(Main(sys.argv[1:]))
+ return num_errors
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab.py b/tools/chrome_remote_control/chrome_remote_control/tab.py
index d4766f6..976eee0 100644
--- a/tools/chrome_remote_control/chrome_remote_control/tab.py
+++ b/tools/chrome_remote_control/chrome_remote_control/tab.py
@@ -6,18 +6,25 @@ import websocket
import socket
import time
+import tab_page
import tab_runtime
import util
+DEFAULT_TAB_TIMEOUT=60
+
class Tab(object):
def __init__(self, inspector_backend):
self._inspector_backend = inspector_backend
+ self.page = tab_page.TabPage(self._inspector_backend)
self.runtime = tab_runtime.TabRuntime(self._inspector_backend)
+
def __del__(self):
self.Close()
def Close(self):
+ self.page = None
+ self.runtime = None
if self._inspector_backend:
self._inspector_backend.Close()
self._inspector_backend = None
@@ -28,31 +35,13 @@ class Tab(object):
def __exit__(self, *args):
self.Close()
- def BeginToLoadUrl(self, url):
- # In order to tell when the document has actually changed,
- # we go to about:blank first and wait. When that has happened, we
- # to go the new URL and detect the document being non-about:blank as
- # indication that the new document is loading.
- self.runtime.Evaluate('document.location = "about:blank";')
- util.WaitFor(lambda:
- self.runtime.Evaluate('document.location.href') == 'about:blank')
-
- self.runtime.Evaluate('document.location = "%s";' % url)
- util.WaitFor(lambda:
- self.runtime.Evaluate('document.location.href') != 'about:blank')
-
- def LoadUrl(self, url):
- self.BeginToLoadUrl(url)
- # TODO(dtu): Detect HTTP redirects.
- time.sleep(2) # Wait for unpredictable redirects.
- self.WaitForDocumentReadyStateToBeInteractiveOrBetter()
-
- def WaitForDocumentReadyStateToBeComplete(self):
+ def WaitForDocumentReadyStateToBeComplete(self, timeout=60):
util.WaitFor(
- lambda: self.runtime.Evaluate('document.readyState') == 'complete')
+ lambda: self.runtime.Evaluate('document.readyState') == 'complete',
+ timeout)
- def WaitForDocumentReadyStateToBeInteractiveOrBetter(self):
+ def WaitForDocumentReadyStateToBeInteractiveOrBetter(self, timeout=60):
def IsReadyStateInteractiveOrBetter():
rs = self.runtime.Evaluate('document.readyState')
return rs == 'complete' or rs == 'interactive'
- util.WaitFor(IsReadyStateInteractiveOrBetter)
+ util.WaitFor(IsReadyStateInteractiveOrBetter, timeout)
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_page.py b/tools/chrome_remote_control/chrome_remote_control/tab_page.py
new file mode 100644
index 0000000..fbf7dea
--- /dev/null
+++ b/tools/chrome_remote_control/chrome_remote_control/tab_page.py
@@ -0,0 +1,67 @@
+# 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 json
+import logging
+import urlparse
+
+import inspector_backend
+import util
+
+class TabPage(object):
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._inspector_backend.RegisterDomain(
+ 'Page',
+ self._OnNotification,
+ self._OnClose)
+ self._pending_navigate_url = None
+
+ def _OnNotification(self, msg):
+ logging.debug("Notification: %s", json.dumps(msg, indent=2))
+ if msg["method"] == "Page.frameNavigated" and self._pending_navigate_url:
+ 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
+
+ def _OnClose(self):
+ pass
+
+ def Navigate(self, url, timeout=60):
+ """Navigates to url"""
+ # Turn on notifications. We need them to get the Page.frameNavigated event.
+ request = {
+ "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)
+
+ self._pending_navigate_url = url
+ def IsNavigationDone():
+ self._inspector_backend.DispatchNotifications()
+ return self._pending_navigate_url == None
+
+ util.WaitFor(IsNavigationDone, timeout)
+
+ # Turn off notifications.
+ request = {
+ "method": "Page.disable"
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ assert len(res["result"].keys()) == 0
+
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_page_unittest.py b/tools/chrome_remote_control/chrome_remote_control/tab_page_unittest.py
new file mode 100644
index 0000000..3586c06
--- /dev/null
+++ b/tools/chrome_remote_control/chrome_remote_control/tab_page_unittest.py
@@ -0,0 +1,43 @@
+# 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 browser
+import browser_finder
+import browser_options
+import tab_page
+import unittest
+
+class TabPageTest(unittest.TestCase):
+ def setUp(self):
+ self._browser = None
+ self._tab = None
+ options = browser_options.options_for_unittests
+ browser_to_create = browser_finder.FindBrowser(options)
+ if not browser_to_create:
+ raise Exception('No browser found, cannot continue test.')
+ try:
+ self._browser = browser_to_create.Create()
+ self._tab = self._browser.ConnectToNthTab(0)
+ except:
+ self.tearDown()
+ raise
+
+ def tearDown(self):
+ if self._tab:
+ self._tab.Close()
+ if self._browser:
+ self._browser.Close()
+
+ def testPageNavigateToNormalUrl(self):
+ res = self._tab.page.Navigate("http://www.google.com")
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testPageNavigateToUrlChanger(self):
+ # The Url that we actually load is http://www.youtube.com/.
+ res = self._tab.page.Navigate("http://youtube.com/")
+
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testPageNavigateToImpossibleURL(self):
+ res = self._tab.page.Navigate("http://23f09f0f9fsdflajsfaldfkj2f3f.com")
+ self._tab.WaitForDocumentReadyStateToBeComplete()
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py b/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py
index de73892..827e1c28 100644
--- a/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py
+++ b/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py
@@ -20,14 +20,14 @@ class TabRuntime(object):
def _OnClose(self):
pass
- def Execute(self, expr):
+ def Execute(self, expr, timeout=60):
"""Executes expr
If the expression failed to evaluate, EvaluateException will be raised.
"""
- self.Evaluate(expr + "; 0;");
+ self.Evaluate(expr + "; 0;", timeout=60);
- def Evaluate(self, expr):
+ def Evaluate(self, expr, timeout=60):
"""Evalutes expr and returns the JSONized result.
Consider using Execute for cases where the result of the expression is not
@@ -46,7 +46,7 @@ class TabRuntime(object):
"returnByValue": True
}
}
- res = self._inspector_backend.SyncRequest(request)
+ res = self._inspector_backend.SyncRequest(request, timeout)
if "error" in res:
raise EvaluateException(res["error"]["message"])
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_runtime_unittest.py b/tools/chrome_remote_control/chrome_remote_control/tab_runtime_unittest.py
index a43a327..65f3a3a 100644
--- a/tools/chrome_remote_control/chrome_remote_control/tab_runtime_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/tab_runtime_unittest.py
@@ -12,7 +12,7 @@ class TabRuntimeTest(unittest.TestCase):
self._browser = None
self._tab = None
options = browser_options.options_for_unittests
- browser_to_create = browser_finder.FindBestPossibleBrowser(options)
+ browser_to_create = browser_finder.FindBrowser(options)
if not browser_to_create:
raise Exception('No browser found, cannot continue test.')
try:
@@ -37,13 +37,18 @@ class TabRuntimeTest(unittest.TestCase):
lambda: self._tab.runtime.Evaluate("fsdfsdfsf"))
def testRuntimeEvaluateOfSomethingThatCantJSONize(self):
- # TODO(nduca): This fails on Android. I wonder why?
- self.assertRaises(tab_runtime.EvaluateException,
- lambda: self._tab.runtime.Evaluate("window"))
- pass
+
+ def test():
+ self._tab.runtime.Evaluate("""
+ var cur = {}
+ var root = {next:cur};
+ for(var i = 0; i < 1000; i++) {
+ next = {};
+ cur.next = next;
+ cur = next;
+ }
+ root;""")
+ self.assertRaises(tab_runtime.EvaluateException, test)
def testRuntimeExecuteOfSomethingThatCantJSONize(self):
self._tab.runtime.Execute("window");
-
- def testRuntimeLoadUrl(self):
- self._tab.BeginToLoadUrl("http://www.google.com")
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_unittest.py b/tools/chrome_remote_control/chrome_remote_control/tab_unittest.py
index c5e1bef..289efe0 100644
--- a/tools/chrome_remote_control/chrome_remote_control/tab_unittest.py
+++ b/tools/chrome_remote_control/chrome_remote_control/tab_unittest.py
@@ -12,7 +12,7 @@ class TabTest(unittest.TestCase):
self._browser = None
self._tab = None
options = browser_options.options_for_unittests
- browser_to_create = browser_finder.FindBestPossibleBrowser(options)
+ browser_to_create = browser_finder.FindBrowser(options)
if not browser_to_create:
raise Exception('No browser found, cannot continue test.')
try:
@@ -28,10 +28,10 @@ class TabTest(unittest.TestCase):
if self._browser:
self._browser.Close()
- def testLoadUrlAndWaitToForCompleteState(self):
- self._tab.BeginToLoadUrl("http://www.google.com")
+ def testNavigateAndWaitToForCompleteState(self):
+ self._tab.page.Navigate("http://www.google.com")
self._tab.WaitForDocumentReadyStateToBeComplete()
- def testLoadUrlAndWaitToForInteractiveState(self):
- self._tab.BeginToLoadUrl("http://www.google.com")
+ def testNavigateAndWaitToForInteractiveState(self):
+ self._tab.page.Navigate("http://www.google.com")
self._tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
diff --git a/tools/chrome_remote_control/chrome_remote_control/util.py b/tools/chrome_remote_control/chrome_remote_control/util.py
index ec2df2b..5ea4fbd 100644
--- a/tools/chrome_remote_control/chrome_remote_control/util.py
+++ b/tools/chrome_remote_control/chrome_remote_control/util.py
@@ -4,31 +4,18 @@
import inspect
import time
-_timeout = 60
-
class TimeoutException(Exception):
pass
-class TimeoutChanger(object):
- def __init__(self, new_timeout):
- self._timeout = new_timeout
-
- def __enter__(self):
- _timeout, self._timeout = self._timeout, _timeout
- return self
-
- def __exit__(self, *args):
- _timeout = self._timeout
-
-def WaitFor(condition):
+def WaitFor(condition, timeout):
assert isinstance(condition, type(lambda: None)) # is function
start_time = time.time()
while not condition():
- if time.time() - start_time > _timeout:
+ if time.time() - start_time > timeout:
if condition.__name__ == '<lambda>':
condition_string = inspect.getsource(condition).strip()
else:
condition_string = condition.__name__
raise TimeoutException('Timed out while waiting %ds for %s.' %
- (_timeout, condition_string))
+ (timeout, condition_string))
time.sleep(0.01)
diff --git a/tools/chrome_remote_control/chrome_remote_control/util_unittest.py b/tools/chrome_remote_control/chrome_remote_control/util_unittest.py
new file mode 100644
index 0000000..7050975
--- /dev/null
+++ b/tools/chrome_remote_control/chrome_remote_control/util_unittest.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.
+import unittest
+
+import util
+
+class TestWait(unittest.TestCase):
+ def testNonTimeout(self):
+ def test():
+ return True
+ util.WaitFor(test, 0.1)
+
+ def testTimeout(self):
+ def test():
+ return False
+ self.assertRaises(util.TimeoutException, lambda: util.WaitFor(test, 0.1))
diff --git a/tools/chrome_remote_control/chrome_remote_control/websocket.py b/tools/chrome_remote_control/chrome_remote_control/websocket.py
index 6f31fb9..99c5b84 100644
--- a/tools/chrome_remote_control/chrome_remote_control/websocket.py
+++ b/tools/chrome_remote_control/chrome_remote_control/websocket.py
@@ -12,4 +12,6 @@ def __init__():
sys.path.append(ws_path)
__init__()
+
from websocket import *
+
diff --git a/tools/chrome_remote_control/examples/rendering_microbenchmark_test.py b/tools/chrome_remote_control/examples/rendering_microbenchmark_test.py
index 000032c..3fa7976 100755
--- a/tools/chrome_remote_control/examples/rendering_microbenchmark_test.py
+++ b/tools/chrome_remote_control/examples/rendering_microbenchmark_test.py
@@ -29,7 +29,7 @@ def Main(args):
urls.append(url)
options.extra_browser_args.append("--enable-gpu-benchmarking")
- browser_to_create = chrome_remote_control.FindBestPossibleBrowser(options)
+ browser_to_create = chrome_remote_control.FindBrowser(options)
if not browser_to_create:
sys.stderr.write("No browser found! Supported types: %s" %
chrome_remote_control.GetAllAvailableBrowserTypes())
@@ -37,7 +37,8 @@ def Main(args):
with browser_to_create.Create() as b:
with b.ConnectToNthTab(0) as tab:
# Check browser for benchmark API. Can only be done on non-chrome URLs.
- tab.BeginToLoadUrl("http://www.google.com")
+ tab.page.Navigate("http://www.google.com")
+ import time; time.sleep(2)
tab.WaitForDocumentReadyStateToBeComplete()
if tab.runtime.Evaluate("window.chrome.gpuBenchmarking === undefined"):
print "Browser does not support gpu benchmarks API."
@@ -63,7 +64,7 @@ def Main(args):
print ",".join(cols)
for u in urls:
- tab.BeginToLoadUrl(u)
+ tab.page.Navigate(u)
tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
results = tab.runtime.Evaluate(
"window.chrome.gpuBenchmarking.runRenderingBenchmarks();")
diff --git a/tools/chrome_remote_control/examples/top1k b/tools/chrome_remote_control/examples/top1k
index a11f26e..f32a38c 100644
--- a/tools/chrome_remote_control/examples/top1k
+++ b/tools/chrome_remote_control/examples/top1k
@@ -1,12 +1,12 @@
youtube.com
-yahoo.com
-baidu.com
wikipedia.org
live.com
twitter.com
+baidu.com
qq.com
amazon.com
blogspot.com
+yahoo.com
linkedin.com
taobao.com
yahoo.co.jp
diff --git a/tools/chrome_remote_control/run_tests b/tools/chrome_remote_control/run_tests
index 4775c69..36b4198 100755
--- a/tools/chrome_remote_control/run_tests
+++ b/tools/chrome_remote_control/run_tests
@@ -1,5 +1,16 @@
-#!/bin/sh
+#!/usr/bin/env python
# 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.
-/usr/bin/env python -m chrome_remote_control.run_tests $*
+import os
+import sys
+
+import chrome_remote_control.run_tests
+
+if __name__ == "__main__":
+ top_level_dir = os.path.abspath(
+ os.path.dirname(__file__))
+ start_dir = "chrome_remote_control"
+ ret = chrome_remote_control.run_tests.Main(
+ sys.argv[1:], start_dir, top_level_dir)
+ sys.exit(ret)
diff --git a/tools/gpu/data/urls.txt b/tools/gpu/data/urls.txt
deleted file mode 100644
index 051228b..0000000
--- a/tools/gpu/data/urls.txt
+++ /dev/null
@@ -1,218 +0,0 @@
-http://www.facebook.com/barackobama
-https://www.google.com/search?q=barack%20obama
-http://youtube.com
-http://yahoo.com
-http://www.baidu.com/s?wd=barack+obama
-http://en.wikipedia.org/wiki/Wikipedia
-http://qq.com
-http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2
-http://googleblog.blogspot.com/
-http://taobao.com
-http://www.linkedin.com/in/linustorvalds
-http://yahoo.co.jp
-http://sina.com.cn
-http://msn.com
-http://yandex.ru/yandsearch?text=barack+obama
-http://translation.babylon.com/
-http://www.bing.com/search?q=barack+obama
-http://wordpress.org/news/
-http://www.ebay.com/sch/i.html?_nkw=antiques
-http://163.com
-http://www.soso.com/q?w=barack+obama
-http://www.microsoft.com/en-us/default.aspx
-http://go.mail.ru/search?mailru=1&mg=1&q=barack+obama
-http://vk.com/id118712387
-http://staff.tumblr.com/
-http://sohu.com
-http://sfbay.craigslist.org/mis/
-http://www.ask.com/web?q=barack+obama&search=&qsrc=0&o=0&l=dir
-http://www.apple.com/ipodtouch/
-http://blog.pinterest.com/
-http://pinterest.com/backdrophome/
-http://paypal.com
-http://bbc.co.uk
-http://www.avg.com/us-en/avg-premium-security
-http://googlesystem.blogspot.com/
-http://tudou.com
-http://blog.fc2.com/en/
-http://imdb.com
-http://youku.com
-http://www.flickr.com/photos/thomashawk/
-http://www.flickr.com/photos/thomashawk/sets/72157600284219965/detail/
-http://search.yahoo.com/search?ei=UTF-8&trackingType=go_search_home&p=barack+obama&fr=hsusgo1&sa.x=0&sa.y=0
-http://www.conduit.com/
-http://ifeng.com
-http://tmall.com
-http://hao123.com
-http://aol.com
-http://zedo.com
-http://search.mywebsearch.com/mywebsearch/GGmain.jhtml?searchfor=barack+obama
-http://cnn.com
-http://portal.ebay.de/deutschland-schraubt-angebote
-http://www.adobe.com/products/photoshopfamily.html?promoid=JOLIW
-http://global.rakuten.com/us/
-http://laundry.about.com/od/kidsandlaundry/f/How-Do-I-Wash-A-Backpack.htm
-http://thepiratebay.se/search/barack%20obama/0/99/0
-http://360buy.com
-http://huffingtonpost.com
-http://alibaba.com
-http://chinaz.com
-http://www.sogou.com/web?query=barack+obama
-http://www.amazon.de/gp/product/B0051QVF7A/ref=amb_link_170625867_1/275-4711375-4099801?ie=UTF8&nav_sdd=aps&pf_rd_m=A3JWKAKR8XB7XF&pf_rd_s=center-1&pf_rd_r=1C0XDBPB12WHDM63V11R&pf_rd_t=101&pf_rd_p=320475427&pf_rd_i=301128
-http://google.pl
-http://mediafire.com
-http://espn.go.com
-http://uol.com.br
-http://www.godaddy.com/products/secure-hosting.aspx?ci=72738
-http://imgur.com/gallery/b90ZE
-http://home.alipay.com/bank/paymentKJ.htm
-http://amazon.co.jp
-http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array
-http://www.google.com/doubleclick/
-http://search.4shared.com/q/CCAD/1/barack%20obama
-http://dailymotion.com
-http://globo.com
-http://instagram.com/developer/
-http://livedoor.com
-http://wordpress.org/showcase/
-http://bp.blogspot.com
-http://wigetmedia.com/advertisers
-http://www.search-results.com/web?&q=barack%20obama
-http://cnet.com
-http://nytimes.com
-http://torrentz.eu/search?f=barack+obama
-http://livejournal.com
-http://douban.com
-http://www.weather.com/weather/right-now/Mountain+View+CA+94043
-http://dailymail.co.uk
-http://www.tianya.cn/bbs/index.shtml
-http://ehow.com
-http://theproject.badoo.com/final.phtml
-http://www.bankofamerica.com/deposits/checksave/index.cfm?template=check_eBanking
-http://vimeo.com
-http://360.cn
-http://indiatimes.com
-http://deviantart.com
-http://reddit.com
-http://aweber.com
-http://warriorforum.com
-http://spiegel.de
-http://pconline.com.cn
-http://mozilla.org
-http://booking.com
-http://goo.ne.jp
-https://www.chase.com/online/Home-Lending/mortgages.htm
-http://addthis.com
-http://56.com
-http://news.blogfa.com/
-http://www.stumbleupon.com/jobs
-https://www.dropbox.com/about
-http://www.clicksor.com/publishers/adformat
-http://answers.com
-http://en.softonic.com/
-http://walmart.com
-http://pengyou.com
-http://outbrain.com
-http://comcast.net
-http://foxnews.com
-http://photobucket.com/findstuff/photography%20styles/
-http://bleach.wikia.com/?redirect=no
-http://sourceforge.net/projects/xoops/?source=frontpage&position=1
-http://onet.pl
-http://guardian.co.uk
-https://www.wellsfargo.com/jump/enterprise/doublediscount?msc=5589&mplx=10918-70119-3408-64
-http://wikimediafoundation.org/wiki/Home
-http://xunlei.com
-http://as.58.com/shuma/
-http://skype.com
-http://etsy.com
-http://bild.de
-http://search.naver.com/search.naver?where=nexearch&query=barack+obama&sm=top_hty&fbm=0&ie=utf8
-http://statcounter.com/features/?PHPSESSID=bbjcvjr681bcul4vqvgq2qgmo7
-http://iqiyi.com
-http://fbcdn.net
-http://www.myspace.com/browse/people
-http://allegro.pl/antyki-i-sztuka
-http://yesky.com
-http://justbeenpaid.com
-http://adultfriendfinder.com
-http://fiverr.com
-http://www.leboncoin.fr/annonces/offres/centre/
-http://dictionary.reference.com/
-http://realtime.rediff.com/instasearch#!barack%20obama
-http://zol.com.cn
-http://optmd.com
-http://www.filestube.com/search.html?q=barack+obama&select=All
-http://xinhuanet.com
-http://www.salesforce.com/sales-cloud/overview/
-http://www.squidoo.com/make-cards-and-gift-bags-with-antique-photos
-http://www.domaintools.com/research/
-http://download.cnet.com/windows/?tag=hdr;brandnav
-https://rapidshare.com/#!shop
-http://people.com.cn
-http://ucoz.ru
-http://free.fr
-http://nicovideo.jp
-http://www.yelp.com/search?find_desc=food&find_loc=San+Jose%2C+CA&ns=1
-http://slideshare.net
-http://archive.org/web/web.php
-http://www.cntv.cn/index.shtml
-http://english.cntv.cn/01/index.shtml
-http://abonnez-vous.orange.fr/residentiel/accueil/accueil.aspx
-http://v.it168.com/
-http://nbcolympics.com
-http://hootsuite.com
-http://www.scribd.com/doc/52210329/The-Masters-Augusta-National-s-Amen-Corner-up-close
-http://themeforest.net
-http://4399.com
-http://www.soku.com/v?keyword=barack%20obama
-http://google.se
-http://funmoods.com
-http://csdn.net
-http://telegraph.co.uk
-http://taringa.net
-http://www.tripadvisor.com/Tourism-g32701-Mendocino_California-Vacations.html
-http://pof.com
-http://wp.pl
-http://soundcloud.com/flosstradamus/tracks
-http://w3schools.com/html/default.asp
-http://ameblo.jp/staff/
-http://wsj.com
-http://web.de
-http://sweetim.com
-http://rambler.ru
-http://gmx.net
-http://www.indeed.com/jobs?q=software&l=Mountain+View%2C+CA
-http://ilivid.com
-http://www.xing.com/search/people?search%5Bq%5D=lufthansa
-http://reuters.com
-http://hostgator.com
-http://www.ikea.com/us/en/catalog/categories/departments/living_room/
-http://www.kaixin001.com/award2012/wenming/index.php
-http://ku6.com
-http://libero.it
-http://samsung.com
-http://hudong.com
-http://espncricinfo.com
-http://china.com
-http://www.ups.com/content/us/en/bussol/browse/smallbiz/new-to-ups.html?WT.svl=SolExp
-http://letv.com
-http://ero-advertising.com
-http://mashable.com
-http://iminent.com
-http://rutracker.org
-http://www.shopping.hp.com/en_US/home-office/-/products/Laptops/Laptops
-http://www.clickbank.com/buy_products.htm?dores=true&mainCategoryId=1340&sortField=POPULARITY&b1=1340
-http://b.hatena.ne.jp/
-http://www.youdao.com/search?q=barack+obama&ue=utf8&keyfrom=web.index
-http://forbes.com
-http://nbcnews.com
-http://bitauto.com
-http://php.net
-http://www.target.com/c/women/-/N-5xtd3#?lnk=nav_t_spc_1_0
-http://dianxin.cn
-http://www.aizhan.com/siteall/www.youboy.com/
-http://veiculos-home.mercadolivre.com.br/
-http://kakaku.com
-http://flipkart.com
-http://paipai.com
diff --git a/tools/gpu/gpu_tools/__init__.py b/tools/gpu/gpu_tools/__init__.py
new file mode 100644
index 0000000..ec38091
--- /dev/null
+++ b/tools/gpu/gpu_tools/__init__.py
@@ -0,0 +1,16 @@
+# 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.
+"""A library for Chrome GPU test code."""
+import os
+import sys
+
+def Init():
+ crc_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'chrome_remote_control')
+ absolute_crc_path = os.path.abspath(crc_path)
+ sys.path.append(absolute_crc_path)
+
+ import chrome_remote_control
+
+Init()
diff --git a/tools/gpu/pylib/file_server.py b/tools/gpu/gpu_tools/file_server.py
index 4056619..0f2bafc 100644
--- a/tools/gpu/pylib/file_server.py
+++ b/tools/gpu/gpu_tools/file_server.py
@@ -6,6 +6,8 @@ import subprocess
class FileServer(object):
def __init__(self, path, port=8000):
+ self._server = None
+ self._devnull = None
assert os.path.exists(path)
if os.path.isdir(path):
self._path = path
@@ -13,16 +15,30 @@ class FileServer(object):
self._path = os.path.dirname(path)
self._port = port
+
def __enter__(self):
+ self._devnull = open(os.devnull, 'w')
self._server = subprocess.Popen(
['python', '-m', 'SimpleHTTPServer', str(self._port)],
- cwd=self._path)
+ cwd=self._path,
+ stdout=self._devnull, stderr=self._devnull)
+ return self
+
+ @property
+ def url(self):
return 'http://localhost:%d' % self._port
def __exit__(self, *args):
- self._server.kill()
- self._server = None
+ if self._server:
+ self._server.kill()
+ self._server = None
+ if self._devnull:
+ self._devnull.close()
+ self._devnull = None
def __del__(self):
if self._server:
self._server.kill()
+ if self._devnull:
+ self._devnull.close()
+ self._devnull = None
diff --git a/tools/gpu/gpu_tools/page_scroller.py b/tools/gpu/gpu_tools/page_scroller.py
new file mode 100644
index 0000000..0dbb909
--- /dev/null
+++ b/tools/gpu/gpu_tools/page_scroller.py
@@ -0,0 +1,50 @@
+# 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.
+
+# The test takes a list of URLs through stdin and prints results in CSV format.
+# Example: python run_scroll_test.py < data/urls.txt > test_results.csv
+import csv
+import logging
+import os
+import sys
+
+import chrome_remote_control
+
+import scroll
+import page_set
+import url_test
+
+
+def Main(args):
+ options = chrome_remote_control.BrowserOptions()
+ parser = options.CreateParser("page_scroller <pageset>")
+ _, args = parser.parse_args(args)
+ if len(args) != 1:
+ parser.print_usage()
+ import page_sets
+ sys.stderr.write("Available pagesets:\n%s\n\n" % ",\n".join(
+ [os.path.relpath(f) for f in page_sets.GetAllPageSetFilenames()]))
+ sys.exit(1)
+
+ ps = page_set.PageSet()
+ ps.LoadFromFile(args[0])
+ return Run(sys.stdout, options, ps)
+
+def Run(output_stream, options, ps):
+ results_writer = csv.writer(output_stream)
+ results_writer.writerow(['URL', 'FPS', 'Mean Frame Time (s)',
+ '% Dropped Frames', 'First Paint Time (s)'])
+ possible_browser = chrome_remote_control.FindBrowser(options)
+ with possible_browser.Create() as b:
+ for result in url_test.UrlTest(b, scroll.Scroll, ps):
+ if not result.DidScroll():
+ # Most likely the page was shorter than the window height.
+ logging.warning('Page did not scroll: %s', result.GetUrl())
+ continue
+
+ results_writer.writerow([result.GetUrl(), result.GetFps(0),
+ result.GetMeanFrameTime(0),
+ result.GetPercentBelow60Fps(0),
+ result.GetFirstPaintTime()])
+ sys.stdout.flush()
diff --git a/tools/gpu/gpu_tools/page_scroller_unittest.py b/tools/gpu/gpu_tools/page_scroller_unittest.py
new file mode 100644
index 0000000..1129223
--- /dev/null
+++ b/tools/gpu/gpu_tools/page_scroller_unittest.py
@@ -0,0 +1,39 @@
+# 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 csv
+import os
+import unittest
+import StringIO
+
+import file_server
+import page_set
+import page_scroller
+import tempfile
+
+import chrome_remote_control.browser_options
+
+class ScrollTestUnitTest(unittest.TestCase):
+
+ def testBasicFunctionality(self):
+ scrollable_page_path = os.path.join(
+ os.path.dirname(__file__),
+ '..', 'unittest_data', 'scrollable_page.html')
+
+ result_count = 0
+ output = StringIO.StringIO()
+ with file_server.FileServer(scrollable_page_path) as server:
+ url = '%s/%s' % (server.url, os.path.basename(scrollable_page_path))
+
+ ps = page_set.PageSet()
+ ps.pages.append(page_set.Page(url))
+ options = chrome_remote_control.browser_options.options_for_unittests
+ page_scroller.Run(output, options, ps)
+
+ output.seek(0)
+ raw_rows = list(csv.reader(output))
+
+ header = raw_rows[0]
+ results = raw_rows[1:]
+ self.assertEqual(len(results), 1)
+ self.assertEqual(results[0][0], url, 'Did not navigate to right URL.')
diff --git a/tools/gpu/gpu_tools/page_set.py b/tools/gpu/gpu_tools/page_set.py
new file mode 100644
index 0000000..0fedb44
--- /dev/null
+++ b/tools/gpu/gpu_tools/page_set.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.
+import json
+import re
+
+class Page(object):
+ def __init__(self, url=None):
+ self.url = url
+
+ def __str__(self):
+ return self.url
+
+class PageSet(object):
+ def __init__(self):
+ self.pages = []
+ self.description = ""
+
+ def LoadFromFile(self, page_set_filename):
+ with open(page_set_filename, 'r') as f:
+ contents = f.read()
+ data = json.loads(contents)
+ self.LoadFromDict(data)
+
+ def LoadFromDict(self, data):
+ self.description = data["description"]
+ for p in data["pages"]:
+ page = Page()
+ for k,v in p.items():
+ if k == "url":
+ if not re.match('(.+)://', v):
+ v = 'http://%s' % v
+ setattr(page, k, v)
+ self.pages.append(page)
+
+ def __iter__(self):
+ return self.pages.__iter__()
diff --git a/tools/gpu/gpu_tools/page_set_unittest.py b/tools/gpu/gpu_tools/page_set_unittest.py
new file mode 100644
index 0000000..3050162
--- /dev/null
+++ b/tools/gpu/gpu_tools/page_set_unittest.py
@@ -0,0 +1,27 @@
+# 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 tempfile
+import unittest
+
+import page_set
+
+set1="""
+{"description": "hello",
+ "pages": [
+ {"url": "http://www.foo.com/"}
+ ]
+}
+"""
+
+class TestPageSet(unittest.TestCase):
+ def testSet1(self):
+ with tempfile.NamedTemporaryFile() as f:
+ f.write(set1)
+ f.flush()
+ ps = page_set.PageSet()
+ ps.LoadFromFile(f.name)
+
+ self.assertEquals("hello", ps.description)
+ self.assertEquals(1, len(ps.pages))
+ self.assertEquals("http://www.foo.com/", ps.pages[0].url)
diff --git a/tools/gpu/pylib/scroll.js b/tools/gpu/gpu_tools/scroll.js
index 48688d0..48688d0 100644
--- a/tools/gpu/pylib/scroll.js
+++ b/tools/gpu/gpu_tools/scroll.js
diff --git a/tools/gpu/pylib/scroll.py b/tools/gpu/gpu_tools/scroll.py
index fea5e3e..4a7effc 100644
--- a/tools/gpu/pylib/scroll.py
+++ b/tools/gpu/gpu_tools/scroll.py
@@ -6,7 +6,7 @@ import os
import chrome_remote_control
import scroll_results
-def Scroll(tab):
+def Scroll(page, tab):
scroll_js_path = os.path.join(os.path.dirname(__file__), 'scroll.js')
scroll_js = open(scroll_js_path, 'r').read()
@@ -22,7 +22,7 @@ def Scroll(tab):
# Poll for scroll result.
chrome_remote_control.WaitFor(
- lambda: tab.runtime.Evaluate('window.__scrollTestResult'))
+ lambda: tab.runtime.Evaluate('window.__scrollTestResult'), 60)
# Get scroll results.
url = tab.runtime.Evaluate('document.location.href')
diff --git a/tools/gpu/pylib/scroll_results.py b/tools/gpu/gpu_tools/scroll_results.py
index ea0ac19..ea0ac19 100644
--- a/tools/gpu/pylib/scroll_results.py
+++ b/tools/gpu/gpu_tools/scroll_results.py
diff --git a/tools/gpu/gpu_tools/url_test.py b/tools/gpu/gpu_tools/url_test.py
new file mode 100644
index 0000000..8475089
--- /dev/null
+++ b/tools/gpu/gpu_tools/url_test.py
@@ -0,0 +1,44 @@
+# 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 logging
+import re
+import time
+import traceback
+
+import chrome_remote_control
+
+def UrlTest(browser, test_method, page_set):
+ skipped_pages = []
+ with browser.ConnectToNthTab(0) as tab:
+ for page in page_set:
+ try:
+ logging.info('Loading %s...', page.url)
+ tab.page.Navigate(page.url)
+ # TODO(dtu): Detect HTTP redirects.
+ time.sleep(2) # Wait for unpredictable redirects.
+ tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+ logging.info('Loaded page: %s', page.url)
+ except chrome_remote_control.TimeoutException:
+ logging.warning('Timed out while loading: %s', page.url)
+ continue
+
+ try:
+ logging.info('Running test on %s...', page.url)
+ result = test_method(page, tab)
+ logging.info('Ran test:', page.url)
+ except:
+ logging.error('Failed on URL: %s', page.url)
+ traceback.print_exc()
+ skipped_pages.append(page)
+ continue
+
+ if not result:
+ logging.warning('No result for URL: %s', page.url)
+ skipped_pages.append(page)
+ continue
+
+ yield result
+
+ if len(skipped_pages) > 0:
+ logging.warning('Skipped pages: %s', skipped_page)
diff --git a/tools/gpu/page_sets/Q32012.json b/tools/gpu/page_sets/Q32012.json
new file mode 100644
index 0000000..d5b6b39
--- /dev/null
+++ b/tools/gpu/page_sets/Q32012.json
@@ -0,0 +1,223 @@
+{
+ "description": "Pages hand-picked from top-lists in Q32012.",
+ "pages": [
+ {"url": "http://www.facebook.com/barackobama"},
+ {"url": "https://www.google.com/search?q=barack%20obama"},
+ {"url": "http://youtube.com"},
+ {"url": "http://yahoo.com"},
+ {"url": "http://www.baidu.com/s?wd=barack+obama"},
+ {"url": "http://en.wikipedia.org/wiki/Wikipedia"},
+ {"url": "http://qq.com"},
+ {"url": "http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2"},
+ {"url": "http://googleblog.blogspot.com/"},
+ {"url": "http://taobao.com"},
+ {"url": "http://www.linkedin.com/in/linustorvalds"},
+ {"url": "http://yahoo.co.jp"},
+ {"url": "http://sina.com.cn"},
+ {"url": "http://msn.com"},
+ {"url": "http://yandex.ru/yandsearch?text=barack+obama"},
+ {"url": "http://translation.babylon.com/"},
+ {"url": "http://www.bing.com/search?q=barack+obama"},
+ {"url": "http://wordpress.org/news/"},
+ {"url": "http://www.ebay.com/sch/i.html?_nkw=antiques"},
+ {"url": "http://163.com"},
+ {"url": "http://www.soso.com/q?w=barack+obama"},
+ {"url": "http://www.microsoft.com/en-us/default.aspx"},
+ {"url": "http://go.mail.ru/search?mailru=1&mg=1&q=barack+obama"},
+ {"url": "http://vk.com/id118712387"},
+ {"url": "http://staff.tumblr.com/"},
+ {"url": "http://sohu.com"},
+ {"url": "http://sfbay.craigslist.org/mis/"},
+ {"url": "http://www.ask.com/web?q=barack+obama&search=&qsrc=0&o=0&l=dir"},
+ {"url": "http://www.apple.com/ipodtouch/"},
+ {"url": "http://blog.pinterest.com/"},
+ {"url": "http://pinterest.com/backdrophome/"},
+ {"url": "http://paypal.com"},
+ {"url": "http://bbc.co.uk"},
+ {"url": "http://www.avg.com/us-en/avg-premium-security"},
+ {"url": "http://googlesystem.blogspot.com/"},
+ {"url": "http://tudou.com"},
+ {"url": "http://blog.fc2.com/en/"},
+ {"url": "http://imdb.com"},
+ {"url": "http://youku.com"},
+ {"url": "http://www.flickr.com/photos/thomashawk/"},
+ {"url": "http://www.flickr.com/photos/thomashawk/sets/72157600284219965/detail/"},
+ {"url": "http://search.yahoo.com/search?ei=UTF-8&trackingType=go_search_home&p=barack+obama&fr=hsusgo1&sa.x=0&sa.y=0"},
+ {"url": "http://www.conduit.com/"},
+ {"url": "http://ifeng.com"},
+ {"url": "http://tmall.com"},
+ {"url": "http://hao123.com"},
+ {"url": "http://aol.com"},
+ {"url": "http://zedo.com"},
+ {"url": "http://search.mywebsearch.com/mywebsearch/GGmain.jhtml?searchfor=barack+obama"},
+ {"url": "http://cnn.com"},
+ {"url": "http://portal.ebay.de/deutschland-schraubt-angebote"},
+ {"url": "http://www.adobe.com/products/photoshopfamily.html?promoid=JOLIW"},
+ {"url": "http://global.rakuten.com/us/"},
+ {"url": "http://laundry.about.com/od/kidsandlaundry/f/How-Do-I-Wash-A-Backpack.htm"},
+ {"url": "http://thepiratebay.se/search/barack%20obama/0/99/0"},
+ {"url": "http://360buy.com"},
+ {"url": "http://huffingtonpost.com"},
+ {"url": "http://alibaba.com"},
+ {"url": "http://chinaz.com"},
+ {"url": "http://www.sogou.com/web?query=barack+obama"},
+ {"url": "http://www.amazon.de/gp/product/B0051QVF7A/ref=amb_link_170625867_1/275-4711375-4099801?ie=UTF8&nav_sdd=aps&pf_rd_m=A3JWKAKR8XB7XF&pf_rd_s=center-1&pf_rd_r=1C0XDBPB12WHDM63V11R&pf_rd_t=101&pf_rd_p=320475427&pf_rd_i=301128"},
+ {"url": "http://google.pl"},
+ {"url": "http://mediafire.com"},
+ {"url": "http://espn.go.com"},
+ {"url": "http://uol.com.br"},
+ {"url": "http://www.godaddy.com/products/secure-hosting.aspx?ci=72738"},
+ {"url": "http://imgur.com/gallery/b90ZE"},
+ {"url": "http://home.alipay.com/bank/paymentKJ.htm"},
+ {"url": "http://amazon.co.jp"},
+ {"url": "http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array"},
+ {"url": "http://www.google.com/doubleclick/"},
+ {"url": "http://search.4shared.com/q/CCAD/1/barack%20obama"},
+ {"url": "http://dailymotion.com"},
+ {"url": "http://globo.com"},
+ {"url": "http://instagram.com/developer/"},
+ {"url": "http://livedoor.com"},
+ {"url": "http://wordpress.org/showcase/"},
+ {"url": "http://bp.blogspot.com"},
+ {"url": "http://wigetmedia.com/advertisers"},
+ {"url": "http://www.search-results.com/web?&q=barack%20obama"},
+ {"url": "http://cnet.com"},
+ {"url": "http://nytimes.com"},
+ {"url": "http://torrentz.eu/search?f=barack+obama"},
+ {"url": "http://livejournal.com"},
+ {"url": "http://douban.com"},
+ {"url": "http://www.weather.com/weather/right-now/Mountain+View+CA+94043"},
+ {"url": "http://dailymail.co.uk"},
+ {"url": "http://www.tianya.cn/bbs/index.shtml"},
+ {"url": "http://ehow.com"},
+ {"url": "http://theproject.badoo.com/final.phtml"},
+ {"url": "http://www.bankofamerica.com/deposits/checksave/index.cfm?template=check_eBanking"},
+ {"url": "http://vimeo.com"},
+ {"url": "http://360.cn"},
+ {"url": "http://indiatimes.com"},
+ {"url": "http://deviantart.com"},
+ {"url": "http://reddit.com"},
+ {"url": "http://aweber.com"},
+ {"url": "http://warriorforum.com"},
+ {"url": "http://spiegel.de"},
+ {"url": "http://pconline.com.cn"},
+ {"url": "http://mozilla.org"},
+ {"url": "http://booking.com"},
+ {"url": "http://goo.ne.jp"},
+ {"url": "https://www.chase.com/online/Home-Lending/mortgages.htm"},
+ {"url": "http://addthis.com"},
+ {"url": "http://56.com"},
+ {"url": "http://news.blogfa.com/"},
+ {"url": "http://www.stumbleupon.com/jobs"},
+ {"url": "https://www.dropbox.com/about"},
+ {"url": "http://www.clicksor.com/publishers/adformat"},
+ {"url": "http://answers.com"},
+ {"url": "http://en.softonic.com/"},
+ {"url": "http://walmart.com"},
+ {"url": "http://pengyou.com"},
+ {"url": "http://outbrain.com"},
+ {"url": "http://comcast.net"},
+ {"url": "http://foxnews.com"},
+ {"url": "http://photobucket.com/findstuff/photography%20styles/"},
+ {"url": "http://bleach.wikia.com/?redirect=no"},
+ {"url": "http://sourceforge.net/projects/xoops/?source=frontpage&position=1"},
+ {"url": "http://onet.pl"},
+ {"url": "http://guardian.co.uk"},
+ {"url": "https://www.wellsfargo.com/jump/enterprise/doublediscount?msc=5589&mplx=10918-70119-3408-64"},
+ {"url": "http://wikimediafoundation.org/wiki/Home"},
+ {"url": "http://xunlei.com"},
+ {"url": "http://as.58.com/shuma/"},
+ {"url": "http://skype.com"},
+ {"url": "http://etsy.com"},
+ {"url": "http://bild.de"},
+ {"url": "http://search.naver.com/search.naver?where=nexearch&query=barack+obama&sm=top_hty&fbm=0&ie=utf8"},
+ {"url": "http://statcounter.com/features/?PHPSESSID=bbjcvjr681bcul4vqvgq2qgmo7"},
+ {"url": "http://iqiyi.com"},
+ {"url": "http://fbcdn.net"},
+ {"url": "http://www.myspace.com/browse/people"},
+ {"url": "http://allegro.pl/antyki-i-sztuka"},
+ {"url": "http://yesky.com"},
+ {"url": "http://justbeenpaid.com"},
+ {"url": "http://adultfriendfinder.com"},
+ {"url": "http://fiverr.com"},
+ {"url": "http://www.leboncoin.fr/annonces/offres/centre/"},
+ {"url": "http://dictionary.reference.com/"},
+ {"url": "http://realtime.rediff.com/instasearch#!barack%20obama"},
+ {"url": "http://zol.com.cn"},
+ {"url": "http://optmd.com"},
+ {"url": "http://www.filestube.com/search.html?q=barack+obama&select=All"},
+ {"url": "http://xinhuanet.com"},
+ {"url": "http://www.salesforce.com/sales-cloud/overview/"},
+ {"url": "http://www.squidoo.com/make-cards-and-gift-bags-with-antique-photos"},
+ {"url": "http://www.domaintools.com/research/"},
+ {"url": "http://download.cnet.com/windows/?tag=hdr;brandnav"},
+ {"url": "https://rapidshare.com/#!shop"},
+ {"url": "http://people.com.cn"},
+ {"url": "http://ucoz.ru"},
+ {"url": "http://free.fr"},
+ {"url": "http://nicovideo.jp"},
+ {"url": "http://www.yelp.com/search?find_desc=food&find_loc=San+Jose%2C+CA&ns=1"},
+ {"url": "http://slideshare.net"},
+ {"url": "http://archive.org/web/web.php"},
+ {"url": "http://www.cntv.cn/index.shtml"},
+ {"url": "http://english.cntv.cn/01/index.shtml"},
+ {"url": "http://abonnez-vous.orange.fr/residentiel/accueil/accueil.aspx"},
+ {"url": "http://v.it168.com/"},
+ {"url": "http://nbcolympics.com"},
+ {"url": "http://hootsuite.com"},
+ {"url": "http://www.scribd.com/doc/52210329/The-Masters-Augusta-National-s-Amen-Corner-up-close"},
+ {"url": "http://themeforest.net"},
+ {"url": "http://4399.com"},
+ {"url": "http://www.soku.com/v?keyword=barack%20obama"},
+ {"url": "http://google.se"},
+ {"url": "http://funmoods.com"},
+ {"url": "http://csdn.net"},
+ {"url": "http://telegraph.co.uk"},
+ {"url": "http://taringa.net"},
+ {"url": "http://www.tripadvisor.com/Tourism-g32701-Mendocino_California-Vacations.html"},
+ {"url": "http://pof.com"},
+ {"url": "http://wp.pl"},
+ {"url": "http://soundcloud.com/flosstradamus/tracks"},
+ {"url": "http://w3schools.com/html/default.asp"},
+ {"url": "http://ameblo.jp/staff/"},
+ {"url": "http://wsj.com"},
+ {"url": "http://web.de"},
+ {"url": "http://sweetim.com"},
+ {"url": "http://rambler.ru"},
+ {"url": "http://gmx.net"},
+ {"url": "http://www.indeed.com/jobs?q=software&l=Mountain+View%2C+CA"},
+ {"url": "http://ilivid.com"},
+ {"url": "http://www.xing.com/search/people?search%5Bq%5D=lufthansa"},
+ {"url": "http://reuters.com"},
+ {"url": "http://hostgator.com"},
+ {"url": "http://www.ikea.com/us/en/catalog/categories/departments/living_room/"},
+ {"url": "http://www.kaixin001.com/award2012/wenming/index.php"},
+ {"url": "http://ku6.com"},
+ {"url": "http://libero.it"},
+ {"url": "http://samsung.com"},
+ {"url": "http://hudong.com"},
+ {"url": "http://espncricinfo.com"},
+ {"url": "http://china.com"},
+ {"url": "http://www.ups.com/content/us/en/bussol/browse/smallbiz/new-to-ups.html?WT.svl=SolExp"},
+ {"url": "http://letv.com"},
+ {"url": "http://ero-advertising.com"},
+ {"url": "http://mashable.com"},
+ {"url": "http://iminent.com"},
+ {"url": "http://rutracker.org"},
+ {"url": "http://www.shopping.hp.com/en_US/home-office/-/products/Laptops/Laptops"},
+ {"url": "http://www.clickbank.com/buy_products.htm?dores=true&mainCategoryId=1340&sortField=POPULARITY&b1=1340"},
+ {"url": "http://b.hatena.ne.jp/"},
+ {"url": "http://www.youdao.com/search?q=barack+obama&ue=utf8&keyfrom=web.index"},
+ {"url": "http://forbes.com"},
+ {"url": "http://nbcnews.com"},
+ {"url": "http://bitauto.com"},
+ {"url": "http://php.net"},
+ {"url": "http://www.target.com/c/women/-/N-5xtd3#?lnk=nav_t_spc_1_0"},
+ {"url": "http://dianxin.cn"},
+ {"url": "http://www.aizhan.com/siteall/www.youboy.com/"},
+ {"url": "http://veiculos-home.mercadolivre.com.br/"},
+ {"url": "http://kakaku.com"},
+ {"url": "http://flipkart.com"},
+ {"url": "http://paipai.com"}
+ ]
+}
diff --git a/tools/gpu/page_sets/__init__.py b/tools/gpu/page_sets/__init__.py
new file mode 100644
index 0000000..8de2699
--- /dev/null
+++ b/tools/gpu/page_sets/__init__.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# 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
+def GetAllPageSetFilenames():
+ results = []
+ start_dir = os.path.dirname(__file__)
+ for (dirpath, dirnames, filenames) in os.walk(start_dir):
+ for f in filenames:
+ if os.path.splitext(f)[1] != ".json":
+ continue
+ filename = os.path.join(dirpath, f)
+ results.append(filename)
+ return results
diff --git a/tools/gpu/page_sets/page_sets_unittest.py b/tools/gpu/page_sets/page_sets_unittest.py
new file mode 100644
index 0000000..a33d9f7
--- /dev/null
+++ b/tools/gpu/page_sets/page_sets_unittest.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.
+import unittest
+
+import gpu_tools.page_set
+import page_sets
+
+class PageSetsUnittest(unittest.TestCase):
+ "Verfies that all the pagesets in this directory are syntactically valid."""
+
+ def testPageSetsParseCorrectly(self):
+ filenames = page_sets.GetAllPageSetFilenames()
+ for filename in filenames:
+ ps = gpu_tools.page_set.PageSet()
+ ps.LoadFromFile(filename)
+
diff --git a/tools/gpu/pylib/browser.py b/tools/gpu/pylib/browser.py
deleted file mode 100644
index 0882bac7..0000000
--- a/tools/gpu/pylib/browser.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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 chrome_remote_control
-
-def StartBrowser():
- parser = chrome_remote_control.BrowserOptions.CreateParser()
- options, _ = parser.parse_args()
-
- possible_browser = chrome_remote_control.FindBestPossibleBrowser(options)
- if possible_browser is None:
- raise Exception('No browsers found of the following types: %s.' %
- options.browser_types_to_use)
-
- return possible_browser.Create()
diff --git a/tools/gpu/pylib/url_test.py b/tools/gpu/pylib/url_test.py
deleted file mode 100644
index c3a5ed2..0000000
--- a/tools/gpu/pylib/url_test.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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 logging
-import re
-import traceback
-
-import browser
-import chrome_remote_control
-
-def UrlTest(test_method, url_list):
- skipped_urls = []
- with browser.StartBrowser() as b:
- with b.ConnectToNthTab(0) as tab:
- for url in url_list:
- url = url.strip()
- if not url:
- continue
- if not re.match('(.+)://', url):
- url = 'http://%s' % url
-
- try:
- logging.info('Loading %s...', url)
- tab.LoadUrl(url)
- logging.info('Loaded page: %s', url)
- except chrome_remote_control.TimeoutException:
- logging.warning('Timed out while loading: %s', url)
- continue
-
- try:
- logging.info('Running test on %s...', url)
- result = test_method(tab)
- logging.info('Ran test:', url)
- except:
- logging.error('Failed on URL: %s', url)
- traceback.print_exc()
- skipped_urls.append(url)
- continue
-
- if not result:
- logging.warning('No result for URL: %s', url)
- skipped_urls.append(url)
- continue
-
- yield result
-
- if len(skipped_urls) > 0:
- logging.warning('Skipped URLs: %s', skipped_urls)
diff --git a/tools/gpu/run_gpu_tools_unittests b/tools/gpu/run_gpu_tools_unittests
new file mode 100755
index 0000000..222ae09
--- /dev/null
+++ b/tools/gpu/run_gpu_tools_unittests
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# 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.
+"""
+This script runs tests to verify that the gpu tools are working.
+
+The actual performance tools are not run by this script.
+"""
+import os
+import sys
+
+import gpu_tools
+import chrome_remote_control.run_tests
+
+if __name__ == "__main__":
+ top_level_dir = os.path.abspath(
+ os.path.dirname(__file__))
+ start_dir = "gpu_tools"
+ ret = chrome_remote_control.run_tests.Main(
+ sys.argv[1:], start_dir, top_level_dir)
+
+ start_dir = "page_sets"
+ ret = chrome_remote_control.run_tests.Main(
+ sys.argv[1:], start_dir, top_level_dir)
+
+ sys.exit(ret)
diff --git a/tools/gpu/pylib/__init__.py b/tools/gpu/run_page_scroller
index e20abd1..c580609 100644..100755
--- a/tools/gpu/pylib/__init__.py
+++ b/tools/gpu/run_page_scroller
@@ -1,9 +1,11 @@
+#!/usr/bin/env python
# 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.
-"""A library for Chrome-based tests."""
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__),
- '..', '..', 'chrome_remote_control'))
+import gpu_tools.page_scroller
+
+if __name__ == "__main__":
+ sys.exit(gpu_tools.page_scroller.Main(sys.argv[1:]))
diff --git a/tools/gpu/run_scroll_test.py b/tools/gpu/run_scroll_test.py
deleted file mode 100755
index a6405a1..0000000
--- a/tools/gpu/run_scroll_test.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-# The test takes a list of URLs through stdin and prints results in CSV format.
-# Example: python run_scroll_test.py < data/urls.txt > test_results.csv
-import csv
-import logging
-import sys
-
-import pylib.scroll
-import pylib.url_test
-
-def Main():
- results_writer = csv.writer(sys.stdout)
- results_writer.writerow(['URL', 'FPS', 'Mean Frame Time (s)',
- '% Dropped Frames', 'First Paint Time (s)'])
- sys.stdout.flush()
-
- for result in pylib.url_test.UrlTest(pylib.scroll.Scroll, sys.stdin):
- if not result.DidScroll():
- # Most likely the page was shorter than the window height.
- logging.warning('Page did not scroll: %s', result.GetUrl())
- continue
-
- results_writer.writerow([result.GetUrl(), result.GetFps(0),
- result.GetMeanFrameTime(0),
- result.GetPercentBelow60Fps(0),
- result.GetFirstPaintTime()])
- sys.stdout.flush()
-
-if __name__ == '__main__':
- Main()
diff --git a/tools/gpu/scroll_test_unittest.py b/tools/gpu/scroll_test_unittest.py
deleted file mode 100755
index e2c295f..0000000
--- a/tools/gpu/scroll_test_unittest.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# 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
-import unittest
-
-import pylib.file_server
-import pylib.scroll
-import pylib.url_test
-
-class ScrollTestUnitTest(unittest.TestCase):
-
- def runTest(self):
- test_file_path = os.path.join(os.path.dirname(__file__),
- 'data', 'scrollable_page.html')
-
- result_count = 0
- with pylib.file_server.FileServer(test_file_path) as root_url:
- url = '%s/%s' % (root_url, os.path.basename(test_file_path))
- for result in pylib.url_test.UrlTest(pylib.scroll.Scroll, [url]):
- result_count += 1
-
- self.assertEqual(result_count, 1, 'Wrong number of test results.')
- self.assertEqual(result.GetUrl(), url, 'Did not navigate to right URL.')
- self.assertTrue(result.GetFirstPaintTime() < 1, 'The page load was slow.')
- self.assertTrue(result.GetFps(0) > 55, 'Scroll seemed kind of slow.')
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/gpu/data/scrollable_page.html b/tools/gpu/unittest_data/scrollable_page.html
index 5dcdd4f..5dcdd4f 100644
--- a/tools/gpu/data/scrollable_page.html
+++ b/tools/gpu/unittest_data/scrollable_page.html