diff options
author | Per Larsen <perlarsen@google.com> | 2022-10-23 07:16:52 +0000 |
---|---|---|
committer | Per Larsen <perlarsen@google.com> | 2022-10-26 23:53:29 +0000 |
commit | 8c14214df0f061b2bb6a5aa2302a0fedf2da17a0 (patch) | |
tree | b74241f0212707f0616cbbf9002bea6edc1a4aca | |
parent | 9007753b8bb2ecc367f553d2a62d75f7f1402787 (diff) | |
download | generic-arm64-8c14214df0f061b2bb6a5aa2302a0fedf2da17a0.tar.gz |
project/qemu: Make state explicit in Runner
Make it explicit whether the qemu.Runner is off, in the bootloader,
or in Android. Launch and reboot methods now take a target state.
Finally, the run_test function in run.py ensures that the Runner is
in the correct target state for the test to run.
Bug: 242077104
Change-Id: I8467d2054ce401625d5e97a40018ba02fd723741
-rw-r--r-- | project/qemu/qemu.py | 42 | ||||
-rwxr-xr-x | project/qemu/run.py | 30 |
2 files changed, 59 insertions, 13 deletions
diff --git a/project/qemu/qemu.py b/project/qemu/qemu.py index b0c3c53..76a1d8b 100644 --- a/project/qemu/qemu.py +++ b/project/qemu/qemu.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Run Trusty under QEMU in different configurations""" +import enum import errno import fcntl import json @@ -310,6 +311,13 @@ class RunnerSession: self.temp_files.append(tmp.name) return tmp + +class RunnerState(enum.Enum): + OFF = 0, + BOOTLOADER = 1, + ANDROID = 2, + + class Runner(object): """Executes tests in QEMU""" @@ -339,6 +347,7 @@ class Runner(object): self.qemu_arch_options = None self.default_timeout = 60 * 10 # 10 Minutes self.session: RunnerSession = None + self.state = RunnerState.OFF # If we're not verbose or interactive, squelch command output if verbose or self.interactive: @@ -770,7 +779,7 @@ class Runner(object): return args - def launch(self, boot_test_only): + def launch(self, target_state): """Launches the QEMU execution. If interactive is specified, it will leave the user connected @@ -792,6 +801,10 @@ class Runner(object): android tests are launched. Specifically, we might stop execution in the bootloader and have it wait for a command to boot android. """ + assert self.state == RunnerState.OFF + assert target_state in [RunnerState.BOOTLOADER, + RunnerState.ANDROID], target_state + self.session = RunnerSession() args = self.universal_args() @@ -813,8 +826,9 @@ class Runner(object): # Create socket for communication channel args += self.msg_channel_up() - if boot_test_only: + if target_state == RunnerState.BOOTLOADER: self.session.args = args + self.state = target_state return # Logging and terminal monitor @@ -863,6 +877,8 @@ class Runner(object): # Bring ADB up talking to the command port self.adb_up(self.session.ports[1]) + + self.state = target_state except: self.session.has_error = True raise @@ -874,7 +890,10 @@ class Runner(object): Calls to launch and shutdown must be correctly paired no matter whether the launch steps and calls to adb succeed or fail. """ - assert self.session, "No session; was shutdown call preceded by launch?" + if self.state == RunnerState.OFF: + return + + assert self.session is not None # Clean up generated device tree for temp_file in self.session.temp_files: @@ -900,10 +919,21 @@ class Runner(object): self.adb_down(self.session.ports[1]) self.session = None + self.state = RunnerState.OFF if unclean_exit: raise RunnerGenericError("QEMU did not exit cleanly") + def reboot(self, target_state): + self.shutdown() + + try: + self.launch(target_state) + except: + self.shutdown() + raise + + def run(self, boot_tests=[], android_tests=[], timeout=None): """Run boot or android tests. @@ -926,13 +956,15 @@ class Runner(object): If android_tests is provided, a Linux and Android dir must be provided in the config. """ - boot_tests = boot_tests if boot_tests else [] + assert self.state == RunnerState.OFF + target_state = (RunnerState.BOOTLOADER if boot_tests else + RunnerState.ANDROID) android_tests = android_tests if android_tests else [] self.config.check_config(self.interactive, boot_tests, android_tests) timeout = timeout if timeout else self.default_timeout try: - self.launch(bool(boot_tests)) + self.launch(target_state) match (boot_tests, android_tests): case ([], []): diff --git a/project/qemu/run.py b/project/qemu/run.py index 643255e..9c92ef8 100755 --- a/project/qemu/run.py +++ b/project/qemu/run.py @@ -46,23 +46,37 @@ def _check_args(args): assert not args.disable_rpmb, args +def _prepare_runner_for_test(runner, args): + """Check if the runner is in the correct state (BOOTLOADER, ANDROID) + to run a given test and reboot the emulator if it is not. + + TODO: Remove the unconditional reboot after boot tests once the test harness + no longers requires it. + """ + if args.boot_test: + target_state = qemu.RunnerState.BOOTLOADER + elif args.shell_command: + target_state = qemu.RunnerState.ANDROID + else: + raise qemu_error.ConfigError( + "Command must request exactly one Android or boot test to run") + + # Due to limitations in the test runner, always reboot between boot tests + if (runner.state != target_state or + runner.state == qemu.RunnerState.BOOTLOADER): + runner.reboot(target_state) + + def run_test(runner: qemu.Runner, cmd: List[str]) -> int: args = build_argparser().parse_args(cmd) _check_args(args) - - # make sure runner was started with rpmb in the state needed for test - assert args.disable_rpmb == (not runner.use_rpmb) + _prepare_runner_for_test(runner, args) timeout = args.timeout if args.timeout else runner.default_timeout if args.boot_test: - runner.launch(boot_test_only=True) return runner.boottest_run(args.boot_test, timeout) elif args.shell_command: - runner.launch(boot_test_only=False) return runner.androidtest_run(args.shell_command, timeout) - else: - raise qemu_error.ConfigError( - "Command must request exactly one Android or boot test to run") def shutdown(runner: Optional[qemu.Runner]): |