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