P08-03: 配置の通常操作受入
This commit is contained in:
@@ -316,6 +316,20 @@ def check(project_root, evidence_dir):
|
||||
process = document(directory+'/'+role+'-process.json')
|
||||
require(process['pid'] == pid and process['failures'] == 0 and process['checks'] > 0, 'process attribution')
|
||||
require(bool(process['engine']['hash']) and bool(process['engine']['string']), 'engine version')
|
||||
save_log = document(directory+'/'+role+'-save-results.json')
|
||||
require(save_log['pid'] == pid and save_log['records'], 'missing actual save results')
|
||||
operations = []
|
||||
for stem in save_log['records']:
|
||||
record = document(directory+'/'+stem+'.json')
|
||||
raw = artifact(directory+'/'+stem+'.var')
|
||||
require(record['pid'] == pid and record['raw_sha256'] == sha(raw), 'save result attribution/SHA')
|
||||
path = record['requested_path']
|
||||
require(path.startswith('user://') and record['absolute_path'] == str(Path(record['user_data_dir'])/path[7:]), 'save outside private user profile')
|
||||
result = decode(record['result'])
|
||||
require(isinstance(result, dict) and result.get('ok') is True, 'actual save/load failed')
|
||||
if record['operation'] == 'runtime_operation':
|
||||
operations.append(result.get('operation'))
|
||||
require(('save' in operations) if role == 'writer' else any(op in ('load','recovery','recovery_candidate') for op in operations), 'missing actual normal save/load result')
|
||||
doc = document(directory+'/'+role+'-actions.json')
|
||||
require(doc['setup'] == 'diagnostic', 'unlabelled diagnostic')
|
||||
expected = WRITER if role == 'writer' else ['resume_overlap']
|
||||
@@ -361,6 +375,30 @@ def check(project_root, evidence_dir):
|
||||
require(set(saved['members']) == set(MEMBERS) and saved['pid'] == expected_pids[0], 'missing formal members/writer')
|
||||
for member in MEMBERS:
|
||||
require(saved['members'][member] == sha(artifact(directory+'/formal/'+member)), 'formal member changed')
|
||||
exported = document(directory+'/formal-export.json')
|
||||
require(exported['pid'] == expected_pids[0] and exported['requested_path'] == 'user://saves/manual_ui', 'formal export attribution')
|
||||
absolute = str(Path(exported['user_data_dir'])/'saves/manual_ui')
|
||||
require(exported['absolute_path'] == absolute, 'save outside private user profile')
|
||||
for name in ('formal','formal.bak'):
|
||||
package = exported['packages'][name]
|
||||
require(package['present'] and package['source_path'] == absolute+('.bak' if name.endswith('.bak') else '') and set(package['members']) == set(MEMBERS), 'missing formal backup export')
|
||||
for member, pin in package['members'].items():
|
||||
file = artifact(directory+'/'+name+'/'+member)
|
||||
require(pin == {'sha256':sha(file),'bytes':file.stat().st_size}, 'formal export SHA')
|
||||
metadata = exported['slot_metadata']
|
||||
require(metadata['file'] == 'formal-slot-metadata.json' and metadata['sha256'] == sha(artifact(directory+'/'+metadata['file'])) == saved['members']['manifest.json'], 'slot metadata SHA')
|
||||
if not native_os:
|
||||
initial = document(directory+'/initial-formal-export.json')
|
||||
initial_absolute = str(Path(initial['user_data_dir'])/'saves/p08_initial')
|
||||
require(initial['pid'] == expected_pids[0] and initial['requested_path'] == 'user://saves/p08_initial' and initial['absolute_path'] == initial_absolute, 'initial formal private path')
|
||||
package = initial['packages']['initial-formal']
|
||||
require(package['present'] and package['source_path'] == initial_absolute and set(package['members']) == set(MEMBERS), 'initial formal members')
|
||||
for member, pin in package['members'].items():
|
||||
file = artifact(directory+'/initial-formal/'+member)
|
||||
require(pin == {'sha256':sha(file),'bytes':file.stat().st_size}, 'initial formal SHA')
|
||||
require(initial['packages']['initial-formal.bak'] == {'present':False,'source_path':initial_absolute+'.bak','members':{}}, 'unexpected initial backup')
|
||||
metadata = initial['slot_metadata']
|
||||
require(metadata['file'] == 'initial-formal-slot-metadata.json' and metadata['sha256'] == sha(artifact(directory+'/'+metadata['file'])) == package['members']['manifest.json']['sha256'], 'initial slot metadata SHA')
|
||||
facilities = keyed(decode(checkpoint)['systems']['runtime']['construction']['facilities'], 'instance_id')
|
||||
require(saved['instance_id'] in facilities and facilities[saved['instance_id']]['origin'] == saved['cell'], 'wrong resume instance')
|
||||
by_id = {r['id']: r for r in rows}
|
||||
|
||||
@@ -124,15 +124,27 @@ class EvidenceTests(unittest.TestCase):
|
||||
|
||||
def test_wrong_resume(self):
|
||||
path = 'pair/reader-checkpoint.json'
|
||||
original = (self.out/path).read_bytes()
|
||||
model = C.decode(json.loads((self.out/path).read_text()))
|
||||
model['clock']['absolute_minute'] += 1
|
||||
F.put(self.out/path, F.typed(model)); F.repin(self.out)
|
||||
self.reject('wrong resume model')
|
||||
(self.out/path).write_bytes(original); F.repin(self.out)
|
||||
self.edit('pair/reader-save-result-0001.json', lambda d: d.update(result=F.typed({'ok':False,'operation':'load','code':'UNSAFE_PATH'})))
|
||||
self.reject('actual save/load failed')
|
||||
self.edit('pair/reader-save-result-0001.json', lambda d: d.update(result=F.typed({'ok':True,'operation':'load'}), requested_path='/outside/formal'))
|
||||
self.reject('save outside private user profile')
|
||||
|
||||
def test_missing_formal_member(self):
|
||||
(self.out/'pair/formal/journal.log').unlink()
|
||||
F.repin(self.out)
|
||||
self.reject('journal.log')
|
||||
for name in ('formal','formal.bak'):
|
||||
with self.subTest(package=name):
|
||||
file = self.out/('pair/'+name+'/journal.log')
|
||||
original = file.read_bytes()
|
||||
file.unlink(); F.repin(self.out)
|
||||
self.reject('journal.log')
|
||||
file.write_bytes(original); F.repin(self.out)
|
||||
self.edit('pair/formal-export.json', lambda d: d['slot_metadata'].update(sha256='0'*64))
|
||||
self.reject('slot metadata SHA')
|
||||
|
||||
def test_missing_model_member(self):
|
||||
path = 'pair/writer-unsupported-before.json'
|
||||
@@ -238,7 +250,9 @@ class EvidenceTests(unittest.TestCase):
|
||||
private_project=C.runner.private_project, fresh_environment=C.runner.fresh_environment,
|
||||
SUPPORT=ROOT/'tools/regression', module=lambda *a:SimpleNamespace(ordinary_gate=lambda *a:{'mock':True}))
|
||||
outer = SimpleNamespace(native=SimpleNamespace(helper={'live_engines':lambda:[]}),finish_captured=cleanup)
|
||||
with patch.object(D.subprocess,'Popen',side_effect=spawn), contextlib.redirect_stdout(io.StringIO()):
|
||||
# Disk admission is an environmental input to this fully mocked collector.
|
||||
# Preserve the real collector's gate; make this fixture independent of host free space.
|
||||
with patch.object(D.shutil,'disk_usage',return_value=SimpleNamespace(free=1024**3)), patch.object(D.subprocess,'Popen',side_effect=spawn), contextlib.redirect_stdout(io.StringIO()):
|
||||
if fail_wait:
|
||||
with self.assertRaisesRegex(AssertionError,'native OS collection failed'):
|
||||
D.collect_os(r,self.root,output,stage,str(Path(self.temp.name)/'synthetic-engine-not-executable'),'1'*40,refs,protected,outer)
|
||||
|
||||
Reference in New Issue
Block a user