Harden base progression and cleanup; validate finite physical resupply
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Run the real archiver against synthetic sealed startup logs, without engines."""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
ROOT=Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0,str(ROOT/'tools'))
|
||||
from native_provenance import snapshot,persist,bindings,seal_run
|
||||
from test_vanilla_game_control import BASE
|
||||
|
||||
ORDINARY='''00 SCRIPT : Module: Game; defines: "PLATFORM_WINDOWS"
|
||||
00 SCRIPT : ERR ORDINARY: header verified project=core systems=MissionSystems
|
||||
00 SCRIPT : Rereintroduced [mission]: phase 0 -> 1
|
||||
00 SCRIPT : ERR ORDINARY: local participant verified project=core phase=prison
|
||||
'''
|
||||
|
||||
class ArchiveControl(unittest.TestCase):
|
||||
def archive(self,project,result,control=None,cleanup=True,content=None):
|
||||
tmp=tempfile.TemporaryDirectory(prefix='erri-archive-control-test-');self.addCleanup(tmp.cleanup)
|
||||
root=Path(tmp.name);(root/'addons/core').mkdir(parents=True)
|
||||
(root/'addons/core/addon.gproj').write_text('Synthetic fixture source, not a native project')
|
||||
tools=root/'tools';tools.mkdir()
|
||||
for name in ('archive_native.py','native_report.py','source_manifest.py','native_provenance.py','headless_game.py'):
|
||||
shutil.copyfile(ROOT/'tools'/name,tools/name)
|
||||
session=root/'session';session.mkdir()
|
||||
(session/'console.log').write_text(content if content is not None else BASE if project=='vanilla-control' else ORDINARY)
|
||||
captured=snapshot(root,['synthetic-archive-test-no-engine']);persist(session,captured)
|
||||
data={**bindings(captured),'started_unix':json.loads(captured[1])['captured_unix'],**seal_run(root,session,captured),'project':project,'result':result,'cleanup_confirmed':cleanup}
|
||||
if control is not None:data['control_only']=control
|
||||
(session/'runner.json').write_text(json.dumps(data))
|
||||
# Deliberately false saved status; actual archiver must recompute sealed log.
|
||||
(session/'game-startup-report.json').write_text('{"ready":true,"failed":false}')
|
||||
command=[sys.executable,str(tools/'archive_native.py'),str(session),'control']
|
||||
done=subprocess.run(command,text=True,capture_output=True)
|
||||
dest=root/'docs/evidence/control'
|
||||
self.assertTrue(dest.exists(),done.stderr)
|
||||
self.assertEqual((dest/'console.log.txt').read_bytes(),(session/'console.log').read_bytes())
|
||||
return done,json.loads((dest/'report.json').read_text()),command,dest
|
||||
def test_clean_control_gets_own_result_and_no_successor_qualification(self):
|
||||
result,report,command,dest=self.archive('vanilla-control','vanilla-control-started',True)
|
||||
self.assertEqual(result.returncode,0,result.stderr)
|
||||
self.assertTrue(report['control_metadata_consistent']);self.assertTrue(report['control_only'])
|
||||
self.assertFalse(report['normal_mission_ready']);self.assertFalse(report['scenario_header_verified'])
|
||||
self.assertIn('no successor',report['qualification'])
|
||||
before=(dest/'report.json').read_bytes()
|
||||
duplicate=subprocess.run(command,capture_output=True,text=True)
|
||||
self.assertNotEqual(duplicate.returncode,0);self.assertEqual((dest/'report.json').read_bytes(),before)
|
||||
def test_control_rejects_ordinary_result_or_inconsistent_flag(self):
|
||||
for result,flag in [('game-started',True),('vanilla-control-started',None),('vanilla-control-started',False),('vanilla-control-started','true')]:
|
||||
with self.subTest(result=result,flag=flag):
|
||||
done,report,_,_=self.archive('vanilla-control',result,flag)
|
||||
self.assertEqual(done.returncode,1);self.assertTrue(report['ready'])
|
||||
def test_control_retains_native_failure_despite_saved_success(self):
|
||||
done,report,_,_=self.archive('vanilla-control','vanilla-control-started',True,content=BASE+"00 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot'")
|
||||
self.assertEqual(done.returncode,1);self.assertFalse(report['ready']);self.assertTrue(report['engine_errors'])
|
||||
def test_cleanup_is_still_required(self):
|
||||
done,_,_,_=self.archive('vanilla-control','vanilla-control-started',True,cleanup=False)
|
||||
self.assertEqual(done.returncode,1)
|
||||
def test_ordinary_current_and_legacy_status_remain_strict(self):
|
||||
for flag in (None,False):
|
||||
done,report,_,_=self.archive('core','game-started',flag)
|
||||
self.assertEqual(done.returncode,0,done.stderr);self.assertTrue(report['normal_mission_ready'])
|
||||
for result,flag in [('vanilla-control-started',False),('game-started',True)]:
|
||||
done,_,_,_=self.archive('core',result,flag);self.assertEqual(done.returncode,1)
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
Reference in New Issue
Block a user