1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors 2*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 4*8975f5c5SAndroid Build Coastguard Worker"""Provides a base class for test running.""" 5*8975f5c5SAndroid Build Coastguard Worker 6*8975f5c5SAndroid Build Coastguard Workerimport os 7*8975f5c5SAndroid Build Coastguard Workerimport subprocess 8*8975f5c5SAndroid Build Coastguard Worker 9*8975f5c5SAndroid Build Coastguard Workerfrom abc import ABC, abstractmethod 10*8975f5c5SAndroid Build Coastguard Workerfrom typing import Dict, List, Optional, Union 11*8975f5c5SAndroid Build Coastguard Worker 12*8975f5c5SAndroid Build Coastguard Workerfrom common import read_package_paths 13*8975f5c5SAndroid Build Coastguard Worker 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Workerclass TestRunner(ABC): 16*8975f5c5SAndroid Build Coastguard Worker """Base class that handles running a test.""" 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Worker def __init__(self, 19*8975f5c5SAndroid Build Coastguard Worker out_dir: str, 20*8975f5c5SAndroid Build Coastguard Worker test_args: List[str], 21*8975f5c5SAndroid Build Coastguard Worker packages: List[str], 22*8975f5c5SAndroid Build Coastguard Worker target_id: Optional[str], 23*8975f5c5SAndroid Build Coastguard Worker package_deps: Union[Dict[str, str], List[str]] = None): 24*8975f5c5SAndroid Build Coastguard Worker self._out_dir = out_dir 25*8975f5c5SAndroid Build Coastguard Worker self._test_args = test_args 26*8975f5c5SAndroid Build Coastguard Worker self._packages = packages 27*8975f5c5SAndroid Build Coastguard Worker self._target_id = target_id 28*8975f5c5SAndroid Build Coastguard Worker if package_deps: 29*8975f5c5SAndroid Build Coastguard Worker if isinstance(package_deps, list): 30*8975f5c5SAndroid Build Coastguard Worker self._package_deps = self._build_package_deps(package_deps) 31*8975f5c5SAndroid Build Coastguard Worker elif isinstance(package_deps, dict): 32*8975f5c5SAndroid Build Coastguard Worker self._package_deps = package_deps 33*8975f5c5SAndroid Build Coastguard Worker else: 34*8975f5c5SAndroid Build Coastguard Worker assert False, 'Unsupported package_deps ' + package_deps 35*8975f5c5SAndroid Build Coastguard Worker else: 36*8975f5c5SAndroid Build Coastguard Worker self._package_deps = self._populate_package_deps() 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Worker @property 39*8975f5c5SAndroid Build Coastguard Worker def package_deps(self) -> Dict[str, str]: 40*8975f5c5SAndroid Build Coastguard Worker """ 41*8975f5c5SAndroid Build Coastguard Worker Returns: 42*8975f5c5SAndroid Build Coastguard Worker A dictionary of packages that |self._packages| depend on, with 43*8975f5c5SAndroid Build Coastguard Worker mapping from the package name to the local path to its far file. 44*8975f5c5SAndroid Build Coastguard Worker """ 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Worker return self._package_deps 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker def _build_package_deps(self, package_paths: List[str]) -> Dict[str, str]: 49*8975f5c5SAndroid Build Coastguard Worker """Retrieve information for all packages listed in |package_paths|.""" 50*8975f5c5SAndroid Build Coastguard Worker package_deps = {} 51*8975f5c5SAndroid Build Coastguard Worker for path in package_paths: 52*8975f5c5SAndroid Build Coastguard Worker path = os.path.join(self._out_dir, path) 53*8975f5c5SAndroid Build Coastguard Worker package_name = os.path.basename(path).replace('.far', '') 54*8975f5c5SAndroid Build Coastguard Worker if package_name in package_deps: 55*8975f5c5SAndroid Build Coastguard Worker assert path == package_deps[package_name] 56*8975f5c5SAndroid Build Coastguard Worker package_deps[package_name] = path 57*8975f5c5SAndroid Build Coastguard Worker return package_deps 58*8975f5c5SAndroid Build Coastguard Worker 59*8975f5c5SAndroid Build Coastguard Worker def _populate_package_deps(self) -> None: 60*8975f5c5SAndroid Build Coastguard Worker """Retrieve information for all packages |self._packages| depend on. 61*8975f5c5SAndroid Build Coastguard Worker Note, this function expects the packages to be built with chromium 62*8975f5c5SAndroid Build Coastguard Worker specified build rules and placed in certain locations. 63*8975f5c5SAndroid Build Coastguard Worker """ 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Worker package_paths = [] 66*8975f5c5SAndroid Build Coastguard Worker for package in self._packages: 67*8975f5c5SAndroid Build Coastguard Worker package_paths.extend(read_package_paths(self._out_dir, package)) 68*8975f5c5SAndroid Build Coastguard Worker 69*8975f5c5SAndroid Build Coastguard Worker return self._build_package_deps(package_paths) 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker @abstractmethod 72*8975f5c5SAndroid Build Coastguard Worker def run_test(self) -> subprocess.Popen: 73*8975f5c5SAndroid Build Coastguard Worker """ 74*8975f5c5SAndroid Build Coastguard Worker Returns: 75*8975f5c5SAndroid Build Coastguard Worker A subprocess.Popen object that ran the test command. 76*8975f5c5SAndroid Build Coastguard Worker """ 77