1#!/usr/bin/env python3 2# 3# Copyright 2024 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the', help="License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an', help="AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import logging 18from pathlib import Path 19import platform 20 21from environment import get_default_environment 22from tasks.task import Task 23from utils import ( 24 AOSP_ROOT, 25 EMULATOR_ARTIFACT_PATH, 26 binary_extension, 27 run, 28) 29 30PYTEST_DIR = AOSP_ROOT / "external" / "adt-infra" / "pytest" / "test_embedded" 31OBJS_DIR = AOSP_ROOT / "tools" / "netsim" / "objs" 32 33 34class RunPyTestTask(Task): 35 36 def __init__(self, args): 37 super().__init__("RunPyTest") 38 self.buildbot = args.buildbot 39 self.pytest_input_dir = args.pytest_input_dir 40 41 def do_run(self): 42 run_pytest_manager = RunPytestManager(self.buildbot, self.pytest_input_dir) 43 return run_pytest_manager.process() 44 45 46class RunPytestManager: 47 """Manager for running e2e integration pytests with Emulator 48 49 The prerequisite is that the emulator installation has to be completed. 50 RunPytestManager runs a run_tests shell script in external/adt-infra. 51 It will take the emulator binary installed as the argument for the 52 script. 53 54 Attributes: 55 56 buildbot: A boolean indicating if it's being invoked with Android Build 57 Bots 58 """ 59 60 def __init__(self, buildbot, pytest_input_dir): 61 """Initializes the instances based on environment 62 63 Args: 64 buildbot: Defines if it's being invoked with Build Bots and defines 65 self.dir as the directory of the emulator binary 66 pytest_input_dir: Defined the directory that includes netsim and 67 emulator binaries and libraries. Ignore if the string is empty. 68 """ 69 # Default self.dir 70 self.dir = EMULATOR_ARTIFACT_PATH / "emulator" if buildbot else OBJS_DIR 71 72 # If pytest_input_dir is provided, set self.dir accordingly 73 if pytest_input_dir: 74 try: 75 self.dir = AOSP_ROOT / "tools" / "netsim" / Path(pytest_input_dir) 76 except Exception as e: 77 logging.error(f"Invalid pytest_input_dir value: {e}") 78 79 def _run_with_n_attempts(cmd, n): 80 for attempt in range(1, n + 1): 81 try: 82 run(cmd, get_default_environment(AOSP_ROOT), "e2e_pytests") 83 return 84 except Exception as e: 85 if attempt == n: 86 raise e 87 else: 88 logging.error(f"PyTest Attempt {attempt} Error: {e}") 89 90 def process(self) -> bool: 91 """Process the emulator e2e pytests 92 93 The process will check if the emulator installation occurred 94 and run the run_tests.sh script. 95 """ 96 emulator_bin = self.dir / binary_extension("emulator") 97 if not (self.dir.exists() and emulator_bin.exists()): 98 logging.info( 99 "Please run 'scripts/build_tools.sh --InstallEmulator' " 100 "before running RunPyTest" 101 ) 102 return False 103 if platform.system() == "Windows": 104 run_tests_script = PYTEST_DIR / "run_tests.cmd" 105 else: 106 run_tests_script = PYTEST_DIR / "run_tests.sh" 107 if platform.system() == "Linux": 108 test_config = PYTEST_DIR / "cfg" / "netsim_linux_tests.json" 109 else: 110 test_config = PYTEST_DIR / "cfg" / "netsim_tests.json" 111 cmd = [ 112 run_tests_script, 113 "--emulator", 114 emulator_bin, 115 "--test_config", 116 test_config, 117 ] 118 # TODO: Resolve Windows PyTest failure 119 if platform.system() != "Windows": 120 cmd.append("--failures_as_errors") 121 run(cmd, get_default_environment(AOSP_ROOT), "e2e_pytests") 122 return True 123