1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2017, The Android Open Source Project 4*c2e18aaaSAndroid Build Coastguard Worker# 5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*c2e18aaaSAndroid Build Coastguard Worker# 11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Worker"""Command line utility for running Android tests through TradeFederation. 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workeratest helps automate the flow of building test modules across the Android 20*c2e18aaaSAndroid Build Coastguard Workercode base and executing the tests via the TradeFederation test harness. 21*c2e18aaaSAndroid Build Coastguard Worker 22*c2e18aaaSAndroid Build Coastguard Workeratest is designed to support any test types that can be ran by TradeFederation. 23*c2e18aaaSAndroid Build Coastguard Worker""" 24*c2e18aaaSAndroid Build Coastguard Worker 25*c2e18aaaSAndroid Build Coastguard Worker# pylint: disable=too-many-lines 26*c2e18aaaSAndroid Build Coastguard Worker 27*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import annotations 28*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import print_function 29*c2e18aaaSAndroid Build Coastguard Worker 30*c2e18aaaSAndroid Build Coastguard Workerimport abc 31*c2e18aaaSAndroid Build Coastguard Workerimport argparse 32*c2e18aaaSAndroid Build Coastguard Workerimport collections 33*c2e18aaaSAndroid Build Coastguard Workerimport dataclasses 34*c2e18aaaSAndroid Build Coastguard Workerimport functools 35*c2e18aaaSAndroid Build Coastguard Workerimport itertools 36*c2e18aaaSAndroid Build Coastguard Workerimport logging 37*c2e18aaaSAndroid Build Coastguard Workerimport os 38*c2e18aaaSAndroid Build Coastguard Workerimport platform 39*c2e18aaaSAndroid Build Coastguard Workerimport subprocess 40*c2e18aaaSAndroid Build Coastguard Workerimport sys 41*c2e18aaaSAndroid Build Coastguard Workerimport tempfile 42*c2e18aaaSAndroid Build Coastguard Workerimport threading 43*c2e18aaaSAndroid Build Coastguard Workerimport time 44*c2e18aaaSAndroid Build Coastguard Workerfrom typing import Any, Dict, List, Set 45*c2e18aaaSAndroid Build Coastguard Worker 46*c2e18aaaSAndroid Build Coastguard Workerfrom atest import arg_parser 47*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_configs 48*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_execution_info 49*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils 50*c2e18aaaSAndroid Build Coastguard Workerfrom atest import banner 51*c2e18aaaSAndroid Build Coastguard Workerfrom atest import bazel_mode 52*c2e18aaaSAndroid Build Coastguard Workerfrom atest import bug_detector 53*c2e18aaaSAndroid Build Coastguard Workerfrom atest import cli_translator 54*c2e18aaaSAndroid Build Coastguard Workerfrom atest import constants 55*c2e18aaaSAndroid Build Coastguard Workerfrom atest import device_update 56*c2e18aaaSAndroid Build Coastguard Workerfrom atest import module_info 57*c2e18aaaSAndroid Build Coastguard Workerfrom atest import result_reporter 58*c2e18aaaSAndroid Build Coastguard Workerfrom atest import test_runner_handler 59*c2e18aaaSAndroid Build Coastguard Workerfrom atest.atest_enum import DetectType 60*c2e18aaaSAndroid Build Coastguard Workerfrom atest.atest_enum import ExitCode 61*c2e18aaaSAndroid Build Coastguard Workerfrom atest.coverage import coverage 62*c2e18aaaSAndroid Build Coastguard Workerfrom atest.metrics import metrics 63*c2e18aaaSAndroid Build Coastguard Workerfrom atest.metrics import metrics_base 64*c2e18aaaSAndroid Build Coastguard Workerfrom atest.metrics import metrics_utils 65*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_finder_utils 66*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_info 67*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders.test_info import TestInfo 68*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_runner_invocation import TestRunnerInvocation 69*c2e18aaaSAndroid Build Coastguard Workerfrom atest.tools import indexing 70*c2e18aaaSAndroid Build Coastguard Workerfrom atest.tools import start_avd as avd 71*c2e18aaaSAndroid Build Coastguard Worker 72*c2e18aaaSAndroid Build Coastguard WorkerEXPECTED_VARS = frozenset([ 73*c2e18aaaSAndroid Build Coastguard Worker constants.ANDROID_BUILD_TOP, 74*c2e18aaaSAndroid Build Coastguard Worker 'ANDROID_TARGET_OUT_TESTCASES', 75*c2e18aaaSAndroid Build Coastguard Worker constants.ANDROID_OUT, 76*c2e18aaaSAndroid Build Coastguard Worker]) 77*c2e18aaaSAndroid Build Coastguard WorkerTEST_RUN_DIR_PREFIX = '%Y%m%d_%H%M%S' 78*c2e18aaaSAndroid Build Coastguard WorkerCUSTOM_ARG_FLAG = '--' 79*c2e18aaaSAndroid Build Coastguard WorkerOPTION_NOT_FOR_TEST_MAPPING = ( 80*c2e18aaaSAndroid Build Coastguard Worker 'Option "{}" does not work for running tests in TEST_MAPPING files' 81*c2e18aaaSAndroid Build Coastguard Worker) 82*c2e18aaaSAndroid Build Coastguard Worker 83*c2e18aaaSAndroid Build Coastguard WorkerDEVICE_TESTS = 'tests that require device' 84*c2e18aaaSAndroid Build Coastguard WorkerHOST_TESTS = 'tests that do NOT require device' 85*c2e18aaaSAndroid Build Coastguard WorkerRESULT_HEADER_FMT = '\nResults from %(test_type)s:' 86*c2e18aaaSAndroid Build Coastguard WorkerRUN_HEADER_FMT = '\nRunning %(test_count)d %(test_type)s.' 87*c2e18aaaSAndroid Build Coastguard WorkerTEST_COUNT = 'test_count' 88*c2e18aaaSAndroid Build Coastguard WorkerTEST_TYPE = 'test_type' 89*c2e18aaaSAndroid Build Coastguard WorkerEND_OF_OPTION = '--' 90*c2e18aaaSAndroid Build Coastguard WorkerHAS_IGNORED_ARGS = False 91*c2e18aaaSAndroid Build Coastguard Worker# Conditions that atest should exit without sending result to metrics. 92*c2e18aaaSAndroid Build Coastguard WorkerEXIT_CODES_BEFORE_TEST = [ 93*c2e18aaaSAndroid Build Coastguard Worker ExitCode.ENV_NOT_SETUP, 94*c2e18aaaSAndroid Build Coastguard Worker ExitCode.TEST_NOT_FOUND, 95*c2e18aaaSAndroid Build Coastguard Worker ExitCode.OUTSIDE_ROOT, 96*c2e18aaaSAndroid Build Coastguard Worker ExitCode.AVD_CREATE_FAILURE, 97*c2e18aaaSAndroid Build Coastguard Worker ExitCode.AVD_INVALID_ARGS, 98*c2e18aaaSAndroid Build Coastguard Worker] 99*c2e18aaaSAndroid Build Coastguard Worker 100*c2e18aaaSAndroid Build Coastguard Worker# Stdout print prefix for results directory. May be used in integration tests. 101*c2e18aaaSAndroid Build Coastguard Worker_RESULTS_DIR_PRINT_PREFIX = 'Atest results and logs directory: ' 102*c2e18aaaSAndroid Build Coastguard Worker# Log prefix for dry-run run command. May be used in integration tests. 103*c2e18aaaSAndroid Build Coastguard Worker_DRY_RUN_COMMAND_LOG_PREFIX = 'Internal run command from dry-run: ' 104*c2e18aaaSAndroid Build Coastguard Worker 105*c2e18aaaSAndroid Build Coastguard Worker 106*c2e18aaaSAndroid Build Coastguard Worker@dataclasses.dataclass 107*c2e18aaaSAndroid Build Coastguard Workerclass Steps: 108*c2e18aaaSAndroid Build Coastguard Worker """A dataclass that stores enabled steps.""" 109*c2e18aaaSAndroid Build Coastguard Worker 110*c2e18aaaSAndroid Build Coastguard Worker build: bool 111*c2e18aaaSAndroid Build Coastguard Worker install: bool 112*c2e18aaaSAndroid Build Coastguard Worker test: bool 113*c2e18aaaSAndroid Build Coastguard Worker 114*c2e18aaaSAndroid Build Coastguard Worker 115*c2e18aaaSAndroid Build Coastguard Workerdef parse_steps(args: arg_parser.AtestArgParser) -> Steps: 116*c2e18aaaSAndroid Build Coastguard Worker """Return Steps object. 117*c2e18aaaSAndroid Build Coastguard Worker 118*c2e18aaaSAndroid Build Coastguard Worker Args: 119*c2e18aaaSAndroid Build Coastguard Worker args: an AtestArgParser object. 120*c2e18aaaSAndroid Build Coastguard Worker 121*c2e18aaaSAndroid Build Coastguard Worker Returns: 122*c2e18aaaSAndroid Build Coastguard Worker Step object that stores the boolean of build, install and test. 123*c2e18aaaSAndroid Build Coastguard Worker """ 124*c2e18aaaSAndroid Build Coastguard Worker # Implicitly running 'build', 'install' and 'test' when args.steps is None. 125*c2e18aaaSAndroid Build Coastguard Worker if not args.steps: 126*c2e18aaaSAndroid Build Coastguard Worker return Steps(True, True, True) 127*c2e18aaaSAndroid Build Coastguard Worker build = constants.BUILD_STEP in args.steps 128*c2e18aaaSAndroid Build Coastguard Worker test = constants.TEST_STEP in args.steps 129*c2e18aaaSAndroid Build Coastguard Worker install = constants.INSTALL_STEP in args.steps 130*c2e18aaaSAndroid Build Coastguard Worker if install and not test: 131*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_warning( 132*c2e18aaaSAndroid Build Coastguard Worker 'Installing without test step is currently not ' 133*c2e18aaaSAndroid Build Coastguard Worker 'supported; Atest will proceed testing!' 134*c2e18aaaSAndroid Build Coastguard Worker ) 135*c2e18aaaSAndroid Build Coastguard Worker test = True 136*c2e18aaaSAndroid Build Coastguard Worker return Steps(build, install, test) 137*c2e18aaaSAndroid Build Coastguard Worker 138*c2e18aaaSAndroid Build Coastguard Worker 139*c2e18aaaSAndroid Build Coastguard Workerdef _get_args_from_config(): 140*c2e18aaaSAndroid Build Coastguard Worker """Get customized atest arguments in the config file. 141*c2e18aaaSAndroid Build Coastguard Worker 142*c2e18aaaSAndroid Build Coastguard Worker If the config has not existed yet, atest will initialize an example 143*c2e18aaaSAndroid Build Coastguard Worker config file for it without any effective options. 144*c2e18aaaSAndroid Build Coastguard Worker 145*c2e18aaaSAndroid Build Coastguard Worker Returns: 146*c2e18aaaSAndroid Build Coastguard Worker A list read from the config file. 147*c2e18aaaSAndroid Build Coastguard Worker """ 148*c2e18aaaSAndroid Build Coastguard Worker _config = atest_utils.get_config_folder().joinpath('config') 149*c2e18aaaSAndroid Build Coastguard Worker if not _config.parent.is_dir(): 150*c2e18aaaSAndroid Build Coastguard Worker _config.parent.mkdir(parents=True) 151*c2e18aaaSAndroid Build Coastguard Worker args = [] 152*c2e18aaaSAndroid Build Coastguard Worker if not _config.is_file(): 153*c2e18aaaSAndroid Build Coastguard Worker with open(_config, 'w+', encoding='utf8') as cache: 154*c2e18aaaSAndroid Build Coastguard Worker cache.write(constants.ATEST_EXAMPLE_ARGS) 155*c2e18aaaSAndroid Build Coastguard Worker return args 156*c2e18aaaSAndroid Build Coastguard Worker warning = 'Line {} contains {} and will be ignored.' 157*c2e18aaaSAndroid Build Coastguard Worker print( 158*c2e18aaaSAndroid Build Coastguard Worker '\n{} {}'.format( 159*c2e18aaaSAndroid Build Coastguard Worker atest_utils.mark_cyan('Reading config:'), 160*c2e18aaaSAndroid Build Coastguard Worker _config, 161*c2e18aaaSAndroid Build Coastguard Worker ) 162*c2e18aaaSAndroid Build Coastguard Worker ) 163*c2e18aaaSAndroid Build Coastguard Worker # pylint: disable=global-statement: 164*c2e18aaaSAndroid Build Coastguard Worker global HAS_IGNORED_ARGS 165*c2e18aaaSAndroid Build Coastguard Worker with open(_config, 'r', encoding='utf8') as cache: 166*c2e18aaaSAndroid Build Coastguard Worker for entry in cache.readlines(): 167*c2e18aaaSAndroid Build Coastguard Worker # Strip comments. 168*c2e18aaaSAndroid Build Coastguard Worker arg_in_line = entry.partition('#')[0].strip() 169*c2e18aaaSAndroid Build Coastguard Worker # Strip test name/path. 170*c2e18aaaSAndroid Build Coastguard Worker if arg_in_line.startswith('-'): 171*c2e18aaaSAndroid Build Coastguard Worker # Process argument that contains whitespaces. 172*c2e18aaaSAndroid Build Coastguard Worker # e.g. ["--serial foo"] -> ["--serial", "foo"] 173*c2e18aaaSAndroid Build Coastguard Worker if len(arg_in_line.split()) > 1: 174*c2e18aaaSAndroid Build Coastguard Worker # remove "--" to avoid messing up atest/tradefed commands. 175*c2e18aaaSAndroid Build Coastguard Worker if END_OF_OPTION in arg_in_line.split(): 176*c2e18aaaSAndroid Build Coastguard Worker HAS_IGNORED_ARGS = True 177*c2e18aaaSAndroid Build Coastguard Worker print( 178*c2e18aaaSAndroid Build Coastguard Worker warning.format( 179*c2e18aaaSAndroid Build Coastguard Worker atest_utils.mark_yellow(arg_in_line), END_OF_OPTION 180*c2e18aaaSAndroid Build Coastguard Worker ) 181*c2e18aaaSAndroid Build Coastguard Worker ) 182*c2e18aaaSAndroid Build Coastguard Worker args.extend(arg_in_line.split()) 183*c2e18aaaSAndroid Build Coastguard Worker else: 184*c2e18aaaSAndroid Build Coastguard Worker if END_OF_OPTION == arg_in_line: 185*c2e18aaaSAndroid Build Coastguard Worker HAS_IGNORED_ARGS = True 186*c2e18aaaSAndroid Build Coastguard Worker print( 187*c2e18aaaSAndroid Build Coastguard Worker warning.format( 188*c2e18aaaSAndroid Build Coastguard Worker atest_utils.mark_yellow(arg_in_line), END_OF_OPTION 189*c2e18aaaSAndroid Build Coastguard Worker ) 190*c2e18aaaSAndroid Build Coastguard Worker ) 191*c2e18aaaSAndroid Build Coastguard Worker args.append(arg_in_line) 192*c2e18aaaSAndroid Build Coastguard Worker return args 193*c2e18aaaSAndroid Build Coastguard Worker 194*c2e18aaaSAndroid Build Coastguard Worker 195*c2e18aaaSAndroid Build Coastguard Workerdef _parse_args(argv: List[str]) -> argparse.Namespace: 196*c2e18aaaSAndroid Build Coastguard Worker """Parse command line arguments. 197*c2e18aaaSAndroid Build Coastguard Worker 198*c2e18aaaSAndroid Build Coastguard Worker Args: 199*c2e18aaaSAndroid Build Coastguard Worker argv: A list of arguments. 200*c2e18aaaSAndroid Build Coastguard Worker 201*c2e18aaaSAndroid Build Coastguard Worker Returns: 202*c2e18aaaSAndroid Build Coastguard Worker A Namespace holding parsed args 203*c2e18aaaSAndroid Build Coastguard Worker """ 204*c2e18aaaSAndroid Build Coastguard Worker # Store everything after '--' in custom_args. 205*c2e18aaaSAndroid Build Coastguard Worker pruned_argv = argv 206*c2e18aaaSAndroid Build Coastguard Worker custom_args_index = None 207*c2e18aaaSAndroid Build Coastguard Worker if CUSTOM_ARG_FLAG in argv: 208*c2e18aaaSAndroid Build Coastguard Worker custom_args_index = argv.index(CUSTOM_ARG_FLAG) 209*c2e18aaaSAndroid Build Coastguard Worker pruned_argv = argv[:custom_args_index] 210*c2e18aaaSAndroid Build Coastguard Worker args = arg_parser.create_atest_arg_parser().parse_args(pruned_argv) 211*c2e18aaaSAndroid Build Coastguard Worker args.custom_args = [] 212*c2e18aaaSAndroid Build Coastguard Worker if custom_args_index is not None: 213*c2e18aaaSAndroid Build Coastguard Worker for arg in argv[custom_args_index + 1 :]: 214*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Quoting regex argument %s', arg) 215*c2e18aaaSAndroid Build Coastguard Worker args.custom_args.append(atest_utils.quote(arg)) 216*c2e18aaaSAndroid Build Coastguard Worker 217*c2e18aaaSAndroid Build Coastguard Worker return args 218*c2e18aaaSAndroid Build Coastguard Worker 219*c2e18aaaSAndroid Build Coastguard Worker 220*c2e18aaaSAndroid Build Coastguard Workerdef _configure_logging(verbose: bool, results_dir: str): 221*c2e18aaaSAndroid Build Coastguard Worker """Configure the logger. 222*c2e18aaaSAndroid Build Coastguard Worker 223*c2e18aaaSAndroid Build Coastguard Worker Args: 224*c2e18aaaSAndroid Build Coastguard Worker verbose: If true display DEBUG level logs on console. 225*c2e18aaaSAndroid Build Coastguard Worker results_dir: A directory which stores the ATest execution information. 226*c2e18aaaSAndroid Build Coastguard Worker """ 227*c2e18aaaSAndroid Build Coastguard Worker log_fmat = '%(asctime)s %(filename)s:%(lineno)s:%(levelname)s: %(message)s' 228*c2e18aaaSAndroid Build Coastguard Worker date_fmt = '%Y-%m-%d %H:%M:%S' 229*c2e18aaaSAndroid Build Coastguard Worker log_path = os.path.join(results_dir, 'atest.log') 230*c2e18aaaSAndroid Build Coastguard Worker 231*c2e18aaaSAndroid Build Coastguard Worker logger = logging.getLogger('') 232*c2e18aaaSAndroid Build Coastguard Worker # Clear the handlers to prevent logging.basicConfig from being called twice. 233*c2e18aaaSAndroid Build Coastguard Worker logger.handlers = [] 234*c2e18aaaSAndroid Build Coastguard Worker 235*c2e18aaaSAndroid Build Coastguard Worker logging.basicConfig( 236*c2e18aaaSAndroid Build Coastguard Worker filename=log_path, level=logging.DEBUG, format=log_fmat, datefmt=date_fmt 237*c2e18aaaSAndroid Build Coastguard Worker ) 238*c2e18aaaSAndroid Build Coastguard Worker 239*c2e18aaaSAndroid Build Coastguard Worker class _StreamToLogger: 240*c2e18aaaSAndroid Build Coastguard Worker """A file like class to that redirect writes to a printer and logger.""" 241*c2e18aaaSAndroid Build Coastguard Worker 242*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, logger, log_level, printer): 243*c2e18aaaSAndroid Build Coastguard Worker self._logger = logger 244*c2e18aaaSAndroid Build Coastguard Worker self._log_level = log_level 245*c2e18aaaSAndroid Build Coastguard Worker self._printer = printer 246*c2e18aaaSAndroid Build Coastguard Worker self._buffers = [] 247*c2e18aaaSAndroid Build Coastguard Worker 248*c2e18aaaSAndroid Build Coastguard Worker def write(self, buf: str) -> None: 249*c2e18aaaSAndroid Build Coastguard Worker self._printer.write(buf) 250*c2e18aaaSAndroid Build Coastguard Worker 251*c2e18aaaSAndroid Build Coastguard Worker if len(buf) == 1 and buf[0] == '\n' and self._buffers: 252*c2e18aaaSAndroid Build Coastguard Worker self._logger.log(self._log_level, ''.join(self._buffers)) 253*c2e18aaaSAndroid Build Coastguard Worker self._buffers.clear() 254*c2e18aaaSAndroid Build Coastguard Worker else: 255*c2e18aaaSAndroid Build Coastguard Worker self._buffers.append(buf) 256*c2e18aaaSAndroid Build Coastguard Worker 257*c2e18aaaSAndroid Build Coastguard Worker def flush(self) -> None: 258*c2e18aaaSAndroid Build Coastguard Worker self._printer.flush() 259*c2e18aaaSAndroid Build Coastguard Worker 260*c2e18aaaSAndroid Build Coastguard Worker stdout_log_level = 25 261*c2e18aaaSAndroid Build Coastguard Worker stderr_log_level = 45 262*c2e18aaaSAndroid Build Coastguard Worker logging.addLevelName(stdout_log_level, 'STDOUT') 263*c2e18aaaSAndroid Build Coastguard Worker logging.addLevelName(stderr_log_level, 'STDERR') 264*c2e18aaaSAndroid Build Coastguard Worker sys.stdout = _StreamToLogger(logger, stdout_log_level, sys.stdout) 265*c2e18aaaSAndroid Build Coastguard Worker sys.stderr = _StreamToLogger(logger, stderr_log_level, sys.stderr) 266*c2e18aaaSAndroid Build Coastguard Worker 267*c2e18aaaSAndroid Build Coastguard Worker 268*c2e18aaaSAndroid Build Coastguard Workerdef _missing_environment_variables(): 269*c2e18aaaSAndroid Build Coastguard Worker """Verify the local environment has been set up to run atest. 270*c2e18aaaSAndroid Build Coastguard Worker 271*c2e18aaaSAndroid Build Coastguard Worker Returns: 272*c2e18aaaSAndroid Build Coastguard Worker List of strings of any missing environment variables. 273*c2e18aaaSAndroid Build Coastguard Worker """ 274*c2e18aaaSAndroid Build Coastguard Worker missing = list( 275*c2e18aaaSAndroid Build Coastguard Worker filter(None, [x for x in EXPECTED_VARS if not os.environ.get(x)]) 276*c2e18aaaSAndroid Build Coastguard Worker ) 277*c2e18aaaSAndroid Build Coastguard Worker if missing: 278*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_error( 279*c2e18aaaSAndroid Build Coastguard Worker "Local environment doesn't appear to have been " 280*c2e18aaaSAndroid Build Coastguard Worker 'initialized. Did you remember to run lunch? Expected ' 281*c2e18aaaSAndroid Build Coastguard Worker 'Environment Variables: %s.', 282*c2e18aaaSAndroid Build Coastguard Worker missing, 283*c2e18aaaSAndroid Build Coastguard Worker ) 284*c2e18aaaSAndroid Build Coastguard Worker return missing 285*c2e18aaaSAndroid Build Coastguard Worker 286*c2e18aaaSAndroid Build Coastguard Worker 287*c2e18aaaSAndroid Build Coastguard Workerdef make_test_run_dir() -> str: 288*c2e18aaaSAndroid Build Coastguard Worker """Make the test run dir in ATEST_RESULT_ROOT. 289*c2e18aaaSAndroid Build Coastguard Worker 290*c2e18aaaSAndroid Build Coastguard Worker Returns: 291*c2e18aaaSAndroid Build Coastguard Worker A string of the dir path. 292*c2e18aaaSAndroid Build Coastguard Worker """ 293*c2e18aaaSAndroid Build Coastguard Worker if not os.path.exists(constants.ATEST_RESULT_ROOT): 294*c2e18aaaSAndroid Build Coastguard Worker os.makedirs(constants.ATEST_RESULT_ROOT) 295*c2e18aaaSAndroid Build Coastguard Worker ctime = time.strftime(TEST_RUN_DIR_PREFIX, time.localtime()) 296*c2e18aaaSAndroid Build Coastguard Worker test_result_dir = tempfile.mkdtemp( 297*c2e18aaaSAndroid Build Coastguard Worker prefix='%s_' % ctime, dir=constants.ATEST_RESULT_ROOT 298*c2e18aaaSAndroid Build Coastguard Worker ) 299*c2e18aaaSAndroid Build Coastguard Worker print(_RESULTS_DIR_PRINT_PREFIX + test_result_dir) 300*c2e18aaaSAndroid Build Coastguard Worker return test_result_dir 301*c2e18aaaSAndroid Build Coastguard Worker 302*c2e18aaaSAndroid Build Coastguard Worker 303*c2e18aaaSAndroid Build Coastguard Workerdef get_extra_args(args): 304*c2e18aaaSAndroid Build Coastguard Worker """Get extra args for test runners. 305*c2e18aaaSAndroid Build Coastguard Worker 306*c2e18aaaSAndroid Build Coastguard Worker Args: 307*c2e18aaaSAndroid Build Coastguard Worker args: arg parsed object. 308*c2e18aaaSAndroid Build Coastguard Worker 309*c2e18aaaSAndroid Build Coastguard Worker Returns: 310*c2e18aaaSAndroid Build Coastguard Worker Dict of extra args for test runners to utilize. 311*c2e18aaaSAndroid Build Coastguard Worker """ 312*c2e18aaaSAndroid Build Coastguard Worker extra_args = {} 313*c2e18aaaSAndroid Build Coastguard Worker if args.wait_for_debugger: 314*c2e18aaaSAndroid Build Coastguard Worker extra_args[constants.WAIT_FOR_DEBUGGER] = None 315*c2e18aaaSAndroid Build Coastguard Worker if not parse_steps(args).install: 316*c2e18aaaSAndroid Build Coastguard Worker extra_args[constants.DISABLE_INSTALL] = None 317*c2e18aaaSAndroid Build Coastguard Worker # The key and its value of the dict can be called via: 318*c2e18aaaSAndroid Build Coastguard Worker # if args.aaaa: 319*c2e18aaaSAndroid Build Coastguard Worker # extra_args[constants.AAAA] = args.aaaa 320*c2e18aaaSAndroid Build Coastguard Worker arg_maps = { 321*c2e18aaaSAndroid Build Coastguard Worker 'all_abi': constants.ALL_ABI, 322*c2e18aaaSAndroid Build Coastguard Worker 'annotation_filter': constants.ANNOTATION_FILTER, 323*c2e18aaaSAndroid Build Coastguard Worker 'bazel_arg': constants.BAZEL_ARG, 324*c2e18aaaSAndroid Build Coastguard Worker 'collect_tests_only': constants.COLLECT_TESTS_ONLY, 325*c2e18aaaSAndroid Build Coastguard Worker 'experimental_coverage': constants.COVERAGE, 326*c2e18aaaSAndroid Build Coastguard Worker 'custom_args': constants.CUSTOM_ARGS, 327*c2e18aaaSAndroid Build Coastguard Worker 'device_only': constants.DEVICE_ONLY, 328*c2e18aaaSAndroid Build Coastguard Worker 'disable_teardown': constants.DISABLE_TEARDOWN, 329*c2e18aaaSAndroid Build Coastguard Worker 'disable_upload_result': constants.DISABLE_UPLOAD_RESULT, 330*c2e18aaaSAndroid Build Coastguard Worker 'dry_run': constants.DRY_RUN, 331*c2e18aaaSAndroid Build Coastguard Worker 'host': constants.HOST, 332*c2e18aaaSAndroid Build Coastguard Worker 'instant': constants.INSTANT, 333*c2e18aaaSAndroid Build Coastguard Worker 'iterations': constants.ITERATIONS, 334*c2e18aaaSAndroid Build Coastguard Worker 'request_upload_result': constants.REQUEST_UPLOAD_RESULT, 335*c2e18aaaSAndroid Build Coastguard Worker 'bazel_mode_features': constants.BAZEL_MODE_FEATURES, 336*c2e18aaaSAndroid Build Coastguard Worker 'rerun_until_failure': constants.RERUN_UNTIL_FAILURE, 337*c2e18aaaSAndroid Build Coastguard Worker 'retry_any_failure': constants.RETRY_ANY_FAILURE, 338*c2e18aaaSAndroid Build Coastguard Worker 'serial': constants.SERIAL, 339*c2e18aaaSAndroid Build Coastguard Worker 'sharding': constants.SHARDING, 340*c2e18aaaSAndroid Build Coastguard Worker 'test_filter': constants.TEST_FILTER, 341*c2e18aaaSAndroid Build Coastguard Worker 'test_timeout': constants.TEST_TIMEOUT, 342*c2e18aaaSAndroid Build Coastguard Worker 'tf_debug': constants.TF_DEBUG, 343*c2e18aaaSAndroid Build Coastguard Worker 'tf_template': constants.TF_TEMPLATE, 344*c2e18aaaSAndroid Build Coastguard Worker 'user_type': constants.USER_TYPE, 345*c2e18aaaSAndroid Build Coastguard Worker 'verbose': constants.VERBOSE, 346*c2e18aaaSAndroid Build Coastguard Worker 'use_tf_min_base_template': constants.USE_TF_MIN_BASE_TEMPLATE, 347*c2e18aaaSAndroid Build Coastguard Worker } 348*c2e18aaaSAndroid Build Coastguard Worker not_match = [k for k in arg_maps if k not in vars(args)] 349*c2e18aaaSAndroid Build Coastguard Worker if not_match: 350*c2e18aaaSAndroid Build Coastguard Worker raise AttributeError( 351*c2e18aaaSAndroid Build Coastguard Worker '%s object has no attribute %s' % (type(args).__name__, not_match) 352*c2e18aaaSAndroid Build Coastguard Worker ) 353*c2e18aaaSAndroid Build Coastguard Worker extra_args.update({ 354*c2e18aaaSAndroid Build Coastguard Worker arg_maps.get(k): v for k, v in vars(args).items() if arg_maps.get(k) and v 355*c2e18aaaSAndroid Build Coastguard Worker }) 356*c2e18aaaSAndroid Build Coastguard Worker return extra_args 357*c2e18aaaSAndroid Build Coastguard Worker 358*c2e18aaaSAndroid Build Coastguard Worker 359*c2e18aaaSAndroid Build Coastguard Workerdef _validate_exec_mode(args, test_infos: list[TestInfo], host_tests=None): 360*c2e18aaaSAndroid Build Coastguard Worker """Validate all test execution modes are not in conflict. 361*c2e18aaaSAndroid Build Coastguard Worker 362*c2e18aaaSAndroid Build Coastguard Worker Exit the program with INVALID_EXEC_MODE code if the desired is a host-side 363*c2e18aaaSAndroid Build Coastguard Worker test but the given is a device-side test. 364*c2e18aaaSAndroid Build Coastguard Worker 365*c2e18aaaSAndroid Build Coastguard Worker If the given is a host-side test and not specified `args.host`, forcibly 366*c2e18aaaSAndroid Build Coastguard Worker set `args.host` to True. 367*c2e18aaaSAndroid Build Coastguard Worker 368*c2e18aaaSAndroid Build Coastguard Worker Args: 369*c2e18aaaSAndroid Build Coastguard Worker args: parsed args object. 370*c2e18aaaSAndroid Build Coastguard Worker test_infos: a list of TestInfo objects. 371*c2e18aaaSAndroid Build Coastguard Worker host_tests: True if all tests should be deviceless, False if all tests 372*c2e18aaaSAndroid Build Coastguard Worker should be device tests. Default is set to None, which means tests can be 373*c2e18aaaSAndroid Build Coastguard Worker either deviceless or device tests. 374*c2e18aaaSAndroid Build Coastguard Worker """ 375*c2e18aaaSAndroid Build Coastguard Worker all_device_modes = {x.get_supported_exec_mode() for x in test_infos} 376*c2e18aaaSAndroid Build Coastguard Worker err_msg = None 377*c2e18aaaSAndroid Build Coastguard Worker # In the case of '$atest <device-only> --host', exit. 378*c2e18aaaSAndroid Build Coastguard Worker if (host_tests or args.host) and constants.DEVICE_TEST in all_device_modes: 379*c2e18aaaSAndroid Build Coastguard Worker device_only_tests = [ 380*c2e18aaaSAndroid Build Coastguard Worker x.test_name 381*c2e18aaaSAndroid Build Coastguard Worker for x in test_infos 382*c2e18aaaSAndroid Build Coastguard Worker if x.get_supported_exec_mode() == constants.DEVICE_TEST 383*c2e18aaaSAndroid Build Coastguard Worker ] 384*c2e18aaaSAndroid Build Coastguard Worker err_msg = ( 385*c2e18aaaSAndroid Build Coastguard Worker 'Specified --host, but the following tests are device-only:\n ' 386*c2e18aaaSAndroid Build Coastguard Worker + '\n '.join(sorted(device_only_tests)) 387*c2e18aaaSAndroid Build Coastguard Worker + '\nPlease remove the option when running device-only tests.' 388*c2e18aaaSAndroid Build Coastguard Worker ) 389*c2e18aaaSAndroid Build Coastguard Worker # In the case of '$atest <host-only> <device-only> --host' or 390*c2e18aaaSAndroid Build Coastguard Worker # '$atest <host-only> <device-only>', exit. 391*c2e18aaaSAndroid Build Coastguard Worker if ( 392*c2e18aaaSAndroid Build Coastguard Worker constants.DEVICELESS_TEST in all_device_modes 393*c2e18aaaSAndroid Build Coastguard Worker and constants.DEVICE_TEST in all_device_modes 394*c2e18aaaSAndroid Build Coastguard Worker ): 395*c2e18aaaSAndroid Build Coastguard Worker err_msg = 'There are host-only and device-only tests in command.' 396*c2e18aaaSAndroid Build Coastguard Worker if host_tests is False and constants.DEVICELESS_TEST in all_device_modes: 397*c2e18aaaSAndroid Build Coastguard Worker err_msg = 'There are host-only tests in command.' 398*c2e18aaaSAndroid Build Coastguard Worker if err_msg: 399*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_error(err_msg) 400*c2e18aaaSAndroid Build Coastguard Worker metrics_utils.send_exit_event(ExitCode.INVALID_EXEC_MODE, logs=err_msg) 401*c2e18aaaSAndroid Build Coastguard Worker sys.exit(ExitCode.INVALID_EXEC_MODE) 402*c2e18aaaSAndroid Build Coastguard Worker # The 'adb' may not be available for the first repo sync or a clean build; 403*c2e18aaaSAndroid Build Coastguard Worker # run `adb devices` in the build step again. 404*c2e18aaaSAndroid Build Coastguard Worker if atest_utils.has_command('adb'): 405*c2e18aaaSAndroid Build Coastguard Worker _validate_adb_devices(args, test_infos) 406*c2e18aaaSAndroid Build Coastguard Worker # In the case of '$atest <host-only>', we add --host to run on host-side. 407*c2e18aaaSAndroid Build Coastguard Worker # The option should only be overridden if `host_tests` is not set. 408*c2e18aaaSAndroid Build Coastguard Worker if not args.host and host_tests is None: 409*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Appending "--host" for a deviceless test...') 410*c2e18aaaSAndroid Build Coastguard Worker args.host = bool(constants.DEVICELESS_TEST in all_device_modes) 411*c2e18aaaSAndroid Build Coastguard Worker 412*c2e18aaaSAndroid Build Coastguard Worker 413*c2e18aaaSAndroid Build Coastguard Workerdef _validate_adb_devices(args, test_infos): 414*c2e18aaaSAndroid Build Coastguard Worker """Validate the availability of connected devices via adb command. 415*c2e18aaaSAndroid Build Coastguard Worker 416*c2e18aaaSAndroid Build Coastguard Worker Exit the program with error code if have device-only and host-only. 417*c2e18aaaSAndroid Build Coastguard Worker 418*c2e18aaaSAndroid Build Coastguard Worker Args: 419*c2e18aaaSAndroid Build Coastguard Worker args: parsed args object. 420*c2e18aaaSAndroid Build Coastguard Worker test_infos: TestInfo object. 421*c2e18aaaSAndroid Build Coastguard Worker """ 422*c2e18aaaSAndroid Build Coastguard Worker # No need to check device availability if the user does not acquire to test. 423*c2e18aaaSAndroid Build Coastguard Worker if not parse_steps(args).test: 424*c2e18aaaSAndroid Build Coastguard Worker return 425*c2e18aaaSAndroid Build Coastguard Worker if args.no_checking_device: 426*c2e18aaaSAndroid Build Coastguard Worker return 427*c2e18aaaSAndroid Build Coastguard Worker # No need to check local device availability if the device test is running 428*c2e18aaaSAndroid Build Coastguard Worker # remotely. 429*c2e18aaaSAndroid Build Coastguard Worker if args.bazel_mode_features and ( 430*c2e18aaaSAndroid Build Coastguard Worker bazel_mode.Features.EXPERIMENTAL_REMOTE_AVD in args.bazel_mode_features 431*c2e18aaaSAndroid Build Coastguard Worker ): 432*c2e18aaaSAndroid Build Coastguard Worker return 433*c2e18aaaSAndroid Build Coastguard Worker all_device_modes = {x.get_supported_exec_mode() for x in test_infos} 434*c2e18aaaSAndroid Build Coastguard Worker device_tests = [ 435*c2e18aaaSAndroid Build Coastguard Worker x.test_name 436*c2e18aaaSAndroid Build Coastguard Worker for x in test_infos 437*c2e18aaaSAndroid Build Coastguard Worker if x.get_supported_exec_mode() != constants.DEVICELESS_TEST 438*c2e18aaaSAndroid Build Coastguard Worker ] 439*c2e18aaaSAndroid Build Coastguard Worker # Only block testing if it is a device test. 440*c2e18aaaSAndroid Build Coastguard Worker if constants.DEVICE_TEST in all_device_modes: 441*c2e18aaaSAndroid Build Coastguard Worker if ( 442*c2e18aaaSAndroid Build Coastguard Worker not any((args.host, args.start_avd, args.acloud_create)) 443*c2e18aaaSAndroid Build Coastguard Worker and not atest_utils.get_adb_devices() 444*c2e18aaaSAndroid Build Coastguard Worker ): 445*c2e18aaaSAndroid Build Coastguard Worker err_msg = ( 446*c2e18aaaSAndroid Build Coastguard Worker f'Stop running test(s): {", ".join(device_tests)} require a device.' 447*c2e18aaaSAndroid Build Coastguard Worker ) 448*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print(err_msg, constants.RED) 449*c2e18aaaSAndroid Build Coastguard Worker logging.debug(atest_utils.mark_red(constants.REQUIRE_DEVICES_MSG)) 450*c2e18aaaSAndroid Build Coastguard Worker metrics_utils.send_exit_event(ExitCode.DEVICE_NOT_FOUND, logs=err_msg) 451*c2e18aaaSAndroid Build Coastguard Worker sys.exit(ExitCode.DEVICE_NOT_FOUND) 452*c2e18aaaSAndroid Build Coastguard Worker 453*c2e18aaaSAndroid Build Coastguard Worker 454*c2e18aaaSAndroid Build Coastguard Workerdef _validate_tm_tests_exec_mode( 455*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 456*c2e18aaaSAndroid Build Coastguard Worker device_test_infos: List[test_info.TestInfo], 457*c2e18aaaSAndroid Build Coastguard Worker host_test_infos: List[test_info.TestInfo], 458*c2e18aaaSAndroid Build Coastguard Worker): 459*c2e18aaaSAndroid Build Coastguard Worker """Validate all test execution modes are not in conflict. 460*c2e18aaaSAndroid Build Coastguard Worker 461*c2e18aaaSAndroid Build Coastguard Worker Validate the tests' platform variant setting. For device tests, exit the 462*c2e18aaaSAndroid Build Coastguard Worker program if any test is found for host-only. For host tests, exit the 463*c2e18aaaSAndroid Build Coastguard Worker program if any test is found for device-only. 464*c2e18aaaSAndroid Build Coastguard Worker 465*c2e18aaaSAndroid Build Coastguard Worker Args: 466*c2e18aaaSAndroid Build Coastguard Worker args: parsed args object. 467*c2e18aaaSAndroid Build Coastguard Worker device_test_infos: TestInfo instances for device tests. 468*c2e18aaaSAndroid Build Coastguard Worker host_test_infos: TestInfo instances for host tests. 469*c2e18aaaSAndroid Build Coastguard Worker """ 470*c2e18aaaSAndroid Build Coastguard Worker 471*c2e18aaaSAndroid Build Coastguard Worker # No need to verify device tests if atest command is set to only run host 472*c2e18aaaSAndroid Build Coastguard Worker # tests. 473*c2e18aaaSAndroid Build Coastguard Worker if device_test_infos and not args.host: 474*c2e18aaaSAndroid Build Coastguard Worker _validate_exec_mode(args, device_test_infos, host_tests=False) 475*c2e18aaaSAndroid Build Coastguard Worker if host_test_infos: 476*c2e18aaaSAndroid Build Coastguard Worker _validate_exec_mode(args, host_test_infos, host_tests=True) 477*c2e18aaaSAndroid Build Coastguard Worker 478*c2e18aaaSAndroid Build Coastguard Worker 479*c2e18aaaSAndroid Build Coastguard Workerdef _has_valid_test_mapping_args(args): 480*c2e18aaaSAndroid Build Coastguard Worker """Validate test mapping args. 481*c2e18aaaSAndroid Build Coastguard Worker 482*c2e18aaaSAndroid Build Coastguard Worker Not all args work when running tests in TEST_MAPPING files. Validate the 483*c2e18aaaSAndroid Build Coastguard Worker args before running the tests. 484*c2e18aaaSAndroid Build Coastguard Worker 485*c2e18aaaSAndroid Build Coastguard Worker Args: 486*c2e18aaaSAndroid Build Coastguard Worker args: parsed args object. 487*c2e18aaaSAndroid Build Coastguard Worker 488*c2e18aaaSAndroid Build Coastguard Worker Returns: 489*c2e18aaaSAndroid Build Coastguard Worker True if args are valid 490*c2e18aaaSAndroid Build Coastguard Worker """ 491*c2e18aaaSAndroid Build Coastguard Worker is_test_mapping = atest_utils.is_test_mapping(args) 492*c2e18aaaSAndroid Build Coastguard Worker if is_test_mapping: 493*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent(detect_type=DetectType.IS_TEST_MAPPING, result=1) 494*c2e18aaaSAndroid Build Coastguard Worker else: 495*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent(detect_type=DetectType.IS_TEST_MAPPING, result=0) 496*c2e18aaaSAndroid Build Coastguard Worker if not is_test_mapping: 497*c2e18aaaSAndroid Build Coastguard Worker return True 498*c2e18aaaSAndroid Build Coastguard Worker options_to_validate = [ 499*c2e18aaaSAndroid Build Coastguard Worker (args.annotation_filter, '--annotation-filter'), 500*c2e18aaaSAndroid Build Coastguard Worker ] 501*c2e18aaaSAndroid Build Coastguard Worker for arg_value, arg in options_to_validate: 502*c2e18aaaSAndroid Build Coastguard Worker if arg_value: 503*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_error( 504*c2e18aaaSAndroid Build Coastguard Worker atest_utils.mark_red(OPTION_NOT_FOR_TEST_MAPPING.format(arg)) 505*c2e18aaaSAndroid Build Coastguard Worker ) 506*c2e18aaaSAndroid Build Coastguard Worker return False 507*c2e18aaaSAndroid Build Coastguard Worker return True 508*c2e18aaaSAndroid Build Coastguard Worker 509*c2e18aaaSAndroid Build Coastguard Worker 510*c2e18aaaSAndroid Build Coastguard Workerdef _print_deprecation_warning(arg_to_deprecate: str): 511*c2e18aaaSAndroid Build Coastguard Worker """For features that are up for deprecation in the near future, print a message 512*c2e18aaaSAndroid Build Coastguard Worker 513*c2e18aaaSAndroid Build Coastguard Worker to alert the user about the upcoming deprecation. 514*c2e18aaaSAndroid Build Coastguard Worker 515*c2e18aaaSAndroid Build Coastguard Worker Args: 516*c2e18aaaSAndroid Build Coastguard Worker arg_to_deprecate: the arg with which the to-be-deprecated feature is 517*c2e18aaaSAndroid Build Coastguard Worker called. 518*c2e18aaaSAndroid Build Coastguard Worker """ 519*c2e18aaaSAndroid Build Coastguard Worker args_to_deprecation_info = { 520*c2e18aaaSAndroid Build Coastguard Worker # arg_to_deprecate : (deprecation timeframe, additional info for users) 521*c2e18aaaSAndroid Build Coastguard Worker '--info': ('is deprecated.', '\nUse CodeSearch or `gomod` instead.') 522*c2e18aaaSAndroid Build Coastguard Worker } 523*c2e18aaaSAndroid Build Coastguard Worker 524*c2e18aaaSAndroid Build Coastguard Worker warning_message = ( 525*c2e18aaaSAndroid Build Coastguard Worker f'\nWARNING: The `{arg_to_deprecate}` feature ' 526*c2e18aaaSAndroid Build Coastguard Worker + ' '.join(args_to_deprecation_info[arg_to_deprecate]) 527*c2e18aaaSAndroid Build Coastguard Worker + '\nPlease file a bug or feature request to the Atest team if you have' 528*c2e18aaaSAndroid Build Coastguard Worker ' any concerns.' 529*c2e18aaaSAndroid Build Coastguard Worker ) 530*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print(warning_message, constants.RED) 531*c2e18aaaSAndroid Build Coastguard Worker 532*c2e18aaaSAndroid Build Coastguard Worker 533*c2e18aaaSAndroid Build Coastguard Workerdef is_from_test_mapping(test_infos): 534*c2e18aaaSAndroid Build Coastguard Worker """Check that the test_infos came from TEST_MAPPING files. 535*c2e18aaaSAndroid Build Coastguard Worker 536*c2e18aaaSAndroid Build Coastguard Worker Args: 537*c2e18aaaSAndroid Build Coastguard Worker test_infos: A set of TestInfos. 538*c2e18aaaSAndroid Build Coastguard Worker 539*c2e18aaaSAndroid Build Coastguard Worker Returns: 540*c2e18aaaSAndroid Build Coastguard Worker True if the test infos are from TEST_MAPPING files. 541*c2e18aaaSAndroid Build Coastguard Worker """ 542*c2e18aaaSAndroid Build Coastguard Worker return list(test_infos)[0].from_test_mapping 543*c2e18aaaSAndroid Build Coastguard Worker 544*c2e18aaaSAndroid Build Coastguard Worker 545*c2e18aaaSAndroid Build Coastguard Workerdef _split_test_mapping_tests(test_infos): 546*c2e18aaaSAndroid Build Coastguard Worker """Split Test Mapping tests into 2 groups: device tests and host tests. 547*c2e18aaaSAndroid Build Coastguard Worker 548*c2e18aaaSAndroid Build Coastguard Worker Args: 549*c2e18aaaSAndroid Build Coastguard Worker test_infos: A set of TestInfos. 550*c2e18aaaSAndroid Build Coastguard Worker 551*c2e18aaaSAndroid Build Coastguard Worker Returns: 552*c2e18aaaSAndroid Build Coastguard Worker A tuple of (device_test_infos, host_test_infos), where 553*c2e18aaaSAndroid Build Coastguard Worker device_test_infos: A set of TestInfos for tests that require device. 554*c2e18aaaSAndroid Build Coastguard Worker host_test_infos: A set of TestInfos for tests that do NOT require 555*c2e18aaaSAndroid Build Coastguard Worker device. 556*c2e18aaaSAndroid Build Coastguard Worker """ 557*c2e18aaaSAndroid Build Coastguard Worker assert is_from_test_mapping(test_infos) 558*c2e18aaaSAndroid Build Coastguard Worker host_test_infos = {info for info in test_infos if info.host} 559*c2e18aaaSAndroid Build Coastguard Worker device_test_infos = {info for info in test_infos if not info.host} 560*c2e18aaaSAndroid Build Coastguard Worker return device_test_infos, host_test_infos 561*c2e18aaaSAndroid Build Coastguard Worker 562*c2e18aaaSAndroid Build Coastguard Worker 563*c2e18aaaSAndroid Build Coastguard Workerdef _exclude_modules_in_targets(build_targets): 564*c2e18aaaSAndroid Build Coastguard Worker """Method that excludes MODULES-IN-* targets. 565*c2e18aaaSAndroid Build Coastguard Worker 566*c2e18aaaSAndroid Build Coastguard Worker Args: 567*c2e18aaaSAndroid Build Coastguard Worker build_targets: A set of build targets. 568*c2e18aaaSAndroid Build Coastguard Worker 569*c2e18aaaSAndroid Build Coastguard Worker Returns: 570*c2e18aaaSAndroid Build Coastguard Worker A set of build targets that excludes MODULES-IN-*. 571*c2e18aaaSAndroid Build Coastguard Worker """ 572*c2e18aaaSAndroid Build Coastguard Worker shrank_build_targets = build_targets.copy() 573*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 574*c2e18aaaSAndroid Build Coastguard Worker 'Will exclude all "%s*" from the build targets.', constants.MODULES_IN 575*c2e18aaaSAndroid Build Coastguard Worker ) 576*c2e18aaaSAndroid Build Coastguard Worker for target in build_targets: 577*c2e18aaaSAndroid Build Coastguard Worker if target.startswith(constants.MODULES_IN): 578*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Ignore %s.', target) 579*c2e18aaaSAndroid Build Coastguard Worker shrank_build_targets.remove(target) 580*c2e18aaaSAndroid Build Coastguard Worker return shrank_build_targets 581*c2e18aaaSAndroid Build Coastguard Worker 582*c2e18aaaSAndroid Build Coastguard Worker 583*c2e18aaaSAndroid Build Coastguard Workerdef get_device_count_config(test_infos, mod_info): 584*c2e18aaaSAndroid Build Coastguard Worker """Get the amount of desired devices from the test config. 585*c2e18aaaSAndroid Build Coastguard Worker 586*c2e18aaaSAndroid Build Coastguard Worker Args: 587*c2e18aaaSAndroid Build Coastguard Worker test_infos: A set of TestInfo instances. 588*c2e18aaaSAndroid Build Coastguard Worker mod_info: ModuleInfo object. 589*c2e18aaaSAndroid Build Coastguard Worker 590*c2e18aaaSAndroid Build Coastguard Worker Returns: the count of devices in test config. If there are more than one 591*c2e18aaaSAndroid Build Coastguard Worker configs, return the maximum. 592*c2e18aaaSAndroid Build Coastguard Worker """ 593*c2e18aaaSAndroid Build Coastguard Worker max_count = 0 594*c2e18aaaSAndroid Build Coastguard Worker for tinfo in test_infos: 595*c2e18aaaSAndroid Build Coastguard Worker test_config, _ = test_finder_utils.get_test_config_and_srcs(tinfo, mod_info) 596*c2e18aaaSAndroid Build Coastguard Worker if test_config: 597*c2e18aaaSAndroid Build Coastguard Worker devices = atest_utils.get_config_device(test_config) 598*c2e18aaaSAndroid Build Coastguard Worker if devices: 599*c2e18aaaSAndroid Build Coastguard Worker max_count = max(len(devices), max_count) 600*c2e18aaaSAndroid Build Coastguard Worker return max_count 601*c2e18aaaSAndroid Build Coastguard Worker 602*c2e18aaaSAndroid Build Coastguard Worker 603*c2e18aaaSAndroid Build Coastguard Workerdef has_set_sufficient_devices( 604*c2e18aaaSAndroid Build Coastguard Worker required_amount: int, serial: List[str] = None 605*c2e18aaaSAndroid Build Coastguard Worker) -> bool: 606*c2e18aaaSAndroid Build Coastguard Worker """Detect whether sufficient device serial is set for test.""" 607*c2e18aaaSAndroid Build Coastguard Worker given_amount = len(serial) if serial else 0 608*c2e18aaaSAndroid Build Coastguard Worker # Only check when both given_amount and required_amount are non zero. 609*c2e18aaaSAndroid Build Coastguard Worker if all((given_amount, required_amount)): 610*c2e18aaaSAndroid Build Coastguard Worker # Base on TF rules, given_amount can be greater than or equal to 611*c2e18aaaSAndroid Build Coastguard Worker # required_amount. 612*c2e18aaaSAndroid Build Coastguard Worker if required_amount > given_amount: 613*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 614*c2e18aaaSAndroid Build Coastguard Worker f'The test requires {required_amount} devices, ' 615*c2e18aaaSAndroid Build Coastguard Worker f'but {given_amount} were given.', 616*c2e18aaaSAndroid Build Coastguard Worker constants.RED, 617*c2e18aaaSAndroid Build Coastguard Worker ) 618*c2e18aaaSAndroid Build Coastguard Worker return False 619*c2e18aaaSAndroid Build Coastguard Worker return True 620*c2e18aaaSAndroid Build Coastguard Worker 621*c2e18aaaSAndroid Build Coastguard Worker 622*c2e18aaaSAndroid Build Coastguard Workerdef setup_metrics_tool_name(no_metrics: bool = False): 623*c2e18aaaSAndroid Build Coastguard Worker """Setup tool_name and sub_tool_name for MetricsBase.""" 624*c2e18aaaSAndroid Build Coastguard Worker if ( 625*c2e18aaaSAndroid Build Coastguard Worker not no_metrics 626*c2e18aaaSAndroid Build Coastguard Worker and metrics_base.MetricsBase.user_type == metrics_base.INTERNAL_USER 627*c2e18aaaSAndroid Build Coastguard Worker ): 628*c2e18aaaSAndroid Build Coastguard Worker metrics_utils.print_data_collection_notice() 629*c2e18aaaSAndroid Build Coastguard Worker 630*c2e18aaaSAndroid Build Coastguard Worker USER_FROM_TOOL = os.getenv(constants.USER_FROM_TOOL) 631*c2e18aaaSAndroid Build Coastguard Worker metrics_base.MetricsBase.tool_name = ( 632*c2e18aaaSAndroid Build Coastguard Worker USER_FROM_TOOL if USER_FROM_TOOL else constants.TOOL_NAME 633*c2e18aaaSAndroid Build Coastguard Worker ) 634*c2e18aaaSAndroid Build Coastguard Worker 635*c2e18aaaSAndroid Build Coastguard Worker USER_FROM_SUB_TOOL = os.getenv(constants.USER_FROM_SUB_TOOL) 636*c2e18aaaSAndroid Build Coastguard Worker metrics_base.MetricsBase.sub_tool_name = ( 637*c2e18aaaSAndroid Build Coastguard Worker USER_FROM_SUB_TOOL if USER_FROM_SUB_TOOL else constants.SUB_TOOL_NAME 638*c2e18aaaSAndroid Build Coastguard Worker ) 639*c2e18aaaSAndroid Build Coastguard Worker 640*c2e18aaaSAndroid Build Coastguard Worker 641*c2e18aaaSAndroid Build Coastguard Workerclass _AtestMain: 642*c2e18aaaSAndroid Build Coastguard Worker """Entry point of atest script.""" 643*c2e18aaaSAndroid Build Coastguard Worker 644*c2e18aaaSAndroid Build Coastguard Worker def __init__( 645*c2e18aaaSAndroid Build Coastguard Worker self, 646*c2e18aaaSAndroid Build Coastguard Worker argv: list[str], 647*c2e18aaaSAndroid Build Coastguard Worker ): 648*c2e18aaaSAndroid Build Coastguard Worker """Initializes the _AtestMain object. 649*c2e18aaaSAndroid Build Coastguard Worker 650*c2e18aaaSAndroid Build Coastguard Worker Args: 651*c2e18aaaSAndroid Build Coastguard Worker argv: A list of command line arguments. 652*c2e18aaaSAndroid Build Coastguard Worker """ 653*c2e18aaaSAndroid Build Coastguard Worker self._argv: list[str] = argv 654*c2e18aaaSAndroid Build Coastguard Worker 655*c2e18aaaSAndroid Build Coastguard Worker self._banner_printer: banner.BannerPrinter = None 656*c2e18aaaSAndroid Build Coastguard Worker self._steps: Steps = None 657*c2e18aaaSAndroid Build Coastguard Worker self._results_dir: str = None 658*c2e18aaaSAndroid Build Coastguard Worker self._mod_info: module_info.ModuleInfo = None 659*c2e18aaaSAndroid Build Coastguard Worker self._test_infos: list[test_info.TestInfo] = None 660*c2e18aaaSAndroid Build Coastguard Worker self._test_execution_plan: _TestExecutionPlan = None 661*c2e18aaaSAndroid Build Coastguard Worker 662*c2e18aaaSAndroid Build Coastguard Worker self._acloud_proc: subprocess.Popen = None 663*c2e18aaaSAndroid Build Coastguard Worker self._acloud_report_file: str = None 664*c2e18aaaSAndroid Build Coastguard Worker self._test_info_loading_duration: float = 0 665*c2e18aaaSAndroid Build Coastguard Worker self._build_duration: float = 0 666*c2e18aaaSAndroid Build Coastguard Worker self._module_info_rebuild_required: bool = False 667*c2e18aaaSAndroid Build Coastguard Worker self._is_out_clean_before_module_info_build: bool = False 668*c2e18aaaSAndroid Build Coastguard Worker self._invocation_begin_time: float = None 669*c2e18aaaSAndroid Build Coastguard Worker 670*c2e18aaaSAndroid Build Coastguard Worker def run(self): 671*c2e18aaaSAndroid Build Coastguard Worker self._results_dir = make_test_run_dir() 672*c2e18aaaSAndroid Build Coastguard Worker 673*c2e18aaaSAndroid Build Coastguard Worker if END_OF_OPTION in self._argv: 674*c2e18aaaSAndroid Build Coastguard Worker end_position = self._argv.index(END_OF_OPTION) 675*c2e18aaaSAndroid Build Coastguard Worker final_args = [ 676*c2e18aaaSAndroid Build Coastguard Worker *self._argv[1:end_position], 677*c2e18aaaSAndroid Build Coastguard Worker *_get_args_from_config(), 678*c2e18aaaSAndroid Build Coastguard Worker *self._argv[end_position:], 679*c2e18aaaSAndroid Build Coastguard Worker ] 680*c2e18aaaSAndroid Build Coastguard Worker else: 681*c2e18aaaSAndroid Build Coastguard Worker final_args = [*self._argv[1:], *_get_args_from_config()] 682*c2e18aaaSAndroid Build Coastguard Worker if final_args != self._argv[1:]: 683*c2e18aaaSAndroid Build Coastguard Worker print( 684*c2e18aaaSAndroid Build Coastguard Worker 'The actual cmd will be: \n\t{}\n'.format( 685*c2e18aaaSAndroid Build Coastguard Worker atest_utils.mark_cyan('atest ' + ' '.join(final_args)) 686*c2e18aaaSAndroid Build Coastguard Worker ) 687*c2e18aaaSAndroid Build Coastguard Worker ) 688*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent(detect_type=DetectType.ATEST_CONFIG, result=1) 689*c2e18aaaSAndroid Build Coastguard Worker if HAS_IGNORED_ARGS: 690*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 691*c2e18aaaSAndroid Build Coastguard Worker 'Please correct the config and try again.', constants.YELLOW 692*c2e18aaaSAndroid Build Coastguard Worker ) 693*c2e18aaaSAndroid Build Coastguard Worker sys.exit(ExitCode.EXIT_BEFORE_MAIN) 694*c2e18aaaSAndroid Build Coastguard Worker else: 695*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent(detect_type=DetectType.ATEST_CONFIG, result=0) 696*c2e18aaaSAndroid Build Coastguard Worker 697*c2e18aaaSAndroid Build Coastguard Worker self._args = _parse_args(final_args) 698*c2e18aaaSAndroid Build Coastguard Worker atest_configs.GLOBAL_ARGS = self._args 699*c2e18aaaSAndroid Build Coastguard Worker _configure_logging(self._args.verbose, self._results_dir) 700*c2e18aaaSAndroid Build Coastguard Worker 701*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 702*c2e18aaaSAndroid Build Coastguard Worker 'Start of atest run. sys.argv: %s, final_args: %s', 703*c2e18aaaSAndroid Build Coastguard Worker self._argv, 704*c2e18aaaSAndroid Build Coastguard Worker final_args, 705*c2e18aaaSAndroid Build Coastguard Worker ) 706*c2e18aaaSAndroid Build Coastguard Worker 707*c2e18aaaSAndroid Build Coastguard Worker self._steps = parse_steps(self._args) 708*c2e18aaaSAndroid Build Coastguard Worker 709*c2e18aaaSAndroid Build Coastguard Worker self._banner_printer = banner.BannerPrinter.create() 710*c2e18aaaSAndroid Build Coastguard Worker 711*c2e18aaaSAndroid Build Coastguard Worker with atest_execution_info.AtestExecutionInfo( 712*c2e18aaaSAndroid Build Coastguard Worker final_args, self._results_dir, atest_configs.GLOBAL_ARGS 713*c2e18aaaSAndroid Build Coastguard Worker ): 714*c2e18aaaSAndroid Build Coastguard Worker setup_metrics_tool_name(atest_configs.GLOBAL_ARGS.no_metrics) 715*c2e18aaaSAndroid Build Coastguard Worker 716*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 717*c2e18aaaSAndroid Build Coastguard Worker 'Creating atest script with argv: %s\n results_dir: %s\n args: %s\n' 718*c2e18aaaSAndroid Build Coastguard Worker ' run id: %s', 719*c2e18aaaSAndroid Build Coastguard Worker self._argv, 720*c2e18aaaSAndroid Build Coastguard Worker self._results_dir, 721*c2e18aaaSAndroid Build Coastguard Worker self._args, 722*c2e18aaaSAndroid Build Coastguard Worker metrics.get_run_id(), 723*c2e18aaaSAndroid Build Coastguard Worker ) 724*c2e18aaaSAndroid Build Coastguard Worker exit_code = self._run_all_steps() 725*c2e18aaaSAndroid Build Coastguard Worker detector = bug_detector.BugDetector(final_args, exit_code) 726*c2e18aaaSAndroid Build Coastguard Worker if exit_code not in EXIT_CODES_BEFORE_TEST: 727*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent( 728*c2e18aaaSAndroid Build Coastguard Worker detect_type=DetectType.BUG_DETECTED, result=detector.caught_result 729*c2e18aaaSAndroid Build Coastguard Worker ) 730*c2e18aaaSAndroid Build Coastguard Worker 731*c2e18aaaSAndroid Build Coastguard Worker self._banner_printer.print() 732*c2e18aaaSAndroid Build Coastguard Worker 733*c2e18aaaSAndroid Build Coastguard Worker sys.exit(exit_code) 734*c2e18aaaSAndroid Build Coastguard Worker 735*c2e18aaaSAndroid Build Coastguard Worker def _check_no_action_argument(self) -> int: 736*c2e18aaaSAndroid Build Coastguard Worker """Method for non-action arguments such as --version, --history, --latest_result, etc. 737*c2e18aaaSAndroid Build Coastguard Worker 738*c2e18aaaSAndroid Build Coastguard Worker Returns: 739*c2e18aaaSAndroid Build Coastguard Worker Exit code if no action. None otherwise. 740*c2e18aaaSAndroid Build Coastguard Worker """ 741*c2e18aaaSAndroid Build Coastguard Worker if self._args.version: 742*c2e18aaaSAndroid Build Coastguard Worker print(atest_utils.get_atest_version()) 743*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 744*c2e18aaaSAndroid Build Coastguard Worker if self._args.history: 745*c2e18aaaSAndroid Build Coastguard Worker atest_execution_info.print_test_result( 746*c2e18aaaSAndroid Build Coastguard Worker constants.ATEST_RESULT_ROOT, self._args.history 747*c2e18aaaSAndroid Build Coastguard Worker ) 748*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 749*c2e18aaaSAndroid Build Coastguard Worker if self._args.latest_result: 750*c2e18aaaSAndroid Build Coastguard Worker atest_execution_info.print_test_result_by_path( 751*c2e18aaaSAndroid Build Coastguard Worker constants.LATEST_RESULT_FILE 752*c2e18aaaSAndroid Build Coastguard Worker ) 753*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 754*c2e18aaaSAndroid Build Coastguard Worker return None 755*c2e18aaaSAndroid Build Coastguard Worker 756*c2e18aaaSAndroid Build Coastguard Worker def _check_envs_and_args(self) -> int: 757*c2e18aaaSAndroid Build Coastguard Worker """Validate environment variables and args. 758*c2e18aaaSAndroid Build Coastguard Worker 759*c2e18aaaSAndroid Build Coastguard Worker Returns: 760*c2e18aaaSAndroid Build Coastguard Worker Exit code if any setup or arg is invalid. None otherwise. 761*c2e18aaaSAndroid Build Coastguard Worker """ 762*c2e18aaaSAndroid Build Coastguard Worker if ( 763*c2e18aaaSAndroid Build Coastguard Worker not os.getenv(constants.ANDROID_BUILD_TOP, ' ') in os.getcwd() 764*c2e18aaaSAndroid Build Coastguard Worker ): # Not under android root. 765*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 766*c2e18aaaSAndroid Build Coastguard Worker '\nAtest must always work under ${}!'.format( 767*c2e18aaaSAndroid Build Coastguard Worker constants.ANDROID_BUILD_TOP 768*c2e18aaaSAndroid Build Coastguard Worker ), 769*c2e18aaaSAndroid Build Coastguard Worker constants.RED, 770*c2e18aaaSAndroid Build Coastguard Worker ) 771*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.OUTSIDE_ROOT 772*c2e18aaaSAndroid Build Coastguard Worker if _missing_environment_variables(): 773*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.ENV_NOT_SETUP 774*c2e18aaaSAndroid Build Coastguard Worker if not _has_valid_test_mapping_args(self._args): 775*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.INVALID_TM_ARGS 776*c2e18aaaSAndroid Build Coastguard Worker 777*c2e18aaaSAndroid Build Coastguard Worker # Checks whether ANDROID_SERIAL environment variable is set to an empty string. 778*c2e18aaaSAndroid Build Coastguard Worker if 'ANDROID_SERIAL' in os.environ and not os.environ['ANDROID_SERIAL']: 779*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_warning( 780*c2e18aaaSAndroid Build Coastguard Worker 'Empty device serial detected in the ANDROID_SERIAL environment' 781*c2e18aaaSAndroid Build Coastguard Worker ' variable. This may causes unexpected behavior in TradeFed. If not' 782*c2e18aaaSAndroid Build Coastguard Worker ' targeting a specific device, consider unset the ANDROID_SERIAL' 783*c2e18aaaSAndroid Build Coastguard Worker ' environment variable. See b/330365573 for details.' 784*c2e18aaaSAndroid Build Coastguard Worker ) 785*c2e18aaaSAndroid Build Coastguard Worker 786*c2e18aaaSAndroid Build Coastguard Worker # Checks whether any empty serial strings exist in the argument array. 787*c2e18aaaSAndroid Build Coastguard Worker if self._args.serial and not all(self._args.serial): 788*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_warning( 789*c2e18aaaSAndroid Build Coastguard Worker 'Empty device serial specified via command-line argument. This may' 790*c2e18aaaSAndroid Build Coastguard Worker ' cause unexpected behavior in TradeFed. If not targeting a specific' 791*c2e18aaaSAndroid Build Coastguard Worker ' device, consider remove the serial argument. See b/330365573 for' 792*c2e18aaaSAndroid Build Coastguard Worker ' details.' 793*c2e18aaaSAndroid Build Coastguard Worker ) 794*c2e18aaaSAndroid Build Coastguard Worker 795*c2e18aaaSAndroid Build Coastguard Worker return None 796*c2e18aaaSAndroid Build Coastguard Worker 797*c2e18aaaSAndroid Build Coastguard Worker def _update_build_env(self): 798*c2e18aaaSAndroid Build Coastguard Worker """Updates build environment variables.""" 799*c2e18aaaSAndroid Build Coastguard Worker # Sets coverage environment variables. 800*c2e18aaaSAndroid Build Coastguard Worker if self._args.experimental_coverage: 801*c2e18aaaSAndroid Build Coastguard Worker atest_utils.update_build_env(coverage.build_env_vars()) 802*c2e18aaaSAndroid Build Coastguard Worker 803*c2e18aaaSAndroid Build Coastguard Worker # Update environment variable dict accordingly to args.build_output 804*c2e18aaaSAndroid Build Coastguard Worker atest_utils.update_build_env({ 805*c2e18aaaSAndroid Build Coastguard Worker 'ANDROID_QUIET_BUILD': 'true', 806*c2e18aaaSAndroid Build Coastguard Worker 'BUILD_OUTPUT_MODE': self._args.build_output.value, 807*c2e18aaaSAndroid Build Coastguard Worker }) 808*c2e18aaaSAndroid Build Coastguard Worker 809*c2e18aaaSAndroid Build Coastguard Worker def _start_acloud_if_requested(self) -> None: 810*c2e18aaaSAndroid Build Coastguard Worker if not self._args.acloud_create and not self._args.start_avd: 811*c2e18aaaSAndroid Build Coastguard Worker return 812*c2e18aaaSAndroid Build Coastguard Worker if not parse_steps(self._args).test: 813*c2e18aaaSAndroid Build Coastguard Worker print('acloud/avd is requested but ignored because no test is requested.') 814*c2e18aaaSAndroid Build Coastguard Worker return 815*c2e18aaaSAndroid Build Coastguard Worker print('Creating acloud/avd...') 816*c2e18aaaSAndroid Build Coastguard Worker self._acloud_proc, self._acloud_report_file = avd.acloud_create_validator( 817*c2e18aaaSAndroid Build Coastguard Worker self._results_dir, self._args 818*c2e18aaaSAndroid Build Coastguard Worker ) 819*c2e18aaaSAndroid Build Coastguard Worker 820*c2e18aaaSAndroid Build Coastguard Worker def _check_acloud_status(self) -> int: 821*c2e18aaaSAndroid Build Coastguard Worker """Checks acloud status if acloud is requested. 822*c2e18aaaSAndroid Build Coastguard Worker 823*c2e18aaaSAndroid Build Coastguard Worker Returns: 824*c2e18aaaSAndroid Build Coastguard Worker acloud status code. None if no acloud requested. 825*c2e18aaaSAndroid Build Coastguard Worker """ 826*c2e18aaaSAndroid Build Coastguard Worker if self._acloud_proc: 827*c2e18aaaSAndroid Build Coastguard Worker self._acloud_proc.join() 828*c2e18aaaSAndroid Build Coastguard Worker status = avd.probe_acloud_status( 829*c2e18aaaSAndroid Build Coastguard Worker self._acloud_report_file, 830*c2e18aaaSAndroid Build Coastguard Worker self._test_info_loading_duration + self._build_duration, 831*c2e18aaaSAndroid Build Coastguard Worker ) 832*c2e18aaaSAndroid Build Coastguard Worker return status 833*c2e18aaaSAndroid Build Coastguard Worker return None 834*c2e18aaaSAndroid Build Coastguard Worker 835*c2e18aaaSAndroid Build Coastguard Worker def _start_indexing_if_required(self) -> threading.Thread: 836*c2e18aaaSAndroid Build Coastguard Worker """Starts indexing if required. 837*c2e18aaaSAndroid Build Coastguard Worker 838*c2e18aaaSAndroid Build Coastguard Worker Returns: 839*c2e18aaaSAndroid Build Coastguard Worker A thread that runs indexing. None if no indexing is required. 840*c2e18aaaSAndroid Build Coastguard Worker """ 841*c2e18aaaSAndroid Build Coastguard Worker if not self._steps.build: 842*c2e18aaaSAndroid Build Coastguard Worker logging.debug("Skip indexing because there's no build required.") 843*c2e18aaaSAndroid Build Coastguard Worker return None 844*c2e18aaaSAndroid Build Coastguard Worker 845*c2e18aaaSAndroid Build Coastguard Worker if indexing.Indices().has_all_indices(): 846*c2e18aaaSAndroid Build Coastguard Worker no_indexing_args = ( 847*c2e18aaaSAndroid Build Coastguard Worker self._args.dry_run, 848*c2e18aaaSAndroid Build Coastguard Worker self._args.list_modules, 849*c2e18aaaSAndroid Build Coastguard Worker ) 850*c2e18aaaSAndroid Build Coastguard Worker if any(no_indexing_args): 851*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 852*c2e18aaaSAndroid Build Coastguard Worker 'Skip indexing for no_indexing_args=%s.', no_indexing_args 853*c2e18aaaSAndroid Build Coastguard Worker ) 854*c2e18aaaSAndroid Build Coastguard Worker return None 855*c2e18aaaSAndroid Build Coastguard Worker else: 856*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 857*c2e18aaaSAndroid Build Coastguard Worker 'Indexing targets is required because some index files do not exist.' 858*c2e18aaaSAndroid Build Coastguard Worker ) 859*c2e18aaaSAndroid Build Coastguard Worker 860*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Starting to index targets in a background thread.') 861*c2e18aaaSAndroid Build Coastguard Worker return atest_utils.start_threading( 862*c2e18aaaSAndroid Build Coastguard Worker indexing.index_targets, 863*c2e18aaaSAndroid Build Coastguard Worker daemon=True, 864*c2e18aaaSAndroid Build Coastguard Worker ) 865*c2e18aaaSAndroid Build Coastguard Worker 866*c2e18aaaSAndroid Build Coastguard Worker @functools.cache 867*c2e18aaaSAndroid Build Coastguard Worker def _get_device_update_method(self) -> device_update.AdeviceUpdateMethod: 868*c2e18aaaSAndroid Build Coastguard Worker """Creates a device update method.""" 869*c2e18aaaSAndroid Build Coastguard Worker return device_update.AdeviceUpdateMethod( 870*c2e18aaaSAndroid Build Coastguard Worker targets=set(self._args.update_modules or []) 871*c2e18aaaSAndroid Build Coastguard Worker ) 872*c2e18aaaSAndroid Build Coastguard Worker 873*c2e18aaaSAndroid Build Coastguard Worker def _get_device_update_dependencies(self) -> set[str]: 874*c2e18aaaSAndroid Build Coastguard Worker """Gets device update dependencies. 875*c2e18aaaSAndroid Build Coastguard Worker 876*c2e18aaaSAndroid Build Coastguard Worker Returns: 877*c2e18aaaSAndroid Build Coastguard Worker A set of dependencies for the device update method. 878*c2e18aaaSAndroid Build Coastguard Worker """ 879*c2e18aaaSAndroid Build Coastguard Worker if not self._args.update_device: 880*c2e18aaaSAndroid Build Coastguard Worker return set() 881*c2e18aaaSAndroid Build Coastguard Worker 882*c2e18aaaSAndroid Build Coastguard Worker if ( 883*c2e18aaaSAndroid Build Coastguard Worker self._test_execution_plan 884*c2e18aaaSAndroid Build Coastguard Worker and not self._test_execution_plan.requires_device_update() 885*c2e18aaaSAndroid Build Coastguard Worker ): 886*c2e18aaaSAndroid Build Coastguard Worker return set() 887*c2e18aaaSAndroid Build Coastguard Worker 888*c2e18aaaSAndroid Build Coastguard Worker return self._get_device_update_method().dependencies() 889*c2e18aaaSAndroid Build Coastguard Worker 890*c2e18aaaSAndroid Build Coastguard Worker def _need_rebuild_module_info(self) -> bool: 891*c2e18aaaSAndroid Build Coastguard Worker """Method that tells whether we need to rebuild module-info.json or not. 892*c2e18aaaSAndroid Build Coastguard Worker 893*c2e18aaaSAndroid Build Coastguard Worker Returns: 894*c2e18aaaSAndroid Build Coastguard Worker True for forcely/smartly rebuild, otherwise False without rebuilding. 895*c2e18aaaSAndroid Build Coastguard Worker """ 896*c2e18aaaSAndroid Build Coastguard Worker # +-----------------+ 897*c2e18aaaSAndroid Build Coastguard Worker # | Explicitly pass | yes 898*c2e18aaaSAndroid Build Coastguard Worker # | '--test' +-------> False (won't rebuild) 899*c2e18aaaSAndroid Build Coastguard Worker # +--------+--------+ 900*c2e18aaaSAndroid Build Coastguard Worker # | no 901*c2e18aaaSAndroid Build Coastguard Worker # V 902*c2e18aaaSAndroid Build Coastguard Worker # +-------------------------+ 903*c2e18aaaSAndroid Build Coastguard Worker # | Explicitly pass | yes 904*c2e18aaaSAndroid Build Coastguard Worker # | '--rebuild-module-info' +-------> True (forcely rebuild) 905*c2e18aaaSAndroid Build Coastguard Worker # +--------+----------------+ 906*c2e18aaaSAndroid Build Coastguard Worker # | no 907*c2e18aaaSAndroid Build Coastguard Worker # V 908*c2e18aaaSAndroid Build Coastguard Worker # +-------------------+ 909*c2e18aaaSAndroid Build Coastguard Worker # | Build files | no 910*c2e18aaaSAndroid Build Coastguard Worker # | integrity is good +-------> True (smartly rebuild) 911*c2e18aaaSAndroid Build Coastguard Worker # +--------+----------+ 912*c2e18aaaSAndroid Build Coastguard Worker # | yes 913*c2e18aaaSAndroid Build Coastguard Worker # V 914*c2e18aaaSAndroid Build Coastguard Worker # False (won't rebuild) 915*c2e18aaaSAndroid Build Coastguard Worker if not self._steps.build: 916*c2e18aaaSAndroid Build Coastguard Worker logging.debug('"--test" mode detected, will not rebuild module-info.') 917*c2e18aaaSAndroid Build Coastguard Worker return False 918*c2e18aaaSAndroid Build Coastguard Worker if self._args.rebuild_module_info: 919*c2e18aaaSAndroid Build Coastguard Worker return True 920*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Examinating the consistency of build files...') 921*c2e18aaaSAndroid Build Coastguard Worker if not atest_utils.build_files_integrity_is_ok(): 922*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Found build files were changed.') 923*c2e18aaaSAndroid Build Coastguard Worker return True 924*c2e18aaaSAndroid Build Coastguard Worker return False 925*c2e18aaaSAndroid Build Coastguard Worker 926*c2e18aaaSAndroid Build Coastguard Worker def _load_module_info(self): 927*c2e18aaaSAndroid Build Coastguard Worker self._is_out_clean_before_module_info_build = not os.path.exists( 928*c2e18aaaSAndroid Build Coastguard Worker os.environ.get(constants.ANDROID_PRODUCT_OUT, '') 929*c2e18aaaSAndroid Build Coastguard Worker ) 930*c2e18aaaSAndroid Build Coastguard Worker self._module_info_rebuild_required = self._need_rebuild_module_info() 931*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 932*c2e18aaaSAndroid Build Coastguard Worker 'need_rebuild_module_info returned %s', 933*c2e18aaaSAndroid Build Coastguard Worker self._module_info_rebuild_required, 934*c2e18aaaSAndroid Build Coastguard Worker ) 935*c2e18aaaSAndroid Build Coastguard Worker 936*c2e18aaaSAndroid Build Coastguard Worker self._mod_info = module_info.load( 937*c2e18aaaSAndroid Build Coastguard Worker force_build=self._module_info_rebuild_required, 938*c2e18aaaSAndroid Build Coastguard Worker sqlite_module_cache=self._args.sqlite_module_cache, 939*c2e18aaaSAndroid Build Coastguard Worker ) 940*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Obtained module info object: %s', self._mod_info) 941*c2e18aaaSAndroid Build Coastguard Worker 942*c2e18aaaSAndroid Build Coastguard Worker def _load_test_info_and_execution_plan(self) -> int | None: 943*c2e18aaaSAndroid Build Coastguard Worker """Loads test info and execution plan. 944*c2e18aaaSAndroid Build Coastguard Worker 945*c2e18aaaSAndroid Build Coastguard Worker Returns: 946*c2e18aaaSAndroid Build Coastguard Worker Exit code if anything went wrong. None otherwise. 947*c2e18aaaSAndroid Build Coastguard Worker """ 948*c2e18aaaSAndroid Build Coastguard Worker indexing_thread = self._start_indexing_if_required() 949*c2e18aaaSAndroid Build Coastguard Worker 950*c2e18aaaSAndroid Build Coastguard Worker self._load_module_info() 951*c2e18aaaSAndroid Build Coastguard Worker 952*c2e18aaaSAndroid Build Coastguard Worker translator = cli_translator.CLITranslator( 953*c2e18aaaSAndroid Build Coastguard Worker mod_info=self._mod_info, 954*c2e18aaaSAndroid Build Coastguard Worker print_cache_msg=not self._args.clear_cache, 955*c2e18aaaSAndroid Build Coastguard Worker bazel_mode_enabled=self._args.bazel_mode, 956*c2e18aaaSAndroid Build Coastguard Worker host=self._args.host, 957*c2e18aaaSAndroid Build Coastguard Worker bazel_mode_features=self._args.bazel_mode_features, 958*c2e18aaaSAndroid Build Coastguard Worker indexing_thread=indexing_thread, 959*c2e18aaaSAndroid Build Coastguard Worker ) 960*c2e18aaaSAndroid Build Coastguard Worker 961*c2e18aaaSAndroid Build Coastguard Worker find_start = time.time() 962*c2e18aaaSAndroid Build Coastguard Worker self._test_infos = translator.translate(self._args) 963*c2e18aaaSAndroid Build Coastguard Worker 964*c2e18aaaSAndroid Build Coastguard Worker _AtestMain._inject_default_arguments_based_on_test_infos( 965*c2e18aaaSAndroid Build Coastguard Worker self._test_infos, self._args 966*c2e18aaaSAndroid Build Coastguard Worker ) 967*c2e18aaaSAndroid Build Coastguard Worker 968*c2e18aaaSAndroid Build Coastguard Worker # Only check for sufficient devices if not dry run. 969*c2e18aaaSAndroid Build Coastguard Worker self._args.device_count_config = get_device_count_config( 970*c2e18aaaSAndroid Build Coastguard Worker self._test_infos, self._mod_info 971*c2e18aaaSAndroid Build Coastguard Worker ) 972*c2e18aaaSAndroid Build Coastguard Worker if not self._args.dry_run and not has_set_sufficient_devices( 973*c2e18aaaSAndroid Build Coastguard Worker self._args.device_count_config, self._args.serial 974*c2e18aaaSAndroid Build Coastguard Worker ): 975*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.INSUFFICIENT_DEVICES 976*c2e18aaaSAndroid Build Coastguard Worker 977*c2e18aaaSAndroid Build Coastguard Worker self._test_info_loading_duration = time.time() - find_start 978*c2e18aaaSAndroid Build Coastguard Worker if not self._test_infos: 979*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.TEST_NOT_FOUND 980*c2e18aaaSAndroid Build Coastguard Worker 981*c2e18aaaSAndroid Build Coastguard Worker self._test_execution_plan = _TestExecutionPlan.create( 982*c2e18aaaSAndroid Build Coastguard Worker args=self._args, 983*c2e18aaaSAndroid Build Coastguard Worker test_infos=self._test_infos, 984*c2e18aaaSAndroid Build Coastguard Worker results_dir=self._results_dir, 985*c2e18aaaSAndroid Build Coastguard Worker mod_info=self._mod_info, 986*c2e18aaaSAndroid Build Coastguard Worker ) 987*c2e18aaaSAndroid Build Coastguard Worker 988*c2e18aaaSAndroid Build Coastguard Worker return None 989*c2e18aaaSAndroid Build Coastguard Worker 990*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 991*c2e18aaaSAndroid Build Coastguard Worker def _inject_default_arguments_based_on_test_infos( 992*c2e18aaaSAndroid Build Coastguard Worker test_infos: list[test_info.TestInfo], args: argparse.Namespace 993*c2e18aaaSAndroid Build Coastguard Worker ) -> None: 994*c2e18aaaSAndroid Build Coastguard Worker if any( 995*c2e18aaaSAndroid Build Coastguard Worker 'performance-tests' in info.compatibility_suites for info in test_infos 996*c2e18aaaSAndroid Build Coastguard Worker ): 997*c2e18aaaSAndroid Build Coastguard Worker if not args.disable_upload_result: 998*c2e18aaaSAndroid Build Coastguard Worker args.request_upload_result = True 999*c2e18aaaSAndroid Build Coastguard Worker 1000*c2e18aaaSAndroid Build Coastguard Worker def _handle_list_modules(self) -> int: 1001*c2e18aaaSAndroid Build Coastguard Worker """Print the testable modules for a given suite. 1002*c2e18aaaSAndroid Build Coastguard Worker 1003*c2e18aaaSAndroid Build Coastguard Worker Returns: 1004*c2e18aaaSAndroid Build Coastguard Worker Exit code. 1005*c2e18aaaSAndroid Build Coastguard Worker """ 1006*c2e18aaaSAndroid Build Coastguard Worker self._load_module_info() 1007*c2e18aaaSAndroid Build Coastguard Worker 1008*c2e18aaaSAndroid Build Coastguard Worker testable_modules = self._mod_info.get_testable_modules( 1009*c2e18aaaSAndroid Build Coastguard Worker self._args.list_modules 1010*c2e18aaaSAndroid Build Coastguard Worker ) 1011*c2e18aaaSAndroid Build Coastguard Worker print( 1012*c2e18aaaSAndroid Build Coastguard Worker '\n%s' 1013*c2e18aaaSAndroid Build Coastguard Worker % atest_utils.mark_cyan( 1014*c2e18aaaSAndroid Build Coastguard Worker '%s Testable %s modules' 1015*c2e18aaaSAndroid Build Coastguard Worker % (len(testable_modules), self._args.list_modules) 1016*c2e18aaaSAndroid Build Coastguard Worker ) 1017*c2e18aaaSAndroid Build Coastguard Worker ) 1018*c2e18aaaSAndroid Build Coastguard Worker print(atest_utils.delimiter('-')) 1019*c2e18aaaSAndroid Build Coastguard Worker for module in sorted(testable_modules): 1020*c2e18aaaSAndroid Build Coastguard Worker print('\t%s' % module) 1021*c2e18aaaSAndroid Build Coastguard Worker 1022*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 1023*c2e18aaaSAndroid Build Coastguard Worker 1024*c2e18aaaSAndroid Build Coastguard Worker def _handle_dry_run(self) -> int: 1025*c2e18aaaSAndroid Build Coastguard Worker """Only print the commands of the target tests rather than running them. 1026*c2e18aaaSAndroid Build Coastguard Worker 1027*c2e18aaaSAndroid Build Coastguard Worker Returns: 1028*c2e18aaaSAndroid Build Coastguard Worker Exit code. 1029*c2e18aaaSAndroid Build Coastguard Worker """ 1030*c2e18aaaSAndroid Build Coastguard Worker error_code = self._load_test_info_and_execution_plan() 1031*c2e18aaaSAndroid Build Coastguard Worker if error_code is not None: 1032*c2e18aaaSAndroid Build Coastguard Worker return error_code 1033*c2e18aaaSAndroid Build Coastguard Worker 1034*c2e18aaaSAndroid Build Coastguard Worker print( 1035*c2e18aaaSAndroid Build Coastguard Worker 'Would build the following targets: %s' 1036*c2e18aaaSAndroid Build Coastguard Worker % (atest_utils.mark_green('%s' % self._get_build_targets())) 1037*c2e18aaaSAndroid Build Coastguard Worker ) 1038*c2e18aaaSAndroid Build Coastguard Worker 1039*c2e18aaaSAndroid Build Coastguard Worker all_run_cmds = [] 1040*c2e18aaaSAndroid Build Coastguard Worker for test_runner, tests in test_runner_handler.group_tests_by_test_runners( 1041*c2e18aaaSAndroid Build Coastguard Worker self._test_infos 1042*c2e18aaaSAndroid Build Coastguard Worker ): 1043*c2e18aaaSAndroid Build Coastguard Worker runner = test_runner( 1044*c2e18aaaSAndroid Build Coastguard Worker self._results_dir, 1045*c2e18aaaSAndroid Build Coastguard Worker mod_info=self._mod_info, 1046*c2e18aaaSAndroid Build Coastguard Worker extra_args=self._test_execution_plan.extra_args, 1047*c2e18aaaSAndroid Build Coastguard Worker ) 1048*c2e18aaaSAndroid Build Coastguard Worker run_cmds = runner.generate_run_commands( 1049*c2e18aaaSAndroid Build Coastguard Worker tests, self._test_execution_plan.extra_args 1050*c2e18aaaSAndroid Build Coastguard Worker ) 1051*c2e18aaaSAndroid Build Coastguard Worker for run_cmd in run_cmds: 1052*c2e18aaaSAndroid Build Coastguard Worker all_run_cmds.append(run_cmd) 1053*c2e18aaaSAndroid Build Coastguard Worker logging.debug(_DRY_RUN_COMMAND_LOG_PREFIX + run_cmd) 1054*c2e18aaaSAndroid Build Coastguard Worker print( 1055*c2e18aaaSAndroid Build Coastguard Worker 'Would run test via command: %s' % (atest_utils.mark_green(run_cmd)) 1056*c2e18aaaSAndroid Build Coastguard Worker ) 1057*c2e18aaaSAndroid Build Coastguard Worker 1058*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 1059*c2e18aaaSAndroid Build Coastguard Worker 1060*c2e18aaaSAndroid Build Coastguard Worker def _update_device_if_requested(self) -> None: 1061*c2e18aaaSAndroid Build Coastguard Worker """Runs the device update step.""" 1062*c2e18aaaSAndroid Build Coastguard Worker if not self._args.update_device: 1063*c2e18aaaSAndroid Build Coastguard Worker if self._test_execution_plan.requires_device_update(): 1064*c2e18aaaSAndroid Build Coastguard Worker self._banner_printer.register( 1065*c2e18aaaSAndroid Build Coastguard Worker 'Tips: If your test requires device update, consider ' 1066*c2e18aaaSAndroid Build Coastguard Worker 'http://go/atest-single-command to simplify your workflow!' 1067*c2e18aaaSAndroid Build Coastguard Worker ) 1068*c2e18aaaSAndroid Build Coastguard Worker return 1069*c2e18aaaSAndroid Build Coastguard Worker if not self._steps.test: 1070*c2e18aaaSAndroid Build Coastguard Worker print( 1071*c2e18aaaSAndroid Build Coastguard Worker 'Device update requested but skipped due to running in build only' 1072*c2e18aaaSAndroid Build Coastguard Worker ' mode.' 1073*c2e18aaaSAndroid Build Coastguard Worker ) 1074*c2e18aaaSAndroid Build Coastguard Worker return 1075*c2e18aaaSAndroid Build Coastguard Worker 1076*c2e18aaaSAndroid Build Coastguard Worker if not self._test_execution_plan.requires_device_update(): 1077*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1078*c2e18aaaSAndroid Build Coastguard Worker '\nWarning: Device update ignored because it is not required by ' 1079*c2e18aaaSAndroid Build Coastguard Worker 'tests in this invocation.', 1080*c2e18aaaSAndroid Build Coastguard Worker constants.YELLOW, 1081*c2e18aaaSAndroid Build Coastguard Worker ) 1082*c2e18aaaSAndroid Build Coastguard Worker return 1083*c2e18aaaSAndroid Build Coastguard Worker 1084*c2e18aaaSAndroid Build Coastguard Worker device_update_start = time.time() 1085*c2e18aaaSAndroid Build Coastguard Worker self._get_device_update_method().update( 1086*c2e18aaaSAndroid Build Coastguard Worker self._test_execution_plan.extra_args.get(constants.SERIAL, []) 1087*c2e18aaaSAndroid Build Coastguard Worker ) 1088*c2e18aaaSAndroid Build Coastguard Worker device_update_duration = time.time() - device_update_start 1089*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Updating device took %ss', device_update_duration) 1090*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent( 1091*c2e18aaaSAndroid Build Coastguard Worker detect_type=DetectType.DEVICE_UPDATE_MS, 1092*c2e18aaaSAndroid Build Coastguard Worker result=int(round(device_update_duration * 1000)), 1093*c2e18aaaSAndroid Build Coastguard Worker ) 1094*c2e18aaaSAndroid Build Coastguard Worker 1095*c2e18aaaSAndroid Build Coastguard Worker def _get_build_targets(self) -> set[str]: 1096*c2e18aaaSAndroid Build Coastguard Worker """Gets the build targets.""" 1097*c2e18aaaSAndroid Build Coastguard Worker build_targets = self._test_execution_plan.required_build_targets() 1098*c2e18aaaSAndroid Build Coastguard Worker 1099*c2e18aaaSAndroid Build Coastguard Worker # Remove MODULE-IN-* from build targets by default. 1100*c2e18aaaSAndroid Build Coastguard Worker if not self._args.use_modules_in: 1101*c2e18aaaSAndroid Build Coastguard Worker build_targets = _exclude_modules_in_targets(build_targets) 1102*c2e18aaaSAndroid Build Coastguard Worker 1103*c2e18aaaSAndroid Build Coastguard Worker if not build_targets: 1104*c2e18aaaSAndroid Build Coastguard Worker return None 1105*c2e18aaaSAndroid Build Coastguard Worker 1106*c2e18aaaSAndroid Build Coastguard Worker if self._args.experimental_coverage: 1107*c2e18aaaSAndroid Build Coastguard Worker build_targets.update(coverage.build_modules()) 1108*c2e18aaaSAndroid Build Coastguard Worker 1109*c2e18aaaSAndroid Build Coastguard Worker # Add module-info.json target to the list of build targets to keep the 1110*c2e18aaaSAndroid Build Coastguard Worker # file up to date. 1111*c2e18aaaSAndroid Build Coastguard Worker build_targets.add(module_info.get_module_info_target()) 1112*c2e18aaaSAndroid Build Coastguard Worker 1113*c2e18aaaSAndroid Build Coastguard Worker build_targets |= self._get_device_update_dependencies() 1114*c2e18aaaSAndroid Build Coastguard Worker return build_targets 1115*c2e18aaaSAndroid Build Coastguard Worker 1116*c2e18aaaSAndroid Build Coastguard Worker def _run_build_step(self) -> int: 1117*c2e18aaaSAndroid Build Coastguard Worker """Runs the build step. 1118*c2e18aaaSAndroid Build Coastguard Worker 1119*c2e18aaaSAndroid Build Coastguard Worker Returns: 1120*c2e18aaaSAndroid Build Coastguard Worker Exit code if failed. None otherwise. 1121*c2e18aaaSAndroid Build Coastguard Worker """ 1122*c2e18aaaSAndroid Build Coastguard Worker build_targets = self._get_build_targets() 1123*c2e18aaaSAndroid Build Coastguard Worker 1124*c2e18aaaSAndroid Build Coastguard Worker # Add the -jx as a build target if user specify it. 1125*c2e18aaaSAndroid Build Coastguard Worker if self._args.build_j: 1126*c2e18aaaSAndroid Build Coastguard Worker build_targets.add(f'-j{self._args.build_j}') 1127*c2e18aaaSAndroid Build Coastguard Worker 1128*c2e18aaaSAndroid Build Coastguard Worker build_start = time.time() 1129*c2e18aaaSAndroid Build Coastguard Worker success = atest_utils.build(build_targets) 1130*c2e18aaaSAndroid Build Coastguard Worker self._build_duration = time.time() - build_start 1131*c2e18aaaSAndroid Build Coastguard Worker metrics.BuildFinishEvent( 1132*c2e18aaaSAndroid Build Coastguard Worker duration=metrics_utils.convert_duration(self._build_duration), 1133*c2e18aaaSAndroid Build Coastguard Worker success=success, 1134*c2e18aaaSAndroid Build Coastguard Worker targets=build_targets, 1135*c2e18aaaSAndroid Build Coastguard Worker ) 1136*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent( 1137*c2e18aaaSAndroid Build Coastguard Worker detect_type=DetectType.BUILD_TIME_PER_TARGET, 1138*c2e18aaaSAndroid Build Coastguard Worker result=int(round(self._build_duration / len(build_targets))), 1139*c2e18aaaSAndroid Build Coastguard Worker ) 1140*c2e18aaaSAndroid Build Coastguard Worker rebuild_module_info = DetectType.NOT_REBUILD_MODULE_INFO 1141*c2e18aaaSAndroid Build Coastguard Worker if self._is_out_clean_before_module_info_build: 1142*c2e18aaaSAndroid Build Coastguard Worker rebuild_module_info = DetectType.CLEAN_BUILD 1143*c2e18aaaSAndroid Build Coastguard Worker elif self._args.rebuild_module_info: 1144*c2e18aaaSAndroid Build Coastguard Worker rebuild_module_info = DetectType.REBUILD_MODULE_INFO 1145*c2e18aaaSAndroid Build Coastguard Worker elif self._module_info_rebuild_required: 1146*c2e18aaaSAndroid Build Coastguard Worker rebuild_module_info = DetectType.SMART_REBUILD_MODULE_INFO 1147*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent( 1148*c2e18aaaSAndroid Build Coastguard Worker detect_type=rebuild_module_info, result=int(round(self._build_duration)) 1149*c2e18aaaSAndroid Build Coastguard Worker ) 1150*c2e18aaaSAndroid Build Coastguard Worker if not success: 1151*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.BUILD_FAILURE 1152*c2e18aaaSAndroid Build Coastguard Worker 1153*c2e18aaaSAndroid Build Coastguard Worker def _run_test_step(self) -> int: 1154*c2e18aaaSAndroid Build Coastguard Worker """Runs the test step. 1155*c2e18aaaSAndroid Build Coastguard Worker 1156*c2e18aaaSAndroid Build Coastguard Worker Returns: 1157*c2e18aaaSAndroid Build Coastguard Worker Exit code. 1158*c2e18aaaSAndroid Build Coastguard Worker """ 1159*c2e18aaaSAndroid Build Coastguard Worker # Stop calling Tradefed if the tests require a device. 1160*c2e18aaaSAndroid Build Coastguard Worker _validate_adb_devices(self._args, self._test_infos) 1161*c2e18aaaSAndroid Build Coastguard Worker 1162*c2e18aaaSAndroid Build Coastguard Worker test_start = time.time() 1163*c2e18aaaSAndroid Build Coastguard Worker # Only send duration to metrics when no --build. 1164*c2e18aaaSAndroid Build Coastguard Worker if not self._steps.build: 1165*c2e18aaaSAndroid Build Coastguard Worker _init_and_find = time.time() - self._invocation_begin_time 1166*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Initiation and finding tests took %ss', _init_and_find) 1167*c2e18aaaSAndroid Build Coastguard Worker metrics.LocalDetectEvent( 1168*c2e18aaaSAndroid Build Coastguard Worker detect_type=DetectType.INIT_AND_FIND_MS, 1169*c2e18aaaSAndroid Build Coastguard Worker result=int(round(_init_and_find * 1000)), 1170*c2e18aaaSAndroid Build Coastguard Worker ) 1171*c2e18aaaSAndroid Build Coastguard Worker 1172*c2e18aaaSAndroid Build Coastguard Worker tests_exit_code = self._test_execution_plan.execute() 1173*c2e18aaaSAndroid Build Coastguard Worker 1174*c2e18aaaSAndroid Build Coastguard Worker if self._args.experimental_coverage: 1175*c2e18aaaSAndroid Build Coastguard Worker coverage.generate_coverage_report( 1176*c2e18aaaSAndroid Build Coastguard Worker self._results_dir, 1177*c2e18aaaSAndroid Build Coastguard Worker self._test_infos, 1178*c2e18aaaSAndroid Build Coastguard Worker self._mod_info, 1179*c2e18aaaSAndroid Build Coastguard Worker self._test_execution_plan.extra_args.get(constants.HOST, False), 1180*c2e18aaaSAndroid Build Coastguard Worker self._args.code_under_test, 1181*c2e18aaaSAndroid Build Coastguard Worker ) 1182*c2e18aaaSAndroid Build Coastguard Worker 1183*c2e18aaaSAndroid Build Coastguard Worker metrics.RunTestsFinishEvent( 1184*c2e18aaaSAndroid Build Coastguard Worker duration=metrics_utils.convert_duration(time.time() - test_start) 1185*c2e18aaaSAndroid Build Coastguard Worker ) 1186*c2e18aaaSAndroid Build Coastguard Worker preparation_time = atest_execution_info.preparation_time(test_start) 1187*c2e18aaaSAndroid Build Coastguard Worker if preparation_time: 1188*c2e18aaaSAndroid Build Coastguard Worker # Send the preparation time only if it's set. 1189*c2e18aaaSAndroid Build Coastguard Worker metrics.RunnerFinishEvent( 1190*c2e18aaaSAndroid Build Coastguard Worker duration=metrics_utils.convert_duration(preparation_time), 1191*c2e18aaaSAndroid Build Coastguard Worker success=True, 1192*c2e18aaaSAndroid Build Coastguard Worker runner_name=constants.TF_PREPARATION, 1193*c2e18aaaSAndroid Build Coastguard Worker test=[], 1194*c2e18aaaSAndroid Build Coastguard Worker ) 1195*c2e18aaaSAndroid Build Coastguard Worker 1196*c2e18aaaSAndroid Build Coastguard Worker return tests_exit_code 1197*c2e18aaaSAndroid Build Coastguard Worker 1198*c2e18aaaSAndroid Build Coastguard Worker def _send_start_event(self) -> None: 1199*c2e18aaaSAndroid Build Coastguard Worker metrics_utils.send_start_event( 1200*c2e18aaaSAndroid Build Coastguard Worker command_line=' '.join(self._argv), 1201*c2e18aaaSAndroid Build Coastguard Worker test_references=self._args.tests, 1202*c2e18aaaSAndroid Build Coastguard Worker cwd=os.getcwd(), 1203*c2e18aaaSAndroid Build Coastguard Worker operating_system=( 1204*c2e18aaaSAndroid Build Coastguard Worker f'{platform.platform()}:{platform.python_version()}/' 1205*c2e18aaaSAndroid Build Coastguard Worker f'{atest_utils.get_manifest_branch(True)}:' 1206*c2e18aaaSAndroid Build Coastguard Worker f'{atest_utils.get_atest_version()}' 1207*c2e18aaaSAndroid Build Coastguard Worker ), 1208*c2e18aaaSAndroid Build Coastguard Worker source_root=os.environ.get('ANDROID_BUILD_TOP', ''), 1209*c2e18aaaSAndroid Build Coastguard Worker hostname=platform.node(), 1210*c2e18aaaSAndroid Build Coastguard Worker ) 1211*c2e18aaaSAndroid Build Coastguard Worker 1212*c2e18aaaSAndroid Build Coastguard Worker def _disable_bazel_mode_if_unsupported(self) -> None: 1213*c2e18aaaSAndroid Build Coastguard Worker if ( 1214*c2e18aaaSAndroid Build Coastguard Worker atest_utils.is_test_mapping(self._args) 1215*c2e18aaaSAndroid Build Coastguard Worker or self._args.experimental_coverage 1216*c2e18aaaSAndroid Build Coastguard Worker ): 1217*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Running test mapping or coverage, disabling bazel mode.') 1218*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1219*c2e18aaaSAndroid Build Coastguard Worker 'Not running using bazel-mode.', constants.YELLOW 1220*c2e18aaaSAndroid Build Coastguard Worker ) 1221*c2e18aaaSAndroid Build Coastguard Worker self._args.bazel_mode = False 1222*c2e18aaaSAndroid Build Coastguard Worker 1223*c2e18aaaSAndroid Build Coastguard Worker def _run_all_steps(self) -> int: 1224*c2e18aaaSAndroid Build Coastguard Worker """Executes the atest script. 1225*c2e18aaaSAndroid Build Coastguard Worker 1226*c2e18aaaSAndroid Build Coastguard Worker Returns: 1227*c2e18aaaSAndroid Build Coastguard Worker Exit code. 1228*c2e18aaaSAndroid Build Coastguard Worker """ 1229*c2e18aaaSAndroid Build Coastguard Worker self._invocation_begin_time = time.time() 1230*c2e18aaaSAndroid Build Coastguard Worker 1231*c2e18aaaSAndroid Build Coastguard Worker self._update_build_env() 1232*c2e18aaaSAndroid Build Coastguard Worker 1233*c2e18aaaSAndroid Build Coastguard Worker invalid_arg_exit_code = self._check_envs_and_args() 1234*c2e18aaaSAndroid Build Coastguard Worker if invalid_arg_exit_code is not None: 1235*c2e18aaaSAndroid Build Coastguard Worker sys.exit(invalid_arg_exit_code) 1236*c2e18aaaSAndroid Build Coastguard Worker 1237*c2e18aaaSAndroid Build Coastguard Worker self._send_start_event() 1238*c2e18aaaSAndroid Build Coastguard Worker 1239*c2e18aaaSAndroid Build Coastguard Worker no_action_exit_code = self._check_no_action_argument() 1240*c2e18aaaSAndroid Build Coastguard Worker if no_action_exit_code is not None: 1241*c2e18aaaSAndroid Build Coastguard Worker sys.exit(no_action_exit_code) 1242*c2e18aaaSAndroid Build Coastguard Worker 1243*c2e18aaaSAndroid Build Coastguard Worker if self._args.list_modules: 1244*c2e18aaaSAndroid Build Coastguard Worker return self._handle_list_modules() 1245*c2e18aaaSAndroid Build Coastguard Worker 1246*c2e18aaaSAndroid Build Coastguard Worker self._disable_bazel_mode_if_unsupported() 1247*c2e18aaaSAndroid Build Coastguard Worker 1248*c2e18aaaSAndroid Build Coastguard Worker if self._args.dry_run: 1249*c2e18aaaSAndroid Build Coastguard Worker return self._handle_dry_run() 1250*c2e18aaaSAndroid Build Coastguard Worker 1251*c2e18aaaSAndroid Build Coastguard Worker self._start_acloud_if_requested() 1252*c2e18aaaSAndroid Build Coastguard Worker 1253*c2e18aaaSAndroid Build Coastguard Worker error_code = self._load_test_info_and_execution_plan() 1254*c2e18aaaSAndroid Build Coastguard Worker if error_code is not None: 1255*c2e18aaaSAndroid Build Coastguard Worker return error_code 1256*c2e18aaaSAndroid Build Coastguard Worker 1257*c2e18aaaSAndroid Build Coastguard Worker if self._steps.build: 1258*c2e18aaaSAndroid Build Coastguard Worker error_code = self._run_build_step() 1259*c2e18aaaSAndroid Build Coastguard Worker if error_code is not None: 1260*c2e18aaaSAndroid Build Coastguard Worker return error_code 1261*c2e18aaaSAndroid Build Coastguard Worker 1262*c2e18aaaSAndroid Build Coastguard Worker acloud_status = self._check_acloud_status() 1263*c2e18aaaSAndroid Build Coastguard Worker if acloud_status: 1264*c2e18aaaSAndroid Build Coastguard Worker return acloud_status 1265*c2e18aaaSAndroid Build Coastguard Worker 1266*c2e18aaaSAndroid Build Coastguard Worker self._update_device_if_requested() 1267*c2e18aaaSAndroid Build Coastguard Worker 1268*c2e18aaaSAndroid Build Coastguard Worker if self._steps.test and self._run_test_step() != ExitCode.SUCCESS: 1269*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.TEST_FAILURE 1270*c2e18aaaSAndroid Build Coastguard Worker 1271*c2e18aaaSAndroid Build Coastguard Worker return ExitCode.SUCCESS 1272*c2e18aaaSAndroid Build Coastguard Worker 1273*c2e18aaaSAndroid Build Coastguard Worker 1274*c2e18aaaSAndroid Build Coastguard Workerclass _TestExecutionPlan(abc.ABC): 1275*c2e18aaaSAndroid Build Coastguard Worker """Represents how an Atest invocation's tests will execute.""" 1276*c2e18aaaSAndroid Build Coastguard Worker 1277*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 1278*c2e18aaaSAndroid Build Coastguard Worker def create( 1279*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1280*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1281*c2e18aaaSAndroid Build Coastguard Worker results_dir: str, 1282*c2e18aaaSAndroid Build Coastguard Worker mod_info: module_info.ModuleInfo, 1283*c2e18aaaSAndroid Build Coastguard Worker ) -> _TestExecutionPlan: 1284*c2e18aaaSAndroid Build Coastguard Worker """Creates a plan to execute the tests. 1285*c2e18aaaSAndroid Build Coastguard Worker 1286*c2e18aaaSAndroid Build Coastguard Worker Args: 1287*c2e18aaaSAndroid Build Coastguard Worker args: An argparse.Namespace instance holding parsed args. 1288*c2e18aaaSAndroid Build Coastguard Worker test_infos: A list of instances of TestInfo. 1289*c2e18aaaSAndroid Build Coastguard Worker results_dir: A directory which stores the ATest execution information. 1290*c2e18aaaSAndroid Build Coastguard Worker mod_info: An instance of ModuleInfo. 1291*c2e18aaaSAndroid Build Coastguard Worker 1292*c2e18aaaSAndroid Build Coastguard Worker Returns: 1293*c2e18aaaSAndroid Build Coastguard Worker An instance of _TestExecutionPlan. 1294*c2e18aaaSAndroid Build Coastguard Worker """ 1295*c2e18aaaSAndroid Build Coastguard Worker 1296*c2e18aaaSAndroid Build Coastguard Worker if is_from_test_mapping(test_infos): 1297*c2e18aaaSAndroid Build Coastguard Worker return _TestMappingExecutionPlan.create( 1298*c2e18aaaSAndroid Build Coastguard Worker args=args, 1299*c2e18aaaSAndroid Build Coastguard Worker test_infos=test_infos, 1300*c2e18aaaSAndroid Build Coastguard Worker results_dir=results_dir, 1301*c2e18aaaSAndroid Build Coastguard Worker mod_info=mod_info, 1302*c2e18aaaSAndroid Build Coastguard Worker ) 1303*c2e18aaaSAndroid Build Coastguard Worker 1304*c2e18aaaSAndroid Build Coastguard Worker return _TestModuleExecutionPlan.create( 1305*c2e18aaaSAndroid Build Coastguard Worker args=args, 1306*c2e18aaaSAndroid Build Coastguard Worker test_infos=test_infos, 1307*c2e18aaaSAndroid Build Coastguard Worker results_dir=results_dir, 1308*c2e18aaaSAndroid Build Coastguard Worker mod_info=mod_info, 1309*c2e18aaaSAndroid Build Coastguard Worker ) 1310*c2e18aaaSAndroid Build Coastguard Worker 1311*c2e18aaaSAndroid Build Coastguard Worker def __init__( 1312*c2e18aaaSAndroid Build Coastguard Worker self, 1313*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1314*c2e18aaaSAndroid Build Coastguard Worker extra_args: Dict[str, Any], 1315*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1316*c2e18aaaSAndroid Build Coastguard Worker ): 1317*c2e18aaaSAndroid Build Coastguard Worker self._args = args 1318*c2e18aaaSAndroid Build Coastguard Worker self._extra_args = extra_args 1319*c2e18aaaSAndroid Build Coastguard Worker self._test_infos = test_infos 1320*c2e18aaaSAndroid Build Coastguard Worker 1321*c2e18aaaSAndroid Build Coastguard Worker @property 1322*c2e18aaaSAndroid Build Coastguard Worker def extra_args(self) -> Dict[str, Any]: 1323*c2e18aaaSAndroid Build Coastguard Worker return self._extra_args 1324*c2e18aaaSAndroid Build Coastguard Worker 1325*c2e18aaaSAndroid Build Coastguard Worker @abc.abstractmethod 1326*c2e18aaaSAndroid Build Coastguard Worker def execute(self) -> ExitCode: 1327*c2e18aaaSAndroid Build Coastguard Worker """Executes all test runner invocations in this plan.""" 1328*c2e18aaaSAndroid Build Coastguard Worker 1329*c2e18aaaSAndroid Build Coastguard Worker @abc.abstractmethod 1330*c2e18aaaSAndroid Build Coastguard Worker def required_build_targets(self) -> Set[str]: 1331*c2e18aaaSAndroid Build Coastguard Worker """Returns the list of build targets required by this plan.""" 1332*c2e18aaaSAndroid Build Coastguard Worker 1333*c2e18aaaSAndroid Build Coastguard Worker @abc.abstractmethod 1334*c2e18aaaSAndroid Build Coastguard Worker def requires_device_update(self) -> bool: 1335*c2e18aaaSAndroid Build Coastguard Worker """Checks whether this plan requires device update.""" 1336*c2e18aaaSAndroid Build Coastguard Worker 1337*c2e18aaaSAndroid Build Coastguard Worker 1338*c2e18aaaSAndroid Build Coastguard Workerclass _TestMappingExecutionPlan(_TestExecutionPlan): 1339*c2e18aaaSAndroid Build Coastguard Worker """A plan to execute Test Mapping tests.""" 1340*c2e18aaaSAndroid Build Coastguard Worker 1341*c2e18aaaSAndroid Build Coastguard Worker def __init__( 1342*c2e18aaaSAndroid Build Coastguard Worker self, 1343*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1344*c2e18aaaSAndroid Build Coastguard Worker extra_args: Dict[str, Any], 1345*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1346*c2e18aaaSAndroid Build Coastguard Worker test_type_to_invocations: Dict[str, List[TestRunnerInvocation]], 1347*c2e18aaaSAndroid Build Coastguard Worker ): 1348*c2e18aaaSAndroid Build Coastguard Worker super().__init__(args, extra_args, test_infos) 1349*c2e18aaaSAndroid Build Coastguard Worker self._test_type_to_invocations = test_type_to_invocations 1350*c2e18aaaSAndroid Build Coastguard Worker 1351*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 1352*c2e18aaaSAndroid Build Coastguard Worker def create( 1353*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1354*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1355*c2e18aaaSAndroid Build Coastguard Worker results_dir: str, 1356*c2e18aaaSAndroid Build Coastguard Worker mod_info: module_info.ModuleInfo, 1357*c2e18aaaSAndroid Build Coastguard Worker ) -> _TestMappingExecutionPlan: 1358*c2e18aaaSAndroid Build Coastguard Worker """Creates an instance of _TestMappingExecutionPlan. 1359*c2e18aaaSAndroid Build Coastguard Worker 1360*c2e18aaaSAndroid Build Coastguard Worker Args: 1361*c2e18aaaSAndroid Build Coastguard Worker args: An argparse.Namespace instance holding parsed args. 1362*c2e18aaaSAndroid Build Coastguard Worker test_infos: A list of instances of TestInfo. 1363*c2e18aaaSAndroid Build Coastguard Worker results_dir: A directory which stores the ATest execution information. 1364*c2e18aaaSAndroid Build Coastguard Worker mod_info: An instance of ModuleInfo. 1365*c2e18aaaSAndroid Build Coastguard Worker 1366*c2e18aaaSAndroid Build Coastguard Worker Returns: 1367*c2e18aaaSAndroid Build Coastguard Worker An instance of _TestMappingExecutionPlan. 1368*c2e18aaaSAndroid Build Coastguard Worker """ 1369*c2e18aaaSAndroid Build Coastguard Worker 1370*c2e18aaaSAndroid Build Coastguard Worker device_test_infos, host_test_infos = _split_test_mapping_tests(test_infos) 1371*c2e18aaaSAndroid Build Coastguard Worker _validate_tm_tests_exec_mode(args, device_test_infos, host_test_infos) 1372*c2e18aaaSAndroid Build Coastguard Worker extra_args = get_extra_args(args) 1373*c2e18aaaSAndroid Build Coastguard Worker 1374*c2e18aaaSAndroid Build Coastguard Worker # TODO: change to another approach that put constants.CUSTOM_ARGS in the 1375*c2e18aaaSAndroid Build Coastguard Worker # end of command to make sure that customized args can override default 1376*c2e18aaaSAndroid Build Coastguard Worker # options. 1377*c2e18aaaSAndroid Build Coastguard Worker # For TEST_MAPPING, set timeout to 600000ms. 1378*c2e18aaaSAndroid Build Coastguard Worker custom_timeout = False 1379*c2e18aaaSAndroid Build Coastguard Worker for custom_args in args.custom_args: 1380*c2e18aaaSAndroid Build Coastguard Worker if '-timeout' in custom_args: 1381*c2e18aaaSAndroid Build Coastguard Worker custom_timeout = True 1382*c2e18aaaSAndroid Build Coastguard Worker 1383*c2e18aaaSAndroid Build Coastguard Worker if args.test_timeout is None and not custom_timeout: 1384*c2e18aaaSAndroid Build Coastguard Worker extra_args.update({constants.TEST_TIMEOUT: 600000}) 1385*c2e18aaaSAndroid Build Coastguard Worker logging.debug( 1386*c2e18aaaSAndroid Build Coastguard Worker 'Set test timeout to %sms to align it in TEST_MAPPING.', 1387*c2e18aaaSAndroid Build Coastguard Worker extra_args.get(constants.TEST_TIMEOUT), 1388*c2e18aaaSAndroid Build Coastguard Worker ) 1389*c2e18aaaSAndroid Build Coastguard Worker 1390*c2e18aaaSAndroid Build Coastguard Worker def create_invocations(runner_extra_args, runner_test_infos): 1391*c2e18aaaSAndroid Build Coastguard Worker return test_runner_handler.create_test_runner_invocations( 1392*c2e18aaaSAndroid Build Coastguard Worker test_infos=runner_test_infos, 1393*c2e18aaaSAndroid Build Coastguard Worker results_dir=results_dir, 1394*c2e18aaaSAndroid Build Coastguard Worker mod_info=mod_info, 1395*c2e18aaaSAndroid Build Coastguard Worker extra_args=runner_extra_args, 1396*c2e18aaaSAndroid Build Coastguard Worker minimal_build=args.minimal_build, 1397*c2e18aaaSAndroid Build Coastguard Worker ) 1398*c2e18aaaSAndroid Build Coastguard Worker 1399*c2e18aaaSAndroid Build Coastguard Worker test_type_to_invocations = collections.OrderedDict() 1400*c2e18aaaSAndroid Build Coastguard Worker if extra_args.get(constants.DEVICE_ONLY): 1401*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1402*c2e18aaaSAndroid Build Coastguard Worker 'Option `--device-only` specified. Skip running deviceless tests.', 1403*c2e18aaaSAndroid Build Coastguard Worker constants.MAGENTA, 1404*c2e18aaaSAndroid Build Coastguard Worker ) 1405*c2e18aaaSAndroid Build Coastguard Worker else: 1406*c2e18aaaSAndroid Build Coastguard Worker # `host` option needs to be set to True to run host side tests. 1407*c2e18aaaSAndroid Build Coastguard Worker host_extra_args = extra_args.copy() 1408*c2e18aaaSAndroid Build Coastguard Worker host_extra_args[constants.HOST] = True 1409*c2e18aaaSAndroid Build Coastguard Worker test_type_to_invocations.setdefault(HOST_TESTS, []).extend( 1410*c2e18aaaSAndroid Build Coastguard Worker create_invocations(host_extra_args, host_test_infos) 1411*c2e18aaaSAndroid Build Coastguard Worker ) 1412*c2e18aaaSAndroid Build Coastguard Worker 1413*c2e18aaaSAndroid Build Coastguard Worker if extra_args.get(constants.HOST): 1414*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1415*c2e18aaaSAndroid Build Coastguard Worker 'Option `--host` specified. Skip running device tests.', 1416*c2e18aaaSAndroid Build Coastguard Worker constants.MAGENTA, 1417*c2e18aaaSAndroid Build Coastguard Worker ) 1418*c2e18aaaSAndroid Build Coastguard Worker else: 1419*c2e18aaaSAndroid Build Coastguard Worker test_type_to_invocations.setdefault(DEVICE_TESTS, []).extend( 1420*c2e18aaaSAndroid Build Coastguard Worker create_invocations(extra_args, device_test_infos) 1421*c2e18aaaSAndroid Build Coastguard Worker ) 1422*c2e18aaaSAndroid Build Coastguard Worker 1423*c2e18aaaSAndroid Build Coastguard Worker return _TestMappingExecutionPlan( 1424*c2e18aaaSAndroid Build Coastguard Worker args=args, 1425*c2e18aaaSAndroid Build Coastguard Worker extra_args=extra_args, 1426*c2e18aaaSAndroid Build Coastguard Worker test_infos=test_infos, 1427*c2e18aaaSAndroid Build Coastguard Worker test_type_to_invocations=test_type_to_invocations, 1428*c2e18aaaSAndroid Build Coastguard Worker ) 1429*c2e18aaaSAndroid Build Coastguard Worker 1430*c2e18aaaSAndroid Build Coastguard Worker def requires_device_update(self) -> bool: 1431*c2e18aaaSAndroid Build Coastguard Worker return any( 1432*c2e18aaaSAndroid Build Coastguard Worker inv.requires_device_update() 1433*c2e18aaaSAndroid Build Coastguard Worker for inv in itertools.chain.from_iterable( 1434*c2e18aaaSAndroid Build Coastguard Worker self._test_type_to_invocations.values() 1435*c2e18aaaSAndroid Build Coastguard Worker ) 1436*c2e18aaaSAndroid Build Coastguard Worker ) 1437*c2e18aaaSAndroid Build Coastguard Worker 1438*c2e18aaaSAndroid Build Coastguard Worker def required_build_targets(self) -> Set[str]: 1439*c2e18aaaSAndroid Build Coastguard Worker build_targets = set() 1440*c2e18aaaSAndroid Build Coastguard Worker for invocation in itertools.chain.from_iterable( 1441*c2e18aaaSAndroid Build Coastguard Worker self._test_type_to_invocations.values() 1442*c2e18aaaSAndroid Build Coastguard Worker ): 1443*c2e18aaaSAndroid Build Coastguard Worker build_targets |= invocation.get_test_runner_reqs() 1444*c2e18aaaSAndroid Build Coastguard Worker 1445*c2e18aaaSAndroid Build Coastguard Worker return build_targets 1446*c2e18aaaSAndroid Build Coastguard Worker 1447*c2e18aaaSAndroid Build Coastguard Worker def execute(self) -> ExitCode: 1448*c2e18aaaSAndroid Build Coastguard Worker """Run all tests in TEST_MAPPING files. 1449*c2e18aaaSAndroid Build Coastguard Worker 1450*c2e18aaaSAndroid Build Coastguard Worker Returns: 1451*c2e18aaaSAndroid Build Coastguard Worker Exit code. 1452*c2e18aaaSAndroid Build Coastguard Worker """ 1453*c2e18aaaSAndroid Build Coastguard Worker 1454*c2e18aaaSAndroid Build Coastguard Worker test_results = [] 1455*c2e18aaaSAndroid Build Coastguard Worker for test_type, invocations in self._test_type_to_invocations.items(): 1456*c2e18aaaSAndroid Build Coastguard Worker tests = list( 1457*c2e18aaaSAndroid Build Coastguard Worker itertools.chain.from_iterable(i.test_infos for i in invocations) 1458*c2e18aaaSAndroid Build Coastguard Worker ) 1459*c2e18aaaSAndroid Build Coastguard Worker if not tests: 1460*c2e18aaaSAndroid Build Coastguard Worker continue 1461*c2e18aaaSAndroid Build Coastguard Worker header = RUN_HEADER_FMT % {TEST_COUNT: len(tests), TEST_TYPE: test_type} 1462*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print(header, constants.MAGENTA) 1463*c2e18aaaSAndroid Build Coastguard Worker logging.debug('\n'.join([str(info) for info in tests])) 1464*c2e18aaaSAndroid Build Coastguard Worker 1465*c2e18aaaSAndroid Build Coastguard Worker reporter = result_reporter.ResultReporter( 1466*c2e18aaaSAndroid Build Coastguard Worker collect_only=self._extra_args.get(constants.COLLECT_TESTS_ONLY), 1467*c2e18aaaSAndroid Build Coastguard Worker wait_for_debugger=atest_configs.GLOBAL_ARGS.wait_for_debugger, 1468*c2e18aaaSAndroid Build Coastguard Worker args=self._args, 1469*c2e18aaaSAndroid Build Coastguard Worker test_infos=self._test_infos, 1470*c2e18aaaSAndroid Build Coastguard Worker ) 1471*c2e18aaaSAndroid Build Coastguard Worker reporter.print_starting_text() 1472*c2e18aaaSAndroid Build Coastguard Worker 1473*c2e18aaaSAndroid Build Coastguard Worker tests_exit_code = ExitCode.SUCCESS 1474*c2e18aaaSAndroid Build Coastguard Worker for invocation in invocations: 1475*c2e18aaaSAndroid Build Coastguard Worker tests_exit_code |= invocation.run_all_tests(reporter) 1476*c2e18aaaSAndroid Build Coastguard Worker 1477*c2e18aaaSAndroid Build Coastguard Worker atest_execution_info.AtestExecutionInfo.result_reporters.append(reporter) 1478*c2e18aaaSAndroid Build Coastguard Worker test_results.append((tests_exit_code, reporter, test_type)) 1479*c2e18aaaSAndroid Build Coastguard Worker 1480*c2e18aaaSAndroid Build Coastguard Worker all_tests_exit_code = ExitCode.SUCCESS 1481*c2e18aaaSAndroid Build Coastguard Worker failed_tests = [] 1482*c2e18aaaSAndroid Build Coastguard Worker for tests_exit_code, reporter, test_type in test_results: 1483*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1484*c2e18aaaSAndroid Build Coastguard Worker RESULT_HEADER_FMT % {TEST_TYPE: test_type}, constants.MAGENTA 1485*c2e18aaaSAndroid Build Coastguard Worker ) 1486*c2e18aaaSAndroid Build Coastguard Worker result = tests_exit_code | reporter.print_summary() 1487*c2e18aaaSAndroid Build Coastguard Worker if result: 1488*c2e18aaaSAndroid Build Coastguard Worker failed_tests.append(test_type) 1489*c2e18aaaSAndroid Build Coastguard Worker all_tests_exit_code |= result 1490*c2e18aaaSAndroid Build Coastguard Worker 1491*c2e18aaaSAndroid Build Coastguard Worker # List failed tests at the end as a reminder. 1492*c2e18aaaSAndroid Build Coastguard Worker if failed_tests: 1493*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print( 1494*c2e18aaaSAndroid Build Coastguard Worker atest_utils.delimiter('=', 30, prenl=1), constants.YELLOW 1495*c2e18aaaSAndroid Build Coastguard Worker ) 1496*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print('\nFollowing tests failed:', constants.MAGENTA) 1497*c2e18aaaSAndroid Build Coastguard Worker for failure in failed_tests: 1498*c2e18aaaSAndroid Build Coastguard Worker atest_utils.colorful_print(failure, constants.RED) 1499*c2e18aaaSAndroid Build Coastguard Worker 1500*c2e18aaaSAndroid Build Coastguard Worker return all_tests_exit_code 1501*c2e18aaaSAndroid Build Coastguard Worker 1502*c2e18aaaSAndroid Build Coastguard Worker 1503*c2e18aaaSAndroid Build Coastguard Workerclass _TestModuleExecutionPlan(_TestExecutionPlan): 1504*c2e18aaaSAndroid Build Coastguard Worker """A plan to execute the test modules explicitly passed on the command-line.""" 1505*c2e18aaaSAndroid Build Coastguard Worker 1506*c2e18aaaSAndroid Build Coastguard Worker def __init__( 1507*c2e18aaaSAndroid Build Coastguard Worker self, 1508*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1509*c2e18aaaSAndroid Build Coastguard Worker extra_args: Dict[str, Any], 1510*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1511*c2e18aaaSAndroid Build Coastguard Worker test_runner_invocations: List[TestRunnerInvocation], 1512*c2e18aaaSAndroid Build Coastguard Worker ): 1513*c2e18aaaSAndroid Build Coastguard Worker super().__init__(args, extra_args, test_infos) 1514*c2e18aaaSAndroid Build Coastguard Worker self._test_runner_invocations = test_runner_invocations 1515*c2e18aaaSAndroid Build Coastguard Worker 1516*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 1517*c2e18aaaSAndroid Build Coastguard Worker def create( 1518*c2e18aaaSAndroid Build Coastguard Worker args: argparse.Namespace, 1519*c2e18aaaSAndroid Build Coastguard Worker test_infos: List[test_info.TestInfo], 1520*c2e18aaaSAndroid Build Coastguard Worker results_dir: str, 1521*c2e18aaaSAndroid Build Coastguard Worker mod_info: module_info.ModuleInfo, 1522*c2e18aaaSAndroid Build Coastguard Worker ) -> _TestModuleExecutionPlan: 1523*c2e18aaaSAndroid Build Coastguard Worker """Creates an instance of _TestModuleExecutionPlan. 1524*c2e18aaaSAndroid Build Coastguard Worker 1525*c2e18aaaSAndroid Build Coastguard Worker Args: 1526*c2e18aaaSAndroid Build Coastguard Worker args: An argparse.Namespace instance holding parsed args. 1527*c2e18aaaSAndroid Build Coastguard Worker test_infos: A list of instances of TestInfo. 1528*c2e18aaaSAndroid Build Coastguard Worker results_dir: A directory which stores the ATest execution information. 1529*c2e18aaaSAndroid Build Coastguard Worker mod_info: An instance of ModuleInfo. 1530*c2e18aaaSAndroid Build Coastguard Worker dry_run: A boolean of whether this invocation is a dry run. 1531*c2e18aaaSAndroid Build Coastguard Worker 1532*c2e18aaaSAndroid Build Coastguard Worker Returns: 1533*c2e18aaaSAndroid Build Coastguard Worker An instance of _TestModuleExecutionPlan. 1534*c2e18aaaSAndroid Build Coastguard Worker """ 1535*c2e18aaaSAndroid Build Coastguard Worker 1536*c2e18aaaSAndroid Build Coastguard Worker if not args.dry_run: 1537*c2e18aaaSAndroid Build Coastguard Worker _validate_exec_mode(args, test_infos) 1538*c2e18aaaSAndroid Build Coastguard Worker 1539*c2e18aaaSAndroid Build Coastguard Worker # _validate_exec_mode appends --host automatically when pure 1540*c2e18aaaSAndroid Build Coastguard Worker # host-side tests, so re-parsing extra_args is a must. 1541*c2e18aaaSAndroid Build Coastguard Worker extra_args = get_extra_args(args) 1542*c2e18aaaSAndroid Build Coastguard Worker 1543*c2e18aaaSAndroid Build Coastguard Worker invocations = test_runner_handler.create_test_runner_invocations( 1544*c2e18aaaSAndroid Build Coastguard Worker test_infos=test_infos, 1545*c2e18aaaSAndroid Build Coastguard Worker results_dir=results_dir, 1546*c2e18aaaSAndroid Build Coastguard Worker mod_info=mod_info, 1547*c2e18aaaSAndroid Build Coastguard Worker extra_args=extra_args, 1548*c2e18aaaSAndroid Build Coastguard Worker minimal_build=args.minimal_build, 1549*c2e18aaaSAndroid Build Coastguard Worker ) 1550*c2e18aaaSAndroid Build Coastguard Worker 1551*c2e18aaaSAndroid Build Coastguard Worker return _TestModuleExecutionPlan( 1552*c2e18aaaSAndroid Build Coastguard Worker args=args, 1553*c2e18aaaSAndroid Build Coastguard Worker extra_args=extra_args, 1554*c2e18aaaSAndroid Build Coastguard Worker test_infos=test_infos, 1555*c2e18aaaSAndroid Build Coastguard Worker test_runner_invocations=invocations, 1556*c2e18aaaSAndroid Build Coastguard Worker ) 1557*c2e18aaaSAndroid Build Coastguard Worker 1558*c2e18aaaSAndroid Build Coastguard Worker def requires_device_update(self) -> bool: 1559*c2e18aaaSAndroid Build Coastguard Worker return any( 1560*c2e18aaaSAndroid Build Coastguard Worker inv.requires_device_update() for inv in self._test_runner_invocations 1561*c2e18aaaSAndroid Build Coastguard Worker ) 1562*c2e18aaaSAndroid Build Coastguard Worker 1563*c2e18aaaSAndroid Build Coastguard Worker def required_build_targets(self) -> Set[str]: 1564*c2e18aaaSAndroid Build Coastguard Worker build_targets = set() 1565*c2e18aaaSAndroid Build Coastguard Worker for test_runner_invocation in self._test_runner_invocations: 1566*c2e18aaaSAndroid Build Coastguard Worker build_targets |= test_runner_invocation.get_test_runner_reqs() 1567*c2e18aaaSAndroid Build Coastguard Worker 1568*c2e18aaaSAndroid Build Coastguard Worker return build_targets 1569*c2e18aaaSAndroid Build Coastguard Worker 1570*c2e18aaaSAndroid Build Coastguard Worker def execute(self) -> ExitCode: 1571*c2e18aaaSAndroid Build Coastguard Worker 1572*c2e18aaaSAndroid Build Coastguard Worker reporter = result_reporter.ResultReporter( 1573*c2e18aaaSAndroid Build Coastguard Worker collect_only=self.extra_args.get(constants.COLLECT_TESTS_ONLY), 1574*c2e18aaaSAndroid Build Coastguard Worker wait_for_debugger=atest_configs.GLOBAL_ARGS.wait_for_debugger, 1575*c2e18aaaSAndroid Build Coastguard Worker args=self._args, 1576*c2e18aaaSAndroid Build Coastguard Worker test_infos=self._test_infos, 1577*c2e18aaaSAndroid Build Coastguard Worker ) 1578*c2e18aaaSAndroid Build Coastguard Worker reporter.print_starting_text() 1579*c2e18aaaSAndroid Build Coastguard Worker 1580*c2e18aaaSAndroid Build Coastguard Worker exit_code = ExitCode.SUCCESS 1581*c2e18aaaSAndroid Build Coastguard Worker for invocation in self._test_runner_invocations: 1582*c2e18aaaSAndroid Build Coastguard Worker exit_code |= invocation.run_all_tests(reporter) 1583*c2e18aaaSAndroid Build Coastguard Worker 1584*c2e18aaaSAndroid Build Coastguard Worker atest_execution_info.AtestExecutionInfo.result_reporters.append(reporter) 1585*c2e18aaaSAndroid Build Coastguard Worker return reporter.print_summary() | exit_code 1586*c2e18aaaSAndroid Build Coastguard Worker 1587*c2e18aaaSAndroid Build Coastguard Worker 1588*c2e18aaaSAndroid Build Coastguard Workerif __name__ == '__main__': 1589*c2e18aaaSAndroid Build Coastguard Worker _AtestMain(sys.argv).run() 1590