1*bb4ee6a4SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*bb4ee6a4SAndroid Build Coastguard Worker# Copyright 2023 The ChromiumOS Authors 3*bb4ee6a4SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*bb4ee6a4SAndroid Build Coastguard Worker# found in the LICENSE file. 5*bb4ee6a4SAndroid Build Coastguard Worker 6*bb4ee6a4SAndroid Build Coastguard Workerimport copy 7*bb4ee6a4SAndroid Build Coastguard Workerimport os 8*bb4ee6a4SAndroid Build Coastguard Workerfrom pathlib import Path 9*bb4ee6a4SAndroid Build Coastguard Workerimport sys 10*bb4ee6a4SAndroid Build Coastguard Workerfrom typing import Any, Iterable, List, Optional, Union 11*bb4ee6a4SAndroid Build Coastguard Workerfrom impl.common import ( 12*bb4ee6a4SAndroid Build Coastguard Worker CROSVM_ROOT, 13*bb4ee6a4SAndroid Build Coastguard Worker TOOLS_ROOT, 14*bb4ee6a4SAndroid Build Coastguard Worker Command, 15*bb4ee6a4SAndroid Build Coastguard Worker Remote, 16*bb4ee6a4SAndroid Build Coastguard Worker quoted, 17*bb4ee6a4SAndroid Build Coastguard Worker Styles, 18*bb4ee6a4SAndroid Build Coastguard Worker argh, 19*bb4ee6a4SAndroid Build Coastguard Worker console, 20*bb4ee6a4SAndroid Build Coastguard Worker chdir, 21*bb4ee6a4SAndroid Build Coastguard Worker cmd, 22*bb4ee6a4SAndroid Build Coastguard Worker record_time, 23*bb4ee6a4SAndroid Build Coastguard Worker run_main, 24*bb4ee6a4SAndroid Build Coastguard Worker sudo_is_passwordless, 25*bb4ee6a4SAndroid Build Coastguard Worker verbose, 26*bb4ee6a4SAndroid Build Coastguard Worker Triple, 27*bb4ee6a4SAndroid Build Coastguard Worker) 28*bb4ee6a4SAndroid Build Coastguard Workerfrom impl.test_config import ROOT_TESTS, DO_NOT_RUN, DO_NOT_RUN_AARCH64, DO_NOT_RUN_WIN64, E2E_TESTS 29*bb4ee6a4SAndroid Build Coastguard Workerfrom impl.test_config import DO_NOT_BUILD_RISCV64, DO_NOT_RUN_WINE64 30*bb4ee6a4SAndroid Build Coastguard Workerfrom impl import testvm 31*bb4ee6a4SAndroid Build Coastguard Worker 32*bb4ee6a4SAndroid Build Coastguard Workerrsync = cmd("rsync") 33*bb4ee6a4SAndroid Build Coastguard Workercargo = cmd("cargo") 34*bb4ee6a4SAndroid Build Coastguard Worker 35*bb4ee6a4SAndroid Build Coastguard Worker# Name of the directory used to package all test files. 36*bb4ee6a4SAndroid Build Coastguard WorkerPACKAGE_NAME = "integration_tests_package" 37*bb4ee6a4SAndroid Build Coastguard Worker 38*bb4ee6a4SAndroid Build Coastguard Worker 39*bb4ee6a4SAndroid Build Coastguard Workerdef join_filters(items: Iterable[str], op: str): 40*bb4ee6a4SAndroid Build Coastguard Worker return op.join(f"({i})" for i in items) 41*bb4ee6a4SAndroid Build Coastguard Worker 42*bb4ee6a4SAndroid Build Coastguard Worker 43*bb4ee6a4SAndroid Build Coastguard Workerclass TestFilter(object): 44*bb4ee6a4SAndroid Build Coastguard Worker """ 45*bb4ee6a4SAndroid Build Coastguard Worker Utility structure to join user-provided filter expressions with additional filters 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker See https://nexte.st/book/filter-expressions.html 48*bb4ee6a4SAndroid Build Coastguard Worker """ 49*bb4ee6a4SAndroid Build Coastguard Worker 50*bb4ee6a4SAndroid Build Coastguard Worker def __init__(self, expression: str): 51*bb4ee6a4SAndroid Build Coastguard Worker self.expression = expression 52*bb4ee6a4SAndroid Build Coastguard Worker 53*bb4ee6a4SAndroid Build Coastguard Worker def exclude(self, *exclude_exprs: str): 54*bb4ee6a4SAndroid Build Coastguard Worker return self.subset(f"not ({join_filters(exclude_exprs, '|')})") 55*bb4ee6a4SAndroid Build Coastguard Worker 56*bb4ee6a4SAndroid Build Coastguard Worker def include(self, *include_exprs: str): 57*bb4ee6a4SAndroid Build Coastguard Worker include_expr = join_filters(include_exprs, "|") 58*bb4ee6a4SAndroid Build Coastguard Worker return TestFilter(f"({self.expression}) | ({include_expr})") 59*bb4ee6a4SAndroid Build Coastguard Worker 60*bb4ee6a4SAndroid Build Coastguard Worker def subset(self, *subset_exprs: str): 61*bb4ee6a4SAndroid Build Coastguard Worker subset_expr = join_filters(subset_exprs, "|") 62*bb4ee6a4SAndroid Build Coastguard Worker if not self.expression: 63*bb4ee6a4SAndroid Build Coastguard Worker return TestFilter(subset_expr) 64*bb4ee6a4SAndroid Build Coastguard Worker return TestFilter(f"({self.expression}) & ({subset_expr})") 65*bb4ee6a4SAndroid Build Coastguard Worker 66*bb4ee6a4SAndroid Build Coastguard Worker def to_args(self): 67*bb4ee6a4SAndroid Build Coastguard Worker if not self.expression: 68*bb4ee6a4SAndroid Build Coastguard Worker return 69*bb4ee6a4SAndroid Build Coastguard Worker yield "--filter-expr" 70*bb4ee6a4SAndroid Build Coastguard Worker yield quoted(self.expression) 71*bb4ee6a4SAndroid Build Coastguard Worker 72*bb4ee6a4SAndroid Build Coastguard Worker 73*bb4ee6a4SAndroid Build Coastguard Workerdef configure_cargo( 74*bb4ee6a4SAndroid Build Coastguard Worker cmd: Command, triple: Triple, features: Optional[str], no_default_features: bool 75*bb4ee6a4SAndroid Build Coastguard Worker): 76*bb4ee6a4SAndroid Build Coastguard Worker "Configures the provided cmd with cargo arguments and environment needed to build for triple." 77*bb4ee6a4SAndroid Build Coastguard Worker return ( 78*bb4ee6a4SAndroid Build Coastguard Worker cmd.with_args( 79*bb4ee6a4SAndroid Build Coastguard Worker "--workspace", 80*bb4ee6a4SAndroid Build Coastguard Worker "--no-default-features" if no_default_features else None, 81*bb4ee6a4SAndroid Build Coastguard Worker f"--features={features}" if features else None, 82*bb4ee6a4SAndroid Build Coastguard Worker ) 83*bb4ee6a4SAndroid Build Coastguard Worker .with_color_flag() 84*bb4ee6a4SAndroid Build Coastguard Worker .with_envs(triple.get_cargo_env()) 85*bb4ee6a4SAndroid Build Coastguard Worker ) 86*bb4ee6a4SAndroid Build Coastguard Worker 87*bb4ee6a4SAndroid Build Coastguard Worker 88*bb4ee6a4SAndroid Build Coastguard Workerclass HostTarget(object): 89*bb4ee6a4SAndroid Build Coastguard Worker def __init__(self, package_dir: Path): 90*bb4ee6a4SAndroid Build Coastguard Worker self.run_cmd = cmd(package_dir / "run.sh").with_color_flag() 91*bb4ee6a4SAndroid Build Coastguard Worker 92*bb4ee6a4SAndroid Build Coastguard Worker def run_tests(self, extra_args: List[Any]): 93*bb4ee6a4SAndroid Build Coastguard Worker return self.run_cmd.with_args(*extra_args).fg(style=Styles.live_truncated(), check=False) 94*bb4ee6a4SAndroid Build Coastguard Worker 95*bb4ee6a4SAndroid Build Coastguard Worker 96*bb4ee6a4SAndroid Build Coastguard Workerclass SshTarget(object): 97*bb4ee6a4SAndroid Build Coastguard Worker def __init__(self, package_archive: Path, remote: Remote): 98*bb4ee6a4SAndroid Build Coastguard Worker console.print("Transfering integration tests package...") 99*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Transfering"): 100*bb4ee6a4SAndroid Build Coastguard Worker remote.scp([package_archive], "") 101*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Unpacking"): 102*bb4ee6a4SAndroid Build Coastguard Worker remote.ssh(cmd("tar xaf", package_archive.name)).fg(style=Styles.live_truncated()) 103*bb4ee6a4SAndroid Build Coastguard Worker self.remote_run_cmd = cmd(f"{PACKAGE_NAME}/run.sh").with_color_flag() 104*bb4ee6a4SAndroid Build Coastguard Worker self.remote = remote 105*bb4ee6a4SAndroid Build Coastguard Worker 106*bb4ee6a4SAndroid Build Coastguard Worker def run_tests(self, extra_args: List[Any]): 107*bb4ee6a4SAndroid Build Coastguard Worker return self.remote.ssh(self.remote_run_cmd.with_args(*extra_args)).fg( 108*bb4ee6a4SAndroid Build Coastguard Worker style=Styles.live_truncated(), 109*bb4ee6a4SAndroid Build Coastguard Worker check=False, 110*bb4ee6a4SAndroid Build Coastguard Worker ) 111*bb4ee6a4SAndroid Build Coastguard Worker 112*bb4ee6a4SAndroid Build Coastguard Worker 113*bb4ee6a4SAndroid Build Coastguard Workerdef check_host_prerequisites(run_root_tests: bool): 114*bb4ee6a4SAndroid Build Coastguard Worker "Check various prerequisites for executing test binaries." 115*bb4ee6a4SAndroid Build Coastguard Worker if os.name == "nt": 116*bb4ee6a4SAndroid Build Coastguard Worker return 117*bb4ee6a4SAndroid Build Coastguard Worker 118*bb4ee6a4SAndroid Build Coastguard Worker if run_root_tests: 119*bb4ee6a4SAndroid Build Coastguard Worker console.print("Running tests that require root privileges. Refreshing sudo now.") 120*bb4ee6a4SAndroid Build Coastguard Worker cmd("sudo true").fg() 121*bb4ee6a4SAndroid Build Coastguard Worker 122*bb4ee6a4SAndroid Build Coastguard Worker for device in ["/dev/kvm", "/dev/vhost-vsock"]: 123*bb4ee6a4SAndroid Build Coastguard Worker if not os.access(device, os.R_OK | os.W_OK): 124*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"{device} access is required", style="red") 125*bb4ee6a4SAndroid Build Coastguard Worker sys.exit(1) 126*bb4ee6a4SAndroid Build Coastguard Worker 127*bb4ee6a4SAndroid Build Coastguard Worker 128*bb4ee6a4SAndroid Build Coastguard Workerdef check_build_prerequisites(triple: Triple): 129*bb4ee6a4SAndroid Build Coastguard Worker installed_toolchains = cmd("rustup target list --installed").lines() 130*bb4ee6a4SAndroid Build Coastguard Worker if str(triple) not in installed_toolchains: 131*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"Your host is not configured to build for [green]{triple}[/green]") 132*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"[green]Tip:[/green] Run tests in the dev container with:") 133*bb4ee6a4SAndroid Build Coastguard Worker console.print() 134*bb4ee6a4SAndroid Build Coastguard Worker console.print( 135*bb4ee6a4SAndroid Build Coastguard Worker f" [blue]$ tools/dev_container tools/run_tests {' '.join(sys.argv[1:])}[/blue]" 136*bb4ee6a4SAndroid Build Coastguard Worker ) 137*bb4ee6a4SAndroid Build Coastguard Worker sys.exit(1) 138*bb4ee6a4SAndroid Build Coastguard Worker 139*bb4ee6a4SAndroid Build Coastguard Worker 140*bb4ee6a4SAndroid Build Coastguard Workerdef get_vm_arch(triple: Triple): 141*bb4ee6a4SAndroid Build Coastguard Worker if str(triple) == "x86_64-unknown-linux-gnu": 142*bb4ee6a4SAndroid Build Coastguard Worker return "x86_64" 143*bb4ee6a4SAndroid Build Coastguard Worker elif str(triple) == "aarch64-unknown-linux-gnu": 144*bb4ee6a4SAndroid Build Coastguard Worker return "aarch64" 145*bb4ee6a4SAndroid Build Coastguard Worker elif str(triple) == "riscv64gc-unknown-linux-gnu": 146*bb4ee6a4SAndroid Build Coastguard Worker return "riscv64" 147*bb4ee6a4SAndroid Build Coastguard Worker else: 148*bb4ee6a4SAndroid Build Coastguard Worker raise Exception(f"{triple} is not supported for running tests in a VM.") 149*bb4ee6a4SAndroid Build Coastguard Worker 150*bb4ee6a4SAndroid Build Coastguard Worker 151*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--filter-expr", "-E", type=str, action="append", help="Nextest filter expression.") 152*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg( 153*bb4ee6a4SAndroid Build Coastguard Worker "--platform", "-p", help="Which platform to test. (x86_64, aarch64, armhw, mingw64, riscv64)" 154*bb4ee6a4SAndroid Build Coastguard Worker) 155*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--dut", help="Which device to test on. (vm or host)") 156*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-default-features", help="Don't enable default features") 157*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-run", "--build-only", help="Build only, do not run any tests.") 158*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-unit-tests", help="Do not run unit tests.") 159*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-integration-tests", help="Do not run integration tests.") 160*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-strip", help="Do not strip test binaries of debug info.") 161*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--run-root-tests", help="Enables integration tests that require root privileges.") 162*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg( 163*bb4ee6a4SAndroid Build Coastguard Worker "--features", 164*bb4ee6a4SAndroid Build Coastguard Worker help=f"List of comma separated features to be passed to cargo. Defaults to `all-$platform`", 165*bb4ee6a4SAndroid Build Coastguard Worker) 166*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--no-parallel", help="Do not parallelize integration tests. Slower but more stable.") 167*bb4ee6a4SAndroid Build Coastguard Worker@argh.arg("--repetitions", help="Repeat all tests, useful for checking test stability.") 168*bb4ee6a4SAndroid Build Coastguard Workerdef main( 169*bb4ee6a4SAndroid Build Coastguard Worker filter_expr: List[str] = [], 170*bb4ee6a4SAndroid Build Coastguard Worker platform: Optional[str] = None, 171*bb4ee6a4SAndroid Build Coastguard Worker dut: Optional[str] = None, 172*bb4ee6a4SAndroid Build Coastguard Worker no_default_features: bool = False, 173*bb4ee6a4SAndroid Build Coastguard Worker no_run: bool = False, 174*bb4ee6a4SAndroid Build Coastguard Worker no_unit_tests: bool = False, 175*bb4ee6a4SAndroid Build Coastguard Worker no_integration_tests: bool = False, 176*bb4ee6a4SAndroid Build Coastguard Worker no_strip: bool = False, 177*bb4ee6a4SAndroid Build Coastguard Worker run_root_tests: bool = False, 178*bb4ee6a4SAndroid Build Coastguard Worker features: Optional[str] = None, 179*bb4ee6a4SAndroid Build Coastguard Worker no_parallel: bool = False, 180*bb4ee6a4SAndroid Build Coastguard Worker repetitions: int = 1, 181*bb4ee6a4SAndroid Build Coastguard Worker): 182*bb4ee6a4SAndroid Build Coastguard Worker """ 183*bb4ee6a4SAndroid Build Coastguard Worker Runs all crosvm tests 184*bb4ee6a4SAndroid Build Coastguard Worker 185*bb4ee6a4SAndroid Build Coastguard Worker For details on how crosvm tests are organized, see https://crosvm.dev/book/testing/index.html 186*bb4ee6a4SAndroid Build Coastguard Worker 187*bb4ee6a4SAndroid Build Coastguard Worker # Basic Usage 188*bb4ee6a4SAndroid Build Coastguard Worker 189*bb4ee6a4SAndroid Build Coastguard Worker To run all unit tests for the hosts native architecture: 190*bb4ee6a4SAndroid Build Coastguard Worker 191*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests 192*bb4ee6a4SAndroid Build Coastguard Worker 193*bb4ee6a4SAndroid Build Coastguard Worker To run all unit tests for another supported architecture using an emulator (e.g. wine64, 194*bb4ee6a4SAndroid Build Coastguard Worker qemu user space emulation). 195*bb4ee6a4SAndroid Build Coastguard Worker 196*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests -p aarch64 197*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests -p armhw 198*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests -p mingw64 199*bb4ee6a4SAndroid Build Coastguard Worker 200*bb4ee6a4SAndroid Build Coastguard Worker # Integration Tests 201*bb4ee6a4SAndroid Build Coastguard Worker 202*bb4ee6a4SAndroid Build Coastguard Worker Integration tests can be run on a built-in virtual machine: 203*bb4ee6a4SAndroid Build Coastguard Worker 204*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests --dut=vm 205*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests --dut=vm -p aarch64 206*bb4ee6a4SAndroid Build Coastguard Worker 207*bb4ee6a4SAndroid Build Coastguard Worker The virtual machine is automatically started for the test process and can be managed via the 208*bb4ee6a4SAndroid Build Coastguard Worker `./tools/x86vm` or `./tools/aarch64vm` tools. 209*bb4ee6a4SAndroid Build Coastguard Worker 210*bb4ee6a4SAndroid Build Coastguard Worker Integration tests can be run on the host machine as well, but cannot be guaranteed to work on 211*bb4ee6a4SAndroid Build Coastguard Worker all configurations. 212*bb4ee6a4SAndroid Build Coastguard Worker 213*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests --dut=host 214*bb4ee6a4SAndroid Build Coastguard Worker 215*bb4ee6a4SAndroid Build Coastguard Worker # Test Filtering 216*bb4ee6a4SAndroid Build Coastguard Worker 217*bb4ee6a4SAndroid Build Coastguard Worker This script supports nextest filter expressions: https://nexte.st/book/filter-expressions.html 218*bb4ee6a4SAndroid Build Coastguard Worker 219*bb4ee6a4SAndroid Build Coastguard Worker For example to run all tests in `my-crate` and all crates that depend on it: 220*bb4ee6a4SAndroid Build Coastguard Worker 221*bb4ee6a4SAndroid Build Coastguard Worker $ ./tools/run_tests [--dut=] -E 'rdeps(my-crate)' 222*bb4ee6a4SAndroid Build Coastguard Worker """ 223*bb4ee6a4SAndroid Build Coastguard Worker chdir(CROSVM_ROOT) 224*bb4ee6a4SAndroid Build Coastguard Worker 225*bb4ee6a4SAndroid Build Coastguard Worker if os.name == "posix" and not cmd("which cargo-nextest").success(): 226*bb4ee6a4SAndroid Build Coastguard Worker raise Exception("Cannot find cargo-nextest. Please re-run `./tools/install-deps`") 227*bb4ee6a4SAndroid Build Coastguard Worker elif os.name == "nt" and not cmd("where.exe cargo-nextest.exe").success(): 228*bb4ee6a4SAndroid Build Coastguard Worker raise Exception("Cannot find cargo-nextest. Please re-run `./tools/install-deps.ps1`") 229*bb4ee6a4SAndroid Build Coastguard Worker 230*bb4ee6a4SAndroid Build Coastguard Worker triple = Triple.from_shorthand(platform) if platform else Triple.host_default() 231*bb4ee6a4SAndroid Build Coastguard Worker 232*bb4ee6a4SAndroid Build Coastguard Worker test_filter = TestFilter(join_filters(filter_expr, "|")) 233*bb4ee6a4SAndroid Build Coastguard Worker 234*bb4ee6a4SAndroid Build Coastguard Worker if not features and not no_default_features: 235*bb4ee6a4SAndroid Build Coastguard Worker features = triple.feature_flag 236*bb4ee6a4SAndroid Build Coastguard Worker 237*bb4ee6a4SAndroid Build Coastguard Worker if no_run: 238*bb4ee6a4SAndroid Build Coastguard Worker no_integration_tests = True 239*bb4ee6a4SAndroid Build Coastguard Worker no_unit_tests = True 240*bb4ee6a4SAndroid Build Coastguard Worker 241*bb4ee6a4SAndroid Build Coastguard Worker # Disable the DUT if integration tests are not run. 242*bb4ee6a4SAndroid Build Coastguard Worker if no_integration_tests: 243*bb4ee6a4SAndroid Build Coastguard Worker dut = None 244*bb4ee6a4SAndroid Build Coastguard Worker 245*bb4ee6a4SAndroid Build Coastguard Worker # Automatically enable tests that require root if sudo is passwordless 246*bb4ee6a4SAndroid Build Coastguard Worker if not run_root_tests: 247*bb4ee6a4SAndroid Build Coastguard Worker if dut == "host": 248*bb4ee6a4SAndroid Build Coastguard Worker run_root_tests = sudo_is_passwordless() 249*bb4ee6a4SAndroid Build Coastguard Worker elif dut == "vm": 250*bb4ee6a4SAndroid Build Coastguard Worker # The test VMs have passwordless sudo configured. 251*bb4ee6a4SAndroid Build Coastguard Worker run_root_tests = True 252*bb4ee6a4SAndroid Build Coastguard Worker 253*bb4ee6a4SAndroid Build Coastguard Worker # Print summary of tests and where they will be executed. 254*bb4ee6a4SAndroid Build Coastguard Worker if dut == "host": 255*bb4ee6a4SAndroid Build Coastguard Worker dut_str = "Run on host" 256*bb4ee6a4SAndroid Build Coastguard Worker elif dut == "vm" and os.name == "posix": 257*bb4ee6a4SAndroid Build Coastguard Worker dut_str = f"Run on built-in {get_vm_arch(triple)} vm" 258*bb4ee6a4SAndroid Build Coastguard Worker elif dut == None: 259*bb4ee6a4SAndroid Build Coastguard Worker dut_str = "[yellow]Skip[/yellow]" 260*bb4ee6a4SAndroid Build Coastguard Worker else: 261*bb4ee6a4SAndroid Build Coastguard Worker raise Exception( 262*bb4ee6a4SAndroid Build Coastguard Worker f"--dut={dut} is not supported. Options are --dut=host or --dut=vm (linux only)" 263*bb4ee6a4SAndroid Build Coastguard Worker ) 264*bb4ee6a4SAndroid Build Coastguard Worker 265*bb4ee6a4SAndroid Build Coastguard Worker skip_str = "[yellow]skip[/yellow]" 266*bb4ee6a4SAndroid Build Coastguard Worker unit_test_str = "Run on host" if not no_unit_tests else skip_str 267*bb4ee6a4SAndroid Build Coastguard Worker integration_test_str = dut_str if dut else skip_str 268*bb4ee6a4SAndroid Build Coastguard Worker profile = os.environ.get("NEXTEST_PROFILE", "default") 269*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"Running tests for [green]{triple}[/green]") 270*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"Profile: [green]{profile}[/green]") 271*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"With features: [green]{features}[/green]") 272*bb4ee6a4SAndroid Build Coastguard Worker console.print(f"no-default-features: [green]{no_default_features}[/green]") 273*bb4ee6a4SAndroid Build Coastguard Worker console.print() 274*bb4ee6a4SAndroid Build Coastguard Worker console.print(f" Unit tests: [bold]{unit_test_str}[/bold]") 275*bb4ee6a4SAndroid Build Coastguard Worker console.print(f" Integration tests: [bold]{integration_test_str}[/bold]") 276*bb4ee6a4SAndroid Build Coastguard Worker console.print() 277*bb4ee6a4SAndroid Build Coastguard Worker 278*bb4ee6a4SAndroid Build Coastguard Worker check_build_prerequisites(triple) 279*bb4ee6a4SAndroid Build Coastguard Worker 280*bb4ee6a4SAndroid Build Coastguard Worker # Print tips in certain configurations. 281*bb4ee6a4SAndroid Build Coastguard Worker if dut and not run_root_tests: 282*bb4ee6a4SAndroid Build Coastguard Worker console.print( 283*bb4ee6a4SAndroid Build Coastguard Worker "[green]Tip:[/green] Skipping tests that require root privileges. " 284*bb4ee6a4SAndroid Build Coastguard Worker + "Use [bold]--run-root-tests[/bold] to enable them." 285*bb4ee6a4SAndroid Build Coastguard Worker ) 286*bb4ee6a4SAndroid Build Coastguard Worker if not dut: 287*bb4ee6a4SAndroid Build Coastguard Worker console.print( 288*bb4ee6a4SAndroid Build Coastguard Worker "[green]Tip:[/green] To run integration tests on a built-in VM: " 289*bb4ee6a4SAndroid Build Coastguard Worker + "Use [bold]--dut=vm[/bold] (preferred)" 290*bb4ee6a4SAndroid Build Coastguard Worker ) 291*bb4ee6a4SAndroid Build Coastguard Worker console.print( 292*bb4ee6a4SAndroid Build Coastguard Worker "[green]Tip:[/green] To run integration tests on the host: Use " 293*bb4ee6a4SAndroid Build Coastguard Worker + "[bold]--dut=host[/bold] (fast, but unreliable)" 294*bb4ee6a4SAndroid Build Coastguard Worker ) 295*bb4ee6a4SAndroid Build Coastguard Worker if dut == "vm": 296*bb4ee6a4SAndroid Build Coastguard Worker vm_arch = get_vm_arch(triple) 297*bb4ee6a4SAndroid Build Coastguard Worker if vm_arch == "x86_64": 298*bb4ee6a4SAndroid Build Coastguard Worker cli_tool = "tools/x86vm" 299*bb4ee6a4SAndroid Build Coastguard Worker elif vm_arch == "aarch64": 300*bb4ee6a4SAndroid Build Coastguard Worker cli_tool = "tools/aarch64vm" 301*bb4ee6a4SAndroid Build Coastguard Worker else: 302*bb4ee6a4SAndroid Build Coastguard Worker raise Exception(f"Unknown vm arch '{vm_arch}'") 303*bb4ee6a4SAndroid Build Coastguard Worker console.print( 304*bb4ee6a4SAndroid Build Coastguard Worker f"[green]Tip:[/green] The test VM will remain alive between tests. You can manage this VM with [bold]{cli_tool}[/bold]" 305*bb4ee6a4SAndroid Build Coastguard Worker ) 306*bb4ee6a4SAndroid Build Coastguard Worker 307*bb4ee6a4SAndroid Build Coastguard Worker # Prepare the dut for test execution 308*bb4ee6a4SAndroid Build Coastguard Worker if dut == "host": 309*bb4ee6a4SAndroid Build Coastguard Worker check_host_prerequisites(run_root_tests) 310*bb4ee6a4SAndroid Build Coastguard Worker if dut == "vm": 311*bb4ee6a4SAndroid Build Coastguard Worker # Start VM ahead of time but don't wait for it to boot. 312*bb4ee6a4SAndroid Build Coastguard Worker testvm.up(get_vm_arch(triple)) 313*bb4ee6a4SAndroid Build Coastguard Worker 314*bb4ee6a4SAndroid Build Coastguard Worker nextest_args = [ 315*bb4ee6a4SAndroid Build Coastguard Worker f"--profile={profile}" if profile else None, 316*bb4ee6a4SAndroid Build Coastguard Worker "--verbose" if verbose() else None, 317*bb4ee6a4SAndroid Build Coastguard Worker ] 318*bb4ee6a4SAndroid Build Coastguard Worker 319*bb4ee6a4SAndroid Build Coastguard Worker console.print() 320*bb4ee6a4SAndroid Build Coastguard Worker console.rule("Building tests") 321*bb4ee6a4SAndroid Build Coastguard Worker 322*bb4ee6a4SAndroid Build Coastguard Worker if triple == Triple.from_shorthand("riscv64"): 323*bb4ee6a4SAndroid Build Coastguard Worker nextest_args += ["--exclude=" + s for s in DO_NOT_BUILD_RISCV64] 324*bb4ee6a4SAndroid Build Coastguard Worker 325*bb4ee6a4SAndroid Build Coastguard Worker nextest_run = configure_cargo( 326*bb4ee6a4SAndroid Build Coastguard Worker cmd("cargo nextest run"), triple, features, no_default_features 327*bb4ee6a4SAndroid Build Coastguard Worker ).with_args(*nextest_args) 328*bb4ee6a4SAndroid Build Coastguard Worker 329*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Build"): 330*bb4ee6a4SAndroid Build Coastguard Worker returncode = nextest_run.with_args("--no-run").fg( 331*bb4ee6a4SAndroid Build Coastguard Worker style=Styles.live_truncated(), check=False 332*bb4ee6a4SAndroid Build Coastguard Worker ) 333*bb4ee6a4SAndroid Build Coastguard Worker if returncode != 0: 334*bb4ee6a4SAndroid Build Coastguard Worker sys.exit(returncode) 335*bb4ee6a4SAndroid Build Coastguard Worker 336*bb4ee6a4SAndroid Build Coastguard Worker if not no_unit_tests: 337*bb4ee6a4SAndroid Build Coastguard Worker unit_test_filter = copy.deepcopy(test_filter).exclude(*E2E_TESTS).include("kind(bench)") 338*bb4ee6a4SAndroid Build Coastguard Worker if triple == Triple.from_shorthand("mingw64") and os.name == "posix": 339*bb4ee6a4SAndroid Build Coastguard Worker unit_test_filter = unit_test_filter.exclude(*DO_NOT_RUN_WINE64) 340*bb4ee6a4SAndroid Build Coastguard Worker console.print() 341*bb4ee6a4SAndroid Build Coastguard Worker console.rule("Running unit tests") 342*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Unit Tests"): 343*bb4ee6a4SAndroid Build Coastguard Worker for i in range(repetitions): 344*bb4ee6a4SAndroid Build Coastguard Worker if repetitions > 1: 345*bb4ee6a4SAndroid Build Coastguard Worker console.rule(f"Round {i}", style="grey") 346*bb4ee6a4SAndroid Build Coastguard Worker 347*bb4ee6a4SAndroid Build Coastguard Worker returncode = nextest_run.with_args("--lib --bins", *unit_test_filter.to_args()).fg( 348*bb4ee6a4SAndroid Build Coastguard Worker style=Styles.live_truncated(), check=False 349*bb4ee6a4SAndroid Build Coastguard Worker ) 350*bb4ee6a4SAndroid Build Coastguard Worker if returncode != 0: 351*bb4ee6a4SAndroid Build Coastguard Worker sys.exit(returncode) 352*bb4ee6a4SAndroid Build Coastguard Worker 353*bb4ee6a4SAndroid Build Coastguard Worker if dut: 354*bb4ee6a4SAndroid Build Coastguard Worker package_dir = triple.target_dir / PACKAGE_NAME 355*bb4ee6a4SAndroid Build Coastguard Worker package_archive = package_dir.with_suffix(".tar.zst") 356*bb4ee6a4SAndroid Build Coastguard Worker nextest_package = configure_cargo( 357*bb4ee6a4SAndroid Build Coastguard Worker cmd(TOOLS_ROOT / "nextest_package"), triple, features, no_default_features 358*bb4ee6a4SAndroid Build Coastguard Worker ) 359*bb4ee6a4SAndroid Build Coastguard Worker 360*bb4ee6a4SAndroid Build Coastguard Worker test_exclusions = [*DO_NOT_RUN] 361*bb4ee6a4SAndroid Build Coastguard Worker if not run_root_tests: 362*bb4ee6a4SAndroid Build Coastguard Worker test_exclusions += ROOT_TESTS 363*bb4ee6a4SAndroid Build Coastguard Worker if triple == Triple.from_shorthand("mingw64"): 364*bb4ee6a4SAndroid Build Coastguard Worker test_exclusions += DO_NOT_RUN_WIN64 365*bb4ee6a4SAndroid Build Coastguard Worker if os.name == "posix": 366*bb4ee6a4SAndroid Build Coastguard Worker test_exclusions += DO_NOT_RUN_WINE64 367*bb4ee6a4SAndroid Build Coastguard Worker if triple == Triple.from_shorthand("aarch64"): 368*bb4ee6a4SAndroid Build Coastguard Worker test_exclusions += DO_NOT_RUN_AARCH64 369*bb4ee6a4SAndroid Build Coastguard Worker test_filter = test_filter.exclude(*test_exclusions) 370*bb4ee6a4SAndroid Build Coastguard Worker 371*bb4ee6a4SAndroid Build Coastguard Worker console.print() 372*bb4ee6a4SAndroid Build Coastguard Worker console.rule("Packaging integration tests") 373*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Packing"): 374*bb4ee6a4SAndroid Build Coastguard Worker nextest_package( 375*bb4ee6a4SAndroid Build Coastguard Worker "--test *", 376*bb4ee6a4SAndroid Build Coastguard Worker f"-d {package_dir}", 377*bb4ee6a4SAndroid Build Coastguard Worker f"-o {package_archive}" if dut != "host" else None, 378*bb4ee6a4SAndroid Build Coastguard Worker "--no-strip" if no_strip else None, 379*bb4ee6a4SAndroid Build Coastguard Worker *test_filter.to_args(), 380*bb4ee6a4SAndroid Build Coastguard Worker "--verbose" if verbose() else None, 381*bb4ee6a4SAndroid Build Coastguard Worker ).fg(style=Styles.live_truncated()) 382*bb4ee6a4SAndroid Build Coastguard Worker 383*bb4ee6a4SAndroid Build Coastguard Worker target: Union[HostTarget, SshTarget] 384*bb4ee6a4SAndroid Build Coastguard Worker if dut == "host": 385*bb4ee6a4SAndroid Build Coastguard Worker target = HostTarget(package_dir) 386*bb4ee6a4SAndroid Build Coastguard Worker elif dut == "vm": 387*bb4ee6a4SAndroid Build Coastguard Worker testvm.up(get_vm_arch(triple), wait=True) 388*bb4ee6a4SAndroid Build Coastguard Worker remote = Remote("localhost", testvm.ssh_opts(get_vm_arch(triple))) 389*bb4ee6a4SAndroid Build Coastguard Worker target = SshTarget(package_archive, remote) 390*bb4ee6a4SAndroid Build Coastguard Worker 391*bb4ee6a4SAndroid Build Coastguard Worker console.print() 392*bb4ee6a4SAndroid Build Coastguard Worker console.rule("Running integration tests") 393*bb4ee6a4SAndroid Build Coastguard Worker with record_time("Integration tests"): 394*bb4ee6a4SAndroid Build Coastguard Worker for i in range(repetitions): 395*bb4ee6a4SAndroid Build Coastguard Worker if repetitions > 1: 396*bb4ee6a4SAndroid Build Coastguard Worker console.rule(f"Round {i}", style="grey") 397*bb4ee6a4SAndroid Build Coastguard Worker returncode = target.run_tests( 398*bb4ee6a4SAndroid Build Coastguard Worker [ 399*bb4ee6a4SAndroid Build Coastguard Worker *test_filter.to_args(), 400*bb4ee6a4SAndroid Build Coastguard Worker *nextest_args, 401*bb4ee6a4SAndroid Build Coastguard Worker "--test-threads=1" if no_parallel else None, 402*bb4ee6a4SAndroid Build Coastguard Worker ] 403*bb4ee6a4SAndroid Build Coastguard Worker ) 404*bb4ee6a4SAndroid Build Coastguard Worker if returncode != 0: 405*bb4ee6a4SAndroid Build Coastguard Worker if not no_parallel: 406*bb4ee6a4SAndroid Build Coastguard Worker console.print( 407*bb4ee6a4SAndroid Build Coastguard Worker "[green]Tip:[/green] Tests may fail when run in parallel on some platforms. " 408*bb4ee6a4SAndroid Build Coastguard Worker + "Try re-running with `--no-parallel`" 409*bb4ee6a4SAndroid Build Coastguard Worker ) 410*bb4ee6a4SAndroid Build Coastguard Worker if dut == "host": 411*bb4ee6a4SAndroid Build Coastguard Worker console.print( 412*bb4ee6a4SAndroid Build Coastguard Worker f"[yellow]Tip:[/yellow] Running tests on the host may not be reliable. " 413*bb4ee6a4SAndroid Build Coastguard Worker "Prefer [bold]--dut=vm[/bold]." 414*bb4ee6a4SAndroid Build Coastguard Worker ) 415*bb4ee6a4SAndroid Build Coastguard Worker sys.exit(returncode) 416*bb4ee6a4SAndroid Build Coastguard Worker 417*bb4ee6a4SAndroid Build Coastguard Worker 418*bb4ee6a4SAndroid Build Coastguard Workerif __name__ == "__main__": 419*bb4ee6a4SAndroid Build Coastguard Worker run_main(main) 420