lazyBoy/tests/file-process-proof.test.py

87 lines
5.0 KiB
Python
Raw Permalink Normal View History

2026-09-11 02:47:43 +00:00
"""Quiescence evidence must distinguish process exit from unavailable identity."""
import os
import hashlib
import json
import sqlite3
import subprocess
from pathlib import Path
import unittest
from unittest.mock import patch
SOURCE = Path(__file__).resolve().parents[1] / 'crates/supervisor/src/runner_files.py'
class FileProcessProof(unittest.TestCase):
def setUp(self):
self.boot = '00000000-0000-0000-0000-000000000000:123'
self.module = {'process_info': lambda pid: {'start': '456', 'state': 'S'}, 'boot_identity': lambda: self.boot}
exec(compile(SOURCE.read_text(), str(SOURCE), 'exec'), self.module)
self.reference = {'pid': os.getpid(), 'start': '456', 'boot': self.boot}
def test_live_reused_and_unavailable_identity(self):
finished = self.module['file_process_finished']
self.assertFalse(finished(self.reference))
self.assertTrue(finished({**self.reference, 'start': '455'}))
self.assertIsNone(finished({**self.reference, 'boot': self.boot[:-3] + '999'}))
self.assertIsNone(finished({**self.reference, 'boot': 'invalid'}))
with patch.object(os, 'stat', side_effect=PermissionError()):
self.assertIsNone(finished(self.reference))
with patch.object(os, 'stat', side_effect=FileNotFoundError()):
self.assertTrue(finished(self.reference))
self.module['boot_identity'] = lambda: (_ for _ in ()).throw(FileNotFoundError())
self.assertIsNone(finished(self.reference), 'missing boot data is not proof of exit')
def test_legacy_and_controller_only_evidence(self):
quiescent = self.module['file_quiescent']
self.assertIsNone(quiescent({}))
self.assertFalse(quiescent({'handoff_required': True, 'controller': self.reference}))
self.assertFalse(quiescent({'handoff_required': True, 'controller': {**self.reference, 'start': '455'}, 'execution': self.reference}))
self.assertTrue(quiescent({'handoff_required': True, 'execution': {**self.reference, 'start': '455'}}))
def test_controller_exit_refreshes_child_committed_after_first_read(self):
identity = {'computer_id': 'fixture', 'bot_id': 'race', 'generation': 1}
encoded = self.module['file_identity'](identity)
key = hashlib.sha256((encoded + ':operation').encode()).hexdigest()
metadata = {'action': 'write', 'path': 'file', 'desiredHash': 'a' * 64,
'handoff_required': True, 'controller': {**self.reference, 'start': '455'}}
with sqlite3.connect(':memory:') as db:
self.module['file_journal_schema'](db)
db.execute('INSERT INTO file_operations VALUES (?,?,?,?,NULL,?,?)',
(key, encoded, 'digest', 'accepted', json.dumps(metadata), 0))
db.commit()
def observe_process(pid):
# The status SELECT already returned controller-only metadata;
# the controller commits its child and dies before /proc is read.
db.execute('UPDATE file_operations SET metadata=? WHERE id=?',
(json.dumps({**metadata, 'execution': self.reference}), key))
db.commit()
return {'start': '456', 'state': 'S'}
self.module['process_info'] = observe_process
fingerprint = subprocess.CompletedProcess([], 0, json.dumps({'path': 'file', 'kind': 'file', 'sha256': 'a' * 64}), '')
with patch.object(subprocess, 'run', return_value=fingerprint):
result = self.module['file_journal_handle'](db, {
'action': 'file_status', 'identity': identity,
'input': json.dumps({'operation_id': 'operation', 'readback': True, 'resolve': True})
}, '', lambda *_: False)
evidence = json.loads(result['stdout'])
self.assertEqual(result['status'], 'unknown')
self.assertTrue(evidence['desired_state_matches'])
self.assertFalse(evidence['helper_quiescent'], 'committed child is still alive')
stored = json.loads(db.execute('SELECT observation FROM file_observations').fetchone()[0])
self.assertFalse(stored['helper_quiescent'])
self.module['process_info'] = lambda pid: {'start': '456', 'state': 'S'}
db.execute('UPDATE file_operations SET metadata=? WHERE id=?', (json.dumps({**metadata,
'controller': self.reference, 'execution': {**self.reference, 'start': '455'}}), key))
db.commit()
with patch.object(subprocess, 'run', return_value=fingerprint):
result = self.module['file_journal_handle'](db, {
'action': 'file_status', 'identity': identity,
'input': json.dumps({'operation_id': 'operation', 'readback': True, 'resolve': True})
}, '', lambda *_: False)
self.assertEqual(result['status'], 'unknown', 'live controller can still commit its original receipt')
self.assertFalse(json.loads(result['stdout'])['controller_quiescent'])
if __name__ == '__main__':
unittest.main()