diff options
author | craigdh@chromium.org <craigdh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-30 19:39:18 +0000 |
---|---|---|
committer | craigdh@chromium.org <craigdh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-30 19:39:18 +0000 |
commit | 32b722a8c97d3da059a7ab0f7eda266c4e40afe2 (patch) | |
tree | 95e6d61629a6bba0f65853ba286abc19dc95bbf4 /build/android/run_tests.py | |
parent | 32c3e98e51fda2fb2da0a3e076d7754e7cccbb5f (diff) | |
download | chromium_src-32b722a8c97d3da059a7ab0f7eda266c4e40afe2.zip chromium_src-32b722a8c97d3da059a7ab0f7eda266c4e40afe2.tar.gz chromium_src-32b722a8c97d3da059a7ab0f7eda266c4e40afe2.tar.bz2 |
Split out gtest dispatcher and sharder.
BUG=168889
TEST=build/android/run_tests.py
Review URL: https://codereview.chromium.org/12094005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179687 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build/android/run_tests.py')
-rwxr-xr-x | build/android/run_tests.py | 268 |
1 files changed, 3 insertions, 265 deletions
diff --git a/build/android/run_tests.py b/build/android/run_tests.py index 020814c..119535da 100755 --- a/build/android/run_tests.py +++ b/build/android/run_tests.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Copyright (c) 2013 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -35,276 +35,14 @@ loaded. We don't care about the rare testcases which succeeded on emuatlor, but failed on device. """ -import copy -import fnmatch -import logging import optparse -import os -import signal -import subprocess import sys -import time -from pylib import android_commands from pylib import cmd_helper -from pylib import ports -from pylib.base.base_test_sharder import BaseTestSharder -from pylib.gtest import debug_info -from pylib.gtest import gtest_config -from pylib.gtest.single_test_runner import SingleTestRunner +from pylib.gtest import dispatch from pylib.utils import emulator from pylib.utils import run_tests_helper from pylib.utils import test_options_parser -from pylib.utils import time_profile -from pylib.utils import xvfb - - -def FullyQualifiedTestSuites(exe, option_test_suite, build_type): - """Get a list of absolute paths to test suite targets. - - Args: - exe: if True, use the executable-based test runner. - option_test_suite: the test_suite specified as an option. - build_type: 'Release' or 'Debug'. - """ - test_suite_dir = os.path.join(cmd_helper.OutDirectory.get(), build_type) - if option_test_suite: - all_test_suites = [option_test_suite] - else: - all_test_suites = gtest_config.STABLE_TEST_SUITES - - if exe: - qualified_test_suites = [os.path.join(test_suite_dir, t) - for t in all_test_suites] - else: - # out/(Debug|Release)/$SUITE_apk/$SUITE-debug.apk - qualified_test_suites = [os.path.join(test_suite_dir, - t + '_apk', - t + '-debug.apk') - for t in all_test_suites] - for t, q in zip(all_test_suites, qualified_test_suites): - if not os.path.exists(q): - raise Exception('Test suite %s not found in %s.\n' - 'Supported test suites:\n %s\n' - 'Ensure it has been built.\n' % - (t, q, gtest_config.STABLE_TEST_SUITES)) - return qualified_test_suites - - -class TestSharder(BaseTestSharder): - """Responsible for sharding the tests on the connected devices.""" - - def __init__(self, attached_devices, test_suite, gtest_filter, - test_arguments, timeout, cleanup_test_files, tool, - log_dump_name, build_type, in_webkit_checkout, - flakiness_server=None): - BaseTestSharder.__init__(self, attached_devices, build_type) - self.test_suite = test_suite - self.gtest_filter = gtest_filter or '' - self.test_arguments = test_arguments - self.timeout = timeout - self.cleanup_test_files = cleanup_test_files - self.tool = tool - self.log_dump_name = log_dump_name - self.in_webkit_checkout = in_webkit_checkout - self.flakiness_server = flakiness_server - self.all_tests = [] - if not self.gtest_filter: - # No filter has been specified, let's add all tests then. - self.all_tests, self.attached_devices = self._GetAllEnabledTests() - self.tests = self.all_tests - - def _GetAllEnabledTests(self): - """Get all enabled tests and available devices. - - Obtains a list of enabled tests from the test package on the device, - then filters it again using the diabled list on the host. - - Returns: - Tuple of (all enabled tests, available devices). - - Raises Exception if all devices failed. - """ - # TODO(frankf): This method is doing too much in a non-systematic way. - # If the intention is to drop flaky devices, why not go through all devices - # instead of breaking on the first succesfull run? - available_devices = list(self.attached_devices) - while available_devices: - try: - return (self._GetTestsFromDevice(available_devices[-1]), - available_devices) - except Exception as e: - logging.warning('Failed obtaining tests from %s %s', - available_devices[-1], e) - available_devices.pop() - - raise Exception('No device available to get the list of tests.') - - def _GetTestsFromDevice(self, device): - logging.info('Obtaining tests from %s', device) - test_runner = SingleTestRunner( - device, - self.test_suite, - self.gtest_filter, - self.test_arguments, - self.timeout, - self.cleanup_test_files, - self.tool, - 0, - not not self.log_dump_name, - self.build_type, - self.in_webkit_checkout) - # The executable/apk needs to be copied before we can call GetAllTests. - test_runner.test_package.StripAndCopyExecutable() - all_tests = test_runner.test_package.GetAllTests() - disabled_list = test_runner.GetDisabledTests() - # Only includes tests that do not have any match in the disabled list. - all_tests = filter(lambda t: - not any([fnmatch.fnmatch(t, disabled_pattern) - for disabled_pattern in disabled_list]), - all_tests) - return all_tests - - def CreateShardedTestRunner(self, device, index): - """Creates a suite-specific test runner. - - Args: - device: Device serial where this shard will run. - index: Index of this device in the pool. - - Returns: - A SingleTestRunner object. - """ - device_num = len(self.attached_devices) - shard_test_list = self.tests[index::device_num] - test_filter = ':'.join(shard_test_list) + self.gtest_filter - return SingleTestRunner( - device, - self.test_suite, - test_filter, - self.test_arguments, - self.timeout, - self.cleanup_test_files, self.tool, index, - not not self.log_dump_name, - self.build_type, - self.in_webkit_checkout) - - def OnTestsCompleted(self, test_runners, test_results): - """Notifies that we completed the tests.""" - test_results.LogFull( - test_type='Unit test', - test_package=test_runners[0].test_package.test_suite_basename, - build_type=self.build_type, - flakiness_server=self.flakiness_server) - test_results.PrintAnnotation() - - if self.log_dump_name: - # Zip all debug info outputs into a file named by log_dump_name. - debug_info.GTestDebugInfo.ZipAndCleanResults( - os.path.join( - cmd_helper.OutDirectory.get(), self.build_type, - 'debug_info_dumps'), - self.log_dump_name) - - -def _RunATestSuite(options): - """Run a single test suite. - - Helper for Dispatch() to allow stop/restart of the emulator across - test bundles. If using the emulator, we start it on entry and stop - it on exit. - - Args: - options: options for running the tests. - - Returns: - 0 if successful, number of failing tests otherwise. - """ - step_name = os.path.basename(options.test_suite).replace('-debug.apk', '') - attached_devices = [] - buildbot_emulators = [] - - if options.use_emulator: - buildbot_emulators = emulator.LaunchEmulators(options.emulator_count, - wait_for_boot=True) - attached_devices = [e.device for e in buildbot_emulators] - elif options.test_device: - attached_devices = [options.test_device] - else: - attached_devices = android_commands.GetAttachedDevices() - - if not attached_devices: - logging.critical('A device must be attached and online.') - return 1 - - # Reset the test port allocation. It's important to do it before starting - # to dispatch any tests. - if not ports.ResetTestServerPortAllocation(): - raise Exception('Failed to reset test server port.') - - if options.gtest_filter: - logging.warning('Sharding is not possible with these configurations.') - attached_devices = [attached_devices[0]] - - sharder = TestSharder( - attached_devices, - options.test_suite, - options.gtest_filter, - options.test_arguments, - options.timeout, - options.cleanup_test_files, - options.tool, - options.log_dump, - options.build_type, - options.webkit, - options.flakiness_dashboard_server) - test_results = sharder.RunShardedTests() - - for buildbot_emulator in buildbot_emulators: - buildbot_emulator.Shutdown() - - return len(test_results.GetAllBroken()) - - -def Dispatch(options): - """Dispatches the tests, sharding if possible. - - If options.use_emulator is True, all tests will be run in new emulator - instance. - - Args: - options: options for running the tests. - - Returns: - 0 if successful, number of failing tests otherwise. - """ - if options.test_suite == 'help': - ListTestSuites() - return 0 - - if options.use_xvfb: - framebuffer = xvfb.Xvfb() - framebuffer.Start() - - all_test_suites = FullyQualifiedTestSuites(options.exe, options.test_suite, - options.build_type) - failures = 0 - for suite in all_test_suites: - # Give each test suite its own copy of options. - test_options = copy.deepcopy(options) - test_options.test_suite = suite - failures += _RunATestSuite(test_options) - - if options.use_xvfb: - framebuffer.Stop() - return failures - - -def ListTestSuites(): - """Display a list of available test suites.""" - print 'Available test suites are:' - for test_suite in gtest_config.STABLE_TEST_SUITES: - print test_suite def main(argv): @@ -323,7 +61,7 @@ def main(argv): if options.use_emulator: emulator.DeleteAllTempAVDs() - failed_tests_count = Dispatch(options) + failed_tests_count = dispatch.Dispatch(options) # Failures of individual test suites are communicated by printing a # STEP_FAILURE message. |