1# Copyright 2017, The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16Aggregates test runners, groups tests by test runners and kicks off tests. 17""" 18 19# pylint: disable=line-too-long 20# pylint: disable=import-outside-toplevel 21 22import itertools 23import time 24import traceback 25 26import atest_error 27import constants 28import result_reporter 29 30from metrics import metrics 31from metrics import metrics_utils 32from test_runners import atest_tf_test_runner 33from test_runners import robolectric_test_runner 34from test_runners import suite_plan_test_runner 35from test_runners import vts_tf_test_runner 36 37_TEST_RUNNERS = { 38 atest_tf_test_runner.AtestTradefedTestRunner.NAME: atest_tf_test_runner.AtestTradefedTestRunner, 39 robolectric_test_runner.RobolectricTestRunner.NAME: robolectric_test_runner.RobolectricTestRunner, 40 suite_plan_test_runner.SuitePlanTestRunner.NAME: suite_plan_test_runner.SuitePlanTestRunner, 41 vts_tf_test_runner.VtsTradefedTestRunner.NAME: vts_tf_test_runner.VtsTradefedTestRunner, 42} 43 44 45def _get_test_runners(): 46 """Returns the test runners. 47 48 If external test runners are defined outside atest, they can be try-except 49 imported into here. 50 51 Returns: 52 Dict of test runner name to test runner class. 53 """ 54 test_runners_dict = _TEST_RUNNERS 55 # Example import of example test runner: 56 try: 57 from test_runners import example_test_runner 58 test_runners_dict[example_test_runner.ExampleTestRunner.NAME] = example_test_runner.ExampleTestRunner 59 except ImportError: 60 pass 61 return test_runners_dict 62 63 64def group_tests_by_test_runners(test_infos): 65 """Group the test_infos by test runners 66 67 Args: 68 test_infos: List of TestInfo. 69 70 Returns: 71 List of tuples (test runner, tests). 72 """ 73 tests_by_test_runner = [] 74 test_runner_dict = _get_test_runners() 75 key = lambda x: x.test_runner 76 sorted_test_infos = sorted(list(test_infos), key=key) 77 for test_runner, tests in itertools.groupby(sorted_test_infos, key): 78 # groupby returns a grouper object, we want to operate on a list. 79 tests = list(tests) 80 test_runner_class = test_runner_dict.get(test_runner) 81 if test_runner_class is None: 82 raise atest_error.UnknownTestRunnerError('Unknown Test Runner %s' % 83 test_runner) 84 tests_by_test_runner.append((test_runner_class, tests)) 85 return tests_by_test_runner 86 87 88def get_test_runner_reqs(module_info, test_infos): 89 """Returns the requirements for all test runners specified in the tests. 90 91 Args: 92 module_info: ModuleInfo object. 93 test_infos: List of TestInfo. 94 95 Returns: 96 Set of build targets required by the test runners. 97 """ 98 dummy_result_dir = '' 99 test_runner_build_req = set() 100 for test_runner, _ in group_tests_by_test_runners(test_infos): 101 test_runner_build_req |= test_runner( 102 dummy_result_dir, 103 module_info=module_info).get_test_runner_build_reqs() 104 return test_runner_build_req 105 106 107def run_all_tests(results_dir, test_infos, extra_args, 108 delay_print_summary=False): 109 """Run the given tests. 110 111 Args: 112 results_dir: String directory to store atest results. 113 test_infos: List of TestInfo. 114 extra_args: Dict of extra args for test runners to use. 115 116 Returns: 117 0 if tests succeed, non-zero otherwise. 118 """ 119 reporter = result_reporter.ResultReporter() 120 reporter.print_starting_text() 121 tests_ret_code = constants.EXIT_CODE_SUCCESS 122 for test_runner, tests in group_tests_by_test_runners(test_infos): 123 test_name = ' '.join([test.test_name for test in tests]) 124 test_start = time.time() 125 is_success = True 126 ret_code = constants.EXIT_CODE_TEST_FAILURE 127 stacktrace = '' 128 try: 129 test_runner = test_runner(results_dir) 130 ret_code = test_runner.run_tests(tests, extra_args, reporter) 131 tests_ret_code |= ret_code 132 # pylint: disable=broad-except 133 except Exception: 134 stacktrace = traceback.format_exc() 135 reporter.runner_failure(test_runner.NAME, stacktrace) 136 tests_ret_code = constants.EXIT_CODE_TEST_FAILURE 137 is_success = False 138 metrics.RunnerFinishEvent( 139 duration=metrics_utils.convert_duration(time.time() - test_start), 140 success=is_success, 141 runner_name=test_runner.NAME, 142 test=[{'name': test_name, 143 'result': ret_code, 144 'stacktrace': stacktrace}]) 145 if delay_print_summary: 146 return tests_ret_code, reporter 147 return (reporter.print_summary(extra_args.get(constants.COLLECT_TESTS_ONLY)) 148 or tests_ret_code, reporter) 149