203 lines
12 KiB
Python
203 lines
12 KiB
Python
"""Synthetic CPU contract tests, not a neural/scientific PASS claim."""
|
|
import ast
|
|
import copy
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
import coordinator as M
|
|
|
|
|
|
class CoordinatorTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.tmp.cleanup)
|
|
self.exp = Path(self.tmp.name)
|
|
self.patch = patch.object(M, 'EXP', self.exp)
|
|
self.patch.start(); self.addCleanup(self.patch.stop)
|
|
for name in ('jobs','receipts','logs','audit','updates','runs','cases'):
|
|
(self.exp/name).mkdir()
|
|
self.row = dict(row_id='D1--reference--epoch-001', arm='D1', diagnostic_mode='reference',
|
|
input_epoch_index=1, previous_delta_row_id='D1--reference--epoch-000',
|
|
origin='new_AP_neural_execution', case_dir=str(self.exp/'cases/one'),
|
|
neural_dir=str(self.exp/'runs/one'), steps=1200)
|
|
|
|
def write(self, path, value):
|
|
path.write_text(__import__('json').dumps(value), encoding='utf8')
|
|
|
|
def fixture(self):
|
|
"""Explicit synthetic files only; no old paths or runtime payload."""
|
|
regsha='1'*64; loc=M.process_locations(self.row,'update')
|
|
output=M.paths(self.row)['update'];output.mkdir()
|
|
worker_source=M.MODEL/'isolated_workers.py'
|
|
authority=loc['job'].parent/'one.authority.json';M.save(authority,{'fixture':True})
|
|
job=dict(job_id=self.row['row_id']+'.update', kind='update',registration_sha256=regsha,
|
|
worker_sha256=M.digest(worker_source),output_dir=str(output),receipt_file=str(loc['worker']),
|
|
sources={},input_sha256={str(authority):M.digest(authority)},authority_sha256=M.digest(authority))
|
|
M.save(loc['job'],job)
|
|
(output/'delta-after.npz').write_bytes(b'SYNTHETIC-NOT-NPZ')
|
|
M.save(output/'overlay-manifest.json',{'fixture':True})
|
|
chain=dict(authority_sha256=M.digest(authority),source_neural_checkpoint_manifest_sha256='2'*64,
|
|
before_overlay_file_sha256='3'*64,before_overlay_manifest_sha256='4'*64,
|
|
after_overlay_file_sha256=M.digest(output/'delta-after.npz'),
|
|
after_overlay_manifest_sha256=M.digest(output/'overlay-manifest.json'))
|
|
M.save(output/'chain-receipt.json',chain)
|
|
attempt=Path(str(loc['worker'])+'.attempt.json');M.save(attempt,{'fixture':True})
|
|
result={**chain,'chain_receipt_sha256':M.digest(output/'chain-receipt.json'),
|
|
'brain_executed':False,'weights_installed':False}
|
|
result.pop('authority_sha256')
|
|
worker=dict(schema='phase4ap-isolated-worker-receipt-v1',complete=True,
|
|
job_sha256=M.digest(loc['job']),registration_sha256=regsha,job_id=job['job_id'],kind='update',
|
|
worker_sha256=job['worker_sha256'],output_dir=str(output),receipt_file=str(loc['worker']),
|
|
source_files={},attempt_sha256=M.digest(attempt),
|
|
verified_input_sha256={**job['input_sha256'],str(loc['job']):M.digest(loc['job']),str(worker_source):M.digest(worker_source)},
|
|
output_files_sha256={p.name:M.digest(p) for p in output.iterdir()},result=result,
|
|
environment={'CUDA_hidden':True,'CUDA_initialized':False})
|
|
M.save(loc['worker'],worker)
|
|
loc['stdout'].write_bytes(b'');loc['stderr'].write_bytes(b'')
|
|
process=dict(complete=True,exit_code=0,registration_sha256=regsha,row_id=self.row['row_id'],kind='update',
|
|
job_sha256=M.digest(loc['job']),worker_receipt_sha256=M.digest(loc['worker']),
|
|
stdout_sha256=M.digest(loc['stdout']),stderr_sha256=M.digest(loc['stderr']))
|
|
M.save(loc['process'],process)
|
|
return regsha,loc,job,worker,process
|
|
|
|
def test_exact_process_fixture(self):
|
|
sha,loc,job,worker,process=self.fixture()
|
|
self.assertEqual(M.verify_process({},sha,self.row,'update',job),worker)
|
|
|
|
def test_mutated_receipt_fields_rejected_even_if_process_rehashed(self):
|
|
sha,loc,job,worker,process=self.fixture()
|
|
mutations=[('output_files_sha256',{}),('verified_input_sha256',{}),('kind','brain'),
|
|
('output_dir',str(self.exp/'wrong')),('source_files',{'wrong':1}),('attempt_sha256','0'*64),
|
|
('worker_sha256','0'*64),('receipt_file',str(self.exp/'fake'))]
|
|
for field,value in mutations:
|
|
with self.subTest(field=field):
|
|
changed={**worker,field:value};self.write(loc['worker'],changed)
|
|
self.write(loc['process'],{**process,'worker_receipt_sha256':M.digest(loc['worker'])})
|
|
with self.assertRaises(ValueError):M.verify_process({},sha,self.row,'update',job)
|
|
|
|
def test_result_chain_mutation_rejected(self):
|
|
sha,loc,job,worker,process=self.fixture()
|
|
for field in ('chain_receipt_sha256','before_overlay_file_sha256','after_overlay_file_sha256',
|
|
'source_neural_checkpoint_manifest_sha256'):
|
|
changed=copy.deepcopy(worker);changed['result'][field]='0'*64
|
|
self.write(loc['worker'],changed)
|
|
self.write(loc['process'],{**process,'worker_receipt_sha256':M.digest(loc['worker'])})
|
|
with self.assertRaises(ValueError):M.verify_process({},sha,self.row,'update',job)
|
|
|
|
def test_output_bytes_and_extra_files_rejected(self):
|
|
sha,loc,job,worker,process=self.fixture()
|
|
(Path(job['output_dir'])/'unregistered').write_bytes(b'new')
|
|
with self.assertRaisesRegex(ValueError,'inventory'):M.verify_process({},sha,self.row,'update',job)
|
|
|
|
def test_job_changes_rejected(self):
|
|
sha,loc,job,worker,process=self.fixture()
|
|
with self.assertRaisesRegex(ValueError,'Job differs'):
|
|
M.verify_process({},sha,self.row,'update',{**job,'job_id':'another'})
|
|
|
|
def test_spec_only_budget_changes(self):
|
|
original={'budget_root':str(self.exp/'old'),'output_budget_bytes':50,'steps':1200,'seed':5717173809506784725,
|
|
'lif':{'dt':.1,'delay':18},'other':[1,2]}
|
|
result,report=M.derive_spec(original,str(self.exp/'new'),100)
|
|
self.assertEqual(result['seed'],5717173809506784725)
|
|
self.assertEqual(set(report['changes']),{'budget_root','output_budget_bytes'})
|
|
result['lif']['dt']=10
|
|
self.assertEqual(original['lif']['dt'],.1)
|
|
with self.assertRaises(ValueError):M.derive_spec(original,original['budget_root'],100)
|
|
|
|
def test_rows_exact_unique_and_safe_paths(self):
|
|
self.assertEqual(M.slot({'slots':[self.row]},self.row['row_id']),self.row)
|
|
for rows in ([],[self.row,self.row]):
|
|
with self.assertRaises(ValueError):M.slot({'slots':rows},self.row['row_id'])
|
|
for value in ('../x','a/b','a\\b','',None):
|
|
with self.assertRaises(ValueError):M.paths({**self.row,'row_id':value})
|
|
|
|
def test_parent_arm_mode_epoch_cannot_cross(self):
|
|
parent={**self.row,'row_id':self.row['previous_delta_row_id'],'input_epoch_index':0}
|
|
for change in ({'arm':'D0'},{'diagnostic_mode':'light'},{'input_epoch_index':2}):
|
|
with self.assertRaisesRegex(ValueError,'ancestry'):
|
|
M.before_overlay({'slots':[{**parent,**change}]},'unused',self.row)
|
|
|
|
def test_parent_verified_before_delta_is_selected(self):
|
|
parent={**self.row,'row_id':self.row['previous_delta_row_id'],'input_epoch_index':0}
|
|
with patch.object(M,'verify_slot',side_effect=ValueError('parent invalid')) as verify:
|
|
with self.assertRaisesRegex(ValueError,'parent invalid'):
|
|
M.before_overlay({'slots':[parent]},'unused',self.row)
|
|
verify.assert_called_once()
|
|
|
|
def test_initial_overlay_has_no_previous_read(self):
|
|
initial={'overlay_file':'immutable'}
|
|
with patch.object(M,'verify_slot') as verify:
|
|
self.assertIs(M.before_overlay({'initial_overlay':initial},'unused',{'previous_delta_row_id':None}),initial)
|
|
verify.assert_not_called()
|
|
|
|
def test_imported_neural_cannot_execute(self):
|
|
worker=str(M.MODEL/'isolated_workers.py')
|
|
reg={'input_sha256':{},'source_sha256':{worker:'1'*64},'prepared_file_sha256':{}}
|
|
with self.assertRaisesRegex(ValueError,'Imported neural'):
|
|
M.job_for(reg,'sha',{**self.row,'origin':'imported_sealed_AO_neural_trajectory'},'brain',{})
|
|
with self.assertRaisesRegex(ValueError,'Unknown child'):
|
|
M.job_for({},'sha',self.row,'other')
|
|
|
|
def test_stopped_run_and_budget_refuse_without_delete(self):
|
|
reg={'budget':{'output_budget_bytes':10,'minimum_free_reserve_bytes':1}}
|
|
marker=self.exp/'audit/stopped.json';marker.write_bytes(b'{}')
|
|
with self.assertRaisesRegex(ValueError,'Stopped/completed'):M.admission(reg)
|
|
self.assertTrue(marker.exists())
|
|
|
|
def test_partial_child_not_retried(self):
|
|
loc=M.process_locations(self.row,'update');loc['stdout'].write_bytes(b'partial')
|
|
with patch.object(M.subprocess,'run') as run:
|
|
with self.assertRaisesRegex(ValueError,'cannot be retried'):M.launch({},'sha',self.row,'update',{})
|
|
run.assert_not_called()
|
|
|
|
def test_failed_child_records_actual_failure(self):
|
|
with patch.object(M,'admission'),patch.object(M.subprocess,'run',return_value=subprocess.CompletedProcess([],7)):
|
|
with self.assertRaisesRegex(ValueError,'failed or timed out'):
|
|
M.launch({'budget':{'child_timeout_seconds':1}},'sha',self.row,'update',{'fixture':True})
|
|
record=M.read(M.process_locations(self.row,'update')['process'])
|
|
self.assertFalse(record['complete']);self.assertEqual(record['exit_code'],7)
|
|
|
|
def test_timedout_child_never_claims_exit_zero(self):
|
|
with patch.object(M,'admission'),patch.object(M.subprocess,'run',side_effect=subprocess.TimeoutExpired([],1)):
|
|
with self.assertRaises(ValueError):
|
|
M.launch({'budget':{'child_timeout_seconds':1}},'sha',self.row,'update',{'fixture':True})
|
|
record=M.read(M.process_locations(self.row,'update')['process'])
|
|
self.assertTrue(record['timed_out']);self.assertIsNone(record['exit_code'])
|
|
|
|
def test_wrong_registration_sha_stops_before_parse(self):
|
|
(self.exp/'protocol').mkdir();M.save(self.exp/'protocol/preregistered.json',{'fake':True})
|
|
with self.assertRaisesRegex(ValueError,'external SHA'):M.registration('0'*64)
|
|
|
|
def test_no_postprocess_or_sampler_call_in_coordinator(self):
|
|
tree=ast.parse(Path(M.__file__).read_text(encoding='utf8'))
|
|
calls=[ast.unparse(n.func) for n in ast.walk(tree) if isinstance(n,ast.Call)]
|
|
self.assertFalse(any('postprocess_epoch' in n or 'generate_epoch_inputs' in n for n in calls))
|
|
self.assertNotIn('os.fork',calls)
|
|
|
|
def test_actual_delta_must_match_correct_receipt(self):
|
|
from test_conditioning_preflight_compare import delta_fixture
|
|
before,after,installed,receipt,manifest=delta_fixture()
|
|
overlay={'overlay_file':'synthetic'}
|
|
with patch.object(M.R,'load_overlay',return_value=(None,{'plastic_delta_mv':after},None,None)), \
|
|
patch.object(M,'npz',return_value={'plastic_delta_mv':before}), \
|
|
patch.object(M,'digest',return_value='3'*64),patch.object(M,'read',return_value=manifest):
|
|
self.assertTrue(M.verify_delta_payload(overlay,self.exp,receipt)[0]['pass_all'])
|
|
after[1]=0
|
|
with self.assertRaisesRegex(ValueError,'Actual delta binding'):
|
|
M.verify_delta_payload(overlay,self.exp,receipt)
|
|
|
|
def test_imported_comparison_uses_bits_and_original_receipt(self):
|
|
import numpy as np
|
|
value=np.zeros(3,np.float32);receipt={'real':'fixture'}
|
|
with patch.object(M,'npz',return_value={'plastic_delta_mv':value}),patch.object(M,'read',return_value=receipt):
|
|
M.verify_imported_delta(value.copy(),copy.deepcopy(receipt))
|
|
changed=value.copy();changed[0]=np.float32(-0.)
|
|
with self.assertRaisesRegex(ValueError,'Imported trajectory'):M.verify_imported_delta(changed,receipt)
|
|
with self.assertRaises(ValueError):M.verify_imported_delta(value,{'different':True})
|
|
|
|
|
|
if __name__=='__main__':unittest.main()
|