Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / lint-shell (push) Has been cancelled
Mark stable commit / lint-python (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from pkgmgr.actions.update.manager import UpdateManager
|
|
|
|
|
|
class TestUpdateSilentContinues(unittest.TestCase):
|
|
def test_update_continues_on_failures_and_silent_controls_exit_code(self) -> None:
|
|
"""
|
|
Integration test for UpdateManager:
|
|
- pull failure on repo A should not stop repo B/C
|
|
- install failure on repo B should not stop repo C
|
|
- without silent -> SystemExit(1) at end if any failures
|
|
- with silent -> no SystemExit even if there are failures
|
|
"""
|
|
|
|
repos = [
|
|
{"provider": "github", "account": "example", "repository": "repo-a"},
|
|
{"provider": "github", "account": "example", "repository": "repo-b"},
|
|
{"provider": "github", "account": "example", "repository": "repo-c"},
|
|
]
|
|
|
|
# We patch the internal calls used by UpdateManager:
|
|
# - pull_with_verification is called once per repo
|
|
# - install_repos is called once per repo that successfully pulled
|
|
#
|
|
# We simulate:
|
|
# repo-a: pull fails
|
|
# repo-b: pull ok, install fails
|
|
# repo-c: pull ok, install ok
|
|
pull_calls = []
|
|
install_calls = []
|
|
|
|
def pull_side_effect(selected_repos, *_args, **_kwargs):
|
|
# selected_repos is a list with exactly one repo in our implementation.
|
|
repo = selected_repos[0]
|
|
pull_calls.append(repo["repository"])
|
|
if repo["repository"] == "repo-a":
|
|
raise SystemExit(2)
|
|
return None
|
|
|
|
def install_side_effect(selected_repos, *_args, **kwargs):
|
|
repo = selected_repos[0]
|
|
install_calls.append(
|
|
(repo["repository"], kwargs.get("silent"), kwargs.get("emit_summary"))
|
|
)
|
|
if repo["repository"] == "repo-b":
|
|
raise SystemExit(3)
|
|
return None
|
|
|
|
# Patch at the exact import locations used inside UpdateManager.run()
|
|
with (
|
|
patch(
|
|
"pkgmgr.actions.repository.pull.pull_with_verification",
|
|
side_effect=pull_side_effect,
|
|
),
|
|
patch(
|
|
"pkgmgr.actions.install.install_repos", side_effect=install_side_effect
|
|
),
|
|
):
|
|
# 1) silent=True: should NOT raise (even though failures happened)
|
|
UpdateManager().run(
|
|
selected_repos=repos,
|
|
repositories_base_dir="/tmp/repos",
|
|
bin_dir="/tmp/bin",
|
|
all_repos=repos,
|
|
no_verification=True,
|
|
system_update=False,
|
|
preview=True,
|
|
quiet=True,
|
|
update_dependencies=False,
|
|
clone_mode="shallow",
|
|
silent=True,
|
|
force_update=True,
|
|
)
|
|
|
|
# Ensure it tried all pulls, and installs happened for B and C only.
|
|
self.assertEqual(pull_calls, ["repo-a", "repo-b", "repo-c"])
|
|
self.assertEqual(
|
|
[r for r, _silent, _emit in install_calls], ["repo-b", "repo-c"]
|
|
)
|
|
|
|
# Ensure UpdateManager suppressed install summary spam by passing emit_summary=False.
|
|
for _repo_name, _silent, emit_summary in install_calls:
|
|
self.assertFalse(emit_summary)
|
|
|
|
# Reset tracking for the non-silent run
|
|
pull_calls.clear()
|
|
install_calls.clear()
|
|
|
|
# 2) silent=False: should raise SystemExit(1) at end due to failures
|
|
with self.assertRaises(SystemExit) as cm:
|
|
UpdateManager().run(
|
|
selected_repos=repos,
|
|
repositories_base_dir="/tmp/repos",
|
|
bin_dir="/tmp/bin",
|
|
all_repos=repos,
|
|
no_verification=True,
|
|
system_update=False,
|
|
preview=True,
|
|
quiet=True,
|
|
update_dependencies=False,
|
|
clone_mode="shallow",
|
|
silent=False,
|
|
force_update=True,
|
|
)
|
|
self.assertEqual(cm.exception.code, 1)
|
|
|
|
# Still must have processed all repos (continue-on-failure behavior).
|
|
self.assertEqual(pull_calls, ["repo-a", "repo-b", "repo-c"])
|
|
self.assertEqual(
|
|
[r for r, _silent, _emit in install_calls], ["repo-b", "repo-c"]
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|