import copy from pathlib import Path import sys import unittest sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools')) from ordinary_gate_choices import parse_choice_record,parse_choice_records,join_choice_snapshots,exact_prison_choices from test_ordinary_gate_evidence import fixture,NONCE def line(index=1,real=2100,selected='ERR_PrisonDoorAction:7',context=1,ordered='0=ERR_PrisonDoorAction:7:0,1=ERR_UnlockPrisonAction:8:1'): return f'ERR GATE CHOICE: run={NONCE} sample={index} real={real} selected={selected} context={context} actions=2 permissions=2 shown=2 truncated=0 ordered=[{ordered}]' class Choices(unittest.TestCase): def test_exact_pair_and_selected_identity(self): c=parse_choice_record(line(),NONCE);self.assertEqual(c['selected_id'],7) self.assertEqual(exact_prison_choices({'choices':c}),c) c['selected_class']='ERR_UnlockPrisonAction';c['selected_id']=8 self.assertEqual(exact_prison_choices({'choices':c})['selected_id'],8) def test_empty_and_truncated_are_diagnostic_only(self): empty=line(selected='none:-1',context=0,ordered='').replace('actions=2 permissions=2 shown=2','actions=0 permissions=0 shown=0') self.assertEqual(parse_choice_record(empty,NONCE)['actions'],[]) with self.assertRaises(ValueError):exact_prison_choices({'choices':parse_choice_record(empty,NONCE)}) entries=','.join(f'{i}=Action:{i}:1' for i in range(8)) truncated=line(ordered=entries).replace('actions=2 permissions=2 shown=2 truncated=0','actions=9 permissions=9 shown=8 truncated=1') self.assertTrue(parse_choice_record(truncated,NONCE)['truncated']) def test_missing_permissions_do_not_become_false_permission(self): text=line(ordered='0=ERR_PrisonDoorAction:7:0,1=ERR_UnlockPrisonAction:8:-1').replace('permissions=2','permissions=1') c=parse_choice_record(text,NONCE);self.assertIsNone(c['actions'][1]['permitted']) with self.assertRaises(ValueError):exact_prison_choices({'choices':c}) def test_malformed_ids_counts_nonce_and_sequence_refuse(self): for text in [line().replace(NONCE,'foreign'),line().replace('shown=2','shown=1'),line().replace('truncated=0','truncated=1'),line().replace('Action:7','Action:-1'),line().replace('0=ERR','1=ERR'),line().replace(':8:1',':8:-1'),line().replace('context=1','context=3')]: with self.subTest(text=text),self.assertRaises(ValueError):parse_choice_record(text,NONCE) for text in [line()+'\n'+line(),line(2),line()+'\n'+line(2,2000)]: with self.assertRaises(ValueError):parse_choice_records(text,NONCE) def test_exact_pair_refuses_other_order_identity_or_permission(self): c=parse_choice_record(line(),NONCE) for fault in ('order','duplicate','permission','selected','class'): d=copy.deepcopy(c) if fault=='order':d['actions'].reverse() elif fault=='duplicate':d['actions'][1]['id']=7 elif fault=='permission':d['actions'][0]['permitted']=True elif fault=='selected':d['selected_id']=9 else:d['actions'][1]['class']='ForeignAction' with self.subTest(fault=fault),self.assertRaises(ValueError):exact_prison_choices({'choices':d}) def test_real_native_schema_join_requires_exact_clock_and_selection(self): from ordinary_gate_evidence import join_gate_snapshots content=fixture();snapshots=join_gate_snapshots(content,NONCE)['snapshots'] choices=[] for i,s in snapshots.items(): choices.append(line(i,s['real_ms'],selected='none:-1',context=0,ordered='').replace('actions=2 permissions=2 shown=2','actions=0 permissions=0 shown=0')) raw=content+'\n'+'\n'.join(choices) self.assertEqual(len(join_choice_snapshots(raw,NONCE)['snapshots']),len(snapshots)) for bad in [raw.replace('selected=none:-1','selected=ERR_UnlockPrisonAction:8',1),raw.replace('context=0 actions=0','context=1 actions=0',1),raw.replace(f'sample=1 real={snapshots[1]["real_ms"]} selected',f'sample=1 real={snapshots[1]["real_ms"]+1} selected',1)]: with self.assertRaises(ValueError):join_choice_snapshots(bad,NONCE) if __name__=='__main__':unittest.main()