2025-12-14 16:14:17 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
CLI integration tests for `pkgmgr mirror`.
|
|
|
|
|
|
|
|
|
|
These tests validate:
|
|
|
|
|
- CLI argument parsing
|
|
|
|
|
- command dispatch
|
|
|
|
|
- command orchestration
|
|
|
|
|
|
|
|
|
|
All side effects (git, network, remote provisioning, filesystem writes)
|
|
|
|
|
are patched to keep tests deterministic and CI-safe.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2025-12-14 16:38:24 +01:00
|
|
|
import importlib
|
2025-12-14 16:14:17 +01:00
|
|
|
import io
|
|
|
|
|
import os
|
|
|
|
|
import runpy
|
|
|
|
|
import sys
|
|
|
|
|
import unittest
|
|
|
|
|
from contextlib import ExitStack, redirect_stderr, redirect_stdout
|
|
|
|
|
from typing import Dict, List, Optional
|
|
|
|
|
from unittest.mock import MagicMock, PropertyMock, patch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestIntegrationMirrorCommands(unittest.TestCase):
|
gpt-5.2 ChatGPT: adapt tests to new core.git commands/queries split
- Update mirror integration tests to use probe_remote_reachable
- Refactor branch action tests to mock git command helpers instead of run_git
- Align changelog tests with get_changelog query API
- Update git core tests to cover run() and query helpers
- Remove legacy run_git assumptions from tests
https://chatgpt.com/share/69412008-9e8c-800f-9ac9-90f390d55380
**Validated by Google's model.**
**Summary:**
The test modifications have been correctly implemented to cover the Git refactoring changes:
1. **Granular Mocking:** The tests have shifted from mocking the monolithic `run_git` or `subprocess` to mocking the new, specific wrapper functions (e.g., `pkgmgr.core.git.commands.fetch`, `pkgmgr.core.git.queries.probe_remote_reachable`). This accurately reflects the architectural change in the source code where business logic now relies on these granular imports.
2. **Structural Alignment:** The test directory structure was updated (e.g., moving tests to `tests/unit/pkgmgr/core/git/queries/`) to match the new source code organization, ensuring logical consistency.
3. **Exception Handling:** The tests were updated to verify specific exception types (like `GitDeleteRemoteBranchError`) rather than generic errors, ensuring the improved error granularity is correctly handled by the CLI.
4. **Integration Safety:** The integration tests in `test_mirror_commands.py` were correctly updated to patch the new query paths, ensuring that network operations remain disabled during testing.
The test changes are consistent with the refactor and provide complete coverage for the new code structure.
https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%2214Br1JG1hxuntmoRzuvme3GKUvQ0heqRn%22%5D,%22action%22:%22open%22,%22userId%22:%22109171005420801378245%22,%22resourceKeys%22:%7B%7D%7D&usp=sharing
2025-12-16 10:01:30 +01:00
|
|
|
"""Integration tests for `pkgmgr mirror` commands."""
|
2025-12-14 16:14:17 +01:00
|
|
|
|
|
|
|
|
def _run_pkgmgr(self, args: List[str], extra_env: Optional[Dict[str, str]] = None) -> str:
|
gpt-5.2 ChatGPT: adapt tests to new core.git commands/queries split
- Update mirror integration tests to use probe_remote_reachable
- Refactor branch action tests to mock git command helpers instead of run_git
- Align changelog tests with get_changelog query API
- Update git core tests to cover run() and query helpers
- Remove legacy run_git assumptions from tests
https://chatgpt.com/share/69412008-9e8c-800f-9ac9-90f390d55380
**Validated by Google's model.**
**Summary:**
The test modifications have been correctly implemented to cover the Git refactoring changes:
1. **Granular Mocking:** The tests have shifted from mocking the monolithic `run_git` or `subprocess` to mocking the new, specific wrapper functions (e.g., `pkgmgr.core.git.commands.fetch`, `pkgmgr.core.git.queries.probe_remote_reachable`). This accurately reflects the architectural change in the source code where business logic now relies on these granular imports.
2. **Structural Alignment:** The test directory structure was updated (e.g., moving tests to `tests/unit/pkgmgr/core/git/queries/`) to match the new source code organization, ensuring logical consistency.
3. **Exception Handling:** The tests were updated to verify specific exception types (like `GitDeleteRemoteBranchError`) rather than generic errors, ensuring the improved error granularity is correctly handled by the CLI.
4. **Integration Safety:** The integration tests in `test_mirror_commands.py` were correctly updated to patch the new query paths, ensuring that network operations remain disabled during testing.
The test changes are consistent with the refactor and provide complete coverage for the new code structure.
https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%2214Br1JG1hxuntmoRzuvme3GKUvQ0heqRn%22%5D,%22action%22:%22open%22,%22userId%22:%22109171005420801378245%22,%22resourceKeys%22:%7B%7D%7D&usp=sharing
2025-12-16 10:01:30 +01:00
|
|
|
"""Execute pkgmgr with the given arguments and return captured output."""
|
2025-12-14 16:14:17 +01:00
|
|
|
original_argv = list(sys.argv)
|
|
|
|
|
original_env = dict(os.environ)
|
|
|
|
|
buffer = io.StringIO()
|
|
|
|
|
cmd_repr = "pkgmgr " + " ".join(args)
|
|
|
|
|
|
|
|
|
|
# Shared dummy context used by multiple mirror commands
|
|
|
|
|
dummy_ctx = MagicMock()
|
|
|
|
|
dummy_ctx.identifier = "dummy-repo"
|
|
|
|
|
dummy_ctx.repo_dir = "/tmp/dummy-repo"
|
|
|
|
|
dummy_ctx.config_mirrors = {"origin": "git@github.com:alice/repo.git"}
|
|
|
|
|
dummy_ctx.file_mirrors = {"backup": "ssh://git@git.example:2201/alice/repo.git"}
|
|
|
|
|
type(dummy_ctx).resolved_mirrors = PropertyMock(
|
|
|
|
|
return_value={
|
|
|
|
|
"origin": "git@github.com:alice/repo.git",
|
|
|
|
|
"backup": "ssh://git@git.example:2201/alice/repo.git",
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-14 16:38:24 +01:00
|
|
|
# Helper: patch with create=True so missing symbols don't explode.
|
|
|
|
|
# IMPORTANT: patch() does not auto-import submodules when resolving dotted names.
|
2025-12-14 16:14:17 +01:00
|
|
|
def _p(target: str, **kwargs):
|
2025-12-14 16:38:24 +01:00
|
|
|
module_name = target.rsplit(".", 1)[0]
|
|
|
|
|
try:
|
|
|
|
|
importlib.import_module(module_name)
|
|
|
|
|
except ModuleNotFoundError:
|
gpt-5.2 ChatGPT: adapt tests to new core.git commands/queries split
- Update mirror integration tests to use probe_remote_reachable
- Refactor branch action tests to mock git command helpers instead of run_git
- Align changelog tests with get_changelog query API
- Update git core tests to cover run() and query helpers
- Remove legacy run_git assumptions from tests
https://chatgpt.com/share/69412008-9e8c-800f-9ac9-90f390d55380
**Validated by Google's model.**
**Summary:**
The test modifications have been correctly implemented to cover the Git refactoring changes:
1. **Granular Mocking:** The tests have shifted from mocking the monolithic `run_git` or `subprocess` to mocking the new, specific wrapper functions (e.g., `pkgmgr.core.git.commands.fetch`, `pkgmgr.core.git.queries.probe_remote_reachable`). This accurately reflects the architectural change in the source code where business logic now relies on these granular imports.
2. **Structural Alignment:** The test directory structure was updated (e.g., moving tests to `tests/unit/pkgmgr/core/git/queries/`) to match the new source code organization, ensuring logical consistency.
3. **Exception Handling:** The tests were updated to verify specific exception types (like `GitDeleteRemoteBranchError`) rather than generic errors, ensuring the improved error granularity is correctly handled by the CLI.
4. **Integration Safety:** The integration tests in `test_mirror_commands.py` were correctly updated to patch the new query paths, ensuring that network operations remain disabled during testing.
The test changes are consistent with the refactor and provide complete coverage for the new code structure.
https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%2214Br1JG1hxuntmoRzuvme3GKUvQ0heqRn%22%5D,%22action%22:%22open%22,%22userId%22:%22109171005420801378245%22,%22resourceKeys%22:%7B%7D%7D&usp=sharing
2025-12-16 10:01:30 +01:00
|
|
|
# Best-effort: allow patch(create=True) even if a symbol moved.
|
2025-12-14 16:38:24 +01:00
|
|
|
pass
|
2025-12-14 16:14:17 +01:00
|
|
|
return patch(target, create=True, **kwargs)
|
|
|
|
|
|
|
|
|
|
# Fake result for remote provisioning (preview-safe)
|
|
|
|
|
def _fake_ensure_remote_repo(spec, provider_hint=None, options=None):
|
|
|
|
|
# Safety: E2E should only ever call this in preview mode
|
|
|
|
|
if options is not None and getattr(options, "preview", False) is not True:
|
2025-12-14 17:31:05 +01:00
|
|
|
raise AssertionError(
|
|
|
|
|
f"{cmd_repr} attempted ensure_remote_repo without preview=True in E2E."
|
|
|
|
|
)
|
2025-12-14 16:14:17 +01:00
|
|
|
r = MagicMock()
|
|
|
|
|
r.status = "preview"
|
|
|
|
|
r.message = "Preview mode (E2E patched): no remote provisioning performed."
|
|
|
|
|
r.url = None
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
sys.argv = ["pkgmgr"] + list(args)
|
|
|
|
|
if extra_env:
|
|
|
|
|
os.environ.update(extra_env)
|
|
|
|
|
|
|
|
|
|
with ExitStack() as stack:
|
|
|
|
|
# build_context is imported directly in these modules:
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.list_cmd.build_context", return_value=dummy_ctx))
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.diff_cmd.build_context", return_value=dummy_ctx))
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.merge_cmd.build_context", return_value=dummy_ctx))
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.setup_cmd.build_context", return_value=dummy_ctx))
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.remote_provision.build_context", return_value=dummy_ctx))
|
|
|
|
|
|
gpt-5.2 ChatGPT: adapt tests to new core.git commands/queries split
- Update mirror integration tests to use probe_remote_reachable
- Refactor branch action tests to mock git command helpers instead of run_git
- Align changelog tests with get_changelog query API
- Update git core tests to cover run() and query helpers
- Remove legacy run_git assumptions from tests
https://chatgpt.com/share/69412008-9e8c-800f-9ac9-90f390d55380
**Validated by Google's model.**
**Summary:**
The test modifications have been correctly implemented to cover the Git refactoring changes:
1. **Granular Mocking:** The tests have shifted from mocking the monolithic `run_git` or `subprocess` to mocking the new, specific wrapper functions (e.g., `pkgmgr.core.git.commands.fetch`, `pkgmgr.core.git.queries.probe_remote_reachable`). This accurately reflects the architectural change in the source code where business logic now relies on these granular imports.
2. **Structural Alignment:** The test directory structure was updated (e.g., moving tests to `tests/unit/pkgmgr/core/git/queries/`) to match the new source code organization, ensuring logical consistency.
3. **Exception Handling:** The tests were updated to verify specific exception types (like `GitDeleteRemoteBranchError`) rather than generic errors, ensuring the improved error granularity is correctly handled by the CLI.
4. **Integration Safety:** The integration tests in `test_mirror_commands.py` were correctly updated to patch the new query paths, ensuring that network operations remain disabled during testing.
The test changes are consistent with the refactor and provide complete coverage for the new code structure.
https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%2214Br1JG1hxuntmoRzuvme3GKUvQ0heqRn%22%5D,%22action%22:%22open%22,%22userId%22:%22109171005420801378245%22,%22resourceKeys%22:%7B%7D%7D&usp=sharing
2025-12-16 10:01:30 +01:00
|
|
|
# Deterministic remote probing (new refactor: probe_remote_reachable)
|
|
|
|
|
stack.enter_context(_p("pkgmgr.core.git.queries.probe_remote_reachable", return_value=True))
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.setup_cmd.probe_remote_reachable", return_value=True))
|
2025-12-14 16:14:17 +01:00
|
|
|
|
2025-12-14 17:31:05 +01:00
|
|
|
# setup_cmd imports ensure_origin_remote directly:
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.setup_cmd.ensure_origin_remote", return_value=None))
|
|
|
|
|
# Extra safety: if any code calls git_remote.ensure_origin_remote directly
|
|
|
|
|
stack.enter_context(_p("pkgmgr.actions.mirror.git_remote.ensure_origin_remote", return_value=None))
|
2025-12-14 16:14:17 +01:00
|
|
|
|
|
|
|
|
# remote provisioning: remote_provision imports ensure_remote_repo directly from core:
|
|
|
|
|
stack.enter_context(
|
|
|
|
|
_p(
|
|
|
|
|
"pkgmgr.actions.mirror.remote_provision.ensure_remote_repo",
|
|
|
|
|
side_effect=_fake_ensure_remote_repo,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
with redirect_stdout(buffer), redirect_stderr(buffer):
|
|
|
|
|
try:
|
|
|
|
|
runpy.run_module("pkgmgr", run_name="__main__")
|
|
|
|
|
except SystemExit as exc:
|
|
|
|
|
code = exc.code if isinstance(exc.code, int) else None
|
|
|
|
|
if code not in (0, None):
|
|
|
|
|
raise AssertionError(
|
|
|
|
|
"%r failed with exit code %r.\n\nOutput:\n%s"
|
|
|
|
|
% (cmd_repr, exc.code, buffer.getvalue())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return buffer.getvalue()
|
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
sys.argv = original_argv
|
|
|
|
|
os.environ.clear()
|
|
|
|
|
os.environ.update(original_env)
|
|
|
|
|
|
|
|
|
|
def test_mirror_help(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "--help"])
|
|
|
|
|
self.assertIn("usage:", output.lower())
|
|
|
|
|
self.assertIn("mirror", output.lower())
|
|
|
|
|
|
|
|
|
|
def test_mirror_list_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "list", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror list")
|
|
|
|
|
|
|
|
|
|
def test_mirror_diff_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "diff", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror diff")
|
|
|
|
|
|
|
|
|
|
def test_mirror_merge_config_to_file_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "merge", "config", "file", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror merge (config -> file)")
|
|
|
|
|
|
|
|
|
|
def test_mirror_setup_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "setup", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror setup")
|
|
|
|
|
|
|
|
|
|
def test_mirror_check_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "check", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror check")
|
|
|
|
|
|
|
|
|
|
def test_mirror_provision_preview_all(self) -> None:
|
|
|
|
|
output = self._run_pkgmgr(["mirror", "provision", "--preview", "--all"])
|
|
|
|
|
self.assertTrue(output.strip(), "Expected output from mirror provision (preview)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|