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