136 lines
5.9 KiB
Python
136 lines
5.9 KiB
Python
"""Small authority/selection tests; never access or run the production brain."""
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
PATH = Path(__file__).with_name('export_fixtures.py')
|
|
SPEC = importlib.util.spec_from_file_location('acceleration_fixture_export_tests', PATH)
|
|
E = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(E)
|
|
|
|
|
|
def task(arm, number, kind='train'):
|
|
return dict(task_id=f'block/normal/{arm}/{number:03d}', arm=arm, kind=kind)
|
|
|
|
|
|
def committed(tasks):
|
|
return {E.task_key(t) + '--' + stage for t in tasks for stage in ('brain', 'update', 'verify')}
|
|
|
|
|
|
class SelectionTests(unittest.TestCase):
|
|
def test_fixed_first_last_all_seven_arms_before_metrics(self):
|
|
tasks = [task(arm, n) for arm in E.ARMS for n in range(5)]
|
|
selected, counts = E.select_tasks(list(reversed(tasks)), committed(tasks))
|
|
self.assertEqual(len(selected), 14)
|
|
self.assertEqual(counts, {arm: 5 for arm in E.ARMS})
|
|
self.assertEqual([(t['arm'], t['task_id'].split('/')[-1]) for t in selected],
|
|
[(arm, n) for arm in E.ARMS for n in ('000', '004')])
|
|
|
|
def test_uncommitted_last_is_not_selected(self):
|
|
tasks = [task('paired', n) for n in range(4)]
|
|
ids = committed(tasks)
|
|
ids.remove(E.task_key(tasks[-1]) + '--verify')
|
|
selected, counts = E.select_tasks(tasks, ids)
|
|
self.assertEqual(selected, [tasks[0], tasks[2]])
|
|
self.assertEqual(counts['paired'], 3)
|
|
|
|
def test_probe_and_duplicate_selection(self):
|
|
train, probe = task('paired', 0), task('paired', 1, 'probe')
|
|
selected, _ = E.select_tasks([train, probe], committed([train, probe]))
|
|
self.assertEqual(selected, [train])
|
|
with self.assertRaisesRegex(ValueError, 'Duplicate'):
|
|
E.select_tasks([train, train], committed([train]))
|
|
|
|
def test_no_complete_triple_fails(self):
|
|
train = task('paired', 0)
|
|
with self.assertRaisesRegex(ValueError, 'No committed'):
|
|
E.select_tasks([train], {E.task_key(train) + '--verify'})
|
|
|
|
|
|
class FileSafetyTests(unittest.TestCase):
|
|
def test_output_must_be_new_and_outside_protected(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary).resolve()
|
|
frozen = root / 'frozen'
|
|
frozen.mkdir()
|
|
with self.assertRaisesRegex(ValueError, 'fresh'):
|
|
E.validate_destination(frozen, [frozen])
|
|
with self.assertRaisesRegex(ValueError, 'overlaps'):
|
|
E.validate_destination(frozen / 'new', [frozen])
|
|
self.assertEqual(E.validate_destination(root / 'allowed', [frozen]), root / 'allowed')
|
|
self.assertFalse((root / 'allowed').exists())
|
|
|
|
def test_exclusive_save_and_mismatch_rejection(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
path = Path(temporary).resolve() / 'new.json'
|
|
E.save(path, {'a': 1})
|
|
original = path.read_bytes()
|
|
with self.assertRaises(FileExistsError):
|
|
E.save(path, {'a': 2})
|
|
self.assertEqual(path.read_bytes(), original)
|
|
with self.assertRaisesRegex(ValueError, 'Pinned bytes'):
|
|
E.check(path, '0' * 64)
|
|
|
|
def test_duplicate_json_rejected(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
path = Path(temporary).resolve() / 'bad.json'
|
|
path.write_text('{"a":1,"a":2}', encoding='utf-8')
|
|
with self.assertRaisesRegex(ValueError, 'Duplicate'):
|
|
E.read(path)
|
|
|
|
|
|
class ProcessAuthorityTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
self.root = Path(self.temp.name).resolve()
|
|
self.name = 'task-synthetic--verify'
|
|
self.job_path = self.root / 'jobs' / (self.name + '.json')
|
|
self.process_path = self.root / 'receipts' / self.name / 'process.json'
|
|
self.job_path.parent.mkdir()
|
|
self.process_path.parent.mkdir(parents=True)
|
|
E.save(self.job_path, dict(registration_sha256=E.REG_SHA, input_sha256={}))
|
|
self.process = dict(entry_id=self.name, registration_sha256=E.REG_SHA,
|
|
job_sha256=E.digest(self.job_path), complete=True, exit_code=0, timed_out=False,
|
|
exit_observed_by_parent=True, launch_error=None, argv=[str(E.ORIGINAL_ENV / 'bin/python'), '-B', 'validator.py'])
|
|
|
|
def tearDown(self):
|
|
self.temp.cleanup()
|
|
|
|
def verify(self, process):
|
|
E.save(self.process_path, process)
|
|
tracked = {str(p): E.identity(p) for p in (self.job_path, self.process_path)}
|
|
row = dict(entry_id=self.name, metadata=dict(job_file=str(self.job_path),
|
|
process_receipt_file=str(self.process_path), observed_returncode=0), consumed_inputs=[],
|
|
new_outputs=[dict(path=p, **info) for p, info in tracked.items()])
|
|
start = dict(job=dict(path=str(self.job_path), sha256=E.digest(self.job_path)))
|
|
return E.validate_process(dict(row=row, start=start), tracked, self.root)
|
|
|
|
def test_observed_complete_zero_is_required(self):
|
|
self.verify(self.process)
|
|
|
|
def test_failed_or_unobserved_process_rejected(self):
|
|
self.process['exit_code'] = 1
|
|
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
|
self.verify(self.process)
|
|
|
|
def test_boolean_zero_is_not_os_exit(self):
|
|
self.process['exit_code'] = False
|
|
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
|
self.verify(self.process)
|
|
|
|
def test_different_registration_rejected(self):
|
|
self.process['registration_sha256'] = '0' * 64
|
|
with self.assertRaisesRegex(ValueError, 'observed exit zero'):
|
|
self.verify(self.process)
|
|
|
|
def test_different_interpreter_rejected(self):
|
|
self.process['argv'][0] = '/different/venv/bin/python'
|
|
with self.assertRaisesRegex(ValueError, 'original -B'):
|
|
self.verify(self.process)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|