1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2018 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport argparse 8*8975f5c5SAndroid Build Coastguard Workerimport collections 9*8975f5c5SAndroid Build Coastguard Workerimport json 10*8975f5c5SAndroid Build Coastguard Workerimport logging 11*8975f5c5SAndroid Build Coastguard Workerimport os 12*8975f5c5SAndroid Build Coastguard Workerimport re 13*8975f5c5SAndroid Build Coastguard Workerimport shutil 14*8975f5c5SAndroid Build Coastguard Workerimport signal 15*8975f5c5SAndroid Build Coastguard Workerimport socket 16*8975f5c5SAndroid Build Coastguard Workerimport sys 17*8975f5c5SAndroid Build Coastguard Workerimport tempfile 18*8975f5c5SAndroid Build Coastguard Worker 19*8975f5c5SAndroid Build Coastguard Worker# The following non-std imports are fetched via vpython. See the list at 20*8975f5c5SAndroid Build Coastguard Worker# //.vpython3 21*8975f5c5SAndroid Build Coastguard Workerimport dateutil.parser # pylint: disable=import-error 22*8975f5c5SAndroid Build Coastguard Workerimport jsonlines # pylint: disable=import-error 23*8975f5c5SAndroid Build Coastguard Workerimport psutil # pylint: disable=import-error 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard WorkerCHROMIUM_SRC_PATH = os.path.abspath( 26*8975f5c5SAndroid Build Coastguard Worker os.path.join(os.path.dirname(__file__), '..', '..')) 27*8975f5c5SAndroid Build Coastguard Worker 28*8975f5c5SAndroid Build Coastguard Worker# Use the android test-runner's gtest results support library for generating 29*8975f5c5SAndroid Build Coastguard Worker# output json ourselves. 30*8975f5c5SAndroid Build Coastguard Workersys.path.insert(0, os.path.join(CHROMIUM_SRC_PATH, 'build', 'android')) 31*8975f5c5SAndroid Build Coastguard Workerfrom pylib.base import base_test_result # pylint: disable=import-error 32*8975f5c5SAndroid Build Coastguard Workerfrom pylib.results import json_results # pylint: disable=import-error 33*8975f5c5SAndroid Build Coastguard Worker 34*8975f5c5SAndroid Build Coastguard Workersys.path.insert(0, os.path.join(CHROMIUM_SRC_PATH, 'build', 'util')) 35*8975f5c5SAndroid Build Coastguard Worker# TODO(crbug.com/40259280): Re-enable the 'no-name-in-module' check. 36*8975f5c5SAndroid Build Coastguard Workerfrom lib.results import result_sink # pylint: disable=import-error,no-name-in-module 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Workerimport subprocess # pylint: disable=import-error,wrong-import-order 39*8975f5c5SAndroid Build Coastguard Worker 40*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_CROS_CACHE = os.path.abspath( 41*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMIUM_SRC_PATH, 'build', 'cros_cache')) 42*8975f5c5SAndroid Build Coastguard WorkerCHROMITE_PATH = os.path.abspath( 43*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMIUM_SRC_PATH, 'third_party', 'chromite')) 44*8975f5c5SAndroid Build Coastguard WorkerCROS_RUN_TEST_PATH = os.path.abspath( 45*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMITE_PATH, 'bin', 'cros_run_test')) 46*8975f5c5SAndroid Build Coastguard Worker 47*8975f5c5SAndroid Build Coastguard Worker# This is a special hostname that resolves to a different DUT in the lab 48*8975f5c5SAndroid Build Coastguard Worker# depending on which lab machine you're on. 49*8975f5c5SAndroid Build Coastguard WorkerLAB_DUT_HOSTNAME = 'variable_chromeos_device_hostname' 50*8975f5c5SAndroid Build Coastguard Worker 51*8975f5c5SAndroid Build Coastguard WorkerSYSTEM_LOG_LOCATIONS = [ 52*8975f5c5SAndroid Build Coastguard Worker '/home/chronos/crash/', 53*8975f5c5SAndroid Build Coastguard Worker '/var/log/chrome/', 54*8975f5c5SAndroid Build Coastguard Worker '/var/log/messages', 55*8975f5c5SAndroid Build Coastguard Worker '/var/log/ui/', 56*8975f5c5SAndroid Build Coastguard Worker] 57*8975f5c5SAndroid Build Coastguard Worker 58*8975f5c5SAndroid Build Coastguard WorkerTAST_DEBUG_DOC = 'https://bit.ly/2LgvIXz' 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker 61*8975f5c5SAndroid Build Coastguard Workerclass TestFormatError(Exception): 62*8975f5c5SAndroid Build Coastguard Worker pass 63*8975f5c5SAndroid Build Coastguard Worker 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Workerclass RemoteTest: 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard Worker # This is a basic shell script that can be appended to in order to invoke the 68*8975f5c5SAndroid Build Coastguard Worker # test on the device. 69*8975f5c5SAndroid Build Coastguard Worker BASIC_SHELL_SCRIPT = [ 70*8975f5c5SAndroid Build Coastguard Worker '#!/bin/sh', 71*8975f5c5SAndroid Build Coastguard Worker 72*8975f5c5SAndroid Build Coastguard Worker # /home and /tmp are mounted with "noexec" in the device, but some of our 73*8975f5c5SAndroid Build Coastguard Worker # tools and tests use those dirs as a workspace (eg: vpython downloads 74*8975f5c5SAndroid Build Coastguard Worker # python binaries to ~/.vpython-root and /tmp/vpython_bootstrap). 75*8975f5c5SAndroid Build Coastguard Worker # /usr/local/tmp doesn't have this restriction, so change the location of 76*8975f5c5SAndroid Build Coastguard Worker # the home and temp dirs for the duration of the test. 77*8975f5c5SAndroid Build Coastguard Worker 'export HOME=/usr/local/tmp', 78*8975f5c5SAndroid Build Coastguard Worker 'export TMPDIR=/usr/local/tmp', 79*8975f5c5SAndroid Build Coastguard Worker ] 80*8975f5c5SAndroid Build Coastguard Worker 81*8975f5c5SAndroid Build Coastguard Worker def __init__(self, args, unknown_args): 82*8975f5c5SAndroid Build Coastguard Worker self._additional_args = unknown_args 83*8975f5c5SAndroid Build Coastguard Worker self._path_to_outdir = args.path_to_outdir 84*8975f5c5SAndroid Build Coastguard Worker self._test_launcher_summary_output = args.test_launcher_summary_output 85*8975f5c5SAndroid Build Coastguard Worker self._logs_dir = args.logs_dir 86*8975f5c5SAndroid Build Coastguard Worker self._use_vm = args.use_vm 87*8975f5c5SAndroid Build Coastguard Worker self._rdb_client = result_sink.TryInitClient() 88*8975f5c5SAndroid Build Coastguard Worker 89*8975f5c5SAndroid Build Coastguard Worker self._retries = 0 90*8975f5c5SAndroid Build Coastguard Worker self._timeout = None 91*8975f5c5SAndroid Build Coastguard Worker self._test_launcher_shard_index = args.test_launcher_shard_index 92*8975f5c5SAndroid Build Coastguard Worker self._test_launcher_total_shards = args.test_launcher_total_shards 93*8975f5c5SAndroid Build Coastguard Worker 94*8975f5c5SAndroid Build Coastguard Worker # The location on disk of a shell script that can be optionally used to 95*8975f5c5SAndroid Build Coastguard Worker # invoke the test on the device. If it's not set, we assume self._test_cmd 96*8975f5c5SAndroid Build Coastguard Worker # contains the test invocation. 97*8975f5c5SAndroid Build Coastguard Worker self._on_device_script = None 98*8975f5c5SAndroid Build Coastguard Worker 99*8975f5c5SAndroid Build Coastguard Worker self._test_cmd = [ 100*8975f5c5SAndroid Build Coastguard Worker CROS_RUN_TEST_PATH, 101*8975f5c5SAndroid Build Coastguard Worker '--board', 102*8975f5c5SAndroid Build Coastguard Worker args.board, 103*8975f5c5SAndroid Build Coastguard Worker '--cache-dir', 104*8975f5c5SAndroid Build Coastguard Worker args.cros_cache, 105*8975f5c5SAndroid Build Coastguard Worker ] 106*8975f5c5SAndroid Build Coastguard Worker if args.use_vm: 107*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 108*8975f5c5SAndroid Build Coastguard Worker '--start', 109*8975f5c5SAndroid Build Coastguard Worker # Don't persist any filesystem changes after the VM shutsdown. 110*8975f5c5SAndroid Build Coastguard Worker '--copy-on-write', 111*8975f5c5SAndroid Build Coastguard Worker ] 112*8975f5c5SAndroid Build Coastguard Worker else: 113*8975f5c5SAndroid Build Coastguard Worker if args.fetch_cros_hostname: 114*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += ['--device', get_cros_hostname()] 115*8975f5c5SAndroid Build Coastguard Worker else: 116*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 117*8975f5c5SAndroid Build Coastguard Worker '--device', args.device if args.device else LAB_DUT_HOSTNAME 118*8975f5c5SAndroid Build Coastguard Worker ] 119*8975f5c5SAndroid Build Coastguard Worker 120*8975f5c5SAndroid Build Coastguard Worker if args.logs_dir: 121*8975f5c5SAndroid Build Coastguard Worker for log in SYSTEM_LOG_LOCATIONS: 122*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += ['--results-src', log] 123*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 124*8975f5c5SAndroid Build Coastguard Worker '--results-dest-dir', 125*8975f5c5SAndroid Build Coastguard Worker os.path.join(args.logs_dir, 'system_logs') 126*8975f5c5SAndroid Build Coastguard Worker ] 127*8975f5c5SAndroid Build Coastguard Worker if args.flash: 128*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += ['--flash'] 129*8975f5c5SAndroid Build Coastguard Worker if args.public_image: 130*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += ['--public-image'] 131*8975f5c5SAndroid Build Coastguard Worker 132*8975f5c5SAndroid Build Coastguard Worker self._test_env = setup_env() 133*8975f5c5SAndroid Build Coastguard Worker 134*8975f5c5SAndroid Build Coastguard Worker @property 135*8975f5c5SAndroid Build Coastguard Worker def suite_name(self): 136*8975f5c5SAndroid Build Coastguard Worker raise NotImplementedError('Child classes need to define suite name.') 137*8975f5c5SAndroid Build Coastguard Worker 138*8975f5c5SAndroid Build Coastguard Worker @property 139*8975f5c5SAndroid Build Coastguard Worker def test_cmd(self): 140*8975f5c5SAndroid Build Coastguard Worker return self._test_cmd 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker def write_test_script_to_disk(self, script_contents): 143*8975f5c5SAndroid Build Coastguard Worker # Since we're using an on_device_script to invoke the test, we'll need to 144*8975f5c5SAndroid Build Coastguard Worker # set cwd. 145*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 146*8975f5c5SAndroid Build Coastguard Worker '--remote-cmd', 147*8975f5c5SAndroid Build Coastguard Worker '--cwd', 148*8975f5c5SAndroid Build Coastguard Worker os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH), 149*8975f5c5SAndroid Build Coastguard Worker ] 150*8975f5c5SAndroid Build Coastguard Worker logging.info('Running the following command on the device:') 151*8975f5c5SAndroid Build Coastguard Worker logging.info('\n%s', '\n'.join(script_contents)) 152*8975f5c5SAndroid Build Coastguard Worker fd, tmp_path = tempfile.mkstemp(suffix='.sh', dir=self._path_to_outdir) 153*8975f5c5SAndroid Build Coastguard Worker os.fchmod(fd, 0o755) 154*8975f5c5SAndroid Build Coastguard Worker with os.fdopen(fd, 'w') as f: 155*8975f5c5SAndroid Build Coastguard Worker f.write('\n'.join(script_contents) + '\n') 156*8975f5c5SAndroid Build Coastguard Worker return tmp_path 157*8975f5c5SAndroid Build Coastguard Worker 158*8975f5c5SAndroid Build Coastguard Worker def write_runtime_files_to_disk(self, runtime_files): 159*8975f5c5SAndroid Build Coastguard Worker logging.info('Writing runtime files to disk.') 160*8975f5c5SAndroid Build Coastguard Worker fd, tmp_path = tempfile.mkstemp(suffix='.txt', dir=self._path_to_outdir) 161*8975f5c5SAndroid Build Coastguard Worker os.fchmod(fd, 0o755) 162*8975f5c5SAndroid Build Coastguard Worker with os.fdopen(fd, 'w') as f: 163*8975f5c5SAndroid Build Coastguard Worker f.write('\n'.join(runtime_files) + '\n') 164*8975f5c5SAndroid Build Coastguard Worker return tmp_path 165*8975f5c5SAndroid Build Coastguard Worker 166*8975f5c5SAndroid Build Coastguard Worker def run_test(self): 167*8975f5c5SAndroid Build Coastguard Worker # Traps SIGTERM and kills all child processes of cros_run_test when it's 168*8975f5c5SAndroid Build Coastguard Worker # caught. This will allow us to capture logs from the device if a test hangs 169*8975f5c5SAndroid Build Coastguard Worker # and gets timeout-killed by swarming. See also: 170*8975f5c5SAndroid Build Coastguard Worker # https://chromium.googlesource.com/infra/luci/luci-py/+/main/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance 171*8975f5c5SAndroid Build Coastguard Worker test_proc = None 172*8975f5c5SAndroid Build Coastguard Worker 173*8975f5c5SAndroid Build Coastguard Worker def _kill_child_procs(trapped_signal, _): 174*8975f5c5SAndroid Build Coastguard Worker logging.warning('Received signal %d. Killing child processes of test.', 175*8975f5c5SAndroid Build Coastguard Worker trapped_signal) 176*8975f5c5SAndroid Build Coastguard Worker if not test_proc or not test_proc.pid: 177*8975f5c5SAndroid Build Coastguard Worker # This shouldn't happen? 178*8975f5c5SAndroid Build Coastguard Worker logging.error('Test process not running.') 179*8975f5c5SAndroid Build Coastguard Worker return 180*8975f5c5SAndroid Build Coastguard Worker for child in psutil.Process(test_proc.pid).children(): 181*8975f5c5SAndroid Build Coastguard Worker logging.warning('Killing process %s', child) 182*8975f5c5SAndroid Build Coastguard Worker child.kill() 183*8975f5c5SAndroid Build Coastguard Worker 184*8975f5c5SAndroid Build Coastguard Worker signal.signal(signal.SIGTERM, _kill_child_procs) 185*8975f5c5SAndroid Build Coastguard Worker 186*8975f5c5SAndroid Build Coastguard Worker for i in range(self._retries + 1): 187*8975f5c5SAndroid Build Coastguard Worker logging.info('########################################') 188*8975f5c5SAndroid Build Coastguard Worker logging.info('Test attempt #%d', i) 189*8975f5c5SAndroid Build Coastguard Worker logging.info('########################################') 190*8975f5c5SAndroid Build Coastguard Worker test_proc = subprocess.Popen( 191*8975f5c5SAndroid Build Coastguard Worker self._test_cmd, 192*8975f5c5SAndroid Build Coastguard Worker stdout=sys.stdout, 193*8975f5c5SAndroid Build Coastguard Worker stderr=sys.stderr, 194*8975f5c5SAndroid Build Coastguard Worker env=self._test_env) 195*8975f5c5SAndroid Build Coastguard Worker try: 196*8975f5c5SAndroid Build Coastguard Worker test_proc.wait(timeout=self._timeout) 197*8975f5c5SAndroid Build Coastguard Worker except subprocess.TimeoutExpired: # pylint: disable=no-member 198*8975f5c5SAndroid Build Coastguard Worker logging.error('Test timed out. Sending SIGTERM.') 199*8975f5c5SAndroid Build Coastguard Worker # SIGTERM the proc and wait 10s for it to close. 200*8975f5c5SAndroid Build Coastguard Worker test_proc.terminate() 201*8975f5c5SAndroid Build Coastguard Worker try: 202*8975f5c5SAndroid Build Coastguard Worker test_proc.wait(timeout=10) 203*8975f5c5SAndroid Build Coastguard Worker except subprocess.TimeoutExpired: # pylint: disable=no-member 204*8975f5c5SAndroid Build Coastguard Worker # If it hasn't closed in 10s, SIGKILL it. 205*8975f5c5SAndroid Build Coastguard Worker logging.error('Test did not exit in time. Sending SIGKILL.') 206*8975f5c5SAndroid Build Coastguard Worker test_proc.kill() 207*8975f5c5SAndroid Build Coastguard Worker test_proc.wait() 208*8975f5c5SAndroid Build Coastguard Worker logging.info('Test exitted with %d.', test_proc.returncode) 209*8975f5c5SAndroid Build Coastguard Worker if test_proc.returncode == 0: 210*8975f5c5SAndroid Build Coastguard Worker break 211*8975f5c5SAndroid Build Coastguard Worker 212*8975f5c5SAndroid Build Coastguard Worker self.post_run(test_proc.returncode) 213*8975f5c5SAndroid Build Coastguard Worker # Allow post_run to override test proc return code. (Useful when the host 214*8975f5c5SAndroid Build Coastguard Worker # side Tast bin returns 0 even for failed tests.) 215*8975f5c5SAndroid Build Coastguard Worker return test_proc.returncode 216*8975f5c5SAndroid Build Coastguard Worker 217*8975f5c5SAndroid Build Coastguard Worker def post_run(self, _): 218*8975f5c5SAndroid Build Coastguard Worker if self._on_device_script: 219*8975f5c5SAndroid Build Coastguard Worker os.remove(self._on_device_script) 220*8975f5c5SAndroid Build Coastguard Worker 221*8975f5c5SAndroid Build Coastguard Worker @staticmethod 222*8975f5c5SAndroid Build Coastguard Worker def get_artifacts(path): 223*8975f5c5SAndroid Build Coastguard Worker """Crawls a given directory for file artifacts to attach to a test. 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard Worker Args: 226*8975f5c5SAndroid Build Coastguard Worker path: Path to a directory to search for artifacts. 227*8975f5c5SAndroid Build Coastguard Worker Returns: 228*8975f5c5SAndroid Build Coastguard Worker A dict mapping name of the artifact to its absolute filepath. 229*8975f5c5SAndroid Build Coastguard Worker """ 230*8975f5c5SAndroid Build Coastguard Worker artifacts = {} 231*8975f5c5SAndroid Build Coastguard Worker for dirpath, _, filenames in os.walk(path): 232*8975f5c5SAndroid Build Coastguard Worker for f in filenames: 233*8975f5c5SAndroid Build Coastguard Worker artifact_path = os.path.join(dirpath, f) 234*8975f5c5SAndroid Build Coastguard Worker artifact_id = os.path.relpath(artifact_path, path) 235*8975f5c5SAndroid Build Coastguard Worker # Some artifacts will have non-Latin characters in the filename, eg: 236*8975f5c5SAndroid Build Coastguard Worker # 'ui_tree_Chinese Pinyin-你好.txt'. ResultDB's API rejects such 237*8975f5c5SAndroid Build Coastguard Worker # characters as an artifact ID, so force the file name down into ascii. 238*8975f5c5SAndroid Build Coastguard Worker # For more info, see: 239*8975f5c5SAndroid Build Coastguard Worker # https://source.chromium.org/chromium/infra/infra/+/main:go/src/go.chromium.org/luci/resultdb/proto/v1/artifact.proto;drc=3bff13b8037ca76ec19f9810033d914af7ec67cb;l=46 240*8975f5c5SAndroid Build Coastguard Worker artifact_id = artifact_id.encode('ascii', 'replace').decode() 241*8975f5c5SAndroid Build Coastguard Worker artifact_id = artifact_id.replace('\\', '?') 242*8975f5c5SAndroid Build Coastguard Worker artifacts[artifact_id] = { 243*8975f5c5SAndroid Build Coastguard Worker 'filePath': artifact_path, 244*8975f5c5SAndroid Build Coastguard Worker } 245*8975f5c5SAndroid Build Coastguard Worker return artifacts 246*8975f5c5SAndroid Build Coastguard Worker 247*8975f5c5SAndroid Build Coastguard Worker 248*8975f5c5SAndroid Build Coastguard Workerclass TastTest(RemoteTest): 249*8975f5c5SAndroid Build Coastguard Worker 250*8975f5c5SAndroid Build Coastguard Worker def __init__(self, args, unknown_args): 251*8975f5c5SAndroid Build Coastguard Worker super().__init__(args, unknown_args) 252*8975f5c5SAndroid Build Coastguard Worker 253*8975f5c5SAndroid Build Coastguard Worker self._suite_name = args.suite_name 254*8975f5c5SAndroid Build Coastguard Worker self._tast_vars = args.tast_vars 255*8975f5c5SAndroid Build Coastguard Worker self._tast_retries = args.tast_retries 256*8975f5c5SAndroid Build Coastguard Worker self._tests = args.tests 257*8975f5c5SAndroid Build Coastguard Worker # The CQ passes in '--gtest_filter' when specifying tests to skip. Store it 258*8975f5c5SAndroid Build Coastguard Worker # here and parse it later to integrate it into Tast executions. 259*8975f5c5SAndroid Build Coastguard Worker self._gtest_style_filter = args.gtest_filter 260*8975f5c5SAndroid Build Coastguard Worker self._attr_expr = args.attr_expr 261*8975f5c5SAndroid Build Coastguard Worker self._should_strip = args.strip_chrome 262*8975f5c5SAndroid Build Coastguard Worker self._deploy_chrome = args.deploy_chrome 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Worker if not self._logs_dir: 265*8975f5c5SAndroid Build Coastguard Worker # The host-side Tast bin returns 0 when tests fail, so we need to capture 266*8975f5c5SAndroid Build Coastguard Worker # and parse its json results to reliably determine if tests fail. 267*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError( 268*8975f5c5SAndroid Build Coastguard Worker 'When using the host-side Tast bin, "--logs-dir" must be passed in ' 269*8975f5c5SAndroid Build Coastguard Worker 'order to parse its results.') 270*8975f5c5SAndroid Build Coastguard Worker 271*8975f5c5SAndroid Build Coastguard Worker # If the first test filter is negative, it should be safe to assume all of 272*8975f5c5SAndroid Build Coastguard Worker # them are, so just test the first filter. 273*8975f5c5SAndroid Build Coastguard Worker if self._gtest_style_filter and self._gtest_style_filter[0] == '-': 274*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError('Negative test filters not supported for Tast.') 275*8975f5c5SAndroid Build Coastguard Worker 276*8975f5c5SAndroid Build Coastguard Worker @property 277*8975f5c5SAndroid Build Coastguard Worker def suite_name(self): 278*8975f5c5SAndroid Build Coastguard Worker return self._suite_name 279*8975f5c5SAndroid Build Coastguard Worker 280*8975f5c5SAndroid Build Coastguard Worker def build_test_command(self): 281*8975f5c5SAndroid Build Coastguard Worker unsupported_args = [ 282*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-retry-limit', 283*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-batch-limit', 284*8975f5c5SAndroid Build Coastguard Worker '--gtest_repeat', 285*8975f5c5SAndroid Build Coastguard Worker ] 286*8975f5c5SAndroid Build Coastguard Worker for unsupported_arg in unsupported_args: 287*8975f5c5SAndroid Build Coastguard Worker if any(arg.startswith(unsupported_arg) for arg in self._additional_args): 288*8975f5c5SAndroid Build Coastguard Worker logging.info( 289*8975f5c5SAndroid Build Coastguard Worker '%s not supported for Tast tests. The arg will be ignored.', 290*8975f5c5SAndroid Build Coastguard Worker unsupported_arg) 291*8975f5c5SAndroid Build Coastguard Worker self._additional_args = [ 292*8975f5c5SAndroid Build Coastguard Worker arg for arg in self._additional_args 293*8975f5c5SAndroid Build Coastguard Worker if not arg.startswith(unsupported_arg) 294*8975f5c5SAndroid Build Coastguard Worker ] 295*8975f5c5SAndroid Build Coastguard Worker 296*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.extend(['--deploy', '--mount']) 297*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 298*8975f5c5SAndroid Build Coastguard Worker '--build-dir', 299*8975f5c5SAndroid Build Coastguard Worker os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH) 300*8975f5c5SAndroid Build Coastguard Worker ] + self._additional_args 301*8975f5c5SAndroid Build Coastguard Worker 302*8975f5c5SAndroid Build Coastguard Worker # Capture tast's results in the logs dir as well. 303*8975f5c5SAndroid Build Coastguard Worker if self._logs_dir: 304*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 305*8975f5c5SAndroid Build Coastguard Worker '--results-dir', 306*8975f5c5SAndroid Build Coastguard Worker self._logs_dir, 307*8975f5c5SAndroid Build Coastguard Worker ] 308*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 309*8975f5c5SAndroid Build Coastguard Worker '--tast-total-shards=%d' % self._test_launcher_total_shards, 310*8975f5c5SAndroid Build Coastguard Worker '--tast-shard-index=%d' % self._test_launcher_shard_index, 311*8975f5c5SAndroid Build Coastguard Worker ] 312*8975f5c5SAndroid Build Coastguard Worker # If we're using a test filter, replace the contents of the Tast 313*8975f5c5SAndroid Build Coastguard Worker # conditional with a long list of "name:test" expressions, one for each 314*8975f5c5SAndroid Build Coastguard Worker # test in the filter. 315*8975f5c5SAndroid Build Coastguard Worker if self._gtest_style_filter: 316*8975f5c5SAndroid Build Coastguard Worker if self._attr_expr or self._tests: 317*8975f5c5SAndroid Build Coastguard Worker logging.warning( 318*8975f5c5SAndroid Build Coastguard Worker 'Presence of --gtest_filter will cause the specified Tast expr' 319*8975f5c5SAndroid Build Coastguard Worker ' or test list to be ignored.') 320*8975f5c5SAndroid Build Coastguard Worker names = [] 321*8975f5c5SAndroid Build Coastguard Worker for test in self._gtest_style_filter.split(':'): 322*8975f5c5SAndroid Build Coastguard Worker names.append('"name:%s"' % test) 323*8975f5c5SAndroid Build Coastguard Worker self._attr_expr = '(' + ' || '.join(names) + ')' 324*8975f5c5SAndroid Build Coastguard Worker 325*8975f5c5SAndroid Build Coastguard Worker if self._attr_expr: 326*8975f5c5SAndroid Build Coastguard Worker # Don't use shlex.quote() here. Something funky happens with the arg 327*8975f5c5SAndroid Build Coastguard Worker # as it gets passed down from cros_run_test to tast. (Tast picks up the 328*8975f5c5SAndroid Build Coastguard Worker # escaping single quotes and complains that the attribute expression 329*8975f5c5SAndroid Build Coastguard Worker # "must be within parentheses".) 330*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.append('--tast=%s' % self._attr_expr) 331*8975f5c5SAndroid Build Coastguard Worker else: 332*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.append('--tast') 333*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.extend(self._tests) 334*8975f5c5SAndroid Build Coastguard Worker 335*8975f5c5SAndroid Build Coastguard Worker for v in self._tast_vars or []: 336*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.extend(['--tast-var', v]) 337*8975f5c5SAndroid Build Coastguard Worker 338*8975f5c5SAndroid Build Coastguard Worker if self._tast_retries: 339*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.append('--tast-retries=%d' % self._tast_retries) 340*8975f5c5SAndroid Build Coastguard Worker 341*8975f5c5SAndroid Build Coastguard Worker # Mounting ash-chrome gives it enough disk space to not need stripping, 342*8975f5c5SAndroid Build Coastguard Worker # but only for one not instrumented with code coverage. 343*8975f5c5SAndroid Build Coastguard Worker if not self._should_strip: 344*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.append('--nostrip') 345*8975f5c5SAndroid Build Coastguard Worker 346*8975f5c5SAndroid Build Coastguard Worker def post_run(self, return_code): 347*8975f5c5SAndroid Build Coastguard Worker tast_results_path = os.path.join(self._logs_dir, 'streamed_results.jsonl') 348*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(tast_results_path): 349*8975f5c5SAndroid Build Coastguard Worker logging.error( 350*8975f5c5SAndroid Build Coastguard Worker 'Tast results not found at %s. Falling back to generic result ' 351*8975f5c5SAndroid Build Coastguard Worker 'reporting.', tast_results_path) 352*8975f5c5SAndroid Build Coastguard Worker return super().post_run(return_code) 353*8975f5c5SAndroid Build Coastguard Worker 354*8975f5c5SAndroid Build Coastguard Worker # See the link below for the format of the results: 355*8975f5c5SAndroid Build Coastguard Worker # https://godoc.org/chromium.googlesource.com/chromiumos/platform/tast.git/src/chromiumos/cmd/tast/run#TestResult 356*8975f5c5SAndroid Build Coastguard Worker with jsonlines.open(tast_results_path) as reader: 357*8975f5c5SAndroid Build Coastguard Worker tast_results = collections.deque(reader) 358*8975f5c5SAndroid Build Coastguard Worker 359*8975f5c5SAndroid Build Coastguard Worker suite_results = base_test_result.TestRunResults() 360*8975f5c5SAndroid Build Coastguard Worker for test in tast_results: 361*8975f5c5SAndroid Build Coastguard Worker errors = test['errors'] 362*8975f5c5SAndroid Build Coastguard Worker start, end = test['start'], test['end'] 363*8975f5c5SAndroid Build Coastguard Worker # Use dateutil to parse the timestamps since datetime can't handle 364*8975f5c5SAndroid Build Coastguard Worker # nanosecond precision. 365*8975f5c5SAndroid Build Coastguard Worker duration = dateutil.parser.parse(end) - dateutil.parser.parse(start) 366*8975f5c5SAndroid Build Coastguard Worker # If the duration is negative, Tast has likely reported an incorrect 367*8975f5c5SAndroid Build Coastguard Worker # duration. See https://issuetracker.google.com/issues/187973541. Round 368*8975f5c5SAndroid Build Coastguard Worker # up to 0 in that case to avoid confusing RDB. 369*8975f5c5SAndroid Build Coastguard Worker duration_ms = max(duration.total_seconds() * 1000, 0) 370*8975f5c5SAndroid Build Coastguard Worker if bool(test['skipReason']): 371*8975f5c5SAndroid Build Coastguard Worker result = base_test_result.ResultType.SKIP 372*8975f5c5SAndroid Build Coastguard Worker elif errors: 373*8975f5c5SAndroid Build Coastguard Worker result = base_test_result.ResultType.FAIL 374*8975f5c5SAndroid Build Coastguard Worker else: 375*8975f5c5SAndroid Build Coastguard Worker result = base_test_result.ResultType.PASS 376*8975f5c5SAndroid Build Coastguard Worker primary_error_message = None 377*8975f5c5SAndroid Build Coastguard Worker error_log = '' 378*8975f5c5SAndroid Build Coastguard Worker if errors: 379*8975f5c5SAndroid Build Coastguard Worker # See the link below for the format of these errors: 380*8975f5c5SAndroid Build Coastguard Worker # https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/tast/src/chromiumos/tast/cmd/tast/internal/run/resultsjson/resultsjson.go 381*8975f5c5SAndroid Build Coastguard Worker primary_error_message = errors[0]['reason'] 382*8975f5c5SAndroid Build Coastguard Worker for err in errors: 383*8975f5c5SAndroid Build Coastguard Worker error_log += err['stack'] + '\n' 384*8975f5c5SAndroid Build Coastguard Worker debug_link = ("If you're unsure why this test failed, consult the steps " 385*8975f5c5SAndroid Build Coastguard Worker 'outlined <a href="%s">here</a>.' % TAST_DEBUG_DOC) 386*8975f5c5SAndroid Build Coastguard Worker base_result = base_test_result.BaseTestResult( 387*8975f5c5SAndroid Build Coastguard Worker test['name'], result, duration=duration_ms, log=error_log) 388*8975f5c5SAndroid Build Coastguard Worker suite_results.AddResult(base_result) 389*8975f5c5SAndroid Build Coastguard Worker self._maybe_handle_perf_results(test['name']) 390*8975f5c5SAndroid Build Coastguard Worker 391*8975f5c5SAndroid Build Coastguard Worker if self._rdb_client: 392*8975f5c5SAndroid Build Coastguard Worker # Walk the contents of the test's "outDir" and atttach any file found 393*8975f5c5SAndroid Build Coastguard Worker # inside as an RDB 'artifact'. (This could include system logs, screen 394*8975f5c5SAndroid Build Coastguard Worker # shots, etc.) 395*8975f5c5SAndroid Build Coastguard Worker artifacts = self.get_artifacts(test['outDir']) 396*8975f5c5SAndroid Build Coastguard Worker html_artifact = debug_link 397*8975f5c5SAndroid Build Coastguard Worker if result == base_test_result.ResultType.SKIP: 398*8975f5c5SAndroid Build Coastguard Worker html_artifact = 'Test was skipped because: ' + test['skipReason'] 399*8975f5c5SAndroid Build Coastguard Worker self._rdb_client.Post( 400*8975f5c5SAndroid Build Coastguard Worker test['name'], 401*8975f5c5SAndroid Build Coastguard Worker result, 402*8975f5c5SAndroid Build Coastguard Worker duration_ms, 403*8975f5c5SAndroid Build Coastguard Worker error_log, 404*8975f5c5SAndroid Build Coastguard Worker None, 405*8975f5c5SAndroid Build Coastguard Worker artifacts=artifacts, 406*8975f5c5SAndroid Build Coastguard Worker failure_reason=primary_error_message, 407*8975f5c5SAndroid Build Coastguard Worker html_artifact=html_artifact) 408*8975f5c5SAndroid Build Coastguard Worker 409*8975f5c5SAndroid Build Coastguard Worker if self._rdb_client and self._logs_dir: 410*8975f5c5SAndroid Build Coastguard Worker # Attach artifacts from the device that don't apply to a single test. 411*8975f5c5SAndroid Build Coastguard Worker artifacts = self.get_artifacts( 412*8975f5c5SAndroid Build Coastguard Worker os.path.join(self._logs_dir, 'system_logs')) 413*8975f5c5SAndroid Build Coastguard Worker artifacts.update( 414*8975f5c5SAndroid Build Coastguard Worker self.get_artifacts(os.path.join(self._logs_dir, 'crashes'))) 415*8975f5c5SAndroid Build Coastguard Worker self._rdb_client.ReportInvocationLevelArtifacts(artifacts) 416*8975f5c5SAndroid Build Coastguard Worker 417*8975f5c5SAndroid Build Coastguard Worker if self._test_launcher_summary_output: 418*8975f5c5SAndroid Build Coastguard Worker with open(self._test_launcher_summary_output, 'w') as f: 419*8975f5c5SAndroid Build Coastguard Worker json.dump(json_results.GenerateResultsDict([suite_results]), f) 420*8975f5c5SAndroid Build Coastguard Worker 421*8975f5c5SAndroid Build Coastguard Worker if not suite_results.DidRunPass(): 422*8975f5c5SAndroid Build Coastguard Worker return 1 423*8975f5c5SAndroid Build Coastguard Worker if return_code: 424*8975f5c5SAndroid Build Coastguard Worker logging.warning( 425*8975f5c5SAndroid Build Coastguard Worker 'No failed tests found, but exit code of %d was returned from ' 426*8975f5c5SAndroid Build Coastguard Worker 'cros_run_test.', return_code) 427*8975f5c5SAndroid Build Coastguard Worker return return_code 428*8975f5c5SAndroid Build Coastguard Worker return 0 429*8975f5c5SAndroid Build Coastguard Worker 430*8975f5c5SAndroid Build Coastguard Worker def _maybe_handle_perf_results(self, test_name): 431*8975f5c5SAndroid Build Coastguard Worker """Prepares any perf results from |test_name| for process_perf_results. 432*8975f5c5SAndroid Build Coastguard Worker 433*8975f5c5SAndroid Build Coastguard Worker - process_perf_results looks for top level directories containing a 434*8975f5c5SAndroid Build Coastguard Worker perf_results.json file and a test_results.json file. The directory names 435*8975f5c5SAndroid Build Coastguard Worker are used as the benchmark names. 436*8975f5c5SAndroid Build Coastguard Worker - If a perf_results.json or results-chart.json file exists in the 437*8975f5c5SAndroid Build Coastguard Worker |test_name| results directory, a top level directory is created and the 438*8975f5c5SAndroid Build Coastguard Worker perf results file is copied to perf_results.json. 439*8975f5c5SAndroid Build Coastguard Worker - A trivial test_results.json file is also created to indicate that the test 440*8975f5c5SAndroid Build Coastguard Worker succeeded (this function would not be called otherwise). 441*8975f5c5SAndroid Build Coastguard Worker - When process_perf_results is run, it will find the expected files in the 442*8975f5c5SAndroid Build Coastguard Worker named directory and upload the benchmark results. 443*8975f5c5SAndroid Build Coastguard Worker """ 444*8975f5c5SAndroid Build Coastguard Worker 445*8975f5c5SAndroid Build Coastguard Worker perf_results = os.path.join(self._logs_dir, 'tests', test_name, 446*8975f5c5SAndroid Build Coastguard Worker 'perf_results.json') 447*8975f5c5SAndroid Build Coastguard Worker # TODO(stevenjb): Remove check for crosbolt results-chart.json file. 448*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(perf_results): 449*8975f5c5SAndroid Build Coastguard Worker perf_results = os.path.join(self._logs_dir, 'tests', test_name, 450*8975f5c5SAndroid Build Coastguard Worker 'results-chart.json') 451*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(perf_results): 452*8975f5c5SAndroid Build Coastguard Worker benchmark_dir = os.path.join(self._logs_dir, test_name) 453*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(benchmark_dir): 454*8975f5c5SAndroid Build Coastguard Worker os.makedirs(benchmark_dir) 455*8975f5c5SAndroid Build Coastguard Worker shutil.copyfile(perf_results, 456*8975f5c5SAndroid Build Coastguard Worker os.path.join(benchmark_dir, 'perf_results.json')) 457*8975f5c5SAndroid Build Coastguard Worker # process_perf_results.py expects a test_results.json file. 458*8975f5c5SAndroid Build Coastguard Worker test_results = {'valid': True, 'failures': []} 459*8975f5c5SAndroid Build Coastguard Worker with open(os.path.join(benchmark_dir, 'test_results.json'), 'w') as out: 460*8975f5c5SAndroid Build Coastguard Worker json.dump(test_results, out) 461*8975f5c5SAndroid Build Coastguard Worker 462*8975f5c5SAndroid Build Coastguard Worker 463*8975f5c5SAndroid Build Coastguard Workerclass GTestTest(RemoteTest): 464*8975f5c5SAndroid Build Coastguard Worker 465*8975f5c5SAndroid Build Coastguard Worker # The following list corresponds to paths that should not be copied over to 466*8975f5c5SAndroid Build Coastguard Worker # the device during tests. In other words, these files are only ever used on 467*8975f5c5SAndroid Build Coastguard Worker # the host. 468*8975f5c5SAndroid Build Coastguard Worker _FILE_IGNORELIST = [ 469*8975f5c5SAndroid Build Coastguard Worker re.compile(r'.*build/android.*'), 470*8975f5c5SAndroid Build Coastguard Worker re.compile(r'.*build/chromeos.*'), 471*8975f5c5SAndroid Build Coastguard Worker re.compile(r'.*build/cros_cache.*'), 472*8975f5c5SAndroid Build Coastguard Worker # The following matches anything under //testing/ that isn't under 473*8975f5c5SAndroid Build Coastguard Worker # //testing/buildbot/filters/. 474*8975f5c5SAndroid Build Coastguard Worker re.compile(r'.*testing/(?!buildbot/filters).*'), 475*8975f5c5SAndroid Build Coastguard Worker re.compile(r'.*third_party/chromite.*'), 476*8975f5c5SAndroid Build Coastguard Worker ] 477*8975f5c5SAndroid Build Coastguard Worker 478*8975f5c5SAndroid Build Coastguard Worker def __init__(self, args, unknown_args): 479*8975f5c5SAndroid Build Coastguard Worker super().__init__(args, unknown_args) 480*8975f5c5SAndroid Build Coastguard Worker 481*8975f5c5SAndroid Build Coastguard Worker self._test_cmd = ['vpython3'] + self._test_cmd 482*8975f5c5SAndroid Build Coastguard Worker if not args.clean: 483*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += ['--no-clean'] 484*8975f5c5SAndroid Build Coastguard Worker 485*8975f5c5SAndroid Build Coastguard Worker self._test_exe = args.test_exe 486*8975f5c5SAndroid Build Coastguard Worker self._runtime_deps_path = args.runtime_deps_path 487*8975f5c5SAndroid Build Coastguard Worker self._vpython_dir = args.vpython_dir 488*8975f5c5SAndroid Build Coastguard Worker 489*8975f5c5SAndroid Build Coastguard Worker self._on_device_script = None 490*8975f5c5SAndroid Build Coastguard Worker self._env_vars = args.env_var 491*8975f5c5SAndroid Build Coastguard Worker self._stop_ui = args.stop_ui 492*8975f5c5SAndroid Build Coastguard Worker self._as_root = args.as_root 493*8975f5c5SAndroid Build Coastguard Worker self._trace_dir = args.trace_dir 494*8975f5c5SAndroid Build Coastguard Worker self._run_test_sudo_helper = args.run_test_sudo_helper 495*8975f5c5SAndroid Build Coastguard Worker self._set_selinux_label = args.set_selinux_label 496*8975f5c5SAndroid Build Coastguard Worker self._use_deployed_dbus_configs = args.use_deployed_dbus_configs 497*8975f5c5SAndroid Build Coastguard Worker 498*8975f5c5SAndroid Build Coastguard Worker @property 499*8975f5c5SAndroid Build Coastguard Worker def suite_name(self): 500*8975f5c5SAndroid Build Coastguard Worker return self._test_exe 501*8975f5c5SAndroid Build Coastguard Worker 502*8975f5c5SAndroid Build Coastguard Worker def build_test_command(self): 503*8975f5c5SAndroid Build Coastguard Worker # To keep things easy for us, ensure both types of output locations are 504*8975f5c5SAndroid Build Coastguard Worker # the same. 505*8975f5c5SAndroid Build Coastguard Worker if self._test_launcher_summary_output and self._logs_dir: 506*8975f5c5SAndroid Build Coastguard Worker json_out_dir = os.path.dirname(self._test_launcher_summary_output) or '.' 507*8975f5c5SAndroid Build Coastguard Worker if os.path.abspath(json_out_dir) != os.path.abspath(self._logs_dir): 508*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError( 509*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-summary-output and --logs-dir must point to ' 510*8975f5c5SAndroid Build Coastguard Worker 'the same directory.') 511*8975f5c5SAndroid Build Coastguard Worker 512*8975f5c5SAndroid Build Coastguard Worker if self._test_launcher_summary_output: 513*8975f5c5SAndroid Build Coastguard Worker result_dir, result_file = os.path.split( 514*8975f5c5SAndroid Build Coastguard Worker self._test_launcher_summary_output) 515*8975f5c5SAndroid Build Coastguard Worker # If args.test_launcher_summary_output is a file in cwd, result_dir will 516*8975f5c5SAndroid Build Coastguard Worker # be an empty string, so replace it with '.' when this is the case so 517*8975f5c5SAndroid Build Coastguard Worker # cros_run_test can correctly handle it. 518*8975f5c5SAndroid Build Coastguard Worker if not result_dir: 519*8975f5c5SAndroid Build Coastguard Worker result_dir = '.' 520*8975f5c5SAndroid Build Coastguard Worker device_result_file = '/tmp/%s' % result_file 521*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 522*8975f5c5SAndroid Build Coastguard Worker '--results-src', 523*8975f5c5SAndroid Build Coastguard Worker device_result_file, 524*8975f5c5SAndroid Build Coastguard Worker '--results-dest-dir', 525*8975f5c5SAndroid Build Coastguard Worker result_dir, 526*8975f5c5SAndroid Build Coastguard Worker ] 527*8975f5c5SAndroid Build Coastguard Worker 528*8975f5c5SAndroid Build Coastguard Worker if self._trace_dir and self._logs_dir: 529*8975f5c5SAndroid Build Coastguard Worker trace_path = os.path.dirname(self._trace_dir) or '.' 530*8975f5c5SAndroid Build Coastguard Worker if os.path.abspath(trace_path) != os.path.abspath(self._logs_dir): 531*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError( 532*8975f5c5SAndroid Build Coastguard Worker '--trace-dir and --logs-dir must point to the same directory.') 533*8975f5c5SAndroid Build Coastguard Worker 534*8975f5c5SAndroid Build Coastguard Worker if self._trace_dir: 535*8975f5c5SAndroid Build Coastguard Worker trace_path, trace_dirname = os.path.split(self._trace_dir) 536*8975f5c5SAndroid Build Coastguard Worker device_trace_dir = '/tmp/%s' % trace_dirname 537*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 538*8975f5c5SAndroid Build Coastguard Worker '--results-src', 539*8975f5c5SAndroid Build Coastguard Worker device_trace_dir, 540*8975f5c5SAndroid Build Coastguard Worker '--results-dest-dir', 541*8975f5c5SAndroid Build Coastguard Worker trace_path, 542*8975f5c5SAndroid Build Coastguard Worker ] 543*8975f5c5SAndroid Build Coastguard Worker 544*8975f5c5SAndroid Build Coastguard Worker # Build the shell script that will be used on the device to invoke the test. 545*8975f5c5SAndroid Build Coastguard Worker # Stored here as a list of lines. 546*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents = self.BASIC_SHELL_SCRIPT[:] 547*8975f5c5SAndroid Build Coastguard Worker for var_name, var_val in self._env_vars: 548*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents += ['export %s=%s' % (var_name, var_val)] 549*8975f5c5SAndroid Build Coastguard Worker 550*8975f5c5SAndroid Build Coastguard Worker if self._vpython_dir: 551*8975f5c5SAndroid Build Coastguard Worker vpython_path = os.path.join(self._path_to_outdir, self._vpython_dir, 552*8975f5c5SAndroid Build Coastguard Worker 'vpython3') 553*8975f5c5SAndroid Build Coastguard Worker cpython_path = os.path.join(self._path_to_outdir, self._vpython_dir, 554*8975f5c5SAndroid Build Coastguard Worker 'bin', 'python3') 555*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(vpython_path) or not os.path.exists(cpython_path): 556*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError( 557*8975f5c5SAndroid Build Coastguard Worker '--vpython-dir must point to a dir with both ' 558*8975f5c5SAndroid Build Coastguard Worker 'infra/3pp/tools/cpython3 and infra/tools/luci/vpython3 ' 559*8975f5c5SAndroid Build Coastguard Worker 'installed.') 560*8975f5c5SAndroid Build Coastguard Worker vpython_spec_path = os.path.relpath( 561*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMIUM_SRC_PATH, '.vpython3'), self._path_to_outdir) 562*8975f5c5SAndroid Build Coastguard Worker # Initialize the vpython cache. This can take 10-20s, and some tests 563*8975f5c5SAndroid Build Coastguard Worker # can't afford to wait that long on the first invocation. 564*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 565*8975f5c5SAndroid Build Coastguard Worker 'export PATH=$PWD/%s:$PWD/%s/bin/:$PATH' % 566*8975f5c5SAndroid Build Coastguard Worker (self._vpython_dir, self._vpython_dir), 567*8975f5c5SAndroid Build Coastguard Worker 'vpython3 -vpython-spec %s -vpython-tool install' % 568*8975f5c5SAndroid Build Coastguard Worker (vpython_spec_path), 569*8975f5c5SAndroid Build Coastguard Worker ]) 570*8975f5c5SAndroid Build Coastguard Worker 571*8975f5c5SAndroid Build Coastguard Worker test_invocation = ('LD_LIBRARY_PATH=./ ./%s --test-launcher-shard-index=%d ' 572*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-total-shards=%d' % 573*8975f5c5SAndroid Build Coastguard Worker (self._test_exe, self._test_launcher_shard_index, 574*8975f5c5SAndroid Build Coastguard Worker self._test_launcher_total_shards)) 575*8975f5c5SAndroid Build Coastguard Worker if self._test_launcher_summary_output: 576*8975f5c5SAndroid Build Coastguard Worker test_invocation += ' --test-launcher-summary-output=%s' % ( 577*8975f5c5SAndroid Build Coastguard Worker device_result_file) 578*8975f5c5SAndroid Build Coastguard Worker 579*8975f5c5SAndroid Build Coastguard Worker if self._trace_dir: 580*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 581*8975f5c5SAndroid Build Coastguard Worker 'rm -rf %s' % device_trace_dir, 582*8975f5c5SAndroid Build Coastguard Worker 'sudo -E -u chronos -- /bin/bash -c "mkdir -p %s"' % device_trace_dir, 583*8975f5c5SAndroid Build Coastguard Worker ]) 584*8975f5c5SAndroid Build Coastguard Worker test_invocation += ' --trace-dir=%s' % device_trace_dir 585*8975f5c5SAndroid Build Coastguard Worker 586*8975f5c5SAndroid Build Coastguard Worker if self._run_test_sudo_helper: 587*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 588*8975f5c5SAndroid Build Coastguard Worker 'TEST_SUDO_HELPER_PATH=$(mktemp)', 589*8975f5c5SAndroid Build Coastguard Worker './test_sudo_helper.py --socket-path=${TEST_SUDO_HELPER_PATH} &', 590*8975f5c5SAndroid Build Coastguard Worker 'TEST_SUDO_HELPER_PID=$!' 591*8975f5c5SAndroid Build Coastguard Worker ]) 592*8975f5c5SAndroid Build Coastguard Worker test_invocation += ( 593*8975f5c5SAndroid Build Coastguard Worker ' --test-sudo-helper-socket-path=${TEST_SUDO_HELPER_PATH}') 594*8975f5c5SAndroid Build Coastguard Worker 595*8975f5c5SAndroid Build Coastguard Worker # Append the selinux labels. The 'setfiles' command takes a file with each 596*8975f5c5SAndroid Build Coastguard Worker # line consisting of "<file-regex> <file-type> <new-label>", where '--' is 597*8975f5c5SAndroid Build Coastguard Worker # the type of a regular file. 598*8975f5c5SAndroid Build Coastguard Worker if self._set_selinux_label: 599*8975f5c5SAndroid Build Coastguard Worker for label_pair in self._set_selinux_label: 600*8975f5c5SAndroid Build Coastguard Worker filename, label = label_pair.split('=', 1) 601*8975f5c5SAndroid Build Coastguard Worker specfile = filename + '.specfile' 602*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 603*8975f5c5SAndroid Build Coastguard Worker 'echo %s -- %s > %s' % (filename, label, specfile), 604*8975f5c5SAndroid Build Coastguard Worker 'setfiles -F %s %s' % (specfile, filename), 605*8975f5c5SAndroid Build Coastguard Worker ]) 606*8975f5c5SAndroid Build Coastguard Worker 607*8975f5c5SAndroid Build Coastguard Worker # Mount the deploy dbus config dir on top of chrome's dbus dir. Send SIGHUP 608*8975f5c5SAndroid Build Coastguard Worker # to dbus daemon to reload config from the newly mounted dir. 609*8975f5c5SAndroid Build Coastguard Worker if self._use_deployed_dbus_configs: 610*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 611*8975f5c5SAndroid Build Coastguard Worker 'mount --bind ./dbus /opt/google/chrome/dbus', 612*8975f5c5SAndroid Build Coastguard Worker 'kill -s HUP $(pgrep dbus)', 613*8975f5c5SAndroid Build Coastguard Worker ]) 614*8975f5c5SAndroid Build Coastguard Worker 615*8975f5c5SAndroid Build Coastguard Worker if self._additional_args: 616*8975f5c5SAndroid Build Coastguard Worker test_invocation += ' %s' % ' '.join(self._additional_args) 617*8975f5c5SAndroid Build Coastguard Worker 618*8975f5c5SAndroid Build Coastguard Worker if self._stop_ui: 619*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents += [ 620*8975f5c5SAndroid Build Coastguard Worker 'stop ui', 621*8975f5c5SAndroid Build Coastguard Worker ] 622*8975f5c5SAndroid Build Coastguard Worker # Send a user activity ping to powerd to ensure the display is on. 623*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents += [ 624*8975f5c5SAndroid Build Coastguard Worker 'dbus-send --system --type=method_call' 625*8975f5c5SAndroid Build Coastguard Worker ' --dest=org.chromium.PowerManager /org/chromium/PowerManager' 626*8975f5c5SAndroid Build Coastguard Worker ' org.chromium.PowerManager.HandleUserActivity int32:0' 627*8975f5c5SAndroid Build Coastguard Worker ] 628*8975f5c5SAndroid Build Coastguard Worker # The UI service on the device owns the chronos user session, so shutting 629*8975f5c5SAndroid Build Coastguard Worker # it down as chronos kills the entire execution of the test. So we'll have 630*8975f5c5SAndroid Build Coastguard Worker # to run as root up until the test invocation. 631*8975f5c5SAndroid Build Coastguard Worker test_invocation = ( 632*8975f5c5SAndroid Build Coastguard Worker 'sudo -E -u chronos -- /bin/bash -c "%s"' % test_invocation) 633*8975f5c5SAndroid Build Coastguard Worker # And we'll need to chown everything since cros_run_test's "--as-chronos" 634*8975f5c5SAndroid Build Coastguard Worker # option normally does that for us. 635*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.append('chown -R chronos: ../..') 636*8975f5c5SAndroid Build Coastguard Worker elif not self._as_root: 637*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 638*8975f5c5SAndroid Build Coastguard Worker # Some tests fail as root, so run as the less privileged user 639*8975f5c5SAndroid Build Coastguard Worker # 'chronos'. 640*8975f5c5SAndroid Build Coastguard Worker '--as-chronos', 641*8975f5c5SAndroid Build Coastguard Worker ] 642*8975f5c5SAndroid Build Coastguard Worker 643*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.append(test_invocation) 644*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.append('TEST_RETURN_CODE=$?') 645*8975f5c5SAndroid Build Coastguard Worker 646*8975f5c5SAndroid Build Coastguard Worker # (Re)start ui after all tests are done. This is for developer convenienve. 647*8975f5c5SAndroid Build Coastguard Worker # Without this, the device would remain in a black screen which looks like 648*8975f5c5SAndroid Build Coastguard Worker # powered off. 649*8975f5c5SAndroid Build Coastguard Worker if self._stop_ui: 650*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents += [ 651*8975f5c5SAndroid Build Coastguard Worker 'start ui', 652*8975f5c5SAndroid Build Coastguard Worker ] 653*8975f5c5SAndroid Build Coastguard Worker 654*8975f5c5SAndroid Build Coastguard Worker # Stop the crosier helper. 655*8975f5c5SAndroid Build Coastguard Worker if self._run_test_sudo_helper: 656*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 657*8975f5c5SAndroid Build Coastguard Worker 'pkill -P $TEST_SUDO_HELPER_PID', 658*8975f5c5SAndroid Build Coastguard Worker 'kill $TEST_SUDO_HELPER_PID', 659*8975f5c5SAndroid Build Coastguard Worker 'unlink ${TEST_SUDO_HELPER_PATH}', 660*8975f5c5SAndroid Build Coastguard Worker ]) 661*8975f5c5SAndroid Build Coastguard Worker 662*8975f5c5SAndroid Build Coastguard Worker # Undo the dbus config mount and reload dbus config. 663*8975f5c5SAndroid Build Coastguard Worker if self._use_deployed_dbus_configs: 664*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.extend([ 665*8975f5c5SAndroid Build Coastguard Worker 'umount /opt/google/chrome/dbus', 666*8975f5c5SAndroid Build Coastguard Worker 'kill -s HUP $(pgrep dbus)', 667*8975f5c5SAndroid Build Coastguard Worker ]) 668*8975f5c5SAndroid Build Coastguard Worker 669*8975f5c5SAndroid Build Coastguard Worker # This command should always be the last bash commandline so infra can 670*8975f5c5SAndroid Build Coastguard Worker # correctly get the error code from test invocations. 671*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents.append('exit $TEST_RETURN_CODE') 672*8975f5c5SAndroid Build Coastguard Worker 673*8975f5c5SAndroid Build Coastguard Worker self._on_device_script = self.write_test_script_to_disk( 674*8975f5c5SAndroid Build Coastguard Worker device_test_script_contents) 675*8975f5c5SAndroid Build Coastguard Worker 676*8975f5c5SAndroid Build Coastguard Worker runtime_files = [os.path.relpath(self._on_device_script)] 677*8975f5c5SAndroid Build Coastguard Worker runtime_files += self._read_runtime_files() 678*8975f5c5SAndroid Build Coastguard Worker if self._vpython_dir: 679*8975f5c5SAndroid Build Coastguard Worker # --vpython-dir is relative to the out dir, but --files-from expects paths 680*8975f5c5SAndroid Build Coastguard Worker # relative to src dir, so fix the path up a bit. 681*8975f5c5SAndroid Build Coastguard Worker runtime_files.append( 682*8975f5c5SAndroid Build Coastguard Worker os.path.relpath( 683*8975f5c5SAndroid Build Coastguard Worker os.path.abspath( 684*8975f5c5SAndroid Build Coastguard Worker os.path.join(self._path_to_outdir, self._vpython_dir)), 685*8975f5c5SAndroid Build Coastguard Worker CHROMIUM_SRC_PATH)) 686*8975f5c5SAndroid Build Coastguard Worker 687*8975f5c5SAndroid Build Coastguard Worker self._test_cmd.extend( 688*8975f5c5SAndroid Build Coastguard Worker ['--files-from', 689*8975f5c5SAndroid Build Coastguard Worker self.write_runtime_files_to_disk(runtime_files)]) 690*8975f5c5SAndroid Build Coastguard Worker 691*8975f5c5SAndroid Build Coastguard Worker self._test_cmd += [ 692*8975f5c5SAndroid Build Coastguard Worker '--', 693*8975f5c5SAndroid Build Coastguard Worker './' + os.path.relpath(self._on_device_script, self._path_to_outdir) 694*8975f5c5SAndroid Build Coastguard Worker ] 695*8975f5c5SAndroid Build Coastguard Worker 696*8975f5c5SAndroid Build Coastguard Worker def _read_runtime_files(self): 697*8975f5c5SAndroid Build Coastguard Worker if not self._runtime_deps_path: 698*8975f5c5SAndroid Build Coastguard Worker return [] 699*8975f5c5SAndroid Build Coastguard Worker 700*8975f5c5SAndroid Build Coastguard Worker abs_runtime_deps_path = os.path.abspath( 701*8975f5c5SAndroid Build Coastguard Worker os.path.join(self._path_to_outdir, self._runtime_deps_path)) 702*8975f5c5SAndroid Build Coastguard Worker with open(abs_runtime_deps_path) as runtime_deps_file: 703*8975f5c5SAndroid Build Coastguard Worker files = [l.strip() for l in runtime_deps_file if l] 704*8975f5c5SAndroid Build Coastguard Worker rel_file_paths = [] 705*8975f5c5SAndroid Build Coastguard Worker for f in files: 706*8975f5c5SAndroid Build Coastguard Worker rel_file_path = os.path.relpath( 707*8975f5c5SAndroid Build Coastguard Worker os.path.abspath(os.path.join(self._path_to_outdir, f))) 708*8975f5c5SAndroid Build Coastguard Worker if not any(regex.match(rel_file_path) for regex in self._FILE_IGNORELIST): 709*8975f5c5SAndroid Build Coastguard Worker rel_file_paths.append(rel_file_path) 710*8975f5c5SAndroid Build Coastguard Worker return rel_file_paths 711*8975f5c5SAndroid Build Coastguard Worker 712*8975f5c5SAndroid Build Coastguard Worker def post_run(self, _): 713*8975f5c5SAndroid Build Coastguard Worker if self._on_device_script: 714*8975f5c5SAndroid Build Coastguard Worker os.remove(self._on_device_script) 715*8975f5c5SAndroid Build Coastguard Worker 716*8975f5c5SAndroid Build Coastguard Worker if self._test_launcher_summary_output and self._rdb_client: 717*8975f5c5SAndroid Build Coastguard Worker logging.error('Native ResultDB integration is not supported for GTests. ' 718*8975f5c5SAndroid Build Coastguard Worker 'Upload results via result_adapter instead. ' 719*8975f5c5SAndroid Build Coastguard Worker 'See crbug.com/1330441.') 720*8975f5c5SAndroid Build Coastguard Worker 721*8975f5c5SAndroid Build Coastguard Worker 722*8975f5c5SAndroid Build Coastguard Workerdef device_test(args, unknown_args): 723*8975f5c5SAndroid Build Coastguard Worker # cros_run_test has trouble with relative paths that go up directories, 724*8975f5c5SAndroid Build Coastguard Worker # so cd to src/, which should be the root of all data deps. 725*8975f5c5SAndroid Build Coastguard Worker os.chdir(CHROMIUM_SRC_PATH) 726*8975f5c5SAndroid Build Coastguard Worker 727*8975f5c5SAndroid Build Coastguard Worker # TODO: Remove the above when depot_tool's pylint is updated to include the 728*8975f5c5SAndroid Build Coastguard Worker # fix to https://github.com/PyCQA/pylint/issues/710. 729*8975f5c5SAndroid Build Coastguard Worker if args.test_type == 'tast': 730*8975f5c5SAndroid Build Coastguard Worker test = TastTest(args, unknown_args) 731*8975f5c5SAndroid Build Coastguard Worker else: 732*8975f5c5SAndroid Build Coastguard Worker test = GTestTest(args, unknown_args) 733*8975f5c5SAndroid Build Coastguard Worker 734*8975f5c5SAndroid Build Coastguard Worker test.build_test_command() 735*8975f5c5SAndroid Build Coastguard Worker logging.info('Running the following command on the device:') 736*8975f5c5SAndroid Build Coastguard Worker logging.info(' '.join(test.test_cmd)) 737*8975f5c5SAndroid Build Coastguard Worker 738*8975f5c5SAndroid Build Coastguard Worker return test.run_test() 739*8975f5c5SAndroid Build Coastguard Worker 740*8975f5c5SAndroid Build Coastguard Worker 741*8975f5c5SAndroid Build Coastguard Workerdef host_cmd(args, cmd_args): 742*8975f5c5SAndroid Build Coastguard Worker if not cmd_args: 743*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError('Must specify command to run on the host.') 744*8975f5c5SAndroid Build Coastguard Worker if args.deploy_chrome and not args.path_to_outdir: 745*8975f5c5SAndroid Build Coastguard Worker raise TestFormatError( 746*8975f5c5SAndroid Build Coastguard Worker '--path-to-outdir must be specified if --deploy-chrome is passed.') 747*8975f5c5SAndroid Build Coastguard Worker 748*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd = [ 749*8975f5c5SAndroid Build Coastguard Worker CROS_RUN_TEST_PATH, 750*8975f5c5SAndroid Build Coastguard Worker '--board', 751*8975f5c5SAndroid Build Coastguard Worker args.board, 752*8975f5c5SAndroid Build Coastguard Worker '--cache-dir', 753*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMIUM_SRC_PATH, args.cros_cache), 754*8975f5c5SAndroid Build Coastguard Worker ] 755*8975f5c5SAndroid Build Coastguard Worker if args.use_vm: 756*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += [ 757*8975f5c5SAndroid Build Coastguard Worker '--start', 758*8975f5c5SAndroid Build Coastguard Worker # Don't persist any filesystem changes after the VM shutsdown. 759*8975f5c5SAndroid Build Coastguard Worker '--copy-on-write', 760*8975f5c5SAndroid Build Coastguard Worker ] 761*8975f5c5SAndroid Build Coastguard Worker else: 762*8975f5c5SAndroid Build Coastguard Worker if args.fetch_cros_hostname: 763*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += ['--device', get_cros_hostname()] 764*8975f5c5SAndroid Build Coastguard Worker else: 765*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += [ 766*8975f5c5SAndroid Build Coastguard Worker '--device', args.device if args.device else LAB_DUT_HOSTNAME 767*8975f5c5SAndroid Build Coastguard Worker ] 768*8975f5c5SAndroid Build Coastguard Worker if args.verbose: 769*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd.append('--debug') 770*8975f5c5SAndroid Build Coastguard Worker if args.flash: 771*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd.append('--flash') 772*8975f5c5SAndroid Build Coastguard Worker if args.public_image: 773*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += ['--public-image'] 774*8975f5c5SAndroid Build Coastguard Worker 775*8975f5c5SAndroid Build Coastguard Worker if args.logs_dir: 776*8975f5c5SAndroid Build Coastguard Worker for log in SYSTEM_LOG_LOCATIONS: 777*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += ['--results-src', log] 778*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += [ 779*8975f5c5SAndroid Build Coastguard Worker '--results-dest-dir', 780*8975f5c5SAndroid Build Coastguard Worker os.path.join(args.logs_dir, 'system_logs') 781*8975f5c5SAndroid Build Coastguard Worker ] 782*8975f5c5SAndroid Build Coastguard Worker 783*8975f5c5SAndroid Build Coastguard Worker test_env = setup_env() 784*8975f5c5SAndroid Build Coastguard Worker if args.deploy_chrome: 785*8975f5c5SAndroid Build Coastguard Worker # Mounting ash-chrome gives it enough disk space to not need stripping 786*8975f5c5SAndroid Build Coastguard Worker # most of the time. 787*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd.extend(['--deploy', '--mount']) 788*8975f5c5SAndroid Build Coastguard Worker 789*8975f5c5SAndroid Build Coastguard Worker if not args.strip_chrome: 790*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd.append('--nostrip') 791*8975f5c5SAndroid Build Coastguard Worker 792*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += [ 793*8975f5c5SAndroid Build Coastguard Worker '--build-dir', 794*8975f5c5SAndroid Build Coastguard Worker os.path.join(CHROMIUM_SRC_PATH, args.path_to_outdir) 795*8975f5c5SAndroid Build Coastguard Worker ] 796*8975f5c5SAndroid Build Coastguard Worker 797*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd += [ 798*8975f5c5SAndroid Build Coastguard Worker '--host-cmd', 799*8975f5c5SAndroid Build Coastguard Worker '--', 800*8975f5c5SAndroid Build Coastguard Worker ] + cmd_args 801*8975f5c5SAndroid Build Coastguard Worker 802*8975f5c5SAndroid Build Coastguard Worker logging.info('Running the following command:') 803*8975f5c5SAndroid Build Coastguard Worker logging.info(' '.join(cros_run_test_cmd)) 804*8975f5c5SAndroid Build Coastguard Worker 805*8975f5c5SAndroid Build Coastguard Worker return subprocess.call( 806*8975f5c5SAndroid Build Coastguard Worker cros_run_test_cmd, stdout=sys.stdout, stderr=sys.stderr, env=test_env) 807*8975f5c5SAndroid Build Coastguard Worker 808*8975f5c5SAndroid Build Coastguard Worker 809*8975f5c5SAndroid Build Coastguard Workerdef get_cros_hostname_from_bot_id(bot_id): 810*8975f5c5SAndroid Build Coastguard Worker """Parse hostname from a chromeos-swarming bot id.""" 811*8975f5c5SAndroid Build Coastguard Worker for prefix in ['cros-', 'crossk-']: 812*8975f5c5SAndroid Build Coastguard Worker if bot_id.startswith(prefix): 813*8975f5c5SAndroid Build Coastguard Worker return bot_id[len(prefix):] 814*8975f5c5SAndroid Build Coastguard Worker return bot_id 815*8975f5c5SAndroid Build Coastguard Worker 816*8975f5c5SAndroid Build Coastguard Worker 817*8975f5c5SAndroid Build Coastguard Workerdef get_cros_hostname(): 818*8975f5c5SAndroid Build Coastguard Worker """Fetch bot_id from env var and parse hostname.""" 819*8975f5c5SAndroid Build Coastguard Worker 820*8975f5c5SAndroid Build Coastguard Worker # In chromeos-swarming, we can extract hostname from bot ID, since 821*8975f5c5SAndroid Build Coastguard Worker # bot ID is formatted as "{prefix}{hostname}". 822*8975f5c5SAndroid Build Coastguard Worker bot_id = os.environ.get('SWARMING_BOT_ID') 823*8975f5c5SAndroid Build Coastguard Worker if bot_id: 824*8975f5c5SAndroid Build Coastguard Worker return get_cros_hostname_from_bot_id(bot_id) 825*8975f5c5SAndroid Build Coastguard Worker 826*8975f5c5SAndroid Build Coastguard Worker logging.warning( 827*8975f5c5SAndroid Build Coastguard Worker 'Attempted to read from SWARMING_BOT_ID env var and it was' 828*8975f5c5SAndroid Build Coastguard Worker ' not defined. Will set %s as device instead.', LAB_DUT_HOSTNAME) 829*8975f5c5SAndroid Build Coastguard Worker return LAB_DUT_HOSTNAME 830*8975f5c5SAndroid Build Coastguard Worker 831*8975f5c5SAndroid Build Coastguard Worker 832*8975f5c5SAndroid Build Coastguard Workerdef setup_env(): 833*8975f5c5SAndroid Build Coastguard Worker """Returns a copy of the current env with some needed vars added.""" 834*8975f5c5SAndroid Build Coastguard Worker env = os.environ.copy() 835*8975f5c5SAndroid Build Coastguard Worker # Some chromite scripts expect chromite/bin to be on PATH. 836*8975f5c5SAndroid Build Coastguard Worker env['PATH'] = env['PATH'] + ':' + os.path.join(CHROMITE_PATH, 'bin') 837*8975f5c5SAndroid Build Coastguard Worker # deploy_chrome needs a set of GN args used to build chrome to determine if 838*8975f5c5SAndroid Build Coastguard Worker # certain libraries need to be pushed to the device. It looks for the args via 839*8975f5c5SAndroid Build Coastguard Worker # an env var. To trigger the default deploying behavior, give it a dummy set 840*8975f5c5SAndroid Build Coastguard Worker # of args. 841*8975f5c5SAndroid Build Coastguard Worker # TODO(crbug.com/40567963): Make the GN-dependent deps controllable via cmd 842*8975f5c5SAndroid Build Coastguard Worker # line args. 843*8975f5c5SAndroid Build Coastguard Worker if not env.get('GN_ARGS'): 844*8975f5c5SAndroid Build Coastguard Worker env['GN_ARGS'] = 'enable_nacl = true' 845*8975f5c5SAndroid Build Coastguard Worker if not env.get('USE'): 846*8975f5c5SAndroid Build Coastguard Worker env['USE'] = 'highdpi' 847*8975f5c5SAndroid Build Coastguard Worker return env 848*8975f5c5SAndroid Build Coastguard Worker 849*8975f5c5SAndroid Build Coastguard Worker 850*8975f5c5SAndroid Build Coastguard Workerdef add_common_args(*parsers): 851*8975f5c5SAndroid Build Coastguard Worker for parser in parsers: 852*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--verbose', '-v', action='store_true') 853*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 854*8975f5c5SAndroid Build Coastguard Worker '--board', type=str, required=True, help='Type of CrOS device.') 855*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 856*8975f5c5SAndroid Build Coastguard Worker '--deploy-chrome', 857*8975f5c5SAndroid Build Coastguard Worker action='store_true', 858*8975f5c5SAndroid Build Coastguard Worker help='Will deploy a locally built ash-chrome binary to the device ' 859*8975f5c5SAndroid Build Coastguard Worker 'before running the host-cmd.') 860*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 861*8975f5c5SAndroid Build Coastguard Worker '--cros-cache', 862*8975f5c5SAndroid Build Coastguard Worker type=str, 863*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_CROS_CACHE, 864*8975f5c5SAndroid Build Coastguard Worker help='Path to cros cache.') 865*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 866*8975f5c5SAndroid Build Coastguard Worker '--path-to-outdir', 867*8975f5c5SAndroid Build Coastguard Worker type=str, 868*8975f5c5SAndroid Build Coastguard Worker required=True, 869*8975f5c5SAndroid Build Coastguard Worker help='Path to output directory, all of whose contents will be ' 870*8975f5c5SAndroid Build Coastguard Worker 'deployed to the device.') 871*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 872*8975f5c5SAndroid Build Coastguard Worker '--runtime-deps-path', 873*8975f5c5SAndroid Build Coastguard Worker type=str, 874*8975f5c5SAndroid Build Coastguard Worker help='Runtime data dependency file from GN.') 875*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 876*8975f5c5SAndroid Build Coastguard Worker '--vpython-dir', 877*8975f5c5SAndroid Build Coastguard Worker type=str, 878*8975f5c5SAndroid Build Coastguard Worker help='Location on host of a directory containing a vpython binary to ' 879*8975f5c5SAndroid Build Coastguard Worker 'deploy to the device before the test starts. The location of ' 880*8975f5c5SAndroid Build Coastguard Worker 'this dir will be added onto PATH in the device. WARNING: The ' 881*8975f5c5SAndroid Build Coastguard Worker 'arch of the device might not match the arch of the host, so ' 882*8975f5c5SAndroid Build Coastguard Worker 'avoid using "${platform}" when downloading vpython via CIPD.') 883*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 884*8975f5c5SAndroid Build Coastguard Worker '--logs-dir', 885*8975f5c5SAndroid Build Coastguard Worker type=str, 886*8975f5c5SAndroid Build Coastguard Worker dest='logs_dir', 887*8975f5c5SAndroid Build Coastguard Worker help='Will copy everything under /var/log/ from the device after the ' 888*8975f5c5SAndroid Build Coastguard Worker 'test into the specified dir.') 889*8975f5c5SAndroid Build Coastguard Worker # Shard args are parsed here since we might also specify them via env vars. 890*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 891*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-shard-index', 892*8975f5c5SAndroid Build Coastguard Worker type=int, 893*8975f5c5SAndroid Build Coastguard Worker default=os.environ.get('GTEST_SHARD_INDEX', 0), 894*8975f5c5SAndroid Build Coastguard Worker help='Index of the external shard to run.') 895*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 896*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-total-shards', 897*8975f5c5SAndroid Build Coastguard Worker type=int, 898*8975f5c5SAndroid Build Coastguard Worker default=os.environ.get('GTEST_TOTAL_SHARDS', 1), 899*8975f5c5SAndroid Build Coastguard Worker help='Total number of external shards.') 900*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 901*8975f5c5SAndroid Build Coastguard Worker '--flash', 902*8975f5c5SAndroid Build Coastguard Worker action='store_true', 903*8975f5c5SAndroid Build Coastguard Worker help='Will flash the device to the current SDK version before running ' 904*8975f5c5SAndroid Build Coastguard Worker 'the test.') 905*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 906*8975f5c5SAndroid Build Coastguard Worker '--no-flash', 907*8975f5c5SAndroid Build Coastguard Worker action='store_false', 908*8975f5c5SAndroid Build Coastguard Worker dest='flash', 909*8975f5c5SAndroid Build Coastguard Worker help='Will not flash the device before running the test.') 910*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 911*8975f5c5SAndroid Build Coastguard Worker '--public-image', 912*8975f5c5SAndroid Build Coastguard Worker action='store_true', 913*8975f5c5SAndroid Build Coastguard Worker help='Will flash a public "full" image to the device.') 914*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 915*8975f5c5SAndroid Build Coastguard Worker '--magic-vm-cache', 916*8975f5c5SAndroid Build Coastguard Worker help='Path to the magic CrOS VM cache dir. See the comment above ' 917*8975f5c5SAndroid Build Coastguard Worker '"magic_cros_vm_cache" in mixins.pyl for more info.') 918*8975f5c5SAndroid Build Coastguard Worker 919*8975f5c5SAndroid Build Coastguard Worker vm_or_device_group = parser.add_mutually_exclusive_group() 920*8975f5c5SAndroid Build Coastguard Worker vm_or_device_group.add_argument( 921*8975f5c5SAndroid Build Coastguard Worker '--use-vm', 922*8975f5c5SAndroid Build Coastguard Worker action='store_true', 923*8975f5c5SAndroid Build Coastguard Worker help='Will run the test in the VM instead of a device.') 924*8975f5c5SAndroid Build Coastguard Worker vm_or_device_group.add_argument( 925*8975f5c5SAndroid Build Coastguard Worker '--device', 926*8975f5c5SAndroid Build Coastguard Worker type=str, 927*8975f5c5SAndroid Build Coastguard Worker help='Hostname (or IP) of device to run the test on. This arg is not ' 928*8975f5c5SAndroid Build Coastguard Worker 'required if --use-vm is set.') 929*8975f5c5SAndroid Build Coastguard Worker vm_or_device_group.add_argument( 930*8975f5c5SAndroid Build Coastguard Worker '--fetch-cros-hostname', 931*8975f5c5SAndroid Build Coastguard Worker action='store_true', 932*8975f5c5SAndroid Build Coastguard Worker help='Will extract device hostname from the SWARMING_BOT_ID env var if ' 933*8975f5c5SAndroid Build Coastguard Worker 'running on ChromeOS Swarming.') 934*8975f5c5SAndroid Build Coastguard Worker 935*8975f5c5SAndroid Build Coastguard Workerdef main(): 936*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 937*8975f5c5SAndroid Build Coastguard Worker subparsers = parser.add_subparsers(dest='test_type') 938*8975f5c5SAndroid Build Coastguard Worker # Host-side test args. 939*8975f5c5SAndroid Build Coastguard Worker host_cmd_parser = subparsers.add_parser( 940*8975f5c5SAndroid Build Coastguard Worker 'host-cmd', 941*8975f5c5SAndroid Build Coastguard Worker help='Runs a host-side test. Pass the host-side command to run after ' 942*8975f5c5SAndroid Build Coastguard Worker '"--". If --use-vm is passed, hostname and port for the device ' 943*8975f5c5SAndroid Build Coastguard Worker 'will be 127.0.0.1:9222.') 944*8975f5c5SAndroid Build Coastguard Worker host_cmd_parser.set_defaults(func=host_cmd) 945*8975f5c5SAndroid Build Coastguard Worker host_cmd_parser.add_argument( 946*8975f5c5SAndroid Build Coastguard Worker '--strip-chrome', 947*8975f5c5SAndroid Build Coastguard Worker action='store_true', 948*8975f5c5SAndroid Build Coastguard Worker help='Strips symbols from ash-chrome before deploying to the device.') 949*8975f5c5SAndroid Build Coastguard Worker 950*8975f5c5SAndroid Build Coastguard Worker gtest_parser = subparsers.add_parser( 951*8975f5c5SAndroid Build Coastguard Worker 'gtest', help='Runs a device-side gtest.') 952*8975f5c5SAndroid Build Coastguard Worker gtest_parser.set_defaults(func=device_test) 953*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 954*8975f5c5SAndroid Build Coastguard Worker '--test-exe', 955*8975f5c5SAndroid Build Coastguard Worker type=str, 956*8975f5c5SAndroid Build Coastguard Worker required=True, 957*8975f5c5SAndroid Build Coastguard Worker help='Path to test executable to run inside the device.') 958*8975f5c5SAndroid Build Coastguard Worker 959*8975f5c5SAndroid Build Coastguard Worker # GTest args. Some are passed down to the test binary in the device. Others 960*8975f5c5SAndroid Build Coastguard Worker # are parsed here since they might need tweaking or special handling. 961*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 962*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-summary-output', 963*8975f5c5SAndroid Build Coastguard Worker type=str, 964*8975f5c5SAndroid Build Coastguard Worker help='When set, will pass the same option down to the test and retrieve ' 965*8975f5c5SAndroid Build Coastguard Worker 'its result file at the specified location.') 966*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 967*8975f5c5SAndroid Build Coastguard Worker '--stop-ui', 968*8975f5c5SAndroid Build Coastguard Worker action='store_true', 969*8975f5c5SAndroid Build Coastguard Worker help='Will stop the UI service in the device before running the test. ' 970*8975f5c5SAndroid Build Coastguard Worker 'Also start the UI service after all tests are done.') 971*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 972*8975f5c5SAndroid Build Coastguard Worker '--as-root', 973*8975f5c5SAndroid Build Coastguard Worker action='store_true', 974*8975f5c5SAndroid Build Coastguard Worker help='Will run the test as root on the device. Runs as user=chronos ' 975*8975f5c5SAndroid Build Coastguard Worker 'otherwise. This is mutually exclusive with "--stop-ui" above due to ' 976*8975f5c5SAndroid Build Coastguard Worker 'setup issues.') 977*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 978*8975f5c5SAndroid Build Coastguard Worker '--trace-dir', 979*8975f5c5SAndroid Build Coastguard Worker type=str, 980*8975f5c5SAndroid Build Coastguard Worker help='When set, will pass down to the test to generate the trace and ' 981*8975f5c5SAndroid Build Coastguard Worker 'retrieve the trace files to the specified location.') 982*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 983*8975f5c5SAndroid Build Coastguard Worker '--env-var', 984*8975f5c5SAndroid Build Coastguard Worker nargs=2, 985*8975f5c5SAndroid Build Coastguard Worker action='append', 986*8975f5c5SAndroid Build Coastguard Worker default=[], 987*8975f5c5SAndroid Build Coastguard Worker help='Env var to set on the device for the duration of the test. ' 988*8975f5c5SAndroid Build Coastguard Worker 'Expected format is "--env-var SOME_VAR_NAME some_var_value". Specify ' 989*8975f5c5SAndroid Build Coastguard Worker 'multiple times for more than one var.') 990*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 991*8975f5c5SAndroid Build Coastguard Worker '--run-test-sudo-helper', 992*8975f5c5SAndroid Build Coastguard Worker action='store_true', 993*8975f5c5SAndroid Build Coastguard Worker help='When set, will run test_sudo_helper before the test and stop it ' 994*8975f5c5SAndroid Build Coastguard Worker 'after test finishes.') 995*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 996*8975f5c5SAndroid Build Coastguard Worker "--no-clean", 997*8975f5c5SAndroid Build Coastguard Worker action="store_false", 998*8975f5c5SAndroid Build Coastguard Worker dest="clean", 999*8975f5c5SAndroid Build Coastguard Worker default=True, 1000*8975f5c5SAndroid Build Coastguard Worker help="Do not clean up the deployed files after running the test. " 1001*8975f5c5SAndroid Build Coastguard Worker "Only supported for --remote-cmd tests") 1002*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 1003*8975f5c5SAndroid Build Coastguard Worker '--set-selinux-label', 1004*8975f5c5SAndroid Build Coastguard Worker action='append', 1005*8975f5c5SAndroid Build Coastguard Worker default=[], 1006*8975f5c5SAndroid Build Coastguard Worker help='Set the selinux label for a file before running. The format is:\n' 1007*8975f5c5SAndroid Build Coastguard Worker ' --set-selinux-label=<filename>=<label>\n' 1008*8975f5c5SAndroid Build Coastguard Worker 'So:\n' 1009*8975f5c5SAndroid Build Coastguard Worker ' --set-selinux-label=my_test=u:r:cros_foo_label:s0\n' 1010*8975f5c5SAndroid Build Coastguard Worker 'You can specify it more than one time to set multiple files tags.') 1011*8975f5c5SAndroid Build Coastguard Worker gtest_parser.add_argument( 1012*8975f5c5SAndroid Build Coastguard Worker '--use-deployed-dbus-configs', 1013*8975f5c5SAndroid Build Coastguard Worker action='store_true', 1014*8975f5c5SAndroid Build Coastguard Worker help='When set, will bind mount deployed dbus config to chrome dbus dir ' 1015*8975f5c5SAndroid Build Coastguard Worker 'and ask dbus daemon to reload config before running tests.') 1016*8975f5c5SAndroid Build Coastguard Worker 1017*8975f5c5SAndroid Build Coastguard Worker # Tast test args. 1018*8975f5c5SAndroid Build Coastguard Worker # pylint: disable=line-too-long 1019*8975f5c5SAndroid Build Coastguard Worker tast_test_parser = subparsers.add_parser( 1020*8975f5c5SAndroid Build Coastguard Worker 'tast', 1021*8975f5c5SAndroid Build Coastguard Worker help='Runs a device-side set of Tast tests. For more details, see: ' 1022*8975f5c5SAndroid Build Coastguard Worker 'https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/running_tests.md' 1023*8975f5c5SAndroid Build Coastguard Worker ) 1024*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.set_defaults(func=device_test) 1025*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1026*8975f5c5SAndroid Build Coastguard Worker '--suite-name', 1027*8975f5c5SAndroid Build Coastguard Worker type=str, 1028*8975f5c5SAndroid Build Coastguard Worker required=True, 1029*8975f5c5SAndroid Build Coastguard Worker help='Name to apply to the set of Tast tests to run. This has no effect ' 1030*8975f5c5SAndroid Build Coastguard Worker 'on what is executed, but is used mainly for test results reporting ' 1031*8975f5c5SAndroid Build Coastguard Worker 'and tracking (eg: flakiness dashboard).') 1032*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1033*8975f5c5SAndroid Build Coastguard Worker '--test-launcher-summary-output', 1034*8975f5c5SAndroid Build Coastguard Worker type=str, 1035*8975f5c5SAndroid Build Coastguard Worker help='Generates a simple GTest-style JSON result file for the test run.') 1036*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1037*8975f5c5SAndroid Build Coastguard Worker '--attr-expr', 1038*8975f5c5SAndroid Build Coastguard Worker type=str, 1039*8975f5c5SAndroid Build Coastguard Worker help='A boolean expression whose matching tests will run ' 1040*8975f5c5SAndroid Build Coastguard Worker '(eg: ("dep:chrome")).') 1041*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1042*8975f5c5SAndroid Build Coastguard Worker '--strip-chrome', 1043*8975f5c5SAndroid Build Coastguard Worker action='store_true', 1044*8975f5c5SAndroid Build Coastguard Worker help='Strips symbols from ash-chrome before deploying to the device.') 1045*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1046*8975f5c5SAndroid Build Coastguard Worker '--tast-var', 1047*8975f5c5SAndroid Build Coastguard Worker action='append', 1048*8975f5c5SAndroid Build Coastguard Worker dest='tast_vars', 1049*8975f5c5SAndroid Build Coastguard Worker help='Runtime variables for Tast tests, and the format are expected to ' 1050*8975f5c5SAndroid Build Coastguard Worker 'be "key=value" pairs.') 1051*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1052*8975f5c5SAndroid Build Coastguard Worker '--tast-retries', 1053*8975f5c5SAndroid Build Coastguard Worker type=int, 1054*8975f5c5SAndroid Build Coastguard Worker dest='tast_retries', 1055*8975f5c5SAndroid Build Coastguard Worker help='Number of retries for failed Tast tests on the same DUT.') 1056*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1057*8975f5c5SAndroid Build Coastguard Worker '--test', 1058*8975f5c5SAndroid Build Coastguard Worker '-t', 1059*8975f5c5SAndroid Build Coastguard Worker action='append', 1060*8975f5c5SAndroid Build Coastguard Worker dest='tests', 1061*8975f5c5SAndroid Build Coastguard Worker help='A Tast test to run in the device (eg: "login.Chrome").') 1062*8975f5c5SAndroid Build Coastguard Worker tast_test_parser.add_argument( 1063*8975f5c5SAndroid Build Coastguard Worker '--gtest_filter', 1064*8975f5c5SAndroid Build Coastguard Worker type=str, 1065*8975f5c5SAndroid Build Coastguard Worker help="Similar to GTest's arg of the same name, this will filter out the " 1066*8975f5c5SAndroid Build Coastguard Worker "specified tests from the Tast run. However, due to the nature of Tast's " 1067*8975f5c5SAndroid Build Coastguard Worker 'cmd-line API, this will overwrite the value(s) of "--test" above.') 1068*8975f5c5SAndroid Build Coastguard Worker 1069*8975f5c5SAndroid Build Coastguard Worker add_common_args(gtest_parser, tast_test_parser, host_cmd_parser) 1070*8975f5c5SAndroid Build Coastguard Worker args, unknown_args = parser.parse_known_args() 1071*8975f5c5SAndroid Build Coastguard Worker 1072*8975f5c5SAndroid Build Coastguard Worker if args.test_type == 'gtest' and args.stop_ui and args.as_root: 1073*8975f5c5SAndroid Build Coastguard Worker parser.error('Unable to run gtests with both --stop-ui and --as-root') 1074*8975f5c5SAndroid Build Coastguard Worker 1075*8975f5c5SAndroid Build Coastguard Worker # Re-add N-1 -v/--verbose flags to the args we'll pass to whatever we are 1076*8975f5c5SAndroid Build Coastguard Worker # running. The assumption is that only one verbosity incrase would be meant 1077*8975f5c5SAndroid Build Coastguard Worker # for this script since it's a boolean value instead of increasing verbosity 1078*8975f5c5SAndroid Build Coastguard Worker # with more instances. 1079*8975f5c5SAndroid Build Coastguard Worker verbose_flags = [a for a in sys.argv if a in ('-v', '--verbose')] 1080*8975f5c5SAndroid Build Coastguard Worker if verbose_flags: 1081*8975f5c5SAndroid Build Coastguard Worker unknown_args += verbose_flags[1:] 1082*8975f5c5SAndroid Build Coastguard Worker 1083*8975f5c5SAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG if args.verbose else logging.WARN) 1084*8975f5c5SAndroid Build Coastguard Worker 1085*8975f5c5SAndroid Build Coastguard Worker if not args.use_vm and not args.device and not args.fetch_cros_hostname: 1086*8975f5c5SAndroid Build Coastguard Worker logging.warning( 1087*8975f5c5SAndroid Build Coastguard Worker 'The test runner is now assuming running in the lab environment, if ' 1088*8975f5c5SAndroid Build Coastguard Worker 'this is unintentional, please re-invoke the test runner with the ' 1089*8975f5c5SAndroid Build Coastguard Worker '"--use-vm" arg if using a VM, otherwise use the "--device=<DUT>" arg ' 1090*8975f5c5SAndroid Build Coastguard Worker 'to specify a DUT.') 1091*8975f5c5SAndroid Build Coastguard Worker 1092*8975f5c5SAndroid Build Coastguard Worker # If we're not running on a VM, but haven't specified a hostname, assume 1093*8975f5c5SAndroid Build Coastguard Worker # we're on a lab bot and are trying to run a test on a lab DUT. See if the 1094*8975f5c5SAndroid Build Coastguard Worker # magic lab DUT hostname resolves to anything. (It will in the lab and will 1095*8975f5c5SAndroid Build Coastguard Worker # not on dev machines.) 1096*8975f5c5SAndroid Build Coastguard Worker try: 1097*8975f5c5SAndroid Build Coastguard Worker socket.getaddrinfo(LAB_DUT_HOSTNAME, None) 1098*8975f5c5SAndroid Build Coastguard Worker except socket.gaierror: 1099*8975f5c5SAndroid Build Coastguard Worker logging.error('The default lab DUT hostname of %s is unreachable.', 1100*8975f5c5SAndroid Build Coastguard Worker LAB_DUT_HOSTNAME) 1101*8975f5c5SAndroid Build Coastguard Worker return 1 1102*8975f5c5SAndroid Build Coastguard Worker 1103*8975f5c5SAndroid Build Coastguard Worker if args.flash and args.public_image: 1104*8975f5c5SAndroid Build Coastguard Worker # The flashing tools depend on being unauthenticated with GS when flashing 1105*8975f5c5SAndroid Build Coastguard Worker # public images, so make sure the env var GS uses to locate its creds is 1106*8975f5c5SAndroid Build Coastguard Worker # unset in that case. 1107*8975f5c5SAndroid Build Coastguard Worker os.environ.pop('BOTO_CONFIG', None) 1108*8975f5c5SAndroid Build Coastguard Worker 1109*8975f5c5SAndroid Build Coastguard Worker if args.magic_vm_cache: 1110*8975f5c5SAndroid Build Coastguard Worker full_vm_cache_path = os.path.join(CHROMIUM_SRC_PATH, args.magic_vm_cache) 1111*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(full_vm_cache_path): 1112*8975f5c5SAndroid Build Coastguard Worker with open(os.path.join(full_vm_cache_path, 'swarming.txt'), 'w') as f: 1113*8975f5c5SAndroid Build Coastguard Worker f.write('non-empty file to make swarming persist this cache') 1114*8975f5c5SAndroid Build Coastguard Worker 1115*8975f5c5SAndroid Build Coastguard Worker return args.func(args, unknown_args) 1116*8975f5c5SAndroid Build Coastguard Worker 1117*8975f5c5SAndroid Build Coastguard Worker 1118*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 1119*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 1120