0

Parallelize telemetry unit tests on Android bots

BUG=379378

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

Cr-Commit-Position: refs/heads/master@{#317621}
This commit is contained in:
zhenw
2015-02-23 11:34:33 -08:00
committed by Commit bot
parent f7767d78cf
commit ac997d3fdc
10 changed files with 65 additions and 51 deletions

@ -143,6 +143,9 @@ def _CreateOptionParser():
action='store_true')
parser.add_option('-z', '--compress', help='Compress the resulting trace '
'with gzip. ', action='store_true')
parser.add_option('-d', '--device', help='The Android device ID to use.'
'If not specified, only 0 or 1 connected devices are '
'supported.', default=None)
return parser
@ -162,9 +165,10 @@ When in doubt, just try out --trace-frame-viewer.
logging.getLogger().setLevel(logging.DEBUG)
devices = android_commands.GetAttachedDevices()
if len(devices) != 1:
if not options.device and len(devices) != 1:
parser.error('Exactly 1 device must be attached.')
device = device_utils.DeviceUtils(devices[0])
device = device_utils.DeviceUtils(
next((d for d in devices if d == options.device), devices[0]))
package_info = profiler.GetSupportedBrowsers()[options.browser]
if options.chrome_categories in ['list', 'help']:

@ -8,6 +8,7 @@ import unittest
from telemetry import benchmark
from telemetry.core.backends import adb_commands
from telemetry.core.backends import android_command_line_backend
from telemetry.unittest_util import options_for_unittests
class _MockBackendSettings(object):
pseudo_exec_name = 'chrome'
@ -48,7 +49,9 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = adb_commands.GetAttachedDevices()[0]
serial = options_for_unittests.GetCopy().device
if not serial:
serial = adb_commands.GetAttachedDevices()[0]
cmd_file = '/data/local/tmp/test_cmd'
adb = adb_commands.AdbCommands(device=serial)
backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd')
@ -69,7 +72,9 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = adb_commands.GetAttachedDevices()[0]
serial = options_for_unittests.GetCopy().device
if not serial:
serial = adb_commands.GetAttachedDevices()[0]
cmd_file = '/data/local/tmp/test_cmd'
adb = adb_commands.AdbCommands(device=serial)
backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd')

@ -61,12 +61,7 @@ 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)
devices = device_finder.GetDevicesMatchingOptions(options)
browsers = []
default_browsers = []
for device in devices:
@ -168,7 +163,7 @@ def GetAllAvailableBrowserTypes(options):
Raises:
BrowserFinderException: Options are improperly set, or an error occurred.
"""
devices = device_finder.GetAllAvailableDevices(options)
devices = device_finder.GetDevicesMatchingOptions(options)
possible_browsers = []
for device in devices:
possible_browsers.extend(GetAllAvailableBrowsers(options, device))

@ -79,7 +79,8 @@ class BrowserFinderOptions(optparse.Values):
group.add_option('--device',
dest='device',
help='The device ID to use.'
'If not specified, only 0 or 1 connected devices are supported.')
'If not specified, only 0 or 1 connected devices are supported. If'
'specified as "android", all available Android devices are used.')
group.add_option('--target-arch',
dest='target_arch',
help='The target architecture of the browser. Options available are: '
@ -161,20 +162,16 @@ class BrowserFinderOptions(optparse.Values):
logging.getLogger().setLevel(logging.WARNING)
if self.device == 'list':
devices = device_finder.GetAllAvailableDeviceNames(self)
devices = device_finder.GetDevicesMatchingOptions(self)
print 'Available devices:'
for device in devices:
print ' ', device
print ' ', device.name
sys.exit(0)
if self.browser_executable and not self.browser_type:
self.browser_type = 'exact'
if self.browser_type == 'list':
devices = []
if self.device and self.device != 'list':
devices = device_finder.GetSpecifiedDevices(self)
else:
devices = device_finder.GetAllAvailableDevices(self)
devices = device_finder.GetDevicesMatchingOptions(self)
if not devices:
sys.exit(0)
browser_types = {}

@ -21,25 +21,24 @@ DEVICES = [
]
def GetAllAvailableDevices(options):
def _GetAllAvailableDevices(options):
"""Returns a list of all available devices."""
devices = []
for device in DEVICES:
devices.extend(device.FindAllAvailableDevices(options))
return devices
def GetDevicesMatchingOptions(options):
"""Returns a list of devices matching the options."""
devices = []
if not options.device or options.device == 'list':
devices = _GetAllAvailableDevices(options)
elif options.device == 'android':
devices = android_device.FindAllAvailableDevices(options)
else:
devices = _GetAllAvailableDevices(options)
devices = [d for d in devices if d.guid == options.device]
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
return devices

@ -24,7 +24,8 @@ _SYSTRACE_CATEGORIES = [
class AndroidSystraceProfiler(profiler.Profiler):
"""Collects a Systrace on Android."""
def __init__(self, browser_backend, platform_backend, output_path, state):
def __init__(self, browser_backend, platform_backend, output_path, state,
device=None):
super(AndroidSystraceProfiler, self).__init__(
browser_backend, platform_backend, output_path, state)
assert self._browser_backend.supports_tracing
@ -37,13 +38,15 @@ class AndroidSystraceProfiler(profiler.Profiler):
options = tracing_options.TracingOptions()
options.enable_chrome_trace = True
self._browser_backend.StartTracing(options, timeout=10)
self._profiler = subprocess.Popen(
['python', os.path.join(util.GetChromiumSrcDir(), 'tools',
'profile_chrome.py'),
'--categories', '', '--continuous', '--output',
self._systrace_output_path, '--json', '--systrace',
','.join(_SYSTRACE_CATEGORIES)],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
command = ['python', os.path.join(util.GetChromiumSrcDir(), 'tools',
'profile_chrome.py'),
'--categories', '', '--continuous', '--output',
self._systrace_output_path, '--json', '--systrace',
','.join(_SYSTRACE_CATEGORIES)]
if device:
command.extend(['--device', device])
self._profiler = subprocess.Popen(command, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
@classmethod
def name(cls):

@ -21,7 +21,8 @@ class TestAndroidSystraceProfiler(tab_test_case.TabTestCase):
self._browser._browser_backend,
self._browser._platform_backend,
os.path.join(out_dir, 'systrace'),
{})
{},
self._device)
result = profiler.CollectProfile()[0]
self.assertTrue(zipfile.is_zipfile(result))
with zipfile.ZipFile(result) as z:

@ -126,7 +126,8 @@ class RecordWprUnitTests(tab_test_case.TabTestCase):
@decorators.Disabled('chromeos') # crbug.com/404868.
def testWprRecorderWithPageSet(self):
flags = ['--browser', self._browser.browser_type]
flags = ['--browser', self._browser.browser_type,
'--device', self._device]
mock_page_set = MockPageSet(url=self._url)
wpr_recorder = record_wpr.WprRecorder(self._test_data_dir,
mock_page_set, flags)
@ -136,7 +137,8 @@ class RecordWprUnitTests(tab_test_case.TabTestCase):
def testWprRecorderWithBenchmark(self):
flags = ['--mock-benchmark-url', self._url,
'--browser', self._browser.browser_type]
'--browser', self._browser.browser_type,
'--device', self._device]
mock_benchmark = MockBenchmark()
wpr_recorder = record_wpr.WprRecorder(self._test_data_dir, mock_benchmark,
flags)
@ -150,6 +152,7 @@ class RecordWprUnitTests(tab_test_case.TabTestCase):
'--page-set-base-dir', self._test_data_dir,
'--mock-benchmark-url', self._url,
'--browser', self._browser.browser_type,
'--device', self._device
]
mock_benchmark = MockBenchmark()
wpr_recorder = record_wpr.WprRecorder(

@ -48,6 +48,7 @@ class BrowserTestCase(unittest.TestCase):
cls.tearDownClass()
raise
cls._browser = current_browser
cls._device = options.device
@classmethod
def tearDownClass(cls):

@ -8,6 +8,7 @@ from telemetry.core import browser_finder
from telemetry.core import browser_finder_exceptions
from telemetry.core import browser_options
from telemetry.core import command_line
from telemetry.core import device_finder
from telemetry.core import util
from telemetry.unittest_util import options_for_unittests
from telemetry.unittest_util import browser_test_case
@ -96,11 +97,13 @@ class RunTestsCommand(command_line.OptparseCommand):
# are long-running, so there's a limit to how much parallelism we
# can effectively use for now anyway.
#
# It should be possible to handle multiple devices if we adjust
# the browser_finder code properly, but for now we only handle the one
# on Android and ChromeOS.
if possible_browser.platform.GetOSName() in ('android', 'chromeos'):
# It should be possible to handle multiple devices if we adjust the
# browser_finder code properly, but for now we only handle one on ChromeOS.
if possible_browser.platform.GetOSName() == 'chromeos':
runner.args.jobs = 1
elif possible_browser.platform.GetOSName() == 'android':
runner.args.jobs = len(device_finder.GetDevicesMatchingOptions(args))
print 'Running tests with %d Android device(s).' % runner.args.jobs
elif possible_browser.platform.GetOSVersionName() == 'xp':
# For an undiagnosed reason, XP falls over with more parallelism.
# See crbug.com/388256
@ -172,6 +175,9 @@ def _MatchesSelectedTest(name, selected_tests, selected_tests_are_exact):
def _SetUpProcess(child, context): # pylint: disable=W0613
args = context
if args.device and args.device == 'android':
android_devices = device_finder.GetDevicesMatchingOptions(args)
args.device = android_devices[child.worker_num-1].guid
options_for_unittests.Push(args)