xref: /aosp_15_r20/external/angle/build/fuchsia/test/run_test.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env vpython3
2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors
3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker"""Implements commands for running tests E2E on a Fuchsia device."""
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Workerimport argparse
8*8975f5c5SAndroid Build Coastguard Workerimport logging
9*8975f5c5SAndroid Build Coastguard Workerimport os
10*8975f5c5SAndroid Build Coastguard Workerimport sys
11*8975f5c5SAndroid Build Coastguard Workerimport tempfile
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Workerfrom contextlib import ExitStack
14*8975f5c5SAndroid Build Coastguard Workerfrom typing import List
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Workerimport monitors
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Workerfrom common import has_ffx_isolate_dir, is_daemon_running, \
19*8975f5c5SAndroid Build Coastguard Worker                   register_common_args, register_device_args, \
20*8975f5c5SAndroid Build Coastguard Worker                   register_log_args, resolve_packages
21*8975f5c5SAndroid Build Coastguard Workerfrom compatible_utils import running_unattended
22*8975f5c5SAndroid Build Coastguard Workerfrom ffx_integration import ScopedFfxConfig
23*8975f5c5SAndroid Build Coastguard Workerfrom flash_device import register_update_args, update
24*8975f5c5SAndroid Build Coastguard Workerfrom isolate_daemon import IsolateDaemon
25*8975f5c5SAndroid Build Coastguard Workerfrom log_manager import LogManager, start_system_log
26*8975f5c5SAndroid Build Coastguard Workerfrom publish_package import publish_packages, register_package_args
27*8975f5c5SAndroid Build Coastguard Workerfrom run_blink_test import BlinkTestRunner
28*8975f5c5SAndroid Build Coastguard Workerfrom run_executable_test import create_executable_test_runner, \
29*8975f5c5SAndroid Build Coastguard Worker                                register_executable_test_args
30*8975f5c5SAndroid Build Coastguard Workerfrom run_telemetry_test import TelemetryTestRunner
31*8975f5c5SAndroid Build Coastguard Workerfrom run_webpage_test import WebpageTestRunner
32*8975f5c5SAndroid Build Coastguard Workerfrom serve_repo import register_serve_args, serve_repository
33*8975f5c5SAndroid Build Coastguard Workerfrom start_emulator import create_emulator_from_args, register_emulator_args
34*8975f5c5SAndroid Build Coastguard Workerfrom test_connection import test_connection, test_device_connection
35*8975f5c5SAndroid Build Coastguard Workerfrom test_runner import TestRunner
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Workerdef _get_test_runner(runner_args: argparse.Namespace,
39*8975f5c5SAndroid Build Coastguard Worker                     test_args: List[str]) -> TestRunner:
40*8975f5c5SAndroid Build Coastguard Worker    """Initialize a suitable TestRunner class."""
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker    if not runner_args.out_dir:
43*8975f5c5SAndroid Build Coastguard Worker        raise ValueError('--out-dir must be specified.')
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker    if runner_args.test_type == 'blink':
46*8975f5c5SAndroid Build Coastguard Worker        return BlinkTestRunner(runner_args.out_dir, test_args,
47*8975f5c5SAndroid Build Coastguard Worker                               runner_args.target_id)
48*8975f5c5SAndroid Build Coastguard Worker    if runner_args.test_type in ['gpu', 'perf']:
49*8975f5c5SAndroid Build Coastguard Worker        return TelemetryTestRunner(runner_args.test_type, runner_args.out_dir,
50*8975f5c5SAndroid Build Coastguard Worker                                   test_args, runner_args.target_id)
51*8975f5c5SAndroid Build Coastguard Worker    if runner_args.test_type == 'webpage':
52*8975f5c5SAndroid Build Coastguard Worker        return WebpageTestRunner(runner_args.out_dir, test_args,
53*8975f5c5SAndroid Build Coastguard Worker                                 runner_args.target_id, runner_args.logs_dir)
54*8975f5c5SAndroid Build Coastguard Worker    return create_executable_test_runner(runner_args, test_args)
55*8975f5c5SAndroid Build Coastguard Worker
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker# pylint: disable=too-many-statements
58*8975f5c5SAndroid Build Coastguard Workerdef main():
59*8975f5c5SAndroid Build Coastguard Worker    """E2E method for installing packages and running a test."""
60*8975f5c5SAndroid Build Coastguard Worker    # Always add time stamps to the logs.
61*8975f5c5SAndroid Build Coastguard Worker    logging.basicConfig(format='%(levelname)s %(asctime)s %(message)s')
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
64*8975f5c5SAndroid Build Coastguard Worker    parser.add_argument(
65*8975f5c5SAndroid Build Coastguard Worker        'test_type',
66*8975f5c5SAndroid Build Coastguard Worker        help='The type of test to run. Options include \'blink\', \'gpu\', '
67*8975f5c5SAndroid Build Coastguard Worker        'or in the case of executable tests, the test name.')
68*8975f5c5SAndroid Build Coastguard Worker    parser.add_argument('--device',
69*8975f5c5SAndroid Build Coastguard Worker                        '-d',
70*8975f5c5SAndroid Build Coastguard Worker                        action='store_true',
71*8975f5c5SAndroid Build Coastguard Worker                        default=False,
72*8975f5c5SAndroid Build Coastguard Worker                        help='Use an existing device.')
73*8975f5c5SAndroid Build Coastguard Worker    parser.add_argument('--extra-path',
74*8975f5c5SAndroid Build Coastguard Worker                        action='append',
75*8975f5c5SAndroid Build Coastguard Worker                        help='Extra paths to append to the PATH environment')
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker    # Register arguments
78*8975f5c5SAndroid Build Coastguard Worker    register_common_args(parser)
79*8975f5c5SAndroid Build Coastguard Worker    register_device_args(parser)
80*8975f5c5SAndroid Build Coastguard Worker    register_emulator_args(parser)
81*8975f5c5SAndroid Build Coastguard Worker    register_executable_test_args(parser)
82*8975f5c5SAndroid Build Coastguard Worker    register_update_args(parser, default_os_check='ignore')
83*8975f5c5SAndroid Build Coastguard Worker    register_log_args(parser)
84*8975f5c5SAndroid Build Coastguard Worker    register_package_args(parser, allow_temp_repo=True)
85*8975f5c5SAndroid Build Coastguard Worker    register_serve_args(parser)
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Worker    # Treat unrecognized arguments as test specific arguments.
88*8975f5c5SAndroid Build Coastguard Worker    runner_args, test_args = parser.parse_known_args()
89*8975f5c5SAndroid Build Coastguard Worker
90*8975f5c5SAndroid Build Coastguard Worker    if runner_args.target_id:
91*8975f5c5SAndroid Build Coastguard Worker        runner_args.device = True
92*8975f5c5SAndroid Build Coastguard Worker
93*8975f5c5SAndroid Build Coastguard Worker    with ExitStack() as stack:
94*8975f5c5SAndroid Build Coastguard Worker        if runner_args.logs_dir:
95*8975f5c5SAndroid Build Coastguard Worker            # TODO(crbug.com/343242386): Find a way to upload metric output when
96*8975f5c5SAndroid Build Coastguard Worker            # logs_dir is not defined.
97*8975f5c5SAndroid Build Coastguard Worker            stack.push(lambda *_: monitors.dump(
98*8975f5c5SAndroid Build Coastguard Worker                os.path.join(runner_args.logs_dir, 'invocations')))
99*8975f5c5SAndroid Build Coastguard Worker        if runner_args.extra_path:
100*8975f5c5SAndroid Build Coastguard Worker            os.environ['PATH'] += os.pathsep + os.pathsep.join(
101*8975f5c5SAndroid Build Coastguard Worker                runner_args.extra_path)
102*8975f5c5SAndroid Build Coastguard Worker        if running_unattended():
103*8975f5c5SAndroid Build Coastguard Worker            # Only restart the daemon if 1) daemon will be run in a new isolate
104*8975f5c5SAndroid Build Coastguard Worker            # dir, or 2) if there isn't a daemon running in the predefined
105*8975f5c5SAndroid Build Coastguard Worker            # isolate dir.
106*8975f5c5SAndroid Build Coastguard Worker            if not has_ffx_isolate_dir() or not is_daemon_running():
107*8975f5c5SAndroid Build Coastguard Worker                stack.enter_context(IsolateDaemon(runner_args.logs_dir))
108*8975f5c5SAndroid Build Coastguard Worker
109*8975f5c5SAndroid Build Coastguard Worker            if runner_args.everlasting:
110*8975f5c5SAndroid Build Coastguard Worker                # Setting the emu.instance_dir to match the named cache, so
111*8975f5c5SAndroid Build Coastguard Worker                # we can keep these files across multiple runs.
112*8975f5c5SAndroid Build Coastguard Worker                # The configuration attaches to the daemon isolate-dir, so it
113*8975f5c5SAndroid Build Coastguard Worker                # needs to go after the IsolateDaemon.
114*8975f5c5SAndroid Build Coastguard Worker                # There isn't a point of enabling the feature on devbox, it
115*8975f5c5SAndroid Build Coastguard Worker                # won't use isolate-dir and the emu.instance_dir always goes to
116*8975f5c5SAndroid Build Coastguard Worker                # the HOME directory.
117*8975f5c5SAndroid Build Coastguard Worker                stack.enter_context(
118*8975f5c5SAndroid Build Coastguard Worker                    ScopedFfxConfig(
119*8975f5c5SAndroid Build Coastguard Worker                        'emu.instance_dir',
120*8975f5c5SAndroid Build Coastguard Worker                        os.path.join(os.environ['HOME'],
121*8975f5c5SAndroid Build Coastguard Worker                                     '.fuchsia_emulator/')))
122*8975f5c5SAndroid Build Coastguard Worker        elif runner_args.logs_dir:
123*8975f5c5SAndroid Build Coastguard Worker            # Never restart daemon if not in the unattended mode.
124*8975f5c5SAndroid Build Coastguard Worker            logging.warning('You are using a --logs-dir, ensure the ffx '
125*8975f5c5SAndroid Build Coastguard Worker                            'daemon is started with the logs.dir config '
126*8975f5c5SAndroid Build Coastguard Worker                            'updated. We won\'t restart the daemon randomly'
127*8975f5c5SAndroid Build Coastguard Worker                            ' anymore.')
128*8975f5c5SAndroid Build Coastguard Worker        log_manager = LogManager(runner_args.logs_dir)
129*8975f5c5SAndroid Build Coastguard Worker        stack.enter_context(log_manager)
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker        if runner_args.device:
132*8975f5c5SAndroid Build Coastguard Worker            update(runner_args.system_image_dir, runner_args.os_check,
133*8975f5c5SAndroid Build Coastguard Worker                   runner_args.target_id, runner_args.serial_num)
134*8975f5c5SAndroid Build Coastguard Worker            # Try to reboot the device if necessary since the ffx may ignore the
135*8975f5c5SAndroid Build Coastguard Worker            # device state after the flash. See
136*8975f5c5SAndroid Build Coastguard Worker            # https://cs.opensource.google/fuchsia/fuchsia/+/main:src/developer/ffx/lib/fastboot/src/common/fastboot.rs;drc=cfba0bdd4f8857adb6409f8ae9e35af52c0da93e;l=454
137*8975f5c5SAndroid Build Coastguard Worker            test_device_connection(runner_args.target_id)
138*8975f5c5SAndroid Build Coastguard Worker        else:
139*8975f5c5SAndroid Build Coastguard Worker            runner_args.target_id = stack.enter_context(
140*8975f5c5SAndroid Build Coastguard Worker                create_emulator_from_args(runner_args))
141*8975f5c5SAndroid Build Coastguard Worker            test_connection(runner_args.target_id)
142*8975f5c5SAndroid Build Coastguard Worker
143*8975f5c5SAndroid Build Coastguard Worker        test_runner = _get_test_runner(runner_args, test_args)
144*8975f5c5SAndroid Build Coastguard Worker        package_deps = test_runner.package_deps
145*8975f5c5SAndroid Build Coastguard Worker
146*8975f5c5SAndroid Build Coastguard Worker        # Start system logging, after all possible restarts of the ffx daemon
147*8975f5c5SAndroid Build Coastguard Worker        # so that logging will not be interrupted.
148*8975f5c5SAndroid Build Coastguard Worker        start_system_log(log_manager, False, package_deps.values(),
149*8975f5c5SAndroid Build Coastguard Worker                         ('--since', 'now'), runner_args.target_id)
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker        if package_deps:
152*8975f5c5SAndroid Build Coastguard Worker            if not runner_args.repo:
153*8975f5c5SAndroid Build Coastguard Worker                # Create a directory that serves as a temporary repository.
154*8975f5c5SAndroid Build Coastguard Worker                runner_args.repo = stack.enter_context(
155*8975f5c5SAndroid Build Coastguard Worker                    tempfile.TemporaryDirectory())
156*8975f5c5SAndroid Build Coastguard Worker            publish_packages(package_deps.values(), runner_args.repo,
157*8975f5c5SAndroid Build Coastguard Worker                             not runner_args.no_repo_init)
158*8975f5c5SAndroid Build Coastguard Worker            stack.enter_context(serve_repository(runner_args))
159*8975f5c5SAndroid Build Coastguard Worker            resolve_packages(package_deps.keys(), runner_args.target_id)
160*8975f5c5SAndroid Build Coastguard Worker
161*8975f5c5SAndroid Build Coastguard Worker        return test_runner.run_test().returncode
162*8975f5c5SAndroid Build Coastguard Worker
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
165*8975f5c5SAndroid Build Coastguard Worker    sys.exit(main())
166