| # |
| # Copyright (C) 2023 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| """Common tools for end-to-end tests.""" |
| import subprocess |
| from pathlib import Path |
| |
| import pytest |
| |
| from .treebuilder import TreeBuilder |
| |
| THIS_DIR = Path(__file__).parent.resolve() |
| EXTERNAL_UPDATER_DIR = THIS_DIR.parent.parent |
| ANDROID_DIR = EXTERNAL_UPDATER_DIR.parent.parent |
| |
| |
| def pytest_addoption(parser: pytest.Parser) -> None: |
| """Add custom options to pytest.""" |
| parser.addoption( |
| "--build-updater", |
| action="store_true", |
| default=True, |
| help=( |
| "Build external_updater before running tests. This is the default behavior." |
| ), |
| ) |
| parser.addoption( |
| "--no-build-updater", |
| action="store_false", |
| dest="build_updater", |
| help=( |
| "Do not build external_updater before running tests. Only use this option " |
| "if you've manually built external_updater. It will make test startup " |
| "faster." |
| ), |
| ) |
| |
| |
| @pytest.fixture(name="should_build_updater", scope="session") |
| def should_build_updater_fixture(request: pytest.FixtureRequest) -> bool: |
| """True if external_updater should be built before running tests.""" |
| return request.config.getoption("--build-updater") |
| |
| |
| # Session scope means that this fixture will only run the first time it's used. We don't |
| # want to re-run soong for every test because it's horrendously slow to do so. |
| @pytest.fixture(scope="session") |
| def updater_cmd(should_build_updater: bool) -> list[str]: |
| """The command to run for external_updater. |
| |
| The result is the prefix of the command that should be used with subprocess.run or |
| similar. |
| """ |
| # Running updater.sh should be a more accurate test, but doing so isn't really |
| # feasible with a no-op `m external_updater` taking ~10 seconds. Doing that would |
| # add 10 seconds to every test. Build the updater once for the first thing that |
| # requires it (that's the "session" scope above) and run the PAR directly. |
| if should_build_updater: |
| subprocess.run( |
| [ |
| ANDROID_DIR / "build/soong/soong_ui.bash", |
| "--make-mode", |
| "external_updater", |
| ], |
| check=True, |
| ) |
| return [str("external_updater")] |
| |
| |
| @pytest.fixture(name="tree_builder") |
| def tree_builder_fixture(tmp_path: Path) -> TreeBuilder: |
| """Creates a TreeBuilder for making test repo trees.""" |
| return TreeBuilder(tmp_path) |