diff options
| -rw-r--r-- | tests/README.md | 20 | ||||
| -rw-r--r-- | tests/test_project.py | 26 | ||||
| -rw-r--r-- | tests/test_subcmds_forall.py | 24 | ||||
| -rw-r--r-- | tests/test_wrapper.py | 16 | ||||
| -rw-r--r-- | tests/utils_for_test.py | 53 |
5 files changed, 83 insertions, 56 deletions
diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..a0f110f08 --- /dev/null +++ b/tests/README.md | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | # Repo Tests | ||
| 2 | |||
| 3 | There is a mixture of [pytest] & [Python unittest] in here. We adopted [pytest] | ||
| 4 | later on but didn't migrate existing tests (since they still work). New tests | ||
| 5 | should be written using [pytest] only. | ||
| 6 | |||
| 7 | ## File layout | ||
| 8 | |||
| 9 | * `test_xxx.py`: Unittests for the `xxx` module in the main repo codebase. | ||
| 10 | Modules that are in subdirs normalize the `/` into `_`. | ||
| 11 | For example, [test_error.py](./test_error.py) is for the | ||
| 12 | [error.py](../error.py) module, and | ||
| 13 | [test_subcmds_forall.py](./test_subcmds_forall.py) is for the | ||
| 14 | [subcmds/forall.py](../subcmds/forall.py) module. | ||
| 15 | * [conftest.py](./conftest.py): Custom pytest fixtures for sharing. | ||
| 16 | * [utils_for_test.py](./utils_for_test.py): Helpers for sharing in tests. | ||
| 17 | |||
| 18 | |||
| 19 | [pytest]: https://pytest.org/ | ||
| 20 | [Python unittest]: https://docs.python.org/3/library/unittest.html#unittest.TestCase | ||
diff --git a/tests/test_project.py b/tests/test_project.py index de26e91a1..e0a6dec07 100644 --- a/tests/test_project.py +++ b/tests/test_project.py | |||
| @@ -21,33 +21,15 @@ import subprocess | |||
| 21 | import tempfile | 21 | import tempfile |
| 22 | import unittest | 22 | import unittest |
| 23 | 23 | ||
| 24 | import utils_for_test | ||
| 25 | |||
| 24 | import error | 26 | import error |
| 25 | import git_command | ||
| 26 | import git_config | 27 | import git_config |
| 27 | import manifest_xml | 28 | import manifest_xml |
| 28 | import platform_utils | 29 | import platform_utils |
| 29 | import project | 30 | import project |
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | @contextlib.contextmanager | ||
| 33 | def TempGitTree(): | ||
| 34 | """Create a new empty git checkout for testing.""" | ||
| 35 | with tempfile.TemporaryDirectory(prefix="repo-tests") as tempdir: | ||
| 36 | # Tests need to assume, that main is default branch at init, | ||
| 37 | # which is not supported in config until 2.28. | ||
| 38 | cmd = ["git", "init"] | ||
| 39 | if git_command.git_require((2, 28, 0)): | ||
| 40 | cmd += ["--initial-branch=main"] | ||
| 41 | else: | ||
| 42 | # Use template dir for init. | ||
| 43 | templatedir = tempfile.mkdtemp(prefix=".test-template") | ||
| 44 | with open(os.path.join(templatedir, "HEAD"), "w") as fp: | ||
| 45 | fp.write("ref: refs/heads/main\n") | ||
| 46 | cmd += ["--template", templatedir] | ||
| 47 | subprocess.check_call(cmd, cwd=tempdir) | ||
| 48 | yield tempdir | ||
| 49 | |||
| 50 | |||
| 51 | class FakeProject: | 33 | class FakeProject: |
| 52 | """A fake for Project for basic functionality.""" | 34 | """A fake for Project for basic functionality.""" |
| 53 | 35 | ||
| @@ -69,7 +51,7 @@ class ReviewableBranchTests(unittest.TestCase): | |||
| 69 | 51 | ||
| 70 | def test_smoke(self): | 52 | def test_smoke(self): |
| 71 | """A quick run through everything.""" | 53 | """A quick run through everything.""" |
| 72 | with TempGitTree() as tempdir: | 54 | with utils_for_test.TempGitTree() as tempdir: |
| 73 | fakeproj = FakeProject(tempdir) | 55 | fakeproj = FakeProject(tempdir) |
| 74 | 56 | ||
| 75 | # Generate some commits. | 57 | # Generate some commits. |
| @@ -467,7 +449,7 @@ class ManifestPropertiesFetchedCorrectly(unittest.TestCase): | |||
| 467 | def test_manifest_config_properties(self): | 449 | def test_manifest_config_properties(self): |
| 468 | """Test we are fetching the manifest config properties correctly.""" | 450 | """Test we are fetching the manifest config properties correctly.""" |
| 469 | 451 | ||
| 470 | with TempGitTree() as tempdir: | 452 | with utils_for_test.TempGitTree() as tempdir: |
| 471 | fakeproj = self.setUpManifest(tempdir) | 453 | fakeproj = self.setUpManifest(tempdir) |
| 472 | 454 | ||
| 473 | # Set property using the expected Set method, then ensure | 455 | # Set property using the expected Set method, then ensure |
diff --git a/tests/test_subcmds_forall.py b/tests/test_subcmds_forall.py index 84744f893..e50b28d8a 100644 --- a/tests/test_subcmds_forall.py +++ b/tests/test_subcmds_forall.py | |||
| @@ -17,12 +17,12 @@ | |||
| 17 | from io import StringIO | 17 | from io import StringIO |
| 18 | import os | 18 | import os |
| 19 | from shutil import rmtree | 19 | from shutil import rmtree |
| 20 | import subprocess | ||
| 21 | import tempfile | 20 | import tempfile |
| 22 | import unittest | 21 | import unittest |
| 23 | from unittest import mock | 22 | from unittest import mock |
| 24 | 23 | ||
| 25 | import git_command | 24 | import utils_for_test |
| 25 | |||
| 26 | import manifest_xml | 26 | import manifest_xml |
| 27 | import project | 27 | import project |
| 28 | import subcmds | 28 | import subcmds |
| @@ -50,24 +50,6 @@ class AllCommands(unittest.TestCase): | |||
| 50 | """Common teardown.""" | 50 | """Common teardown.""" |
| 51 | rmtree(self.tempdir, ignore_errors=True) | 51 | rmtree(self.tempdir, ignore_errors=True) |
| 52 | 52 | ||
| 53 | def initTempGitTree(self, git_dir): | ||
| 54 | """Create a new empty git checkout for testing.""" | ||
| 55 | |||
| 56 | # Tests need to assume, that main is default branch at init, | ||
| 57 | # which is not supported in config until 2.28. | ||
| 58 | cmd = ["git", "init", "-q"] | ||
| 59 | if git_command.git_require((2, 28, 0)): | ||
| 60 | cmd += ["--initial-branch=main"] | ||
| 61 | else: | ||
| 62 | # Use template dir for init | ||
| 63 | templatedir = os.path.join(self.tempdirobj.name, ".test-template") | ||
| 64 | os.makedirs(templatedir) | ||
| 65 | with open(os.path.join(templatedir, "HEAD"), "w") as fp: | ||
| 66 | fp.write("ref: refs/heads/main\n") | ||
| 67 | cmd += ["--template", templatedir] | ||
| 68 | cmd += [git_dir] | ||
| 69 | subprocess.check_call(cmd) | ||
| 70 | |||
| 71 | def getXmlManifestWith8Projects(self): | 53 | def getXmlManifestWith8Projects(self): |
| 72 | """Create and return a setup of 8 projects with enough dummy | 54 | """Create and return a setup of 8 projects with enough dummy |
| 73 | files and setup to execute forall.""" | 55 | files and setup to execute forall.""" |
| @@ -114,7 +96,7 @@ class AllCommands(unittest.TestCase): | |||
| 114 | ) | 96 | ) |
| 115 | ) | 97 | ) |
| 116 | git_path = os.path.join(self.tempdir, "tests/path" + str(x)) | 98 | git_path = os.path.join(self.tempdir, "tests/path" + str(x)) |
| 117 | self.initTempGitTree(git_path) | 99 | utils_for_test.init_git_tree(git_path) |
| 118 | 100 | ||
| 119 | return manifest_xml.XmlManifest(self.repodir, self.manifest_file) | 101 | return manifest_xml.XmlManifest(self.repodir, self.manifest_file) |
| 120 | 102 | ||
diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 77ceda8f7..a38705675 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py | |||
| @@ -23,7 +23,8 @@ import tempfile | |||
| 23 | import unittest | 23 | import unittest |
| 24 | from unittest import mock | 24 | from unittest import mock |
| 25 | 25 | ||
| 26 | import git_command | 26 | import utils_for_test |
| 27 | |||
| 27 | import main | 28 | import main |
| 28 | import wrapper | 29 | import wrapper |
| 29 | 30 | ||
| @@ -408,18 +409,7 @@ class GitCheckoutTestCase(RepoWrapperTestCase): | |||
| 408 | remote = os.path.join(cls.GIT_DIR, "remote") | 409 | remote = os.path.join(cls.GIT_DIR, "remote") |
| 409 | os.mkdir(remote) | 410 | os.mkdir(remote) |
| 410 | 411 | ||
| 411 | # Tests need to assume, that main is default branch at init, | 412 | utils_for_test.init_git_tree(remote) |
| 412 | # which is not supported in config until 2.28. | ||
| 413 | if git_command.git_require((2, 28, 0)): | ||
| 414 | initstr = "--initial-branch=main" | ||
| 415 | else: | ||
| 416 | # Use template dir for init. | ||
| 417 | templatedir = tempfile.mkdtemp(prefix=".test-template") | ||
| 418 | with open(os.path.join(templatedir, "HEAD"), "w") as fp: | ||
| 419 | fp.write("ref: refs/heads/main\n") | ||
| 420 | initstr = "--template=" + templatedir | ||
| 421 | |||
| 422 | run_git("init", initstr, cwd=remote) | ||
| 423 | run_git("commit", "--allow-empty", "-minit", cwd=remote) | 413 | run_git("commit", "--allow-empty", "-minit", cwd=remote) |
| 424 | run_git("branch", "stable", cwd=remote) | 414 | run_git("branch", "stable", cwd=remote) |
| 425 | run_git("tag", "v1.0", cwd=remote) | 415 | run_git("tag", "v1.0", cwd=remote) |
diff --git a/tests/utils_for_test.py b/tests/utils_for_test.py new file mode 100644 index 000000000..e162e8666 --- /dev/null +++ b/tests/utils_for_test.py | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | # Copyright (C) 2026 The Android Open Source Project | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | """Various utility code used by tests. | ||
| 16 | |||
| 17 | If you want to write a per-test fixture, see conftest.py instead. | ||
| 18 | """ | ||
| 19 | |||
| 20 | import contextlib | ||
| 21 | from pathlib import Path | ||
| 22 | import subprocess | ||
| 23 | import tempfile | ||
| 24 | from typing import Union | ||
| 25 | |||
| 26 | import git_command | ||
| 27 | |||
| 28 | |||
| 29 | def init_git_tree(path: Union[str, Path]) -> None: | ||
| 30 | """Initialize `path` as a new git repo.""" | ||
| 31 | with contextlib.ExitStack() as stack: | ||
| 32 | # Tests need to assume, that main is default branch at init, | ||
| 33 | # which is not supported in config until 2.28. | ||
| 34 | cmd = ["git", "init"] | ||
| 35 | if git_command.git_require((2, 28, 0)): | ||
| 36 | cmd += ["--initial-branch=main"] | ||
| 37 | else: | ||
| 38 | # Use template dir for init. | ||
| 39 | templatedir = stack.enter_context( | ||
| 40 | tempfile.mkdtemp(prefix="git-template") | ||
| 41 | ) | ||
| 42 | (Path(templatedir) / "HEAD").write_text("ref: refs/heads/main\n") | ||
| 43 | cmd += ["--template", templatedir] | ||
| 44 | cmd += [path] | ||
| 45 | subprocess.run(cmd, check=True) | ||
| 46 | |||
| 47 | |||
| 48 | @contextlib.contextmanager | ||
| 49 | def TempGitTree(): | ||
| 50 | """Create a new empty git checkout for testing.""" | ||
| 51 | with tempfile.TemporaryDirectory(prefix="repo-tests") as tempdir: | ||
| 52 | init_git_tree(tempdir) | ||
| 53 | yield tempdir | ||
