"""Offline source, persistent budget and actual D2/F evidence negatives.""" import argparse,copy,json,re,sys,tempfile,time,unittest from pathlib import Path from types import SimpleNamespace from unittest.mock import Mock,patch import gate from plans import RUNS,HIST from geometry import * from validators import held_configure,native_pairs from cases import marker_host_baseline,root_state,associated_root from transition import observed_epochs DATA=HIST class PureTests(unittest.TestCase): def test_compile_sources(self): for p in gate.HERE.glob('*.py'):compile(p.read_text(),str(p),'exec') def test_fixed_allocation(self): self.assertEqual(len(RUNS),13);self.assertLessEqual(sum(s['limits']['capture'] for s in RUNS.values()),174) for campaign,cap in gate.CAPS.items():self.assertLessEqual(sum(s['limits']['capture'] for s in RUNS.values() if s['campaign']==campaign),cap) self.assertTrue(all(s['limits']['capture']<=16 for s in RUNS.values())) def test_halfopen_and_scale(self): o=RUNS['scale-A']['outputs'][0] for p in ([-700,100],[-500,300],[-200,400]):self.assertEqual(png_global(global_png(p,o,'logical'),o,'logical'),p) self.assertFalse(contains([-800,0,800,600],[0,300])) def test_stale_invalidation(self): from engine import Session s=Session.__new__(Session);s.coordinate_epoch=4;s.proofs={(1,2):dict(epoch=4)};s.record=Mock();s.invalidate('focus') self.assertEqual(s.coordinate_epoch,5);self.assertEqual(s.proofs,{}) def test_held_serial(self): before='ACK ns=1 serial=30 size=420x320\nxdg_surface#5.ack_configure(30)\nwl_shm_pool#6.create_buffer(8)\nCOMMIT ns=2' after='xdg_surface#5.configure(44)\nXDG_CONFIGURE ns=4 serial=44 size=300x200 hold=1 previous=0\nHELD ns=5 serial=44' self.assertEqual(held_configure(before,after,30)['serial'],44) for b,a,p in [(before,after+'\nxdg_surface#5.ack_configure(44)',30),(before,after.replace('.configure(44)','.configure(999)'),30),(before,after.replace('serial=44','serial=30').replace('configure(44)','configure(30)'),30),(before,after.replace('HELD','ABSENT'),30),(before.replace('ACK ns=1 serial=30','ABSENT'),after,30)]: with self.assertRaises(ValueError):held_configure(b,a,p) def test_pair_all_not12(self): text='\n'.join(f'PI_OUTPUT_COMMIT output=H1 commit_seq={i} ns={i*10}\nPI_OUTPUT_PRESENT output=H1 commit_seq={i} ns={i*10+1} presented=1' for i in range(1,20)) r=native_pairs(text);self.assertEqual(r['paired'],19);self.assertEqual(r['missing'],0) r=native_pairs(text.replace('PI_OUTPUT_PRESENT output=H1 commit_seq=19','OMITTED output=H1 commit_seq=19'));self.assertEqual(r['missing'],1) with self.assertRaises(ValueError):native_pairs(text+'\nPI_OUTPUT_COMMIT output=H1 commit_seq=1 ns=500') def test_review_refusal_no_token(self): with patch.object(gate,'owned',return_value=Path('/missing')),patch.object(gate,'verify',side_effect=ValueError('review absent')),patch.object(gate,'locked') as locked: with self.assertRaises(ValueError):gate.begin('/missing','scale-A') locked.assert_not_called() def test_ledger_atomic_no_retry_and_reconciliation(self): with tempfile.TemporaryDirectory() as d: lab=Path(d);state=dict(scope=gate.SCOPE,runs={},events=[],used=dict(run=0,capture=0),campaign_used=dict.fromkeys(gate.CAPS,0),campaign_runs=dict.fromkeys(gate.CAPS,0));gate.durable(lab/'budget.json',state,True) with patch.object(gate,'owned',return_value=lab): def consume(s): p=RUNS['scale-A']['limits'];s['runs']['scale-A']=dict(campaign='scale',planned=p,reserved=dict.fromkeys(p,0));s['used']['run']=1;s['campaign_runs']['scale']=1 gate.locked(lab,consume);gate.action_debit(lab,'scale-A','capture','configuration','click') s=gate.read(lab/'budget.json');self.assertEqual(s['used']['capture'],1);self.assertEqual(s['runs']['scale-A']['reserved']['click'],1) bad=copy.deepcopy(s);bad['events'].pop() with self.assertRaises(ValueError):gate.validate(bad) gate.action_debit(lab,'scale-A',*(['capture']*11));before=(lab/'budget.json').read_bytes() with self.assertRaises(ValueError):gate.action_debit(lab,'scale-A','capture') self.assertEqual(before,(lab/'budget.json').read_bytes()) def test_incomplete_receipt_rejected(self): with tempfile.TemporaryDirectory() as d: lab=Path(d);gate.durable(lab/'offline.json',{'status':'PASS'},True) with self.assertRaises(ValueError):gate.test_receipt(lab,'offline.json',14) gate.durable(lab/'replay.json',{'status':'PASS'},True) with self.assertRaises(ValueError):gate.replay_receipt(lab) def test_geometry_held_unchanged_rejected(self): before='ACK ns=1 serial=30 size=420x320\nxdg_surface#5.ack_configure(30)\nwl_shm_pool#6.create_buffer(8)\nCOMMIT ns=2' after='xdg_surface#5.configure(44)\nXDG_CONFIGURE ns=4 serial=44 size=420x320 hold=1 previous=0\nHELD ns=5 serial=44' with self.assertRaises(ValueError):held_configure(before,after,30) class HistoricalTests(unittest.TestCase): def fixture(self): run=DATA/'matrix/D2-mosaic/run';events=[json.loads(l) for l in (run/'events.jsonl').read_text().splitlines()];owner_start=next(e['ns'] for e in events if e['kind']=='spawn' and e['name']=='owner');trace=(run/'compositor.log').read_text() before=[] for l in trace.splitlines(): m=re.search(r'\bns=(\d+)',l) if m and int(m[1])>=owner_start:break before.append(l) session=SimpleNamespace(spec={'marker':True,'mode':'mosaic'},proc={'marker-background':Mock(pid=77)},events=[e for e in events if e['ns']