From 66dc372e7e87901474963b5b9acd65ac854b56c3 Mon Sep 17 00:00:00 2001 From: jbudorick Date: Thu, 6 Nov 2014 13:33:51 -0800 Subject: [PATCH] [Android] Skeleton of test script layer mode. BUG=428729 Review URL: https://codereview.chromium.org/698573003 Cr-Commit-Position: refs/heads/master@{#303093} --- build/android/pylib/base/base_test_runner.py | 4 ++ build/android/pylib/base/environment.py | 34 ++++++++++++++ build/android/pylib/base/environment_factory.py | 11 +++++ build/android/pylib/base/test_dispatcher.py | 3 ++ build/android/pylib/base/test_instance.py | 35 +++++++++++++++ build/android/pylib/base/test_instance_factory.py | 11 +++++ build/android/pylib/base/test_run.py | 39 ++++++++++++++++ build/android/pylib/base/test_run_factory.py | 10 +++++ build/android/pylib/constants.py | 3 ++ build/android/pylib/gtest/setup.py | 9 +++- build/android/test_runner.py | 55 ++++++++++++++++++++--- 11 files changed, 206 insertions(+), 8 deletions(-) create mode 100644 build/android/pylib/base/environment.py create mode 100644 build/android/pylib/base/environment_factory.py create mode 100644 build/android/pylib/base/test_instance.py create mode 100644 build/android/pylib/base/test_instance_factory.py create mode 100644 build/android/pylib/base/test_run.py create mode 100644 build/android/pylib/base/test_run_factory.py diff --git a/build/android/pylib/base/base_test_runner.py b/build/android/pylib/base/base_test_runner.py index d857f5938058..1f76149be6c0 100644 --- a/build/android/pylib/base/base_test_runner.py +++ b/build/android/pylib/base/base_test_runner.py @@ -4,6 +4,10 @@ """Base class for running tests on a single device.""" +# TODO(jbudorick) Deprecate and remove this class and all subclasses after +# any relevant parts have been ported to the new environment + test instance +# model. + import logging import time diff --git a/build/android/pylib/base/environment.py b/build/android/pylib/base/environment.py new file mode 100644 index 000000000000..3f49f41f2991 --- /dev/null +++ b/build/android/pylib/base/environment.py @@ -0,0 +1,34 @@ +# 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. + + +class Environment(object): + """An environment in which tests can be run. + + This is expected to handle all logic that is applicable to an entire specific + environment but is independent of the test type. + + Examples include: + - The local device environment, for running tests on devices attached to + the local machine. + - The local machine environment, for running tests directly on the local + machine. + """ + + def __init__(self): + pass + + def SetUp(self): + raise NotImplementedError + + def TearDown(self): + raise NotImplementedError + + def __enter__(self): + self.SetUp() + return self + + def __exit__(self, _exc_type, _exc_val, _exc_tb): + self.TearDown() + diff --git a/build/android/pylib/base/environment_factory.py b/build/android/pylib/base/environment_factory.py new file mode 100644 index 000000000000..ad2eafd6b0c1 --- /dev/null +++ b/build/android/pylib/base/environment_factory.py @@ -0,0 +1,11 @@ +# 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. + + +def CreateEnvironment(_command, _options, error_func): + + # TODO(jbudorick) Add local device environment. + # TODO(jbudorick) Add local machine environment. + error_func('No environments currently supported.') + diff --git a/build/android/pylib/base/test_dispatcher.py b/build/android/pylib/base/test_dispatcher.py index 677a908a396c..7b00ccd51f6b 100644 --- a/build/android/pylib/base/test_dispatcher.py +++ b/build/android/pylib/base/test_dispatcher.py @@ -15,6 +15,9 @@ Performs the following steps: collection until there are no tests left. """ +# TODO(jbudorick) Deprecate and remove this class after any relevant parts have +# been ported to the new environment / test instance model. + import logging import threading diff --git a/build/android/pylib/base/test_instance.py b/build/android/pylib/base/test_instance.py new file mode 100644 index 000000000000..cdf678f2d287 --- /dev/null +++ b/build/android/pylib/base/test_instance.py @@ -0,0 +1,35 @@ +# 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. + + +class TestInstance(object): + """A type of test. + + This is expected to handle all logic that is test-type specific but + independent of the environment or device. + + Examples include: + - gtests + - instrumentation tests + """ + + def __init__(self): + pass + + def TestType(self): + raise NotImplementedError + + def SetUp(self): + raise NotImplementedError + + def TearDown(self): + raise NotImplementedError + + def __enter__(self): + self.SetUp() + return self + + def __exit__(self, _exc_type, _exc_val, _exc_tb): + self.TearDown() + diff --git a/build/android/pylib/base/test_instance_factory.py b/build/android/pylib/base/test_instance_factory.py new file mode 100644 index 000000000000..fd74b960bef0 --- /dev/null +++ b/build/android/pylib/base/test_instance_factory.py @@ -0,0 +1,11 @@ +# 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. + + +def CreateTestInstance(_command, _options, error_func): + + # TODO(jbudorick) Add gtest test instance. + # TODO(jbudorick) Add instrumentation test instance. + error_func('No test instances currently supported.') + diff --git a/build/android/pylib/base/test_run.py b/build/android/pylib/base/test_run.py new file mode 100644 index 000000000000..2c594fdd61b2 --- /dev/null +++ b/build/android/pylib/base/test_run.py @@ -0,0 +1,39 @@ +# 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. + + +class TestRun(object): + """An execution of a particular test on a particular device. + + This is expected to handle all logic that is specific to the combination of + environment and test type. + + Examples include: + - local gtests + - local instrumentation tests + """ + + def __init__(self, env, test_instance): + self._env = env + self._test_instance = test_instance + + def TestPackage(self): + raise NotImplementedError + + def SetUp(self): + raise NotImplementedError + + def RunTest(self): + raise NotImplementedError + + def TearDown(self): + raise NotImplementedError + + def __enter__(self): + self.SetUp() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.TearDown() + diff --git a/build/android/pylib/base/test_run_factory.py b/build/android/pylib/base/test_run_factory.py new file mode 100644 index 000000000000..50a9690bc4ff --- /dev/null +++ b/build/android/pylib/base/test_run_factory.py @@ -0,0 +1,10 @@ +# 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. + +def CreateTestRun(_options, _env, _test_instance, error_func): + + # TODO(jbudorick) Add local gtest test runs + # TODO(jbudorick) Add local instrumentation test runs. + error_func('No test runs are currently supported.') + diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py index 95b1868760c5..cef098fa0d92 100644 --- a/build/android/pylib/constants.py +++ b/build/android/pylib/constants.py @@ -198,6 +198,9 @@ PYTHON_UNIT_TEST_SUITES = { # }, } +LOCAL_MACHINE_TESTS = ['junit', 'python'] +VALID_ENVIRONMENTS = ['local'] + def GetBuildType(): try: diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py index d73d862b33db..3206bda67cb6 100644 --- a/build/android/pylib/gtest/setup.py +++ b/build/android/pylib/gtest/setup.py @@ -143,11 +143,16 @@ def _GetTests(test_options, test_package, devices): Returns: A list of all the tests in the test suite. """ + class TestListResult(base_test_result.BaseTestResult): + def __init__(self): + super(TestListResult, self).__init__( + 'gtest_list_tests', base_test_result.ResultType.PASS) + self.test_list = [] + def TestListerRunnerFactory(device, _shard_index): class TestListerRunner(test_runner.TestRunner): def RunTest(self, _test): - result = base_test_result.BaseTestResult( - 'gtest_list_tests', base_test_result.ResultType.PASS) + result = TestListResult() self.test_package.Install(self.device) result.test_list = self.test_package.GetAllTests(self.device) results = base_test_result.TestRunResults() diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 1baebc1bd69c..2e39c3c3e31f 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py @@ -21,7 +21,10 @@ from pylib import constants from pylib import forwarder from pylib import ports from pylib.base import base_test_result +from pylib.base import environment_factory from pylib.base import test_dispatcher +from pylib.base import test_instance_factory +from pylib.base import test_run_factory from pylib.gtest import gtest_config from pylib.gtest import setup as gtest_setup from pylib.gtest import test_options as gtest_test_options @@ -45,9 +48,6 @@ from pylib.utils import reraiser_thread from pylib.utils import run_tests_helper -HOST_TESTS = ['junit', 'python'] - - def AddCommonOptions(option_parser): """Adds all common options to |option_parser|.""" @@ -78,15 +78,26 @@ def AddCommonOptions(option_parser): dest='flakiness_dashboard_server', help=('Address of the server that is hosting the ' 'Chrome for Android flakiness dashboard.')) + group.add_option('--enable-platform-mode', action='store_true', + help=('Run the test scripts in platform mode, which ' + 'conceptually separates the test runner from the ' + '"device" (local or remote, real or emulated) on ' + 'which the tests are running. [experimental]')) + group.add_option('-e', '--environment', default='local', + help=('Test environment to run in. Must be one of: %s' % + ', '.join(constants.VALID_ENVIRONMENTS))) option_parser.add_option_group(group) -def ProcessCommonOptions(options): +def ProcessCommonOptions(options, error_func): """Processes and handles all common options.""" run_tests_helper.SetLogLevel(options.verbose_count) constants.SetBuildType(options.build_type) if options.build_directory: constants.SetBuildDirectory(options.build_directory) + if options.environment not in constants.VALID_ENVIRONMENTS: + error_func('--environment must be one of: %s' % + ', '.join(constants.VALID_ENVIRONMENTS)) def AddDeviceOptions(option_parser): @@ -832,9 +843,12 @@ def RunTestsCommand(command, options, args, option_parser): option_parser.error('Unrecognized arguments: %s' % (' '.join(args))) return constants.ERROR_EXIT_CODE - ProcessCommonOptions(options) + ProcessCommonOptions(options, option_parser.error) + + if options.enable_platform_mode: + return RunTestsInPlatformMode(command, options, option_parser) - if command in HOST_TESTS: + if command in constants.LOCAL_MACHINE_TESTS: devices = [] else: devices = _GetAttachedDevices(options.test_device) @@ -863,6 +877,35 @@ def RunTestsCommand(command, options, args, option_parser): raise Exception('Unknown test type.') +_SUPPORTED_IN_PLATFORM_MODE = [ + # TODO(jbudorick): Add support for more test types. + 'gtest', +] + + +def RunTestsInPlatformMode(command, options, option_parser): + + if command not in _SUPPORTED_IN_PLATFORM_MODE: + option_parser.error('%s is not yet supported in platform mode' % command) + + with environment_factory.CreateEnvironment( + command, options, option_parser.error) as env: + with test_instance_factory.CreateTestInstance( + command, options, option_parser.error) as test: + with test_run_factory.CreateTestRun( + options, env, test, option_parser.error) as test_run: + results = test_run.RunTests() + + report_results.LogFull( + results=results, + test_type=test.TestType(), + test_package=test_run.TestPackage(), + annotation=options.annotations, + flakiness_server=options.flakiness_dashboard_server) + + return results + + def HelpCommand(command, _options, args, option_parser): """Display help for a certain command, or overall help. -- 2.11.4.GIT