72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
"""Update recovery checks; external git and installer operations are isolated."""
|
|
|
|
import io
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from rich.console import Console
|
|
|
|
from cobot.commands import update
|
|
|
|
|
|
class UpdateTests(unittest.TestCase):
|
|
def run_update(self, codes, behind="1"):
|
|
output = io.StringIO()
|
|
commands = []
|
|
|
|
def stream(command, **kwargs):
|
|
commands.append(command)
|
|
result = next(codes, 0)
|
|
if isinstance(result, Exception):
|
|
raise result
|
|
return result
|
|
|
|
def git(*args):
|
|
return {"rev-parse": "controller", "rev-list": behind,
|
|
"log": "abc123 Update CLI"}[args[0]]
|
|
|
|
console = Console(file=output, color_system=None)
|
|
with patch.object(update, "_git", side_effect=git), \
|
|
patch.object(update.process, "stream", side_effect=stream), \
|
|
patch.object(update, "_plain"), \
|
|
patch("cobot.process.console", console), \
|
|
patch("cobot.ui.console", console):
|
|
code = update._update()
|
|
return code, output.getvalue(), commands
|
|
|
|
def test_install_failure_reports_failure(self):
|
|
for install_code in (1, -9, -15):
|
|
with self.subTest(install_code=install_code):
|
|
code, output, _ = self.run_update(iter([0, 0, install_code]))
|
|
self.assertEqual(code, 1)
|
|
self.assertNotIn("Проект обновлён", output)
|
|
|
|
def test_current_checkout_still_retries_installation(self):
|
|
code, _, commands = self.run_update(iter([0, 0]), behind="0")
|
|
self.assertEqual([command[:2] for command in commands],
|
|
[["git", "fetch"], ["uv", "tool"]])
|
|
self.assertEqual(code, 0)
|
|
|
|
def test_killed_git_stops_before_next_step(self):
|
|
for codes, expected_count in [([-9], 1), ([0, -15], 2)]:
|
|
with self.subTest(codes=codes):
|
|
code, output, commands = self.run_update(iter(codes))
|
|
self.assertNotEqual(code, 0)
|
|
self.assertEqual(len(commands), expected_count)
|
|
self.assertNotIn("Проект обновлён", output)
|
|
|
|
def test_missing_installer_reports_failure_without_traceback(self):
|
|
code, _, _ = self.run_update(
|
|
iter([0, 0, FileNotFoundError("uv not found")]))
|
|
self.assertNotEqual(code, 0)
|
|
|
|
def test_command_exits_nonzero_after_failed_installation(self):
|
|
with patch.object(update, "_update", return_value=1):
|
|
with self.assertRaises(SystemExit) as result:
|
|
update.run(None)
|
|
self.assertEqual(result.exception.code, 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|