1#!/bin/sh 2"exec" "`dirname $0`/py3-cmd" "$0" "-c" "`dirname $0`/config.json" "$@" 3 4import argparse 5import logging 6import os 7from typing import List, Optional 8import sys 9 10 11import qemu 12import qemu_error 13 14__all__ = ["init", "run_test", "shutdown"] 15 16 17TRUSTY_PROJECT_FOLDER = os.path.dirname(os.path.realpath(__file__)) 18 19 20def init(*, android=None, instance_dir: os.PathLike, disable_rpmb=False, 21 verbose=False, debug_on_error=False 22) -> qemu.Runner: 23 24 with open(f"{TRUSTY_PROJECT_FOLDER}/config.json", encoding="utf-8") as json: 25 config = qemu.Config(json) 26 27 if android: 28 config.android_image_dir = qemu.find_android_image_dir(android) 29 config.adb = qemu.find_adb_path(android) 30 config.boot_android = True 31 32 runner = qemu.Runner(config, 33 interactive=False, 34 instance_dir=instance_dir, 35 verbose=verbose, 36 rpmb=not disable_rpmb, 37 debug=False, 38 debug_on_error=debug_on_error) 39 return runner 40 41 42def _check_args(args): 43 """Validate arguments passed to run_test.""" 44 assert args.headless, args 45 assert not args.linux, args 46 assert not args.atf, args 47 assert not args.qemu, args 48 assert not args.arch, args 49 assert not args.debug, args 50 assert not args.extra_qemu_flags, args 51 assert not args.disable_rpmb, args 52 53 54def _prepare_runner_for_test(runner, args): 55 """Check if the runner is in the correct state (BOOTLOADER, ANDROID) 56 to run a given test and reboot the emulator if it is not. 57 58 TODO: Remove the unconditional reboot after boot tests once the test harness 59 no longers requires it. 60 """ 61 if args.boot_test: 62 target_state = qemu.RunnerState.BOOTLOADER 63 elif args.shell_command: 64 target_state = qemu.RunnerState.ANDROID 65 else: 66 raise qemu_error.ConfigError( 67 "Command must request exactly one Android or boot test to run") 68 69 # Due to limitations in the test runner, always reboot between boot tests 70 if (runner.state != target_state or 71 runner.state == qemu.RunnerState.BOOTLOADER): 72 runner.reboot(target_state, factory_reset=True, full_wipe=False) 73 74 75def run_test(runner: qemu.Runner, cmd: List[str]) -> int: 76 args = build_argparser().parse_args(cmd) 77 _check_args(args) 78 _prepare_runner_for_test(runner, args) 79 80 timeout = args.timeout if args.timeout else runner.default_timeout 81 if args.boot_test: 82 return runner.boottest_run(args.boot_test, timeout) 83 if args.shell_command: 84 return runner.androidtest_run(args.shell_command, timeout) 85 86 raise qemu.RunnerGenericError( 87 "Command contained neither a boot test nor an Android test to run") 88 89 90def shutdown(runner: Optional[qemu.Runner], 91 factory_reset: bool = True, 92 full_wipe: bool = False): 93 if runner: 94 runner.shutdown(factory_reset, full_wipe) 95 96 97def build_argparser(): 98 argument_parser = argparse.ArgumentParser() 99 argument_parser.add_argument("-c", "--config", type=argparse.FileType("r")) 100 argument_parser.add_argument("--headless", action="store_true") 101 argument_parser.add_argument("-v", "--verbose", action="store_true") 102 argument_parser.add_argument("--debug", action="store_true") 103 argument_parser.add_argument("--debug-on-error", action="store_true") 104 argument_parser.add_argument("--boot-test", action="append") 105 argument_parser.add_argument("--shell-command", action="append") 106 argument_parser.add_argument("--android") 107 argument_parser.add_argument("--linux") 108 argument_parser.add_argument("--instance-dir", type=str, 109 default="/tmp/trusty-qemu-generic-arm64") 110 argument_parser.add_argument("--atf") 111 argument_parser.add_argument("--qemu") 112 argument_parser.add_argument("--arch") 113 argument_parser.add_argument("--disable-rpmb", action="store_true") 114 argument_parser.add_argument("--timeout", type=int) 115 argument_parser.add_argument("extra_qemu_flags", nargs="*") 116 return argument_parser 117 118 119def main(): 120 args = build_argparser().parse_args() 121 log_level = logging.DEBUG if args.verbose else logging.WARN 122 logging.basicConfig(level=log_level) 123 124 config = qemu.Config(args.config) 125 if args.android: 126 config.android_image_dir = qemu.find_android_image_dir(args.android) 127 config.adb = qemu.find_adb_path(args.android) 128 config.boot_android = True 129 if args.linux: 130 config.linux = args.linux 131 if args.atf: 132 config.atf = args.atf 133 if args.qemu: 134 config.qemu = args.qemu 135 if args.arch: 136 config.arch = args.arch 137 if args.extra_qemu_flags: 138 config.extra_qemu_flags += args.extra_qemu_flags 139 140 runner = qemu.Runner(config, 141 interactive=not args.headless, 142 instance_dir=args.instance_dir, 143 verbose=args.verbose, 144 rpmb=not args.disable_rpmb, 145 debug=args.debug, 146 debug_on_error=args.debug_on_error) 147 148 try: 149 results = runner.run(args.boot_test, args.shell_command, args.timeout) 150 print("Command results: " + repr(results)) 151 152 if any(results): 153 sys.exit(1) 154 else: 155 sys.exit(0) 156 except qemu_error.RunnerError as exn: 157 print(exn) 158 sys.exit(2) 159 160 161if __name__ == "__main__": 162 main() 163