from __future__ import annotations import shutil import subprocess import tempfile import unittest from pathlib import Path SCRIPTS = Path(__file__).resolve().parent CONTRACT = SCRIPTS / "public-runtime-task-definition-cutover.ps1" REPO_ROOT = SCRIPTS.parent class PublicRuntimeTaskDefinitionCutoverTest(unittest.TestCase): def _run_powershell(self, body: str) -> subprocess.CompletedProcess[str]: powershell = shutil.which("powershell.exe") if powershell is None: self.skipTest("Windows PowerShell 5.1 is not available") with tempfile.TemporaryDirectory(prefix="vignette-task-cutover-") as raw: harness = Path(raw) / "task-cutover.ps1" harness.write_text(body, encoding="utf-8-sig") return subprocess.run( [ powershell, "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", str(harness), ], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=30, check=False, ) def _assert_harness_passes(self, body: str) -> None: completed = self._run_powershell(body) self.assertEqual( 0, completed.returncode, msg=f"stdout={completed.stdout}\nstderr={completed.stderr}", ) def test_contract_digest_ignores_only_enabled_state(self) -> None: contract = str(CONTRACT).replace("'", "''") self._assert_harness_passes( f""" . '{contract}' $enabled = 'trueone' $disabled = 'falseone' $drifted = 'falsetwo' $enabledDigest = Get-PublicRuntimeTaskXmlContractSha256 -Xml $enabled $disabledDigest = Get-PublicRuntimeTaskXmlContractSha256 -Xml $disabled $driftedDigest = Get-PublicRuntimeTaskXmlContractSha256 -Xml $drifted if ($enabledDigest -cne $disabledDigest) {{ exit 2 }} if ($enabledDigest -ceq $driftedDigest) {{ exit 3 }} exit 0 """ ) def test_exact_action_contract_accepts_disabled_and_operational_snapshots(self) -> None: contract = str(CONTRACT).replace("'", "''") root = str(REPO_ROOT).replace("'", "''") self._assert_harness_passes( f""" . '{contract}' $contracts = @(Get-PublicRuntimeExpectedTaskActionContracts ` -StableSourceRoot '{root}' ` -ExpectedSourceCommit ('a' * 40) ` -ExpectedSourceTree ('b' * 40) ` -PythonPath 'C:\\Python311\\python.exe' ` -UserUploadDir 'C:\\Runtime\\uploads' ` -UserUploadManifestPath 'C:\\RuntimeState\\manifest.json' ` -ExpectedUserUploadManifestSha256 ('c' * 64) ` -UserUploadWriteFreezePath 'C:\\RuntimeState\\freeze.json' ` -CloudflaredPath 'C:\\Tools\\cloudflared.exe' ` -CloudflaredConfigPath 'C:\\RuntimeState\\cloudflared.yml' ` -PublicHealthUrl 'https://api-vignette.chanpaca.net/health') $entries = @() foreach ($item in $contracts) {{ $entries += [pscustomobject]@{{ role = $item.role enabled = $false action_execute = $item.execute action_arguments = $item.arguments action_working_directory = $item.working_directory }} }} $snapshot = [pscustomobject]@{{ entries = $entries }} $null = Assert-NewPublicRuntimeTaskDefinitionsPinned ` -Snapshot $snapshot ` -StableSourceRoot '{root}' ` -ExpectedSourceCommit ('a' * 40) ` -ExpectedSourceTree ('b' * 40) ` -PythonPath 'C:\\Python311\\python.exe' ` -UserUploadDir 'C:\\Runtime\\uploads' ` -UserUploadManifestPath 'C:\\RuntimeState\\manifest.json' ` -ExpectedUserUploadManifestSha256 ('c' * 64) ` -UserUploadWriteFreezePath 'C:\\RuntimeState\\freeze.json' ` -CloudflaredPath 'C:\\Tools\\cloudflared.exe' ` -CloudflaredConfigPath 'C:\\RuntimeState\\cloudflared.yml' ` -PublicHealthUrl 'https://api-vignette.chanpaca.net/health' foreach ($entry in $entries) {{ $entry.enabled = $true }} $null = Assert-NewPublicRuntimeTaskDefinitionsPinned ` -Snapshot $snapshot ` -StableSourceRoot '{root}' ` -ExpectedSourceCommit ('a' * 40) ` -ExpectedSourceTree ('b' * 40) ` -PythonPath 'C:\\Python311\\python.exe' ` -UserUploadDir 'C:\\Runtime\\uploads' ` -UserUploadManifestPath 'C:\\RuntimeState\\manifest.json' ` -ExpectedUserUploadManifestSha256 ('c' * 64) ` -UserUploadWriteFreezePath 'C:\\RuntimeState\\freeze.json' ` -CloudflaredPath 'C:\\Tools\\cloudflared.exe' ` -CloudflaredConfigPath 'C:\\RuntimeState\\cloudflared.yml' ` -PublicHealthUrl 'https://api-vignette.chanpaca.net/health' ` -AllowEnabled $entries[0].action_arguments += ' -InjectedDrift' try {{ $null = Assert-NewPublicRuntimeTaskDefinitionsPinned ` -Snapshot $snapshot ` -StableSourceRoot '{root}' ` -ExpectedSourceCommit ('a' * 40) ` -ExpectedSourceTree ('b' * 40) ` -PythonPath 'C:\\Python311\\python.exe' ` -UserUploadDir 'C:\\Runtime\\uploads' ` -UserUploadManifestPath 'C:\\RuntimeState\\manifest.json' ` -ExpectedUserUploadManifestSha256 ('c' * 64) ` -UserUploadWriteFreezePath 'C:\\RuntimeState\\freeze.json' ` -CloudflaredPath 'C:\\Tools\\cloudflared.exe' ` -CloudflaredConfigPath 'C:\\RuntimeState\\cloudflared.yml' ` -PublicHealthUrl 'https://api-vignette.chanpaca.net/health' ` -AllowEnabled exit 2 }} catch {{ exit 0 }} """ ) def test_second_installer_failure_compensates_both_tasks_to_disabled(self) -> None: contract = str(CONTRACT).replace("'", "''") self._assert_harness_passes( f""" . '{contract}' $script:states = @{{ Boot = $false; Watchdog = $false }} $script:bootCalls = 0 $script:watchdogCalls = 0 $script:suspendCalls = 0 $script:assertCalls = 0 function Suspend-PublicRuntimeTasks {{ param($Snapshot, $TimeoutSec) $script:suspendCalls += 1 $script:states.Boot = $false $script:states.Watchdog = $false }} function Assert-PublicRuntimeTasksDisabledAndIdle {{ param($Snapshot, $TimeoutSec) $script:assertCalls += 1 if ($script:states.Boot -or $script:states.Watchdog) {{ throw 'task was not compensated to disabled' }} }} $bootInstaller = {{ $script:bootCalls += 1 $script:states.Boot = $true }} $watchdogInstaller = {{ $script:watchdogCalls += 1 throw 'synthetic second installer failure' }} $maintenance = @( [pscustomobject]@{{ role='boot'; task_name='Boot' }}, [pscustomobject]@{{ role='watchdog'; task_name='Watchdog' }} ) try {{ Invoke-PublicRuntimeTaskDefinitionInstallerPairDisabled ` -BootInstaller $bootInstaller ` -WatchdogInstaller $watchdogInstaller ` -MaintenanceSnapshot $maintenance ` -TimeoutSec 3 exit 2 }} catch {{ if ($script:bootCalls -ne 1 -or $script:watchdogCalls -ne 1) {{ exit 3 }} if ($script:suspendCalls -ne 1 -or $script:assertCalls -ne 1) {{ exit 4 }} if ($script:states.Boot -or $script:states.Watchdog) {{ exit 5 }} exit 0 }} """ ) def test_second_enable_failure_compensates_both_tasks_to_disabled(self) -> None: contract = str(CONTRACT).replace("'", "''") self._assert_harness_passes( f""" . '{contract}' $script:states = @{{ Boot = $false; Watchdog = $false }} $script:taskPaths = @() function Assert-PublicRuntimeTaskDefinitionSnapshotCurrent {{ param($ExpectedSnapshot) return $ExpectedSnapshot }} function Enable-ScheduledTask {{ param($TaskName, $TaskPath, $ErrorAction) $script:taskPaths += $TaskPath if ($TaskPath -cne '\\') {{ throw 'wrong task path' }} if ($TaskName -eq 'Watchdog') {{ throw 'synthetic second enable failure' }} $script:states[$TaskName] = $true }} function Disable-ScheduledTask {{ param($TaskName, $TaskPath, $ErrorAction) $script:taskPaths += $TaskPath if ($TaskPath -cne '\\') {{ throw 'wrong task path' }} $script:states[$TaskName] = $false }} function Get-PublicRuntimeTaskDefinitionSnapshot {{ param($BootTaskName, $WatchdogTaskName, [switch]$RequireEnabled) return [pscustomobject]@{{ entries = @( [pscustomobject]@{{ role='boot'; task_name='Boot'; enabled=$script:states.Boot }}, [pscustomobject]@{{ role='watchdog'; task_name='Watchdog'; enabled=$script:states.Watchdog }} ) }} }} $snapshot = [pscustomobject]@{{ entries = @( [pscustomobject]@{{ role='boot'; task_name='Boot'; contract_sha256=('a' * 64); action_execute='one'; action_arguments='one'; action_working_directory='one' }}, [pscustomobject]@{{ role='watchdog'; task_name='Watchdog'; contract_sha256=('b' * 64); action_execute='two'; action_arguments='two'; action_working_directory='two' }} ) }} try {{ Enable-NewPublicRuntimeTaskDefinitions -DisabledSnapshot $snapshot | Out-Null exit 2 }} catch {{ if ($script:states.Boot -or $script:states.Watchdog) {{ exit 3 }} if ($script:taskPaths.Count -lt 3) {{ exit 4 }} if (@($script:taskPaths | Where-Object {{ $_ -cne '\\' }}).Count -ne 0) {{ exit 5 }} exit 0 }} """ ) def test_operational_definition_drift_disables_both_tasks(self) -> None: contract = str(CONTRACT).replace("'", "''") self._assert_harness_passes( f""" . '{contract}' $script:states = @{{ Boot = $false; Watchdog = $false }} function Assert-PublicRuntimeTaskDefinitionSnapshotCurrent {{ param($ExpectedSnapshot); return $ExpectedSnapshot }} function Enable-ScheduledTask {{ param($TaskName, $TaskPath, $ErrorAction) if ($TaskPath -cne '\\') {{ throw 'wrong task path' }} $script:states[$TaskName] = $true }} function Disable-ScheduledTask {{ param($TaskName, $TaskPath, $ErrorAction) if ($TaskPath -cne '\\') {{ throw 'wrong task path' }} $script:states[$TaskName] = $false }} function Get-PublicRuntimeTaskDefinitionSnapshot {{ param($BootTaskName, $WatchdogTaskName, [switch]$RequireEnabled) return [pscustomobject]@{{ entries = @( [pscustomobject]@{{ role='boot'; task_name='Boot'; enabled=$true; contract_sha256=('a' * 64); action_execute='one'; action_arguments='one'; action_working_directory='one' }}, [pscustomobject]@{{ role='watchdog'; task_name='Watchdog'; enabled=$true; contract_sha256=('c' * 64); action_execute='two'; action_arguments='two'; action_working_directory='two' }} ); set_sha256=('d' * 64) }} }} $snapshot = [pscustomobject]@{{ entries = @( [pscustomobject]@{{ role='boot'; task_name='Boot'; contract_sha256=('a' * 64); action_execute='one'; action_arguments='one'; action_working_directory='one' }}, [pscustomobject]@{{ role='watchdog'; task_name='Watchdog'; contract_sha256=('b' * 64); action_execute='two'; action_arguments='two'; action_working_directory='two' }} ) }} try {{ Enable-NewPublicRuntimeTaskDefinitions -DisabledSnapshot $snapshot | Out-Null exit 2 }} catch {{ if ($script:states.Boot -or $script:states.Watchdog) {{ exit 3 }} exit 0 }} """ ) if __name__ == "__main__": unittest.main()