| # Copyright (C) 2024 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. |
| |
| """Unittests for the forall subcmd.""" |
| |
| import contextlib |
| import io |
| from pathlib import Path |
| from unittest import mock |
| |
| import utils_for_test |
| |
| import manifest_xml |
| import project |
| import subcmds |
| |
| |
| def _create_manifest_with_8_projects( |
| topdir: Path, |
| ) -> manifest_xml.XmlManifest: |
| """Create a setup of 8 projects to execute forall.""" |
| repodir = topdir / ".repo" |
| manifest_dir = repodir / "manifests" |
| manifest_file = repodir / manifest_xml.MANIFEST_FILE_NAME |
| |
| repodir.mkdir() |
| manifest_dir.mkdir() |
| |
| # Set up a manifest git dir for parsing to work. |
| gitdir = repodir / "manifests.git" |
| gitdir.mkdir() |
| (gitdir / "config").write_text( |
| """[remote "origin"] |
| url = https://localhost:0/manifest |
| verbose = false |
| """ |
| ) |
| |
| # Add the manifest data. |
| manifest_file.write_text( |
| """ |
| <manifest> |
| <remote name="origin" fetch="http://localhost" /> |
| <default remote="origin" revision="refs/heads/main" /> |
| <project name="project1" path="tests/path1" /> |
| <project name="project2" path="tests/path2" /> |
| <project name="project3" path="tests/path3" /> |
| <project name="project4" path="tests/path4" /> |
| <project name="project5" path="tests/path5" /> |
| <project name="project6" path="tests/path6" /> |
| <project name="project7" path="tests/path7" /> |
| <project name="project8" path="tests/path8" /> |
| </manifest> |
| """, |
| encoding="utf-8", |
| ) |
| |
| # Set up 8 empty projects to match the manifest. |
| for x in range(1, 9): |
| (repodir / "projects" / "tests" / f"path{x}.git").mkdir(parents=True) |
| (repodir / "project-objects" / f"project{x}.git").mkdir(parents=True) |
| git_path = topdir / "tests" / f"path{x}" |
| utils_for_test.init_git_tree(git_path) |
| |
| return manifest_xml.XmlManifest(str(repodir), str(manifest_file)) |
| |
| |
| def test_forall_all_projects_called_once(tmp_path: Path) -> None: |
| """Test that all projects get a command run once each.""" |
| manifest = _create_manifest_with_8_projects(tmp_path) |
| |
| cmd = subcmds.forall.Forall() |
| cmd.manifest = manifest |
| |
| # Use echo project names as the test of forall. |
| opts, args = cmd.OptionParser.parse_args(["-c", "echo $REPO_PROJECT"]) |
| opts.verbose = False |
| |
| with contextlib.redirect_stdout(io.StringIO()) as stdout: |
| # Mock to not have the Execute fail on remote check. |
| with mock.patch.object( |
| project.Project, "GetRevisionId", return_value="refs/heads/main" |
| ): |
| # Run the forall command. |
| cmd.Execute(opts, args) |
| |
| output = stdout.getvalue() |
| # Verify that we got every project name in the output. |
| for x in range(1, 9): |
| assert f"project{x}" in output |
| |
| # Split the captured output into lines to count them. |
| line_count = sum(1 for x in output.splitlines() if x) |
| # Verify that we didn't get more lines than expected. |
| assert line_count == 8 |