the-custodian/docs/changes/netkingdom-target-2026-10-17/native-runtime-install-r3/test_receipt_cleanup.py
codex 4016f3bdee
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 9s
Record failed runtime trial and reviewed verification proposal (3/4)
2026-10-17 13:27:00 +02:00

72 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""Exercise actual controller receipt/cleanup ordering with local disposable IO.
Only native admission/launch inputs are stubbed; no runtime/native calls.
"""
import contextlib
import importlib.util
import io
import json
from pathlib import Path
import shutil
import sys
import tempfile
from types import SimpleNamespace
import unittest
from unittest.mock import patch
HERE=Path(__file__).resolve().parent
class ReceiptCleanupTests(unittest.TestCase):
def exercise(self,fail_persist):
spec=importlib.util.spec_from_file_location('controller',HERE/'verify-installed.py')
m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
with tempfile.TemporaryDirectory(prefix='nk-receipt-order-') as d:
base=Path(d);stage=base/'stage';stage.mkdir(mode=0o700)
receipt=base/'receipt.json';destination=base/'installed';destination.mkdir()
for name in ('runtime.py','verify-installed.py','process_supervision.py'):(stage/name).touch(mode=0o600)
jobs=[{'label':name,'returncode':0,'status':'completed'} for name in ('rein-aharness','glas-harness','claude')]
class FakeSupervisor:
def __init__(self,state):
state.mkdir(mode=0o700);p=state/'public-journal.json';p.write_text(json.dumps({'jobs':jobs}));p.chmod(0o600)
def close(self):return {'quiescent':True,'no_live_or_waitable_descendants':True,'jobs':jobs}
original_protected=m.protected
def protected(path,**kwargs):
actual=original_protected(path,**kwargs)
if path==stage:return SimpleNamespace(st_ino=actual.st_ino,st_dev=2049)
return actual
removed=[];real_rmtree=shutil.rmtree
def checked_remove(path):
before=json.loads(receipt.read_text())
self.assertTrue(before['durable_receipt_before_cleanup'])
self.assertTrue(before['process_supervision']['quiescent'])
self.assertEqual(before['cleanup_status'],'pending')
self.assertEqual([x['exit_code'] for x in before['launcher_status']],[0,0,0])
removed.append(True);real_rmtree(path)
output=io.StringIO()
with contextlib.ExitStack() as stack:
for name,value in {'STAGE':stage,'DESTINATION':destination,'DURABLE_RECEIPT':receipt,
'protected':protected,'identify':lambda supervisor:None,
'supervision_module':lambda:SimpleNamespace(Supervisor=FakeSupervisor),
'runtime_reader':lambda:SimpleNamespace(runtime_digest=lambda path:m.DIGEST),
'phase':lambda *args:(0,{'status':'rehearsed','steps':{j['label']:0 for j in jobs}})}.items():
stack.enter_context(patch.object(m,name,value))
stack.enter_context(patch.object(m.os,'nice',lambda value:None))
stack.enter_context(patch.object(m.shutil,'rmtree',checked_remove))
stack.enter_context(patch.object(sys,'argv',['verify-installed.py','--stage-inode',str(stage.stat().st_ino)]))
if fail_persist:stack.enter_context(patch.object(m,'persist',side_effect=OSError('fixture write failure')))
with contextlib.redirect_stdout(output):code=m.main()
result=json.loads(output.getvalue())
if fail_persist:
self.assertEqual(code,1);self.assertFalse(removed);self.assertTrue(stage.exists())
self.assertFalse(result['durable_receipt_before_cleanup'])
else:
self.assertEqual(code,0);self.assertEqual(removed,[True]);self.assertFalse(stage.exists())
checkpoint=json.loads(receipt.read_text());self.assertEqual(checkpoint['cleanup_status'],'pending')
self.assertTrue(result['owned_staging_removed']);self.assertEqual(receipt.stat().st_mode&0o777,0o600)
def test_actual_cleanup_waits_for_durable_complete_public_receipt(self):self.exercise(False)
def test_actual_cleanup_refuses_when_durable_receipt_write_fails(self):self.exercise(True)
if __name__=='__main__':unittest.main()