"""Updater transaction and service tests; all targets live in temporary roots.""" import importlib.util from contextlib import ExitStack, nullcontext import io import json import os from pathlib import Path import stat import subprocess import sys import unittest from unittest.mock import patch import zipfile from test_regressions import IsolatedTest, ROOT, bash_path, function spec = importlib.util.spec_from_file_location('cups_project_updater', ROOT / 'update_cups.py') updater = importlib.util.module_from_spec(spec) sys.modules[spec.name] = updater spec.loader.exec_module(updater) class FakeServices: def __init__(self, fail_restore=False, fail_pause=False): self.calls = [] self.fail_restore = fail_restore self.fail_pause = fail_pause def snapshot(self, manager_changed): self.calls.append(('snapshot', manager_changed)) def pause(self): self.calls.append('pause') if self.fail_pause: raise updater.UpdateError('simulated busy service') def restore(self): self.calls.append('restore') if self.fail_restore: self.fail_restore = False raise updater.UpdateError('simulated startup failure') def stop_for_rollback(self): self.calls.append('stop_for_rollback') class UpdateTests(IsolatedTest): def setUp(self): super().setUp() self.source = self.directory / 'release' self.system = self.directory / 'system' self.source.mkdir() self.system.mkdir() self.write(self.source, 'setup_cups.sh', b'#!/bin/bash\necho installer\n') for source, target in updater.PROGRAMS.items(): new = b'version = 2\n' if source.endswith('.py') else b'#!/bin/bash\necho new\n' old = b'version = 1\n' if source.endswith('.py') else b'#!/bin/bash\necho old\n' self.write(self.source, source, new) self.write(self.system, target, old) self.write(self.source, 'cups-templates-zh_CN/header.tmpl', b'