• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env vpython3
2# Copyright 2022 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""Implements commands for running tests E2E on a Fuchsia device."""
6
7import argparse
8import sys
9import tempfile
10
11from contextlib import ExitStack
12from typing import List
13
14from common import register_common_args, register_device_args, \
15                   register_log_args, resolve_packages, run_ffx_command, \
16                   set_ffx_isolate_dir
17from compatible_utils import running_unattended
18from ffx_integration import ScopedFfxConfig, test_connection
19from flash_device import register_update_args, update
20from log_manager import LogManager, start_system_log
21from publish_package import publish_packages, register_package_args
22from run_blink_test import BlinkTestRunner
23from run_executable_test import create_executable_test_runner, \
24                                register_executable_test_args
25from run_telemetry_test import TelemetryTestRunner
26from run_webpage_test import WebpageTestRunner
27from serve_repo import register_serve_args, serve_repository
28from start_emulator import create_emulator_from_args, register_emulator_args
29from test_runner import TestRunner
30from ermine_ctl import ErmineCtl
31
32
33def _get_test_runner(runner_args: argparse.Namespace,
34                     test_args: List[str]) -> TestRunner:
35    """Initialize a suitable TestRunner class."""
36
37    if runner_args.test_type == 'blink':
38        return BlinkTestRunner(runner_args.out_dir, test_args,
39                               runner_args.target_id)
40    if runner_args.test_type in ['gpu', 'perf']:
41        return TelemetryTestRunner(runner_args.test_type, runner_args.out_dir,
42                                   test_args, runner_args.target_id)
43    if runner_args.test_type in ['webpage']:
44        return WebpageTestRunner(runner_args.out_dir, test_args,
45                                 runner_args.target_id)
46    return create_executable_test_runner(runner_args, test_args)
47
48
49def main():
50    """E2E method for installing packages and running a test."""
51    parser = argparse.ArgumentParser()
52    parser.add_argument(
53        'test_type',
54        help='The type of test to run. Options include \'blink\', \'gpu\', '
55        'or in the case of executable tests, the test name.')
56    parser.add_argument('--device',
57                        '-d',
58                        action='store_true',
59                        default=False,
60                        help='Use an existing device.')
61
62    # Register arguments
63    register_common_args(parser)
64    register_device_args(parser)
65    register_emulator_args(parser)
66    register_executable_test_args(parser)
67    register_update_args(parser, default_os_check='ignore', default_pave=False)
68    register_log_args(parser)
69    register_package_args(parser, allow_temp_repo=True)
70    register_serve_args(parser)
71
72    # Treat unrecognized arguments as test specific arguments.
73    runner_args, test_args = parser.parse_known_args()
74
75    if not runner_args.out_dir:
76        raise ValueError('--out-dir must be specified.')
77
78    if runner_args.target_id:
79        runner_args.device = True
80
81    with ExitStack() as stack:
82        if running_unattended():
83            set_ffx_isolate_dir(
84                stack.enter_context(tempfile.TemporaryDirectory()))
85        run_ffx_command(('daemon', 'stop'), check=False)
86        if running_unattended():
87            stack.enter_context(
88                ScopedFfxConfig('repository.server.listen', '"[::]:0"'))
89        log_manager = stack.enter_context(LogManager(runner_args.logs_dir))
90        if runner_args.device:
91            update(runner_args.system_image_dir, runner_args.os_check,
92                   runner_args.target_id, runner_args.serial_num,
93                   runner_args.pave)
94        else:
95            runner_args.target_id = stack.enter_context(
96                create_emulator_from_args(runner_args))
97
98        test_connection(runner_args.target_id)
99
100        test_runner = _get_test_runner(runner_args, test_args)
101        package_deps = test_runner.package_deps
102
103        if not runner_args.repo:
104            # Create a directory that serves as a temporary repository.
105            runner_args.repo = stack.enter_context(
106                tempfile.TemporaryDirectory())
107
108        publish_packages(package_deps.values(), runner_args.repo,
109                         not runner_args.no_repo_init)
110
111        stack.enter_context(serve_repository(runner_args))
112
113        # Start system logging, after all possible restarts of the ffx daemon
114        # so that logging will not be interrupted.
115        start_system_log(log_manager, False, package_deps.values(),
116                         ('--since', 'now'), runner_args.target_id)
117
118        ermine = ErmineCtl(runner_args.target_id)
119        if ermine.exists:
120            ermine.take_to_shell()
121
122        resolve_packages(package_deps.keys(), runner_args.target_id)
123        return test_runner.run_test().returncode
124
125
126if __name__ == '__main__':
127    sys.exit(main())
128