Files
EscapistsReintroduced/tests/test_ordinary_gate_evidence.py
T

126 lines
9.2 KiB
Python

#!/usr/bin/env python3
"""Native gate record contracts and negative cases, without input or engine use."""
import copy
from pathlib import Path
import sys
import unittest
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools'))
from ordinary_gate_evidence import parse_gate_record,parse_gate_records,join_gate_snapshots,validate_gate_geometry
NONCE='gateTrial123'
def fixture():
lines=[f'SCRIPT : ERR INPUT OBSERVE: run={NONCE} sample=0 real=1000 world=10000 QUEUED']
for i in range(1,31):
t=1000+i*110;w=10000+i*110
lines.append(f'SCRIPT : ERR INPUT OBSERVE: run={NONCE} sample={i} real={t} world={w} SAMPLE origin=<6088.5,211.389,7158.5> forward=0 input=<0,0,0> velocity=<0,0,0> inventory=0')
if i==1:
lines.append(f'SCRIPT : ERR LOOK OBSERVE: run={NONCE} sample={i} real={t} BASIS native-player-camera-world-transform')
lines.append(f'SCRIPT : ERR LOOK OBSERVE: run={NONCE} sample={i} real={t} SAMPLE direction=<0,0,1> camera=<6088.58,213.019,7158.56> body=<6088.5,211.389,7158.5> bodyForward=<0,0,1> turn=<0,0,0>')
if i==1:
lines.append(f'SCRIPT : ERR GATE OBSERVE: run={NONCE} sample={i} real={t} BASIS registered-prison-lock-native-interaction')
lines.append(f'SCRIPT : ERR GATE OBSERVE: run={NONCE} sample={i} real={t} SAMPLE phase=1 selected=0 context=0 cachedPerformable=0 progressBound=0 performing=0 progress=0 duration=4 pressed=0')
lines.append(f'SCRIPT : ERR GATE OBSERVE: run={NONCE} sample={i} real={t} GEOMETRY body=<6088.5,211.389,7158.5> context=<6092.77,213.226,7154> radius=2 doorState=0 doorControl=0 prison=<6090,211.444,7160> gate=<6090,211.344,7154> gateForward=<0,0,1>')
if i==19:
lines.append(f'SCRIPT : ERR INPUT OBSERVE: run={NONCE} sample={i} real={t+1} world={w} READY')
lines.append(f'SCRIPT : ERR GATE OBSERVE: run={NONCE} sample=31 real=4410 CANCELLED native-player-or-prison-context-lost')
lines.append(f'SCRIPT : ERR LOOK OBSERVE: run={NONCE} sample=31 real=4410 CANCELLED menu-opened')
return '\n'.join(lines)+'\n'
def matching(raw,text):
return next(line for line in raw.splitlines() if text in line)
class GateEvidenceTests(unittest.TestCase):
def reject(self,raw,start=20,end=25):
result=validate_gate_geometry(raw,NONCE,start,end)
self.assertFalse(result['verified'],result);self.assertTrue(result['errors'])
def test_native_shape_parse_join_and_geometry_only(self):
raw=fixture();parsed=parse_gate_records(raw,NONCE);joined=join_gate_snapshots(raw,NONCE)
self.assertEqual(len(parsed['snapshots']),30)
self.assertEqual(len(parsed['records']),62)
self.assertEqual(joined['snapshots'][20]['input']['real_ms'],3200)
self.assertEqual(joined['snapshots'][20]['look']['body'],joined['snapshots'][20]['geometry']['body'])
result=validate_gate_geometry(raw,NONCE,20,25)
self.assertTrue(result['verified'],result)
self.assertEqual(result['snapshot_count'],6)
self.assertFalse(result['approach_verified']);self.assertFalse(result['held_action_verified'])
self.assertEqual(result['radius'],2)
self.assertEqual(result['prison'],[6090,211.444,7160])
self.assertTrue(validate_gate_geometry(raw,NONCE)['verified'])
self.assertIsNone(parse_gate_record('irrelevant native log line',NONCE))
def test_no_success_inferred_from_native_selected_or_full_progress(self):
raw=fixture().replace('selected=0 context=0 cachedPerformable=0 progressBound=0 performing=0 progress=0 duration=4 pressed=0',
'selected=1 context=1 cachedPerformable=1 progressBound=1 performing=1 progress=4 duration=4 pressed=1')
result=validate_gate_geometry(raw,NONCE,20,25)
self.assertTrue(result['verified'],result)
self.assertFalse(result['held_action_verified']);self.assertFalse(result['approach_verified'])
def test_malformed_foreign_unknown_and_numeric_records_rejected(self):
raw=fixture()
record=matching(raw,'ERR GATE OBSERVE: run='+NONCE+' sample=20 real=3200 SAMPLE')
for old,new in (('run='+NONCE,'run=foreign'),('phase=1','phase=3'),('selected=0','selected=2'),
('duration=4','duration=5'),('progress=0','progress=nan'),('progress=0','progress=1e999'),
('pressed=0','pressed=-1'),('progressBound=0','progressBound=1'),('performing=0','performing=1'),
('cachedPerformable=0','cachedPerformable=1'),('SAMPLE phase','UNKNOWN phase'),
('OBSERVE: ','OBSERVE:')):
with self.subTest(new=new):self.reject(raw.replace(record,record.replace(old,new)))
geometry=matching(raw,'sample=20 real=3200 GEOMETRY')
for old,new in (('radius=2','radius=0'),('radius=2','radius=11'),('doorState=0','doorState=2'),
('gateForward=<0,0,1>','gateForward=<0,0,0>'),('gateForward=<0,0,1>','gateForward=<0,0,2>'),
('gateForward=<0,0,1>','gateForward=<0,1,0>'),('body=<6088.5,211.389,7158.5>','body=<nan,0,1>')):
self.reject(raw.replace(geometry,geometry.replace(old,new)))
def test_pair_order_duplicates_gaps_and_missing_ack_refused(self):
raw=fixture();sample=matching(raw,'sample=20 real=3200 SAMPLE phase');geometry=matching(raw,'sample=20 real=3200 GEOMETRY')
for changed in (raw.replace(sample+'\n',''),raw.replace(geometry+'\n',''),raw.replace(sample,sample+'\n'+sample),
raw.replace(sample+'\n'+geometry,geometry+'\n'+sample),
raw.replace(geometry,geometry.replace('real=3200','real=3201')),
raw.replace(geometry,geometry.replace('sample=20','sample=19')),
'\n'.join(line for line in raw.splitlines() if 'BASIS registered-prison' not in line)):
self.reject(changed)
def test_native_three_centimetre_cross_api_difference_is_bounded(self):
raw=fixture();pose=matching(raw,'ERR LOOK OBSERVE: run='+NONCE+' sample=22 real=3420 SAMPLE')
accepted=raw.replace(pose,pose.replace('body=<6088.5,211.389,7158.5>','body=<6088.5,211.389,7158.47>'))
self.assertTrue(validate_gate_geometry(accepted,NONCE,20,25)['verified'])
self.reject(raw.replace(pose,pose.replace('body=<6088.5,211.389,7158.5>','body=<6088.5,211.389,7158.44>')))
geometry=matching(raw,'sample=22 real=3420 GEOMETRY')
self.reject(raw.replace(geometry,geometry.replace('body=<6088.5,211.389,7158.5>','body=<6088.5,211.389,7158.52>')))
def test_geometry_drift_and_clock_mismatch_refused(self):
raw=fixture();geometry=matching(raw,'sample=22 real=3420 GEOMETRY')
for old,new in (('context=<6092.77,213.226,7154>','context=<6092.80,213.226,7154>'),
('prison=<6090,211.444,7160>','prison=<6090.02,211.444,7160>'),
('gate=<6090,211.344,7154>','gate=<6090,211.344,7154.02>'),('radius=2','radius=2.01'),
('doorState=0','doorState=0.01'),('doorControl=0','doorControl=0.01'),
('gateForward=<0,0,1>','gateForward=<0.01,0,0.99995>')):
self.reject(raw.replace(geometry,geometry.replace(old,new)))
self.reject(raw.replace('sample=22 real=3420 SAMPLE phase','sample=22 real=3421 SAMPLE phase').replace('sample=22 real=3420 GEOMETRY','sample=22 real=3421 GEOMETRY'))
def test_phase_menu_and_cancellation_span(self):
raw=fixture();sample=matching(raw,'sample=22 real=3420 SAMPLE phase')
phase2=raw.replace(sample,sample.replace('phase=1','phase=2'))
self.reject(phase2)
self.assertTrue(validate_gate_geometry(phase2,NONCE,23,25)['verified'])
inp=matching(raw,'sample=22 real=3420 world=12420 SAMPLE origin')
self.reject(raw.replace(inp,inp.replace('inventory=0','inventory=1')))
self.reject(raw.replace('sample=31 real=4410 CANCELLED native-player-or-prison-context-lost','sample=24 real=3640 CANCELLED native-player-or-prison-context-lost'))
self.reject(raw+'SCRIPT : ERR GATE OBSERVE: run='+NONCE+' sample=31 real=4410 CANCELLED explicit-scope-lost\n')
def test_invalid_span_types_and_unknown_nonce(self):
raw=fixture()
for start,end in ((True,25),(20,False),(20,20),(25,20),(18,25),(20,451),(20,31),('20',25)):
result=validate_gate_geometry(raw,NONCE,start,end);self.assertFalse(result['verified'],result)
for nonce in (None,'','../unsafe','a'*33):
self.assertFalse(validate_gate_geometry(raw,nonce,20,25)['verified'])
def test_readonly_body_approach_not_credited_as_success(self):
raw=fixture()
for index in range(20,31):
real=1000+index*110;body=f'<6088.5,211.389,{7158.5-(index-19)*.1}>'
lines=[]
for line in raw.splitlines():
if f'sample={index} real={real} ' in line:
line=line.replace('<6088.5,211.389,7158.5>',body)
lines.append(line)
raw='\n'.join(lines)+'\n'
result=validate_gate_geometry(raw,NONCE,20,25)
self.assertTrue(result['verified'],result)
self.assertLess(result['final_context_distance_metres'],result['initial_context_distance_metres'])
self.assertFalse(result['approach_verified']);self.assertFalse(result['held_action_verified'])
if __name__=='__main__':unittest.main()