1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6777b538SAndroid Build Coastguard Worker# 3*6777b538SAndroid Build Coastguard Worker# Copyright 2020 The Chromium Authors 4*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 6*6777b538SAndroid Build Coastguard Worker"""This script facilitates running tests for lacros on Linux. 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker In order to run lacros tests on Linux, please first follow bit.ly/3juQVNJ 9*6777b538SAndroid Build Coastguard Worker to setup build directory with the lacros-chrome-on-linux build configuration, 10*6777b538SAndroid Build Coastguard Worker and corresponding test targets are built successfully. 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard WorkerExample usages 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker ./build/lacros/test_runner.py test out/lacros/url_unittests 15*6777b538SAndroid Build Coastguard Worker ./build/lacros/test_runner.py test out/lacros/browser_tests 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker The commands above run url_unittests and browser_tests respectively, and more 18*6777b538SAndroid Build Coastguard Worker specifically, url_unitests is executed directly while browser_tests is 19*6777b538SAndroid Build Coastguard Worker executed with the latest version of prebuilt ash-chrome, and the behavior is 20*6777b538SAndroid Build Coastguard Worker controlled by |_TARGETS_REQUIRE_ASH_CHROME|, and it's worth noting that the 21*6777b538SAndroid Build Coastguard Worker list is maintained manually, so if you see something is wrong, please upload a 22*6777b538SAndroid Build Coastguard Worker CL to fix it. 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker ./build/lacros/test_runner.py test out/lacros/browser_tests \\ 25*6777b538SAndroid Build Coastguard Worker --gtest_filter=BrowserTest.Title 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker The above command only runs 'BrowserTest.Title', and any argument accepted by 28*6777b538SAndroid Build Coastguard Worker the underlying test binary can be specified in the command. 29*6777b538SAndroid Build Coastguard Worker 30*6777b538SAndroid Build Coastguard Worker ./build/lacros/test_runner.py test out/lacros/browser_tests \\ 31*6777b538SAndroid Build Coastguard Worker --ash-chrome-version=120.0.6099.0 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker The above command runs tests with a given version of ash-chrome, which is 34*6777b538SAndroid Build Coastguard Worker useful to reproduce test failures. A list of prebuilt versions can 35*6777b538SAndroid Build Coastguard Worker be found at: 36*6777b538SAndroid Build Coastguard Worker https://chrome-infra-packages.appspot.com/p/chromium/testing/linux-ash-chromium/x86_64/ash.zip 37*6777b538SAndroid Build Coastguard Worker Click on any instance, you should see the version number for that instance. 38*6777b538SAndroid Build Coastguard Worker Also, there are refs, which points to the instance for that channel. It should 39*6777b538SAndroid Build Coastguard Worker be close the prod version but no guarantee. 40*6777b538SAndroid Build Coastguard Worker For legacy refs, like legacy119, it point to the latest version for that 41*6777b538SAndroid Build Coastguard Worker milestone. 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Worker ./testing/xvfb.py ./build/lacros/test_runner.py test out/lacros/browser_tests 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker The above command starts ash-chrome with xvfb instead of an X11 window, and 46*6777b538SAndroid Build Coastguard Worker it's useful when running tests without a display attached, such as sshing. 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker For version skew testing when passing --ash-chrome-path-override, the runner 49*6777b538SAndroid Build Coastguard Worker will try to find the ash major version and Lacros major version. If ash is 50*6777b538SAndroid Build Coastguard Worker newer(major version larger), the runner will not run any tests and just 51*6777b538SAndroid Build Coastguard Worker returns success. 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard WorkerInteractively debugging tests 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker Any of the previous examples accept the switches 56*6777b538SAndroid Build Coastguard Worker --gdb 57*6777b538SAndroid Build Coastguard Worker --lldb 58*6777b538SAndroid Build Coastguard Worker to run the tests in the corresponding debugger. 59*6777b538SAndroid Build Coastguard Worker""" 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Workerimport argparse 62*6777b538SAndroid Build Coastguard Workerimport json 63*6777b538SAndroid Build Coastguard Workerimport os 64*6777b538SAndroid Build Coastguard Workerimport logging 65*6777b538SAndroid Build Coastguard Workerimport re 66*6777b538SAndroid Build Coastguard Workerimport shutil 67*6777b538SAndroid Build Coastguard Workerimport signal 68*6777b538SAndroid Build Coastguard Workerimport subprocess 69*6777b538SAndroid Build Coastguard Workerimport sys 70*6777b538SAndroid Build Coastguard Workerimport tempfile 71*6777b538SAndroid Build Coastguard Workerimport time 72*6777b538SAndroid Build Coastguard Workerimport zipfile 73*6777b538SAndroid Build Coastguard Worker 74*6777b538SAndroid Build Coastguard Worker_SRC_ROOT = os.path.abspath( 75*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) 76*6777b538SAndroid Build Coastguard Workersys.path.append(os.path.join(_SRC_ROOT, 'third_party', 'depot_tools')) 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker# The cipd path for prebuilt ash chrome. 80*6777b538SAndroid Build Coastguard Worker_ASH_CIPD_PATH = 'chromium/testing/linux-ash-chromium/x86_64/ash.zip' 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker# Directory to cache downloaded ash-chrome versions to avoid re-downloading. 84*6777b538SAndroid Build Coastguard Worker_PREBUILT_ASH_CHROME_DIR = os.path.join(os.path.dirname(__file__), 85*6777b538SAndroid Build Coastguard Worker 'prebuilt_ash_chrome') 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker# File path to the asan symbolizer executable. 88*6777b538SAndroid Build Coastguard Worker_ASAN_SYMBOLIZER_PATH = os.path.join(_SRC_ROOT, 'tools', 'valgrind', 'asan', 89*6777b538SAndroid Build Coastguard Worker 'asan_symbolize.py') 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker# Number of seconds to wait for ash-chrome to start. 92*6777b538SAndroid Build Coastguard WorkerASH_CHROME_TIMEOUT_SECONDS = ( 93*6777b538SAndroid Build Coastguard Worker 300 if os.environ.get('ASH_WRAPPER', None) else 25) 94*6777b538SAndroid Build Coastguard Worker 95*6777b538SAndroid Build Coastguard Worker# List of targets that require ash-chrome as a Wayland server in order to run. 96*6777b538SAndroid Build Coastguard Worker_TARGETS_REQUIRE_ASH_CHROME = [ 97*6777b538SAndroid Build Coastguard Worker 'app_shell_unittests', 98*6777b538SAndroid Build Coastguard Worker 'aura_unittests', 99*6777b538SAndroid Build Coastguard Worker 'browser_tests', 100*6777b538SAndroid Build Coastguard Worker 'components_unittests', 101*6777b538SAndroid Build Coastguard Worker 'compositor_unittests', 102*6777b538SAndroid Build Coastguard Worker 'content_unittests', 103*6777b538SAndroid Build Coastguard Worker 'dbus_unittests', 104*6777b538SAndroid Build Coastguard Worker 'extensions_unittests', 105*6777b538SAndroid Build Coastguard Worker 'media_unittests', 106*6777b538SAndroid Build Coastguard Worker 'message_center_unittests', 107*6777b538SAndroid Build Coastguard Worker 'snapshot_unittests', 108*6777b538SAndroid Build Coastguard Worker 'sync_integration_tests', 109*6777b538SAndroid Build Coastguard Worker 'unit_tests', 110*6777b538SAndroid Build Coastguard Worker 'views_unittests', 111*6777b538SAndroid Build Coastguard Worker 'wm_unittests', 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard Worker # regex patterns. 114*6777b538SAndroid Build Coastguard Worker '.*_browsertests', 115*6777b538SAndroid Build Coastguard Worker '.*interactive_ui_tests' 116*6777b538SAndroid Build Coastguard Worker] 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker# List of targets that require ash-chrome to support crosapi mojo APIs. 119*6777b538SAndroid Build Coastguard Worker_TARGETS_REQUIRE_MOJO_CROSAPI = [ 120*6777b538SAndroid Build Coastguard Worker # TODO(jamescook): Add 'browser_tests' after multiple crosapi connections 121*6777b538SAndroid Build Coastguard Worker # are allowed. For now we only enable crosapi in targets that run tests 122*6777b538SAndroid Build Coastguard Worker # serially. 123*6777b538SAndroid Build Coastguard Worker 'interactive_ui_tests', 124*6777b538SAndroid Build Coastguard Worker 'lacros_chrome_browsertests', 125*6777b538SAndroid Build Coastguard Worker] 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker# Default test filter file for each target. These filter files will be 128*6777b538SAndroid Build Coastguard Worker# used by default if no other filter file get specified. 129*6777b538SAndroid Build Coastguard Worker_DEFAULT_FILTER_FILES_MAPPING = { 130*6777b538SAndroid Build Coastguard Worker 'browser_tests': 'linux-lacros.browser_tests.filter', 131*6777b538SAndroid Build Coastguard Worker 'components_unittests': 'linux-lacros.components_unittests.filter', 132*6777b538SAndroid Build Coastguard Worker 'content_browsertests': 'linux-lacros.content_browsertests.filter', 133*6777b538SAndroid Build Coastguard Worker 'interactive_ui_tests': 'linux-lacros.interactive_ui_tests.filter', 134*6777b538SAndroid Build Coastguard Worker 'lacros_chrome_browsertests': 135*6777b538SAndroid Build Coastguard Worker 'linux-lacros.lacros_chrome_browsertests.filter', 136*6777b538SAndroid Build Coastguard Worker 'sync_integration_tests': 'linux-lacros.sync_integration_tests.filter', 137*6777b538SAndroid Build Coastguard Worker 'unit_tests': 'linux-lacros.unit_tests.filter', 138*6777b538SAndroid Build Coastguard Worker} 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Workerdef _GetAshChromeDirPath(version): 142*6777b538SAndroid Build Coastguard Worker """Returns a path to the dir storing the downloaded version of ash-chrome.""" 143*6777b538SAndroid Build Coastguard Worker return os.path.join(_PREBUILT_ASH_CHROME_DIR, version) 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker 146*6777b538SAndroid Build Coastguard Workerdef _remove_unused_ash_chrome_versions(version_to_skip): 147*6777b538SAndroid Build Coastguard Worker """Removes unused ash-chrome versions to save disk space. 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker Currently, when an ash-chrome zip is downloaded and unpacked, the atime/mtime 150*6777b538SAndroid Build Coastguard Worker of the dir and the files are NOW instead of the time when they were built, but 151*6777b538SAndroid Build Coastguard Worker there is no garanteen it will always be the behavior in the future, so avoid 152*6777b538SAndroid Build Coastguard Worker removing the current version just in case. 153*6777b538SAndroid Build Coastguard Worker 154*6777b538SAndroid Build Coastguard Worker Args: 155*6777b538SAndroid Build Coastguard Worker version_to_skip (str): the version to skip removing regardless of its age. 156*6777b538SAndroid Build Coastguard Worker """ 157*6777b538SAndroid Build Coastguard Worker days = 7 158*6777b538SAndroid Build Coastguard Worker expiration_duration = 60 * 60 * 24 * days 159*6777b538SAndroid Build Coastguard Worker 160*6777b538SAndroid Build Coastguard Worker for f in os.listdir(_PREBUILT_ASH_CHROME_DIR): 161*6777b538SAndroid Build Coastguard Worker if f == version_to_skip: 162*6777b538SAndroid Build Coastguard Worker continue 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker p = os.path.join(_PREBUILT_ASH_CHROME_DIR, f) 165*6777b538SAndroid Build Coastguard Worker if os.path.isfile(p): 166*6777b538SAndroid Build Coastguard Worker # The prebuilt ash-chrome dir is NOT supposed to contain any files, remove 167*6777b538SAndroid Build Coastguard Worker # them to keep the directory clean. 168*6777b538SAndroid Build Coastguard Worker os.remove(p) 169*6777b538SAndroid Build Coastguard Worker continue 170*6777b538SAndroid Build Coastguard Worker chrome_path = os.path.join(p, 'test_ash_chrome') 171*6777b538SAndroid Build Coastguard Worker if not os.path.exists(chrome_path): 172*6777b538SAndroid Build Coastguard Worker chrome_path = p 173*6777b538SAndroid Build Coastguard Worker age = time.time() - os.path.getatime(chrome_path) 174*6777b538SAndroid Build Coastguard Worker if age > expiration_duration: 175*6777b538SAndroid Build Coastguard Worker logging.info( 176*6777b538SAndroid Build Coastguard Worker 'Removing ash-chrome: "%s" as it hasn\'t been used in the ' 177*6777b538SAndroid Build Coastguard Worker 'past %d days', p, days) 178*6777b538SAndroid Build Coastguard Worker shutil.rmtree(p) 179*6777b538SAndroid Build Coastguard Worker 180*6777b538SAndroid Build Coastguard Worker 181*6777b538SAndroid Build Coastguard Workerdef _GetLatestVersionOfAshChrome(): 182*6777b538SAndroid Build Coastguard Worker '''Get the latest ash chrome version. 183*6777b538SAndroid Build Coastguard Worker 184*6777b538SAndroid Build Coastguard Worker Get the package version info with canary ref. 185*6777b538SAndroid Build Coastguard Worker 186*6777b538SAndroid Build Coastguard Worker Returns: 187*6777b538SAndroid Build Coastguard Worker A string with the chrome version. 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker Raises: 190*6777b538SAndroid Build Coastguard Worker RuntimeError: if we can not get the version. 191*6777b538SAndroid Build Coastguard Worker ''' 192*6777b538SAndroid Build Coastguard Worker cp = subprocess.run( 193*6777b538SAndroid Build Coastguard Worker ['cipd', 'describe', _ASH_CIPD_PATH, '-version', 'canary'], 194*6777b538SAndroid Build Coastguard Worker capture_output=True) 195*6777b538SAndroid Build Coastguard Worker assert (cp.returncode == 0) 196*6777b538SAndroid Build Coastguard Worker groups = re.search(r'version:(?P<version>[\d\.]+)', str(cp.stdout)) 197*6777b538SAndroid Build Coastguard Worker if not groups: 198*6777b538SAndroid Build Coastguard Worker raise RuntimeError('Can not find the version. Error message: %s' % 199*6777b538SAndroid Build Coastguard Worker cp.stdout) 200*6777b538SAndroid Build Coastguard Worker return groups.group('version') 201*6777b538SAndroid Build Coastguard Worker 202*6777b538SAndroid Build Coastguard Worker 203*6777b538SAndroid Build Coastguard Workerdef _DownloadAshChromeFromCipd(path, version): 204*6777b538SAndroid Build Coastguard Worker '''Download the ash chrome with the requested version. 205*6777b538SAndroid Build Coastguard Worker 206*6777b538SAndroid Build Coastguard Worker Args: 207*6777b538SAndroid Build Coastguard Worker path: string for the downloaded ash chrome folder. 208*6777b538SAndroid Build Coastguard Worker version: string for the ash chrome version. 209*6777b538SAndroid Build Coastguard Worker 210*6777b538SAndroid Build Coastguard Worker Returns: 211*6777b538SAndroid Build Coastguard Worker A string representing the path for the downloaded ash chrome. 212*6777b538SAndroid Build Coastguard Worker ''' 213*6777b538SAndroid Build Coastguard Worker with tempfile.TemporaryDirectory() as temp_dir: 214*6777b538SAndroid Build Coastguard Worker ensure_file_path = os.path.join(temp_dir, 'ensure_file.txt') 215*6777b538SAndroid Build Coastguard Worker f = open(ensure_file_path, 'w+') 216*6777b538SAndroid Build Coastguard Worker f.write(_ASH_CIPD_PATH + ' version:' + version) 217*6777b538SAndroid Build Coastguard Worker f.close() 218*6777b538SAndroid Build Coastguard Worker subprocess.run( 219*6777b538SAndroid Build Coastguard Worker ['cipd', 'ensure', '-ensure-file', ensure_file_path, '-root', path]) 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Workerdef _DoubleCheckDownloadedAshChrome(path, version): 223*6777b538SAndroid Build Coastguard Worker '''Check the downloaded ash is the expected version. 224*6777b538SAndroid Build Coastguard Worker 225*6777b538SAndroid Build Coastguard Worker Double check by running the chrome binary with --version. 226*6777b538SAndroid Build Coastguard Worker 227*6777b538SAndroid Build Coastguard Worker Args: 228*6777b538SAndroid Build Coastguard Worker path: string for the downloaded ash chrome folder. 229*6777b538SAndroid Build Coastguard Worker version: string for the expected ash chrome version. 230*6777b538SAndroid Build Coastguard Worker 231*6777b538SAndroid Build Coastguard Worker Raises: 232*6777b538SAndroid Build Coastguard Worker RuntimeError if no test_ash_chrome binary can be found. 233*6777b538SAndroid Build Coastguard Worker ''' 234*6777b538SAndroid Build Coastguard Worker test_ash_chrome = os.path.join(path, 'test_ash_chrome') 235*6777b538SAndroid Build Coastguard Worker if not os.path.exists(test_ash_chrome): 236*6777b538SAndroid Build Coastguard Worker raise RuntimeError('Can not find test_ash_chrome binary under %s' % path) 237*6777b538SAndroid Build Coastguard Worker cp = subprocess.run([test_ash_chrome, '--version'], capture_output=True) 238*6777b538SAndroid Build Coastguard Worker assert (cp.returncode == 0) 239*6777b538SAndroid Build Coastguard Worker if str(cp.stdout).find(version) == -1: 240*6777b538SAndroid Build Coastguard Worker logging.warning( 241*6777b538SAndroid Build Coastguard Worker 'The downloaded ash chrome version is %s, but the ' 242*6777b538SAndroid Build Coastguard Worker 'expected ash chrome is %s. There is a version mismatch. Please ' 243*6777b538SAndroid Build Coastguard Worker 'file a bug to OS>Lacros so someone can take a look.' % 244*6777b538SAndroid Build Coastguard Worker (cp.stdout, version)) 245*6777b538SAndroid Build Coastguard Worker 246*6777b538SAndroid Build Coastguard Worker 247*6777b538SAndroid Build Coastguard Workerdef _DownloadAshChromeIfNecessary(version): 248*6777b538SAndroid Build Coastguard Worker """Download a given version of ash-chrome if not already exists. 249*6777b538SAndroid Build Coastguard Worker 250*6777b538SAndroid Build Coastguard Worker Args: 251*6777b538SAndroid Build Coastguard Worker version: A string representing the version, such as "793554". 252*6777b538SAndroid Build Coastguard Worker 253*6777b538SAndroid Build Coastguard Worker Raises: 254*6777b538SAndroid Build Coastguard Worker RuntimeError: If failed to download the specified version, for example, 255*6777b538SAndroid Build Coastguard Worker if the version is not present on gcs. 256*6777b538SAndroid Build Coastguard Worker """ 257*6777b538SAndroid Build Coastguard Worker 258*6777b538SAndroid Build Coastguard Worker def IsAshChromeDirValid(ash_chrome_dir): 259*6777b538SAndroid Build Coastguard Worker # This function assumes that once 'chrome' is present, other dependencies 260*6777b538SAndroid Build Coastguard Worker # will be present as well, it's not always true, for example, if the test 261*6777b538SAndroid Build Coastguard Worker # runner process gets killed in the middle of unzipping (~2 seconds), but 262*6777b538SAndroid Build Coastguard Worker # it's unlikely for the assumption to break in practice. 263*6777b538SAndroid Build Coastguard Worker return os.path.isdir(ash_chrome_dir) and os.path.isfile( 264*6777b538SAndroid Build Coastguard Worker os.path.join(ash_chrome_dir, 'test_ash_chrome')) 265*6777b538SAndroid Build Coastguard Worker 266*6777b538SAndroid Build Coastguard Worker ash_chrome_dir = _GetAshChromeDirPath(version) 267*6777b538SAndroid Build Coastguard Worker if IsAshChromeDirValid(ash_chrome_dir): 268*6777b538SAndroid Build Coastguard Worker return 269*6777b538SAndroid Build Coastguard Worker 270*6777b538SAndroid Build Coastguard Worker shutil.rmtree(ash_chrome_dir, ignore_errors=True) 271*6777b538SAndroid Build Coastguard Worker os.makedirs(ash_chrome_dir) 272*6777b538SAndroid Build Coastguard Worker _DownloadAshChromeFromCipd(ash_chrome_dir, version) 273*6777b538SAndroid Build Coastguard Worker _DoubleCheckDownloadedAshChrome(ash_chrome_dir, version) 274*6777b538SAndroid Build Coastguard Worker _remove_unused_ash_chrome_versions(version) 275*6777b538SAndroid Build Coastguard Worker 276*6777b538SAndroid Build Coastguard Worker 277*6777b538SAndroid Build Coastguard Workerdef _WaitForAshChromeToStart(tmp_xdg_dir, lacros_mojo_socket_file, 278*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi, ash_ready_file): 279*6777b538SAndroid Build Coastguard Worker """Waits for Ash-Chrome to be up and running and returns a boolean indicator. 280*6777b538SAndroid Build Coastguard Worker 281*6777b538SAndroid Build Coastguard Worker Determine whether ash-chrome is up and running by checking whether two files 282*6777b538SAndroid Build Coastguard Worker (lock file + socket) have been created in the |XDG_RUNTIME_DIR| and the lacros 283*6777b538SAndroid Build Coastguard Worker mojo socket file has been created if enabling the mojo "crosapi" interface. 284*6777b538SAndroid Build Coastguard Worker TODO(crbug.com/1107966): Figure out a more reliable hook to determine the 285*6777b538SAndroid Build Coastguard Worker status of ash-chrome, likely through mojo connection. 286*6777b538SAndroid Build Coastguard Worker 287*6777b538SAndroid Build Coastguard Worker Args: 288*6777b538SAndroid Build Coastguard Worker tmp_xdg_dir (str): Path to the XDG_RUNTIME_DIR. 289*6777b538SAndroid Build Coastguard Worker lacros_mojo_socket_file (str): Path to the lacros mojo socket file. 290*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi (bool): Whether to bootstrap the crosapi mojo interface 291*6777b538SAndroid Build Coastguard Worker between ash and the lacros test binary. 292*6777b538SAndroid Build Coastguard Worker ash_ready_file (str): Path to a non-existing file. After ash is ready for 293*6777b538SAndroid Build Coastguard Worker testing, the file will be created. 294*6777b538SAndroid Build Coastguard Worker 295*6777b538SAndroid Build Coastguard Worker Returns: 296*6777b538SAndroid Build Coastguard Worker A boolean indicating whether Ash-chrome is up and running. 297*6777b538SAndroid Build Coastguard Worker """ 298*6777b538SAndroid Build Coastguard Worker 299*6777b538SAndroid Build Coastguard Worker def IsAshChromeReady(tmp_xdg_dir, lacros_mojo_socket_file, 300*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi, ash_ready_file): 301*6777b538SAndroid Build Coastguard Worker # There should be 2 wayland files. 302*6777b538SAndroid Build Coastguard Worker if len(os.listdir(tmp_xdg_dir)) < 2: 303*6777b538SAndroid Build Coastguard Worker return False 304*6777b538SAndroid Build Coastguard Worker if enable_mojo_crosapi and not os.path.exists(lacros_mojo_socket_file): 305*6777b538SAndroid Build Coastguard Worker return False 306*6777b538SAndroid Build Coastguard Worker return os.path.exists(ash_ready_file) 307*6777b538SAndroid Build Coastguard Worker 308*6777b538SAndroid Build Coastguard Worker time_counter = 0 309*6777b538SAndroid Build Coastguard Worker while not IsAshChromeReady(tmp_xdg_dir, lacros_mojo_socket_file, 310*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi, ash_ready_file): 311*6777b538SAndroid Build Coastguard Worker time.sleep(0.5) 312*6777b538SAndroid Build Coastguard Worker time_counter += 0.5 313*6777b538SAndroid Build Coastguard Worker if time_counter > ASH_CHROME_TIMEOUT_SECONDS: 314*6777b538SAndroid Build Coastguard Worker break 315*6777b538SAndroid Build Coastguard Worker 316*6777b538SAndroid Build Coastguard Worker return IsAshChromeReady(tmp_xdg_dir, lacros_mojo_socket_file, 317*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi, ash_ready_file) 318*6777b538SAndroid Build Coastguard Worker 319*6777b538SAndroid Build Coastguard Worker 320*6777b538SAndroid Build Coastguard Workerdef _ExtractAshMajorVersion(file_path): 321*6777b538SAndroid Build Coastguard Worker """Extract major version from file_path. 322*6777b538SAndroid Build Coastguard Worker 323*6777b538SAndroid Build Coastguard Worker File path like this: 324*6777b538SAndroid Build Coastguard Worker ../../lacros_version_skew_tests_v94.0.4588.0/test_ash_chrome 325*6777b538SAndroid Build Coastguard Worker 326*6777b538SAndroid Build Coastguard Worker Returns: 327*6777b538SAndroid Build Coastguard Worker int representing the major version. Or 0 if it can't extract 328*6777b538SAndroid Build Coastguard Worker major version. 329*6777b538SAndroid Build Coastguard Worker """ 330*6777b538SAndroid Build Coastguard Worker m = re.search( 331*6777b538SAndroid Build Coastguard Worker 'lacros_version_skew_tests_v(?P<version>[0-9]+).[0-9]+.[0-9]+.[0-9]+/', 332*6777b538SAndroid Build Coastguard Worker file_path) 333*6777b538SAndroid Build Coastguard Worker if (m and 'version' in m.groupdict().keys()): 334*6777b538SAndroid Build Coastguard Worker return int(m.group('version')) 335*6777b538SAndroid Build Coastguard Worker logging.warning('Can not find the ash version in %s.' % file_path) 336*6777b538SAndroid Build Coastguard Worker # Returns ash major version as 0, so we can still run tests. 337*6777b538SAndroid Build Coastguard Worker # This is likely happen because user is running in local environments. 338*6777b538SAndroid Build Coastguard Worker return 0 339*6777b538SAndroid Build Coastguard Worker 340*6777b538SAndroid Build Coastguard Worker 341*6777b538SAndroid Build Coastguard Workerdef _FindLacrosMajorVersionFromMetadata(): 342*6777b538SAndroid Build Coastguard Worker # This handles the logic on bots. When running on bots, 343*6777b538SAndroid Build Coastguard Worker # we don't copy source files to test machines. So we build a 344*6777b538SAndroid Build Coastguard Worker # metadata.json file which contains version information. 345*6777b538SAndroid Build Coastguard Worker if not os.path.exists('metadata.json'): 346*6777b538SAndroid Build Coastguard Worker logging.error('Can not determine current version.') 347*6777b538SAndroid Build Coastguard Worker # Returns 0 so it can't run any tests. 348*6777b538SAndroid Build Coastguard Worker return 0 349*6777b538SAndroid Build Coastguard Worker version = '' 350*6777b538SAndroid Build Coastguard Worker with open('metadata.json', 'r') as file: 351*6777b538SAndroid Build Coastguard Worker content = json.load(file) 352*6777b538SAndroid Build Coastguard Worker version = content['content']['version'] 353*6777b538SAndroid Build Coastguard Worker return int(version[:version.find('.')]) 354*6777b538SAndroid Build Coastguard Worker 355*6777b538SAndroid Build Coastguard Worker 356*6777b538SAndroid Build Coastguard Workerdef _FindLacrosMajorVersion(): 357*6777b538SAndroid Build Coastguard Worker """Returns the major version in the current checkout. 358*6777b538SAndroid Build Coastguard Worker 359*6777b538SAndroid Build Coastguard Worker It would try to read src/chrome/VERSION. If it's not available, 360*6777b538SAndroid Build Coastguard Worker then try to read metadata.json. 361*6777b538SAndroid Build Coastguard Worker 362*6777b538SAndroid Build Coastguard Worker Returns: 363*6777b538SAndroid Build Coastguard Worker int representing the major version. Or 0 if it fails to 364*6777b538SAndroid Build Coastguard Worker determine the version. 365*6777b538SAndroid Build Coastguard Worker """ 366*6777b538SAndroid Build Coastguard Worker version_file = os.path.abspath( 367*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.abspath(os.path.dirname(__file__)), 368*6777b538SAndroid Build Coastguard Worker '../../chrome/VERSION')) 369*6777b538SAndroid Build Coastguard Worker # This is mostly happens for local development where 370*6777b538SAndroid Build Coastguard Worker # src/chrome/VERSION exists. 371*6777b538SAndroid Build Coastguard Worker if os.path.exists(version_file): 372*6777b538SAndroid Build Coastguard Worker lines = open(version_file, 'r').readlines() 373*6777b538SAndroid Build Coastguard Worker return int(lines[0][lines[0].find('=') + 1:-1]) 374*6777b538SAndroid Build Coastguard Worker return _FindLacrosMajorVersionFromMetadata() 375*6777b538SAndroid Build Coastguard Worker 376*6777b538SAndroid Build Coastguard Worker 377*6777b538SAndroid Build Coastguard Workerdef _ParseSummaryOutput(forward_args): 378*6777b538SAndroid Build Coastguard Worker """Find the summary output file path. 379*6777b538SAndroid Build Coastguard Worker 380*6777b538SAndroid Build Coastguard Worker Args: 381*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 382*6777b538SAndroid Build Coastguard Worker 383*6777b538SAndroid Build Coastguard Worker Returns: 384*6777b538SAndroid Build Coastguard Worker None if not found, or str representing the output file path. 385*6777b538SAndroid Build Coastguard Worker """ 386*6777b538SAndroid Build Coastguard Worker logging.warning(forward_args) 387*6777b538SAndroid Build Coastguard Worker for arg in forward_args: 388*6777b538SAndroid Build Coastguard Worker if arg.startswith('--test-launcher-summary-output='): 389*6777b538SAndroid Build Coastguard Worker return arg[len('--test-launcher-summary-output='):] 390*6777b538SAndroid Build Coastguard Worker return None 391*6777b538SAndroid Build Coastguard Worker 392*6777b538SAndroid Build Coastguard Worker 393*6777b538SAndroid Build Coastguard Workerdef _IsRunningOnBots(forward_args): 394*6777b538SAndroid Build Coastguard Worker """Detects if the script is running on bots or not. 395*6777b538SAndroid Build Coastguard Worker 396*6777b538SAndroid Build Coastguard Worker Args: 397*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 398*6777b538SAndroid Build Coastguard Worker 399*6777b538SAndroid Build Coastguard Worker Returns: 400*6777b538SAndroid Build Coastguard Worker True if the script is running on bots. Otherwise returns False. 401*6777b538SAndroid Build Coastguard Worker """ 402*6777b538SAndroid Build Coastguard Worker return '--test-launcher-bot-mode' in forward_args 403*6777b538SAndroid Build Coastguard Worker 404*6777b538SAndroid Build Coastguard Worker 405*6777b538SAndroid Build Coastguard Workerdef _KillNicely(proc, timeout_secs=2, first_wait_secs=0): 406*6777b538SAndroid Build Coastguard Worker """Kills a subprocess nicely. 407*6777b538SAndroid Build Coastguard Worker 408*6777b538SAndroid Build Coastguard Worker Args: 409*6777b538SAndroid Build Coastguard Worker proc: The subprocess to kill. 410*6777b538SAndroid Build Coastguard Worker timeout_secs: The timeout to wait in seconds. 411*6777b538SAndroid Build Coastguard Worker first_wait_secs: The grace period before sending first SIGTERM in seconds. 412*6777b538SAndroid Build Coastguard Worker """ 413*6777b538SAndroid Build Coastguard Worker if not proc: 414*6777b538SAndroid Build Coastguard Worker return 415*6777b538SAndroid Build Coastguard Worker 416*6777b538SAndroid Build Coastguard Worker if first_wait_secs: 417*6777b538SAndroid Build Coastguard Worker try: 418*6777b538SAndroid Build Coastguard Worker proc.wait(first_wait_secs) 419*6777b538SAndroid Build Coastguard Worker return 420*6777b538SAndroid Build Coastguard Worker except subprocess.TimeoutExpired: 421*6777b538SAndroid Build Coastguard Worker pass 422*6777b538SAndroid Build Coastguard Worker 423*6777b538SAndroid Build Coastguard Worker if proc.poll() is None: 424*6777b538SAndroid Build Coastguard Worker proc.terminate() 425*6777b538SAndroid Build Coastguard Worker try: 426*6777b538SAndroid Build Coastguard Worker proc.wait(timeout_secs) 427*6777b538SAndroid Build Coastguard Worker except subprocess.TimeoutExpired: 428*6777b538SAndroid Build Coastguard Worker proc.kill() 429*6777b538SAndroid Build Coastguard Worker proc.wait() 430*6777b538SAndroid Build Coastguard Worker 431*6777b538SAndroid Build Coastguard Worker 432*6777b538SAndroid Build Coastguard Workerdef _ClearDir(dirpath): 433*6777b538SAndroid Build Coastguard Worker """Deletes everything within the directory. 434*6777b538SAndroid Build Coastguard Worker 435*6777b538SAndroid Build Coastguard Worker Args: 436*6777b538SAndroid Build Coastguard Worker dirpath: The path of the directory. 437*6777b538SAndroid Build Coastguard Worker """ 438*6777b538SAndroid Build Coastguard Worker for e in os.scandir(dirpath): 439*6777b538SAndroid Build Coastguard Worker if e.is_dir(): 440*6777b538SAndroid Build Coastguard Worker shutil.rmtree(e.path, ignore_errors=True) 441*6777b538SAndroid Build Coastguard Worker elif e.is_file(): 442*6777b538SAndroid Build Coastguard Worker os.remove(e.path) 443*6777b538SAndroid Build Coastguard Worker 444*6777b538SAndroid Build Coastguard Worker 445*6777b538SAndroid Build Coastguard Workerdef _LaunchDebugger(args, forward_args, test_env): 446*6777b538SAndroid Build Coastguard Worker """Launches the requested debugger. 447*6777b538SAndroid Build Coastguard Worker 448*6777b538SAndroid Build Coastguard Worker This is used to wrap the test invocation in a debugger. It returns the 449*6777b538SAndroid Build Coastguard Worker created Popen class of the debugger process. 450*6777b538SAndroid Build Coastguard Worker 451*6777b538SAndroid Build Coastguard Worker Args: 452*6777b538SAndroid Build Coastguard Worker args (dict): Args for this script. 453*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 454*6777b538SAndroid Build Coastguard Worker test_env (dict): Computed environment variables for the test. 455*6777b538SAndroid Build Coastguard Worker """ 456*6777b538SAndroid Build Coastguard Worker logging.info('Starting debugger.') 457*6777b538SAndroid Build Coastguard Worker 458*6777b538SAndroid Build Coastguard Worker # Redirect fatal signals to "ignore." When running an interactive debugger, 459*6777b538SAndroid Build Coastguard Worker # these signals should go only to the debugger so the user can break back out 460*6777b538SAndroid Build Coastguard Worker # of the debugged test process into the debugger UI without killing this 461*6777b538SAndroid Build Coastguard Worker # parent script. 462*6777b538SAndroid Build Coastguard Worker for sig in (signal.SIGTERM, signal.SIGINT): 463*6777b538SAndroid Build Coastguard Worker signal.signal(sig, signal.SIG_IGN) 464*6777b538SAndroid Build Coastguard Worker 465*6777b538SAndroid Build Coastguard Worker # Force the tests into single-process-test mode for debugging unless manually 466*6777b538SAndroid Build Coastguard Worker # specified. Otherwise the tests will run in a child process that the debugger 467*6777b538SAndroid Build Coastguard Worker # won't be attached to and the debugger won't do anything. 468*6777b538SAndroid Build Coastguard Worker if not ("--single-process" in forward_args 469*6777b538SAndroid Build Coastguard Worker or "--single-process-tests" in forward_args): 470*6777b538SAndroid Build Coastguard Worker forward_args += ["--single-process-tests"] 471*6777b538SAndroid Build Coastguard Worker 472*6777b538SAndroid Build Coastguard Worker # Adding --single-process-tests can cause some tests to fail when they're 473*6777b538SAndroid Build Coastguard Worker # run in the same process. Forcing the user to specify a filter will prevent 474*6777b538SAndroid Build Coastguard Worker # a later error. 475*6777b538SAndroid Build Coastguard Worker if not [i for i in forward_args if i.startswith("--gtest_filter")]: 476*6777b538SAndroid Build Coastguard Worker logging.error("""Interactive debugging requested without --gtest_filter 477*6777b538SAndroid Build Coastguard Worker 478*6777b538SAndroid Build Coastguard WorkerThis script adds --single-process-tests to support interactive debugging but 479*6777b538SAndroid Build Coastguard Workersome tests will fail in this mode unless run independently. To debug a test 480*6777b538SAndroid Build Coastguard Workerspecify a --gtest_filter=Foo.Bar to name the test you want to debug. 481*6777b538SAndroid Build Coastguard Worker""") 482*6777b538SAndroid Build Coastguard Worker sys.exit(1) 483*6777b538SAndroid Build Coastguard Worker 484*6777b538SAndroid Build Coastguard Worker # This code attempts to source the debugger configuration file. Some 485*6777b538SAndroid Build Coastguard Worker # users will have this in their init but sourcing it more than once is 486*6777b538SAndroid Build Coastguard Worker # harmless and helps people that haven't configured it. 487*6777b538SAndroid Build Coastguard Worker if args.gdb: 488*6777b538SAndroid Build Coastguard Worker gdbinit_file = os.path.normpath( 489*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.realpath(__file__), "../../../tools/gdb/gdbinit")) 490*6777b538SAndroid Build Coastguard Worker debugger_command = [ 491*6777b538SAndroid Build Coastguard Worker 'gdb', '--init-eval-command', 'source ' + gdbinit_file, '--args' 492*6777b538SAndroid Build Coastguard Worker ] 493*6777b538SAndroid Build Coastguard Worker else: 494*6777b538SAndroid Build Coastguard Worker lldbinit_dir = os.path.normpath( 495*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.realpath(__file__), "../../../tools/lldb")) 496*6777b538SAndroid Build Coastguard Worker debugger_command = [ 497*6777b538SAndroid Build Coastguard Worker 'lldb', '-O', 498*6777b538SAndroid Build Coastguard Worker "script sys.path[:0] = ['%s']" % lldbinit_dir, '-O', 499*6777b538SAndroid Build Coastguard Worker 'script import lldbinit', '--' 500*6777b538SAndroid Build Coastguard Worker ] 501*6777b538SAndroid Build Coastguard Worker debugger_command += [args.command] + forward_args 502*6777b538SAndroid Build Coastguard Worker return subprocess.Popen(debugger_command, env=test_env) 503*6777b538SAndroid Build Coastguard Worker 504*6777b538SAndroid Build Coastguard Worker 505*6777b538SAndroid Build Coastguard Workerdef _RunTestWithAshChrome(args, forward_args): 506*6777b538SAndroid Build Coastguard Worker """Runs tests with ash-chrome. 507*6777b538SAndroid Build Coastguard Worker 508*6777b538SAndroid Build Coastguard Worker Args: 509*6777b538SAndroid Build Coastguard Worker args (dict): Args for this script. 510*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 511*6777b538SAndroid Build Coastguard Worker """ 512*6777b538SAndroid Build Coastguard Worker if args.ash_chrome_path_override: 513*6777b538SAndroid Build Coastguard Worker ash_chrome_file = args.ash_chrome_path_override 514*6777b538SAndroid Build Coastguard Worker ash_major_version = _ExtractAshMajorVersion(ash_chrome_file) 515*6777b538SAndroid Build Coastguard Worker lacros_major_version = _FindLacrosMajorVersion() 516*6777b538SAndroid Build Coastguard Worker if ash_major_version > lacros_major_version: 517*6777b538SAndroid Build Coastguard Worker logging.warning('''Not running any tests, because we do not \ 518*6777b538SAndroid Build Coastguard Workersupport version skew testing for Lacros M%s against ash M%s''' % 519*6777b538SAndroid Build Coastguard Worker (lacros_major_version, ash_major_version)) 520*6777b538SAndroid Build Coastguard Worker # Create an empty output.json file so result adapter can read 521*6777b538SAndroid Build Coastguard Worker # the file. Or else result adapter will report no file found 522*6777b538SAndroid Build Coastguard Worker # and result infra failure. 523*6777b538SAndroid Build Coastguard Worker output_json = _ParseSummaryOutput(forward_args) 524*6777b538SAndroid Build Coastguard Worker if output_json: 525*6777b538SAndroid Build Coastguard Worker with open(output_json, 'w') as f: 526*6777b538SAndroid Build Coastguard Worker f.write("""{"all_tests":[],"disabled_tests":[],"global_tags":[], 527*6777b538SAndroid Build Coastguard Worker"per_iteration_data":[],"test_locations":{}}""") 528*6777b538SAndroid Build Coastguard Worker # Although we don't run any tests, this is considered as success. 529*6777b538SAndroid Build Coastguard Worker return 0 530*6777b538SAndroid Build Coastguard Worker if not os.path.exists(ash_chrome_file): 531*6777b538SAndroid Build Coastguard Worker logging.error("""Can not find ash chrome at %s. Did you download \ 532*6777b538SAndroid Build Coastguard Workerthe ash from CIPD? If you don't plan to build your own ash, you need \ 533*6777b538SAndroid Build Coastguard Workerto download first. Example commandlines: 534*6777b538SAndroid Build Coastguard Worker $ cipd auth-login 535*6777b538SAndroid Build Coastguard Worker $ echo "chromium/testing/linux-ash-chromium/x86_64/ash.zip \ 536*6777b538SAndroid Build Coastguard Workerversion:92.0.4515.130" > /tmp/ensure-file.txt 537*6777b538SAndroid Build Coastguard Worker $ cipd ensure -ensure-file /tmp/ensure-file.txt \ 538*6777b538SAndroid Build Coastguard Worker-root lacros_version_skew_tests_v92.0.4515.130 539*6777b538SAndroid Build Coastguard Worker Then you can use --ash-chrome-path-override=\ 540*6777b538SAndroid Build Coastguard Workerlacros_version_skew_tests_v92.0.4515.130/test_ash_chrome 541*6777b538SAndroid Build Coastguard Worker""" % ash_chrome_file) 542*6777b538SAndroid Build Coastguard Worker return 1 543*6777b538SAndroid Build Coastguard Worker elif args.ash_chrome_path: 544*6777b538SAndroid Build Coastguard Worker ash_chrome_file = args.ash_chrome_path 545*6777b538SAndroid Build Coastguard Worker else: 546*6777b538SAndroid Build Coastguard Worker ash_chrome_version = (args.ash_chrome_version 547*6777b538SAndroid Build Coastguard Worker or _GetLatestVersionOfAshChrome()) 548*6777b538SAndroid Build Coastguard Worker _DownloadAshChromeIfNecessary(ash_chrome_version) 549*6777b538SAndroid Build Coastguard Worker logging.info('Ash-chrome version: %s', ash_chrome_version) 550*6777b538SAndroid Build Coastguard Worker 551*6777b538SAndroid Build Coastguard Worker ash_chrome_file = os.path.join(_GetAshChromeDirPath(ash_chrome_version), 552*6777b538SAndroid Build Coastguard Worker 'test_ash_chrome') 553*6777b538SAndroid Build Coastguard Worker try: 554*6777b538SAndroid Build Coastguard Worker # Starts Ash-Chrome. 555*6777b538SAndroid Build Coastguard Worker tmp_xdg_dir_name = tempfile.mkdtemp() 556*6777b538SAndroid Build Coastguard Worker tmp_ash_data_dir_name = tempfile.mkdtemp() 557*6777b538SAndroid Build Coastguard Worker tmp_unique_ash_dir_name = tempfile.mkdtemp() 558*6777b538SAndroid Build Coastguard Worker 559*6777b538SAndroid Build Coastguard Worker # Please refer to below file for how mojo connection is set up in testing. 560*6777b538SAndroid Build Coastguard Worker # //chrome/browser/ash/crosapi/test_mojo_connection_manager.h 561*6777b538SAndroid Build Coastguard Worker lacros_mojo_socket_file = '%s/lacros.sock' % tmp_ash_data_dir_name 562*6777b538SAndroid Build Coastguard Worker lacros_mojo_socket_arg = ('--lacros-mojo-socket-for-testing=%s' % 563*6777b538SAndroid Build Coastguard Worker lacros_mojo_socket_file) 564*6777b538SAndroid Build Coastguard Worker ash_ready_file = '%s/ash_ready.txt' % tmp_ash_data_dir_name 565*6777b538SAndroid Build Coastguard Worker enable_mojo_crosapi = any(t == os.path.basename(args.command) 566*6777b538SAndroid Build Coastguard Worker for t in _TARGETS_REQUIRE_MOJO_CROSAPI) 567*6777b538SAndroid Build Coastguard Worker ash_wayland_socket_name = 'wayland-exo' 568*6777b538SAndroid Build Coastguard Worker 569*6777b538SAndroid Build Coastguard Worker ash_process = None 570*6777b538SAndroid Build Coastguard Worker ash_env = os.environ.copy() 571*6777b538SAndroid Build Coastguard Worker ash_env['XDG_RUNTIME_DIR'] = tmp_xdg_dir_name 572*6777b538SAndroid Build Coastguard Worker ash_cmd = [ 573*6777b538SAndroid Build Coastguard Worker ash_chrome_file, 574*6777b538SAndroid Build Coastguard Worker '--user-data-dir=%s' % tmp_ash_data_dir_name, 575*6777b538SAndroid Build Coastguard Worker '--enable-wayland-server', 576*6777b538SAndroid Build Coastguard Worker '--no-startup-window', 577*6777b538SAndroid Build Coastguard Worker '--disable-input-event-activation-protection', 578*6777b538SAndroid Build Coastguard Worker '--disable-lacros-keep-alive', 579*6777b538SAndroid Build Coastguard Worker '--disable-login-lacros-opening', 580*6777b538SAndroid Build Coastguard Worker '--enable-field-trial-config', 581*6777b538SAndroid Build Coastguard Worker '--enable-logging=stderr', 582*6777b538SAndroid Build Coastguard Worker '--enable-features=LacrosSupport,LacrosPrimary,LacrosOnly', 583*6777b538SAndroid Build Coastguard Worker '--ash-ready-file-path=%s' % ash_ready_file, 584*6777b538SAndroid Build Coastguard Worker '--wayland-server-socket=%s' % ash_wayland_socket_name, 585*6777b538SAndroid Build Coastguard Worker ] 586*6777b538SAndroid Build Coastguard Worker if '--enable-pixel-output-in-tests' not in forward_args: 587*6777b538SAndroid Build Coastguard Worker ash_cmd.append('--disable-gl-drawing-for-tests') 588*6777b538SAndroid Build Coastguard Worker 589*6777b538SAndroid Build Coastguard Worker if enable_mojo_crosapi: 590*6777b538SAndroid Build Coastguard Worker ash_cmd.append(lacros_mojo_socket_arg) 591*6777b538SAndroid Build Coastguard Worker 592*6777b538SAndroid Build Coastguard Worker # Users can specify a wrapper for the ash binary to do things like 593*6777b538SAndroid Build Coastguard Worker # attaching debuggers. For example, this will open a new terminal window 594*6777b538SAndroid Build Coastguard Worker # and run GDB. 595*6777b538SAndroid Build Coastguard Worker # $ export ASH_WRAPPER="gnome-terminal -- gdb --ex=r --args" 596*6777b538SAndroid Build Coastguard Worker ash_wrapper = os.environ.get('ASH_WRAPPER', None) 597*6777b538SAndroid Build Coastguard Worker if ash_wrapper: 598*6777b538SAndroid Build Coastguard Worker logging.info('Running ash with "ASH_WRAPPER": %s', ash_wrapper) 599*6777b538SAndroid Build Coastguard Worker ash_cmd = list(ash_wrapper.split()) + ash_cmd 600*6777b538SAndroid Build Coastguard Worker 601*6777b538SAndroid Build Coastguard Worker ash_process = None 602*6777b538SAndroid Build Coastguard Worker ash_process_has_started = False 603*6777b538SAndroid Build Coastguard Worker total_tries = 3 604*6777b538SAndroid Build Coastguard Worker num_tries = 0 605*6777b538SAndroid Build Coastguard Worker ash_start_time = None 606*6777b538SAndroid Build Coastguard Worker 607*6777b538SAndroid Build Coastguard Worker # Create a log file if the user wanted to have one. 608*6777b538SAndroid Build Coastguard Worker ash_log = None 609*6777b538SAndroid Build Coastguard Worker ash_log_path = None 610*6777b538SAndroid Build Coastguard Worker 611*6777b538SAndroid Build Coastguard Worker run_tests_in_debugger = args.gdb or args.lldb 612*6777b538SAndroid Build Coastguard Worker 613*6777b538SAndroid Build Coastguard Worker if args.ash_logging_path: 614*6777b538SAndroid Build Coastguard Worker ash_log_path = args.ash_logging_path 615*6777b538SAndroid Build Coastguard Worker # Put ash logs in a separate file on bots. 616*6777b538SAndroid Build Coastguard Worker # For asan builds, the ash log is not symbolized. In order to 617*6777b538SAndroid Build Coastguard Worker # read the stack strace, we don't redirect logs to another file. 618*6777b538SAndroid Build Coastguard Worker elif _IsRunningOnBots(forward_args) and not args.combine_ash_logs_on_bots: 619*6777b538SAndroid Build Coastguard Worker summary_file = _ParseSummaryOutput(forward_args) 620*6777b538SAndroid Build Coastguard Worker if summary_file: 621*6777b538SAndroid Build Coastguard Worker ash_log_path = os.path.join(os.path.dirname(summary_file), 622*6777b538SAndroid Build Coastguard Worker 'ash_chrome.log') 623*6777b538SAndroid Build Coastguard Worker elif run_tests_in_debugger: 624*6777b538SAndroid Build Coastguard Worker # The debugger is unusable when all Ash logs are getting dumped to the 625*6777b538SAndroid Build Coastguard Worker # same terminal. Redirect to a log file if there isn't one specified. 626*6777b538SAndroid Build Coastguard Worker logging.info("Running in the debugger and --ash-logging-path is not " + 627*6777b538SAndroid Build Coastguard Worker "specified, defaulting to the current directory.") 628*6777b538SAndroid Build Coastguard Worker ash_log_path = 'ash_chrome.log' 629*6777b538SAndroid Build Coastguard Worker 630*6777b538SAndroid Build Coastguard Worker if ash_log_path: 631*6777b538SAndroid Build Coastguard Worker ash_log = open(ash_log_path, 'a') 632*6777b538SAndroid Build Coastguard Worker logging.info('Writing ash-chrome logs to: %s', ash_log_path) 633*6777b538SAndroid Build Coastguard Worker 634*6777b538SAndroid Build Coastguard Worker ash_stdout = ash_log or None 635*6777b538SAndroid Build Coastguard Worker test_stdout = None 636*6777b538SAndroid Build Coastguard Worker 637*6777b538SAndroid Build Coastguard Worker # Setup asan symbolizer. 638*6777b538SAndroid Build Coastguard Worker ash_symbolize_process = None 639*6777b538SAndroid Build Coastguard Worker test_symbolize_process = None 640*6777b538SAndroid Build Coastguard Worker should_symbolize = False 641*6777b538SAndroid Build Coastguard Worker if args.asan_symbolize_output and os.path.exists(_ASAN_SYMBOLIZER_PATH): 642*6777b538SAndroid Build Coastguard Worker should_symbolize = True 643*6777b538SAndroid Build Coastguard Worker ash_symbolize_stdout = ash_stdout 644*6777b538SAndroid Build Coastguard Worker ash_stdout = subprocess.PIPE 645*6777b538SAndroid Build Coastguard Worker test_stdout = subprocess.PIPE 646*6777b538SAndroid Build Coastguard Worker 647*6777b538SAndroid Build Coastguard Worker while not ash_process_has_started and num_tries < total_tries: 648*6777b538SAndroid Build Coastguard Worker num_tries += 1 649*6777b538SAndroid Build Coastguard Worker ash_start_time = time.monotonic() 650*6777b538SAndroid Build Coastguard Worker logging.info('Starting ash-chrome: ' + ' '.join(ash_cmd)) 651*6777b538SAndroid Build Coastguard Worker 652*6777b538SAndroid Build Coastguard Worker # Using preexec_fn=os.setpgrp here will detach the forked process from 653*6777b538SAndroid Build Coastguard Worker # this process group before exec-ing Ash. This prevents interactive 654*6777b538SAndroid Build Coastguard Worker # Control-C from being seen by Ash. Otherwise Control-C in a debugger 655*6777b538SAndroid Build Coastguard Worker # can kill Ash out from under the debugger. In non-debugger cases, this 656*6777b538SAndroid Build Coastguard Worker # script attempts to clean up the spawned processes nicely. 657*6777b538SAndroid Build Coastguard Worker ash_process = subprocess.Popen(ash_cmd, 658*6777b538SAndroid Build Coastguard Worker env=ash_env, 659*6777b538SAndroid Build Coastguard Worker preexec_fn=os.setpgrp, 660*6777b538SAndroid Build Coastguard Worker stdout=ash_stdout, 661*6777b538SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 662*6777b538SAndroid Build Coastguard Worker 663*6777b538SAndroid Build Coastguard Worker if should_symbolize: 664*6777b538SAndroid Build Coastguard Worker logging.info('Symbolizing ash logs with asan symbolizer.') 665*6777b538SAndroid Build Coastguard Worker ash_symbolize_process = subprocess.Popen([_ASAN_SYMBOLIZER_PATH], 666*6777b538SAndroid Build Coastguard Worker stdin=ash_process.stdout, 667*6777b538SAndroid Build Coastguard Worker preexec_fn=os.setpgrp, 668*6777b538SAndroid Build Coastguard Worker stdout=ash_symbolize_stdout, 669*6777b538SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 670*6777b538SAndroid Build Coastguard Worker # Allow ash_process to receive a SIGPIPE if symbolize process exits. 671*6777b538SAndroid Build Coastguard Worker ash_process.stdout.close() 672*6777b538SAndroid Build Coastguard Worker 673*6777b538SAndroid Build Coastguard Worker ash_process_has_started = _WaitForAshChromeToStart( 674*6777b538SAndroid Build Coastguard Worker tmp_xdg_dir_name, lacros_mojo_socket_file, enable_mojo_crosapi, 675*6777b538SAndroid Build Coastguard Worker ash_ready_file) 676*6777b538SAndroid Build Coastguard Worker if ash_process_has_started: 677*6777b538SAndroid Build Coastguard Worker break 678*6777b538SAndroid Build Coastguard Worker 679*6777b538SAndroid Build Coastguard Worker logging.warning('Starting ash-chrome timed out after %ds', 680*6777b538SAndroid Build Coastguard Worker ASH_CHROME_TIMEOUT_SECONDS) 681*6777b538SAndroid Build Coastguard Worker logging.warning('Are you using test_ash_chrome?') 682*6777b538SAndroid Build Coastguard Worker logging.warning('Printing the output of "ps aux" for debugging:') 683*6777b538SAndroid Build Coastguard Worker subprocess.call(['ps', 'aux']) 684*6777b538SAndroid Build Coastguard Worker _KillNicely(ash_process) 685*6777b538SAndroid Build Coastguard Worker _KillNicely(ash_symbolize_process, first_wait_secs=1) 686*6777b538SAndroid Build Coastguard Worker 687*6777b538SAndroid Build Coastguard Worker # Clean up for retry. 688*6777b538SAndroid Build Coastguard Worker _ClearDir(tmp_xdg_dir_name) 689*6777b538SAndroid Build Coastguard Worker _ClearDir(tmp_ash_data_dir_name) 690*6777b538SAndroid Build Coastguard Worker 691*6777b538SAndroid Build Coastguard Worker if not ash_process_has_started: 692*6777b538SAndroid Build Coastguard Worker raise RuntimeError('Timed out waiting for ash-chrome to start') 693*6777b538SAndroid Build Coastguard Worker 694*6777b538SAndroid Build Coastguard Worker ash_elapsed_time = time.monotonic() - ash_start_time 695*6777b538SAndroid Build Coastguard Worker logging.info('Started ash-chrome in %.3fs on try %d.', ash_elapsed_time, 696*6777b538SAndroid Build Coastguard Worker num_tries) 697*6777b538SAndroid Build Coastguard Worker 698*6777b538SAndroid Build Coastguard Worker # Starts tests. 699*6777b538SAndroid Build Coastguard Worker if enable_mojo_crosapi: 700*6777b538SAndroid Build Coastguard Worker forward_args.append(lacros_mojo_socket_arg) 701*6777b538SAndroid Build Coastguard Worker 702*6777b538SAndroid Build Coastguard Worker forward_args.append('--ash-chrome-path=' + ash_chrome_file) 703*6777b538SAndroid Build Coastguard Worker forward_args.append('--unique-ash-dir=' + tmp_unique_ash_dir_name) 704*6777b538SAndroid Build Coastguard Worker 705*6777b538SAndroid Build Coastguard Worker test_env = os.environ.copy() 706*6777b538SAndroid Build Coastguard Worker test_env['WAYLAND_DISPLAY'] = ash_wayland_socket_name 707*6777b538SAndroid Build Coastguard Worker test_env['EGL_PLATFORM'] = 'surfaceless' 708*6777b538SAndroid Build Coastguard Worker test_env['XDG_RUNTIME_DIR'] = tmp_xdg_dir_name 709*6777b538SAndroid Build Coastguard Worker 710*6777b538SAndroid Build Coastguard Worker if run_tests_in_debugger: 711*6777b538SAndroid Build Coastguard Worker test_process = _LaunchDebugger(args, forward_args, test_env) 712*6777b538SAndroid Build Coastguard Worker else: 713*6777b538SAndroid Build Coastguard Worker logging.info('Starting test process.') 714*6777b538SAndroid Build Coastguard Worker test_process = subprocess.Popen([args.command] + forward_args, 715*6777b538SAndroid Build Coastguard Worker env=test_env, 716*6777b538SAndroid Build Coastguard Worker stdout=test_stdout, 717*6777b538SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 718*6777b538SAndroid Build Coastguard Worker if should_symbolize: 719*6777b538SAndroid Build Coastguard Worker logging.info('Symbolizing test logs with asan symbolizer.') 720*6777b538SAndroid Build Coastguard Worker test_symbolize_process = subprocess.Popen([_ASAN_SYMBOLIZER_PATH], 721*6777b538SAndroid Build Coastguard Worker stdin=test_process.stdout) 722*6777b538SAndroid Build Coastguard Worker # Allow test_process to receive a SIGPIPE if symbolize process exits. 723*6777b538SAndroid Build Coastguard Worker test_process.stdout.close() 724*6777b538SAndroid Build Coastguard Worker return test_process.wait() 725*6777b538SAndroid Build Coastguard Worker 726*6777b538SAndroid Build Coastguard Worker finally: 727*6777b538SAndroid Build Coastguard Worker _KillNicely(ash_process) 728*6777b538SAndroid Build Coastguard Worker # Give symbolizer processes time to finish writing with first_wait_secs. 729*6777b538SAndroid Build Coastguard Worker _KillNicely(ash_symbolize_process, first_wait_secs=1) 730*6777b538SAndroid Build Coastguard Worker _KillNicely(test_symbolize_process, first_wait_secs=1) 731*6777b538SAndroid Build Coastguard Worker 732*6777b538SAndroid Build Coastguard Worker shutil.rmtree(tmp_xdg_dir_name, ignore_errors=True) 733*6777b538SAndroid Build Coastguard Worker shutil.rmtree(tmp_ash_data_dir_name, ignore_errors=True) 734*6777b538SAndroid Build Coastguard Worker shutil.rmtree(tmp_unique_ash_dir_name, ignore_errors=True) 735*6777b538SAndroid Build Coastguard Worker 736*6777b538SAndroid Build Coastguard Worker 737*6777b538SAndroid Build Coastguard Workerdef _RunTestDirectly(args, forward_args): 738*6777b538SAndroid Build Coastguard Worker """Runs tests by invoking the test command directly. 739*6777b538SAndroid Build Coastguard Worker 740*6777b538SAndroid Build Coastguard Worker args (dict): Args for this script. 741*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 742*6777b538SAndroid Build Coastguard Worker """ 743*6777b538SAndroid Build Coastguard Worker try: 744*6777b538SAndroid Build Coastguard Worker p = None 745*6777b538SAndroid Build Coastguard Worker p = subprocess.Popen([args.command] + forward_args) 746*6777b538SAndroid Build Coastguard Worker return p.wait() 747*6777b538SAndroid Build Coastguard Worker finally: 748*6777b538SAndroid Build Coastguard Worker _KillNicely(p) 749*6777b538SAndroid Build Coastguard Worker 750*6777b538SAndroid Build Coastguard Worker 751*6777b538SAndroid Build Coastguard Workerdef _HandleSignal(sig, _): 752*6777b538SAndroid Build Coastguard Worker """Handles received signals to make sure spawned test process are killed. 753*6777b538SAndroid Build Coastguard Worker 754*6777b538SAndroid Build Coastguard Worker sig (int): An integer representing the received signal, for example SIGTERM. 755*6777b538SAndroid Build Coastguard Worker """ 756*6777b538SAndroid Build Coastguard Worker logging.warning('Received signal: %d, killing spawned processes', sig) 757*6777b538SAndroid Build Coastguard Worker 758*6777b538SAndroid Build Coastguard Worker # Don't do any cleanup here, instead, leave it to the finally blocks. 759*6777b538SAndroid Build Coastguard Worker # Assumption is based on https://docs.python.org/3/library/sys.html#sys.exit: 760*6777b538SAndroid Build Coastguard Worker # cleanup actions specified by finally clauses of try statements are honored. 761*6777b538SAndroid Build Coastguard Worker 762*6777b538SAndroid Build Coastguard Worker # https://tldp.org/LDP/abs/html/exitcodes.html: 763*6777b538SAndroid Build Coastguard Worker # Exit code 128+n -> Fatal error signal "n". 764*6777b538SAndroid Build Coastguard Worker sys.exit(128 + sig) 765*6777b538SAndroid Build Coastguard Worker 766*6777b538SAndroid Build Coastguard Worker 767*6777b538SAndroid Build Coastguard Workerdef _ExpandFilterFileIfNeeded(test_target, forward_args): 768*6777b538SAndroid Build Coastguard Worker if (test_target in _DEFAULT_FILTER_FILES_MAPPING.keys() and not any( 769*6777b538SAndroid Build Coastguard Worker [arg.startswith('--test-launcher-filter-file') for arg in forward_args])): 770*6777b538SAndroid Build Coastguard Worker file_path = os.path.abspath( 771*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.dirname(__file__), '..', '..', 'testing', 772*6777b538SAndroid Build Coastguard Worker 'buildbot', 'filters', 773*6777b538SAndroid Build Coastguard Worker _DEFAULT_FILTER_FILES_MAPPING[test_target])) 774*6777b538SAndroid Build Coastguard Worker forward_args.append(f'--test-launcher-filter-file={file_path}') 775*6777b538SAndroid Build Coastguard Worker 776*6777b538SAndroid Build Coastguard Worker 777*6777b538SAndroid Build Coastguard Workerdef _RunTest(args, forward_args): 778*6777b538SAndroid Build Coastguard Worker """Runs tests with given args. 779*6777b538SAndroid Build Coastguard Worker 780*6777b538SAndroid Build Coastguard Worker args (dict): Args for this script. 781*6777b538SAndroid Build Coastguard Worker forward_args (list): Args to be forwarded to the test command. 782*6777b538SAndroid Build Coastguard Worker 783*6777b538SAndroid Build Coastguard Worker Raises: 784*6777b538SAndroid Build Coastguard Worker RuntimeError: If the given test binary doesn't exist or the test runner 785*6777b538SAndroid Build Coastguard Worker doesn't know how to run it. 786*6777b538SAndroid Build Coastguard Worker """ 787*6777b538SAndroid Build Coastguard Worker 788*6777b538SAndroid Build Coastguard Worker if not os.path.isfile(args.command): 789*6777b538SAndroid Build Coastguard Worker raise RuntimeError('Specified test command: "%s" doesn\'t exist' % 790*6777b538SAndroid Build Coastguard Worker args.command) 791*6777b538SAndroid Build Coastguard Worker 792*6777b538SAndroid Build Coastguard Worker test_target = os.path.basename(args.command) 793*6777b538SAndroid Build Coastguard Worker _ExpandFilterFileIfNeeded(test_target, forward_args) 794*6777b538SAndroid Build Coastguard Worker 795*6777b538SAndroid Build Coastguard Worker # |_TARGETS_REQUIRE_ASH_CHROME| may not always be accurate as it is updated 796*6777b538SAndroid Build Coastguard Worker # with a best effort only, therefore, allow the invoker to override the 797*6777b538SAndroid Build Coastguard Worker # behavior with a specified ash-chrome version, which makes sure that 798*6777b538SAndroid Build Coastguard Worker # automated CI/CQ builders would always work correctly. 799*6777b538SAndroid Build Coastguard Worker requires_ash_chrome = any( 800*6777b538SAndroid Build Coastguard Worker re.match(t, test_target) for t in _TARGETS_REQUIRE_ASH_CHROME) 801*6777b538SAndroid Build Coastguard Worker if not requires_ash_chrome and not args.ash_chrome_version: 802*6777b538SAndroid Build Coastguard Worker return _RunTestDirectly(args, forward_args) 803*6777b538SAndroid Build Coastguard Worker 804*6777b538SAndroid Build Coastguard Worker return _RunTestWithAshChrome(args, forward_args) 805*6777b538SAndroid Build Coastguard Worker 806*6777b538SAndroid Build Coastguard Worker 807*6777b538SAndroid Build Coastguard Workerdef Main(): 808*6777b538SAndroid Build Coastguard Worker for sig in (signal.SIGTERM, signal.SIGINT): 809*6777b538SAndroid Build Coastguard Worker signal.signal(sig, _HandleSignal) 810*6777b538SAndroid Build Coastguard Worker 811*6777b538SAndroid Build Coastguard Worker logging.basicConfig(level=logging.INFO) 812*6777b538SAndroid Build Coastguard Worker arg_parser = argparse.ArgumentParser() 813*6777b538SAndroid Build Coastguard Worker arg_parser.usage = __doc__ 814*6777b538SAndroid Build Coastguard Worker 815*6777b538SAndroid Build Coastguard Worker subparsers = arg_parser.add_subparsers() 816*6777b538SAndroid Build Coastguard Worker 817*6777b538SAndroid Build Coastguard Worker test_parser = subparsers.add_parser('test', help='Run tests') 818*6777b538SAndroid Build Coastguard Worker test_parser.set_defaults(func=_RunTest) 819*6777b538SAndroid Build Coastguard Worker 820*6777b538SAndroid Build Coastguard Worker test_parser.add_argument( 821*6777b538SAndroid Build Coastguard Worker 'command', 822*6777b538SAndroid Build Coastguard Worker help='A single command to invoke the tests, for example: ' 823*6777b538SAndroid Build Coastguard Worker '"./url_unittests". Any argument unknown to this test runner script will ' 824*6777b538SAndroid Build Coastguard Worker 'be forwarded to the command, for example: "--gtest_filter=Suite.Test"') 825*6777b538SAndroid Build Coastguard Worker 826*6777b538SAndroid Build Coastguard Worker version_group = test_parser.add_mutually_exclusive_group() 827*6777b538SAndroid Build Coastguard Worker version_group.add_argument( 828*6777b538SAndroid Build Coastguard Worker '--ash-chrome-version', 829*6777b538SAndroid Build Coastguard Worker type=str, 830*6777b538SAndroid Build Coastguard Worker help='Version of an prebuilt ash-chrome to use for testing, for example: ' 831*6777b538SAndroid Build Coastguard Worker '"120.0.6099.0", and the version corresponds to the commit position of ' 832*6777b538SAndroid Build Coastguard Worker 'commits on the main branch. If not specified, will use the latest ' 833*6777b538SAndroid Build Coastguard Worker 'version available') 834*6777b538SAndroid Build Coastguard Worker version_group.add_argument( 835*6777b538SAndroid Build Coastguard Worker '--ash-chrome-path', 836*6777b538SAndroid Build Coastguard Worker type=str, 837*6777b538SAndroid Build Coastguard Worker help='Path to an locally built ash-chrome to use for testing. ' 838*6777b538SAndroid Build Coastguard Worker 'In general you should build //chrome/test:test_ash_chrome.') 839*6777b538SAndroid Build Coastguard Worker 840*6777b538SAndroid Build Coastguard Worker debugger_group = test_parser.add_mutually_exclusive_group() 841*6777b538SAndroid Build Coastguard Worker debugger_group.add_argument('--gdb', 842*6777b538SAndroid Build Coastguard Worker action='store_true', 843*6777b538SAndroid Build Coastguard Worker help='Run the test in GDB.') 844*6777b538SAndroid Build Coastguard Worker debugger_group.add_argument('--lldb', 845*6777b538SAndroid Build Coastguard Worker action='store_true', 846*6777b538SAndroid Build Coastguard Worker help='Run the test in LLDB.') 847*6777b538SAndroid Build Coastguard Worker 848*6777b538SAndroid Build Coastguard Worker # This is for version skew testing. The current CI/CQ builder builds 849*6777b538SAndroid Build Coastguard Worker # an ash chrome and pass it using --ash-chrome-path. In order to use the same 850*6777b538SAndroid Build Coastguard Worker # builder for version skew testing, we use a new argument to override 851*6777b538SAndroid Build Coastguard Worker # the ash chrome. 852*6777b538SAndroid Build Coastguard Worker test_parser.add_argument( 853*6777b538SAndroid Build Coastguard Worker '--ash-chrome-path-override', 854*6777b538SAndroid Build Coastguard Worker type=str, 855*6777b538SAndroid Build Coastguard Worker help='The same as --ash-chrome-path. But this will override ' 856*6777b538SAndroid Build Coastguard Worker '--ash-chrome-path or --ash-chrome-version if any of these ' 857*6777b538SAndroid Build Coastguard Worker 'arguments exist.') 858*6777b538SAndroid Build Coastguard Worker test_parser.add_argument( 859*6777b538SAndroid Build Coastguard Worker '--ash-logging-path', 860*6777b538SAndroid Build Coastguard Worker type=str, 861*6777b538SAndroid Build Coastguard Worker help='File & path to ash-chrome logging output while running Lacros ' 862*6777b538SAndroid Build Coastguard Worker 'browser tests. If not provided, no output will be generated.') 863*6777b538SAndroid Build Coastguard Worker test_parser.add_argument('--combine-ash-logs-on-bots', 864*6777b538SAndroid Build Coastguard Worker action='store_true', 865*6777b538SAndroid Build Coastguard Worker help='Whether to combine ash logs on bots.') 866*6777b538SAndroid Build Coastguard Worker test_parser.add_argument( 867*6777b538SAndroid Build Coastguard Worker '--asan-symbolize-output', 868*6777b538SAndroid Build Coastguard Worker action='store_true', 869*6777b538SAndroid Build Coastguard Worker help='Whether to run subprocess log outputs through the asan symbolizer.') 870*6777b538SAndroid Build Coastguard Worker 871*6777b538SAndroid Build Coastguard Worker args = arg_parser.parse_known_args() 872*6777b538SAndroid Build Coastguard Worker if not hasattr(args[0], "func"): 873*6777b538SAndroid Build Coastguard Worker # No command specified. 874*6777b538SAndroid Build Coastguard Worker print(__doc__) 875*6777b538SAndroid Build Coastguard Worker sys.exit(1) 876*6777b538SAndroid Build Coastguard Worker 877*6777b538SAndroid Build Coastguard Worker return args[0].func(args[0], args[1]) 878*6777b538SAndroid Build Coastguard Worker 879*6777b538SAndroid Build Coastguard Worker 880*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__': 881*6777b538SAndroid Build Coastguard Worker sys.exit(Main()) 882