1# Copyright 2022 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Provides a base class for test running.""" 5 6import os 7import subprocess 8 9from abc import ABC, abstractmethod 10from argparse import Namespace 11from typing import Dict, List, Optional 12 13from common import read_package_paths 14 15 16class TestRunner(ABC): 17 """Base class that handles running a test.""" 18 19 def __init__(self, 20 out_dir: str, 21 test_args: Namespace, 22 packages: List[str], 23 target_id: Optional[str], 24 package_deps: Optional[List[str]] = None) -> None: 25 self._target_id = target_id 26 self._out_dir = out_dir 27 self._test_args = test_args 28 self._packages = packages 29 self._package_deps = None 30 if package_deps: 31 self._package_deps = TestRunner._build_package_deps(package_deps) 32 33 # TODO(crbug.com/1256503): Remove when all tests are converted to CFv2. 34 @staticmethod 35 def is_cfv2() -> bool: 36 """ 37 Returns True if packages are CFv2, False otherwise. Subclasses can 38 override this and return False if needed. 39 """ 40 41 return True 42 43 @property 44 def package_deps(self) -> Dict[str, str]: 45 """ 46 Returns: 47 A dictionary of packages that |self._packages| depend on, with 48 mapping from the package name to the local path to its far file. 49 """ 50 51 if not self._package_deps: 52 self._populate_package_deps() 53 return self._package_deps 54 55 @staticmethod 56 def _build_package_deps(package_paths: List[str]) -> Dict[str, str]: 57 """Retrieve information for all packages listed in |package_paths|.""" 58 package_deps = {} 59 for path in package_paths: 60 package_name = os.path.basename(path).replace('.far', '') 61 if package_name in package_deps: 62 assert path == package_deps[package_name] 63 package_deps[package_name] = path 64 return package_deps 65 66 def _populate_package_deps(self) -> None: 67 """Retrieve information for all packages |self._packages| depend on. 68 """ 69 70 package_paths = [] 71 for package in self._packages: 72 package_paths.extend(read_package_paths(self._out_dir, package)) 73 74 self._package_deps = TestRunner._build_package_deps(package_paths) 75 76 @abstractmethod 77 def run_test(self) -> subprocess.Popen: 78 """ 79 Returns: 80 A subprocess.Popen object that ran the test command. 81 """ 82