Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
71 lines
4.4 KiB
Python
71 lines
4.4 KiB
Python
"""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 : Reintroduced [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','project_schema.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())
|
|
self.assertTrue((dest/'report.json').is_file(), done.stderr)
|
|
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()
|