Commit d5f6ea98 authored by zhenw's avatar zhenw Committed by Commit bot

Telemetry --device

Enable Telemetry to discover devices and find browsers for each device.

BUG=435723

Review URL: https://codereview.chromium.org/760653002

Cr-Commit-Position: refs/heads/master@{#314420}
parent af499319
......@@ -200,14 +200,13 @@ def _FindAllPossibleBrowsers(finder_options, android_platform):
return possible_browsers
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Finds all the possible browsers on one device.
The device is either the only device on the host platform,
or |finder_options| specifies a particular device.
"""
device = android_device.GetDevice(finder_options)
if not device:
if not isinstance(device, android_device.AndroidDevice):
return []
android_platform = platform.GetPlatformForDevice(device, finder_options)
return _FindAllPossibleBrowsers(finder_options, android_platform)
......@@ -16,10 +16,6 @@ from telemetry.core.backends.chrome import cros_browser_backend
from telemetry.core.backends.chrome import cros_browser_with_oobe
def _IsRunningOnCrOS():
return platform_module.GetHostPlatform().GetOSName() == 'chromeos'
class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
"""A launchable CrOS browser instance."""
def __init__(self, browser_type, finder_options, cros_platform, is_guest):
......@@ -65,14 +61,14 @@ class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
pass
def SelectDefaultBrowser(possible_browsers):
if _IsRunningOnCrOS():
if cros_device.IsRunningOnCrOS():
for b in possible_browsers:
if b.browser_type == 'system':
return b
return None
def CanFindAvailableBrowsers(finder_options):
return (_IsRunningOnCrOS() or
return (cros_device.IsRunningOnCrOS() or
finder_options.cros_remote or
cros_interface.HasSSH())
......@@ -84,9 +80,12 @@ def FindAllBrowserTypes(_):
'system-guest',
]
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Finds all available CrOS browsers, locally and remotely."""
if _IsRunningOnCrOS():
if not isinstance(device, cros_device.CrOSDevice):
return []
if cros_device.IsRunningOnCrOS():
return [PossibleCrOSBrowser('system', finder_options,
platform_module.GetHostPlatform(),
is_guest=False),
......@@ -94,16 +93,6 @@ def FindAllAvailableBrowsers(finder_options):
platform_module.GetHostPlatform(),
is_guest=True)]
if finder_options.cros_remote == None:
logging.debug('No --remote specified, will not probe for CrOS.')
return []
if not cros_interface.HasSSH():
logging.debug('ssh not found. Cannot talk to CrOS devices.')
return []
device = cros_device.CrOSDevice(
finder_options.cros_remote, finder_options.cros_remote_ssh_port,
finder_options.cros_ssh_identity)
# Check ssh
try:
platform = platform_module.GetPlatformForDevice(device, finder_options)
......
......@@ -13,6 +13,7 @@ from telemetry.core import browser
from telemetry.core import exceptions
from telemetry.core import possible_browser
from telemetry.core.backends.chrome import desktop_browser_backend
from telemetry.core.platform import desktop_device
from telemetry.util import path
......@@ -113,8 +114,11 @@ def FindAllBrowserTypes(_):
'content-shell-release_x64',
'system']
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Finds all the desktop browsers available on this machine."""
if not isinstance(device, desktop_device.DesktopDevice):
return []
browsers = []
if not CanFindAvailableBrowsers():
......
......@@ -5,6 +5,7 @@ import unittest
from telemetry.core import browser_options
from telemetry.core.backends.chrome import desktop_browser_finder
from telemetry.core.platform import desktop_device
from telemetry.unittest_util import system_stub
......@@ -32,7 +33,8 @@ class FindTestBase(unittest.TestCase):
return self._path_stubs.os.path.files
def DoFindAll(self):
return desktop_browser_finder.FindAllAvailableBrowsers(self._finder_options)
return desktop_browser_finder.FindAllAvailableBrowsers(
self._finder_options, desktop_device.DesktopDevice())
def DoFindAllTypes(self):
browsers = self.DoFindAll()
......
......@@ -14,6 +14,7 @@ from telemetry.core import platform
from telemetry.core import possible_browser
from telemetry.core.backends.chrome_inspector import inspector_backend
from telemetry.core.backends.chrome import ios_browser_backend
from telemetry.core.platform import ios_device
from telemetry.core.platform import ios_platform_backend
......@@ -66,21 +67,12 @@ def FindAllBrowserTypes(_):
return IOS_BROWSERS.values()
@decorators.Cache
def _IsIosDeviceAttached():
devices = subprocess.check_output('system_profiler SPUSBDataType', shell=True)
for line in devices.split('\n'):
if line and re.match(r'\s*(iPod|iPhone|iPad):', line):
return True
return False
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Find all running iOS browsers on connected devices."""
if not CanFindAvailableBrowsers():
if not isinstance(device, ios_device.IOSDevice):
return []
if not _IsIosDeviceAttached():
if not CanFindAvailableBrowsers():
return []
options = finder_options.browser_options
......
......@@ -6,6 +6,7 @@ import unittest
from telemetry import decorators
from telemetry.core import browser_options
from telemetry.core.backends.chrome import ios_browser_finder
from telemetry.core.platform import ios_device
class IosBrowserFinderUnitTest(unittest.TestCase):
......@@ -15,7 +16,8 @@ class IosBrowserFinderUnitTest(unittest.TestCase):
@decorators.Enabled('ios')
def testFindIosChrome(self):
finder_options = browser_options.BrowserFinderOptions()
browsers = ios_browser_finder.FindAllAvailableBrowsers(finder_options)
browsers = ios_browser_finder.FindAllAvailableBrowsers(
finder_options, ios_device.IOSDevice())
self.assertTrue(browsers)
for browser in browsers:
self.assertEqual('ios-chrome', browser.browser_type)
......
......@@ -15,12 +15,14 @@ import urllib2
from telemetry import decorators
from telemetry.core import platform
from telemetry.core import possible_browser
from telemetry.core.platform import trybot_device
CHROMIUM_CONFIG_FILENAME = 'tools/run-perf-test.cfg'
BLINK_CONFIG_FILENAME = 'Tools/run-perf-test.cfg'
SUCCESS, NO_CHANGES, ERROR = range(3)
class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
"""A script that sends a job to a trybot."""
......@@ -34,7 +36,7 @@ class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
raise NotImplementedError()
def SupportsOptions(self, finder_options):
if (finder_options.android_device or
if ((finder_options.device and finder_options.device != 'trybot') or
finder_options.chrome_root or
finder_options.cros_remote or
finder_options.extensions_to_load or
......@@ -250,7 +252,10 @@ def FindAllBrowserTypes(finder_options):
return []
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Find all perf trybots on tryserver.chromium.perf."""
if not isinstance(device, trybot_device.TrybotDevice):
return []
return [PossibleTrybotBrowser(b, finder_options) for b in
FindAllBrowserTypes(finder_options)]
......@@ -12,6 +12,7 @@ from telemetry.core import platform as platform_module
from telemetry.core import possible_browser
from telemetry.core import util
from telemetry.core.backends.webdriver import webdriver_ie_backend
from telemetry.core.platform import desktop_device
from telemetry.util import support_binaries
# Try to import the selenium python lib which may be not available.
......@@ -96,8 +97,11 @@ def FindAllBrowserTypes(_):
'https://code.google.com/p/selenium/wiki/PythonBindings.')
return []
def FindAllAvailableBrowsers(finder_options):
def FindAllAvailableBrowsers(finder_options, device):
"""Finds all the desktop browsers available on this machine."""
if not isinstance(device, desktop_device.DesktopDevice):
return []
browsers = []
if not webdriver:
return browsers
......
......@@ -9,6 +9,7 @@ import operator
from telemetry import decorators
from telemetry.core import browser_finder_exceptions
from telemetry.core import device_finder
from telemetry.core.backends.chrome import android_browser_finder
from telemetry.core.backends.chrome import cros_browser_finder
from telemetry.core.backends.chrome import desktop_browser_finder
......@@ -60,17 +61,24 @@ def FindBrowser(options):
raise browser_finder_exceptions.BrowserFinderException(
'--remote requires --browser=cros-chrome or cros-chrome-guest.')
devices = []
if options.device and options.device != 'list':
devices = device_finder.GetSpecifiedDevices(options)
else:
devices = device_finder.GetAllAvailableDevices(options)
browsers = []
default_browsers = []
for finder in BROWSER_FINDERS:
if(options.browser_type and options.browser_type != 'any' and
options.browser_type not in finder.FindAllBrowserTypes(options)):
continue
curr_browsers = finder.FindAllAvailableBrowsers(options)
new_default_browser = finder.SelectDefaultBrowser(curr_browsers)
if new_default_browser:
default_browsers.append(new_default_browser)
browsers.extend(curr_browsers)
for device in devices:
for finder in BROWSER_FINDERS:
if(options.browser_type and options.browser_type != 'any' and
options.browser_type not in finder.FindAllBrowserTypes(options)):
continue
curr_browsers = finder.FindAllAvailableBrowsers(options, device)
new_default_browser = finder.SelectDefaultBrowser(curr_browsers)
if new_default_browser:
default_browsers.append(new_default_browser)
browsers.extend(curr_browsers)
if options.browser_type == None:
if default_browsers:
......@@ -124,6 +132,29 @@ def FindBrowser(options):
return chosen_browser
@decorators.Cache
def GetAllAvailableBrowsers(options, device):
"""Returns a list of available browsers on the device.
Args:
options: A BrowserOptions object.
device: The target device, which can be None.
Returns:
A list of browser instances.
Raises:
BrowserFinderException: Options are improperly set, or an error occurred.
"""
if not device:
return []
possible_browsers = []
for browser_finder in BROWSER_FINDERS:
possible_browsers.extend(
browser_finder.FindAllAvailableBrowsers(options, device))
return possible_browsers
@decorators.Cache
def GetAllAvailableBrowserTypes(options):
"""Returns a list of available browser types.
......@@ -137,11 +168,11 @@ def GetAllAvailableBrowserTypes(options):
Raises:
BrowserFinderException: Options are improperly set, or an error occurred.
"""
browsers = []
for finder in BROWSER_FINDERS:
browsers.extend(finder.FindAllAvailableBrowsers(options))
type_list = set([browser.browser_type for browser in browsers])
devices = device_finder.GetAllAvailableDevices(options)
possible_browsers = []
for device in devices:
possible_browsers.extend(GetAllAvailableBrowsers(options, device))
type_list = set([browser.browser_type for browser in possible_browsers])
type_list = list(type_list)
type_list.sort()
return type_list
......@@ -12,6 +12,7 @@ import sys
from telemetry.core import browser_finder
from telemetry.core import browser_finder_exceptions
from telemetry.core import device_finder
from telemetry.core import platform
from telemetry.core import profile_types
from telemetry.core import util
......@@ -32,7 +33,7 @@ class BrowserFinderOptions(optparse.Values):
self.browser_type = browser_type
self.browser_executable = None
self.chrome_root = None
self.android_device = None
self.device = None
self.cros_ssh_identity = None
self.extensions_to_load = []
......@@ -76,8 +77,8 @@ class BrowserFinderOptions(optparse.Values):
help='Where to look for chrome builds.'
'Defaults to searching parent dirs by default.')
group.add_option('--device',
dest='android_device',
help='The android device ID to use'
dest='device',
help='The device ID to use.'
'If not specified, only 0 or 1 connected devices are supported.')
group.add_option('--target-arch',
dest='target_arch',
......@@ -159,16 +160,40 @@ class BrowserFinderOptions(optparse.Values):
else:
logging.getLogger().setLevel(logging.WARNING)
if self.device == 'list':
devices = device_finder.GetAllAvailableDeviceNames(self)
print 'Available devices:'
for device in devices:
print ' ', device
sys.exit(0)
if self.browser_executable and not self.browser_type:
self.browser_type = 'exact'
if self.browser_type == 'list':
try:
types = browser_finder.GetAllAvailableBrowserTypes(self)
except browser_finder_exceptions.BrowserFinderException, ex:
sys.stderr.write('ERROR: ' + str(ex))
sys.exit(1)
sys.stdout.write('Available browsers:\n')
sys.stdout.write(' %s\n' % '\n '.join(types))
devices = []
if self.device and self.device != 'list':
devices = device_finder.GetSpecifiedDevices(self)
else:
devices = device_finder.GetAllAvailableDevices(self)
if not devices:
sys.exit(0)
browser_types = {}
for device in devices:
try:
possible_browsers = browser_finder.GetAllAvailableBrowsers(self,
device)
browser_types[device.name] = sorted(
[browser.browser_type for browser in possible_browsers])
except browser_finder_exceptions.BrowserFinderException as ex:
print >> sys.stderr, 'ERROR: ', ex
sys.exit(1)
print 'Available browsers:'
if len(browser_types) == 0:
print ' No devices were found.'
for device_name in sorted(browser_types.keys()):
print ' ', device_name
for browser_type in browser_types[device_name]:
print ' ', browser_type
sys.exit(0)
# Parse browser options.
......
# Copyright 2014 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.
"""Finds devices that can be controlled by telemetry."""
import logging
from telemetry.core.platform import android_device
from telemetry.core.platform import cros_device
from telemetry.core.platform import desktop_device
from telemetry.core.platform import ios_device
from telemetry.core.platform import trybot_device
DEVICES = [
android_device,
cros_device,
desktop_device,
ios_device,
trybot_device,
]
def GetAllAvailableDevices(options):
"""Returns a list of all available devices."""
devices = []
for device in DEVICES:
devices.extend(device.FindAllAvailableDevices(options))
devices.sort(key=lambda device: device.name)
return devices
def GetAllAvailableDeviceNames(options):
"""Returns a list of all available device names."""
devices = GetAllAvailableDevices(options)
device_names = [device.name for device in devices]
return device_names
def GetSpecifiedDevices(options):
"""Returns the specified devices."""
assert options.device and options.device != 'list'
devices = GetAllAvailableDevices(options)
devices = [d for d in devices if d.guid == options.device]
return devices
......@@ -31,17 +31,30 @@ class AndroidDevice(device.Device):
@classmethod
def GetAllConnectedDevices(cls):
device_serials = adb_commands.GetAttachedDevices()
# The monsoon provides power for the device, so for devices with no
# real battery, we need to turn them on after the monsoon enables voltage
# output to the device.
if not device_serials:
try:
m = monsoon.Monsoon(wait=False)
m.SetUsbPassthrough(1)
m.SetVoltage(3.8)
m.SetMaxCurrent(8)
logging.warn("""
device_serials = GetDeviceSerials()
return [cls(s) for s in device_serials]
@property
def device_id(self):
return self._device_id
@property
def enable_performance_mode(self):
return self._enable_performance_mode
def GetDeviceSerials():
device_serials = adb_commands.GetAttachedDevices()
# The monsoon provides power for the device, so for devices with no
# real battery, we need to turn them on after the monsoon enables voltage
# output to the device.
if not device_serials:
try:
m = monsoon.Monsoon(wait=False)
m.SetUsbPassthrough(1)
m.SetVoltage(3.8)
m.SetMaxCurrent(8)
logging.warn("""
Monsoon power monitor detected, but no Android devices.
The Monsoon's power output has been enabled. Please now ensure that:
......@@ -52,19 +65,11 @@ The Monsoon's power output has been enabled. Please now ensure that:
Waiting for device...
""")
util.WaitFor(adb_commands.GetAttachedDevices, 600)
device_serials = adb_commands.GetAttachedDevices()
except IOError:
return []
return [cls(s) for s in device_serials]
@property
def device_id(self):
return self._device_id
@property
def enable_performance_mode(self):
return self._enable_performance_mode
util.WaitFor(adb_commands.GetAttachedDevices, 600)
device_serials = adb_commands.GetAttachedDevices()
except IOError:
return []
return device_serials
def GetDevice(finder_options):
......@@ -74,9 +79,9 @@ def GetDevice(finder_options):
'No adb command found. Will not try searching for Android browsers.')
return None
if finder_options.android_device:
if finder_options.device and finder_options.device in GetDeviceSerials():
return AndroidDevice(
finder_options.android_device,
finder_options.device,
enable_performance_mode=not finder_options.no_performance_mode)
devices = AndroidDevice.GetAllConnectedDevices()
......@@ -121,3 +126,11 @@ def CanDiscoverDevices():
return True
return False
def FindAllAvailableDevices(_):
"""Returns a list of available devices.
"""
if not CanDiscoverDevices():
return []
else:
return AndroidDevice.GetAllConnectedDevices()
......@@ -83,7 +83,7 @@ class GetDeviceTest(unittest.TestCase):
def testAdbPickOneDeviceReturnsDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
finder_options.android_device = '555d14fecddddddd' # pick one
finder_options.device = '555d14fecddddddd' # pick one
self._android_device_stub.adb_commands.attached_devices = [
'015d14fec128220c', '555d14fecddddddd']
device = android_device.GetDevice(finder_options)
......@@ -97,3 +97,44 @@ class GetDeviceTest(unittest.TestCase):
device = android_device.GetDevice(finder_options)
self.assertEquals([], self._android_device_stub.logging.warnings)
self.assertEquals('015d14fec128220c', device.device_id)
class FindAllAvailableDevicesTest(unittest.TestCase):
def setUp(self):
self._android_device_stub = system_stub.Override(
android_device, ['adb_commands', 'os', 'subprocess', 'logging'])
self._apb_stub = system_stub.Override(
android_platform_backend, ['adb_commands'])
def tearDown(self):
self._android_device_stub.Restore()
self._apb_stub.Restore()
def testAdbNoDeviceReturnsEmptyList(self):
finder_options = browser_options.BrowserFinderOptions()
devices = android_device.FindAllAvailableDevices(finder_options)
self.assertEquals([], self._android_device_stub.logging.warnings)
self.assertIsNotNone(devices)
self.assertEquals(len(devices), 0)
def testAdbOneDeviceReturnsListWithOneDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
self._android_device_stub.adb_commands.attached_devices = (
['015d14fec128220c'])
devices = android_device.FindAllAvailableDevices(finder_options)
self.assertEquals([], self._android_device_stub.logging.warnings)
self.assertIsNotNone(devices)
self.assertEquals(len(devices), 1)
self.assertEquals('015d14fec128220c', devices[0].device_id)
def testAdbMultipleDevicesReturnsListWithAllDeviceInstances(self):
finder_options = browser_options.BrowserFinderOptions()
self._android_device_stub.adb_commands.attached_devices = [
'015d14fec128220c', '015d14fec128220d', '015d14fec128220e']
devices = android_device.FindAllAvailableDevices(finder_options)
self.assertEquals([], self._android_device_stub.logging.warnings)
self.assertIsNotNone(devices)
self.assertEquals(len(devices), 3)
self.assertEquals(devices[0].guid, '015d14fec128220c')
self.assertEquals(devices[1].guid, '015d14fec128220d')
self.assertEquals(devices[2].guid, '015d14fec128220e')
# Copyright 2014 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
from telemetry.core import platform
from telemetry.core.platform import cros_interface
from telemetry.core.platform import device
......@@ -29,3 +33,25 @@ class CrOSDevice(device.Device):
@property
def ssh_identity(self):
return self._ssh_identity
def IsRunningOnCrOS():
return platform.GetHostPlatform().GetOSName() == 'chromeos'
def FindAllAvailableDevices(options):
"""Returns a list of available device types.
"""
if IsRunningOnCrOS():
return [CrOSDevice('localhost', -1)]
if options.cros_remote == None:
logging.debug('No --remote specified, will not probe for CrOS.')
return []
if not cros_interface.HasSSH():
logging.debug('ssh not found. Cannot talk to CrOS devices.')
return []
return [CrOSDevice(options.cros_remote, options.cros_remote_ssh_port,
options.cros_ssh_identity)]
# Copyright 2014 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.core import platform
from telemetry.core.platform import device
class DesktopDevice(device.Device):
def __init__(self):
super(DesktopDevice, self).__init__(name='desktop', guid='desktop')
@classmethod
def GetAllConnectedDevices(cls):
return []
def FindAllAvailableDevices(_):
"""Returns a list of available devices.
"""
# If the host platform is Chrome OS, the device is also considered as cros.
if platform.GetHostPlatform().GetOSName() == 'chromeos':
return []
return [DesktopDevice()]
\ No newline at end of file
# Copyright 2014 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 re
import subprocess
from telemetry.core import platform
from telemetry.core.platform import device
class IOSDevice(device.Device):
def __init__(self):
super(IOSDevice, self).__init__(name='ios', guid='ios')
@classmethod
def GetAllConnectedDevices(cls):
return []
def _IsIosDeviceAttached():
devices = subprocess.check_output('system_profiler SPUSBDataType', shell=True)
for line in devices.split('\n'):
if line and re.match(r'\s*(iPod|iPhone|iPad):', line):
return True
return False
def FindAllAvailableDevices(_):
"""Returns a list of available devices.
"""
# TODO(baxley): Add support for all platforms possible. Probably Linux,
# probably not Windows.
if platform.GetHostPlatform().GetOSName() != 'mac':
return []
if not _IsIosDeviceAttached():
return []
return [IOSDevice()]
\ No newline at end of file
# Copyright 2014 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.core.platform import device
class TrybotDevice(device.Device):
def __init__(self):
super(TrybotDevice, self).__init__(name='trybot', guid='trybot')
@classmethod
def GetAllConnectedDevices(cls):
return []
def FindAllAvailableDevices(_):
"""Returns a list of available devices.
"""
return [TrybotDevice()]
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment