1# 2# Copyright (C) 2023 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16"""Common tools for end-to-end tests.""" 17import subprocess 18from pathlib import Path 19 20import pytest 21 22from .treebuilder import TreeBuilder 23 24THIS_DIR = Path(__file__).parent.resolve() 25EXTERNAL_UPDATER_DIR = THIS_DIR.parent.parent 26ANDROID_DIR = EXTERNAL_UPDATER_DIR.parent.parent 27 28 29def pytest_addoption(parser: pytest.Parser) -> None: 30 """Add custom options to pytest.""" 31 parser.addoption( 32 "--build-updater", 33 action="store_true", 34 default=True, 35 help=( 36 "Build external_updater before running tests. This is the default behavior." 37 ), 38 ) 39 parser.addoption( 40 "--no-build-updater", 41 action="store_false", 42 dest="build_updater", 43 help=( 44 "Do not build external_updater before running tests. Only use this option " 45 "if you've manually built external_updater. It will make test startup " 46 "faster." 47 ), 48 ) 49 50 51@pytest.fixture(name="should_build_updater", scope="session") 52def should_build_updater_fixture(request: pytest.FixtureRequest) -> bool: 53 """True if external_updater should be built before running tests.""" 54 return request.config.getoption("--build-updater") 55 56 57# Session scope means that this fixture will only run the first time it's used. We don't 58# want to re-run soong for every test because it's horrendously slow to do so. 59@pytest.fixture(scope="session") 60def updater_cmd(should_build_updater: bool) -> list[str]: 61 """The command to run for external_updater. 62 63 The result is the prefix of the command that should be used with subprocess.run or 64 similar. 65 """ 66 # Running updater.sh should be a more accurate test, but doing so isn't really 67 # feasible with a no-op `m external_updater` taking ~10 seconds. Doing that would 68 # add 10 seconds to every test. Build the updater once for the first thing that 69 # requires it (that's the "session" scope above) and run the PAR directly. 70 if should_build_updater: 71 subprocess.run( 72 [ 73 ANDROID_DIR / "build/soong/soong_ui.bash", 74 "--make-mode", 75 "external_updater", 76 ], 77 check=True, 78 ) 79 return [str("external_updater")] 80 81 82@pytest.fixture(name="tree_builder") 83def tree_builder_fixture(tmp_path: Path) -> TreeBuilder: 84 """Creates a TreeBuilder for making test repo trees.""" 85 return TreeBuilder(tmp_path) 86