Files
TheTree_mock/tools/test_p23_life_observation_evidence.py
T

762 lines
44 KiB
Python

#!/usr/bin/env python3
"""Local semantic-checker tests; synthetic examples are never game evidence."""
import copy
import ast
import unittest
import sys
import contextlib
import io
import json
import hashlib
import struct
import zlib
import tempfile
from pathlib import Path
from unittest import mock
sys.dont_write_bytecode = True
import check_p23_life_observation_evidence as check
class QueuedElevatorTests(unittest.TestCase):
def setUp(self):
fixture = json.loads((check.ROOT / 'tests/fixtures/p23-03/queued_elevator.json').read_text())
self.state = {'systems': {'runtime': {'elevators': fixture['saved']}}}
def test_queued_trip_without_cabin_seat_uses_config_shaft(self):
saved = self.state['systems']['runtime']['elevators']
self.assertNotIn('shaft_id', saved['shafts'][0])
self.assertEqual(saved['shafts'][0]['boarded'], [])
report = check.elevator_report(self.state)
self.assertEqual(report['shafts'][0]['waiting_count'], 1)
self.assertEqual(report['shafts'][0]['passenger_count'], 0)
self.assertAlmostEqual(report['shafts'][0]['visual_floor'], .9)
self.assertEqual(report['trips'], saved['trips'])
def test_tampered_shaft_attribution_fails(self):
self.state['systems']['runtime']['elevators']['trips'][0]['shaft_id'] = 'wrong.shaft'
with self.assertRaisesRegex(ValueError, 'shaft attribution'):
check.elevator_report(self.state)
def test_wrong_waiting_count_fails_whole_report_comparison(self):
expected = check.elevator_report(self.state)
tampered = copy.deepcopy(expected)
tampered['shafts'][0]['waiting_count'] = 0
directory = mock.MagicMock()
manifest = dict(label='queued-fixture', pid=123, state='state',
state_after='state', report='report')
directory.__truediv__.return_value.open.return_value = io.StringIO(json.dumps(manifest)+'\n')
# Exercise the actual stream comparison; isolate unrelated actor fields.
with mock.patch.object(check, 'read_object', side_effect=[self.state, self.state,
{'elevators': tampered}]), \
mock.patch.object(check, 'compare_actor_rows', return_value=[]):
with self.assertRaisesRegex(ValueError, 'typed elevator report mismatch'):
check.inspect_stream(directory)
def test_extra_and_missing_trip_keys_fail(self):
for mutation in ('extra', 'missing'):
with self.subTest(mutation=mutation):
state = copy.deepcopy(self.state)
trip = state['systems']['runtime']['elevators']['trips'][0]
if mutation == 'extra':
trip['unexpected'] = True
else:
del trip['shaft_id']
with self.assertRaisesRegex(ValueError, 'exact elevator trip keys'):
check.elevator_report(state)
class SnapshotCellTests(unittest.TestCase):
def test_layout_arrival_compares_serialized_cell_arrays(self):
source = (check.ROOT / 'tests/fixtures/p23-03/layout_comparison.gd').read_text()
serializer = (check.ROOT / 'scripts/guest/guest_runtime.gd').read_text()
self.assertIn('&"current_cell": _cell_to_array(current_cell)', serializer)
goal = check.re.search(r'const GOAL := Vector3i\(([^)]+)\)', source)
self.assertIsNotNone(goal)
coordinates = ast.literal_eval('[' + goal.group(1) + ']')
comparison = check.re.search(r'if guest\[&"current_cell"\] != (.+?) or finished\.has', source)
self.assertIsNotNone(comparison)
expression = comparison.group(1)
self.assertEqual(expression, '[GOAL.x, GOAL.y, GOAL.z]')
for axis, value in zip('xyz', coordinates):
expression = expression.replace('GOAL.' + axis, str(value))
target = ast.literal_eval(expression)
self.assertEqual(json.loads('[2, 1, 0]'), target)
for cell in ([2, 0, 0], [3, 1, 0], [2, 1, 1]):
self.assertNotEqual(cell, target)
class ImageTests(unittest.TestCase):
def test_collector_conversion_is_bound_to_each_cua_screenshot(self):
runner = check.module('p23_unit_collector', check.ROOT/'tools/run_p23_life_observation.py')
with tempfile.TemporaryDirectory(dir=check.ROOT/'tests/fixtures/p23-03') as temporary:
root = Path(temporary)
pair = root/'os-pair/A'
request_dir = pair/'writer-request-0001'
request_dir.mkdir(parents=True)
request = request_dir/'request.json'
request.write_text(json.dumps(dict(sequence=1, target_pid=123)))
raw = request_dir/'raw.jpg'
raw.write_bytes(b'\xff\xd8unit-only\xff\xd9')
shot = dict(path=str(raw.relative_to(root)), raw_sha256=check.sha(raw), tool_call_id='unit-shot-call')
receipt = request_dir/'cua.json'
receipt.write_text(json.dumps(dict(screenshots=[shot])))
ack = request_dir/'ack.json'
ack.write_text(json.dumps(dict(request_sha256=check.sha(request), input_receipt=str(receipt.relative_to(root)))))
(pair/'writer-requests.json').write_text(json.dumps(dict(requests=[str(ack.relative_to(root))])))
def convert(raw_path, png_path, cua, receipt_path):
self.assertEqual(cua, shot)
self.assertEqual(Path(raw_path).read_bytes(), b'\xff\xd8unit-only\xff\xd9')
Path(png_path).write_bytes(self.png())
Path(receipt_path).write_text('{}')
with mock.patch.object(runner, 'module', return_value=check), \
mock.patch.object(check, 'image_kind', return_value=('jpeg', 2, 2)), \
mock.patch.object(runner, 'convert_screenshot', side_effect=convert) as converter:
output = runner.collect_screenshots(root, pair, 'writer')
converter.assert_called_once()
rows = json.loads((root/output).read_text())
self.assertEqual(rows[0]['tool_call_id'], shot['tool_call_id'])
self.assertEqual(rows[0]['raw_sha256'], check.sha(raw))
self.assertEqual(rows[0]['png_sha256'], check.sha(root/rows[0]['png_path']))
self.assertTrue(rows[0]['conversion'])
@staticmethod
def png(mode=0, channels=3):
def chunk(kind, body):
return struct.pack('>I', len(body)) + kind + body + struct.pack('>I', zlib.crc32(kind + body))
rows = [bytes([10, 20, 30, 40][:channels] * 2),
bytes([50, 60, 70, 80][:channels] * 2)]
filtered = bytearray()
prior = bytes(2 * channels)
for row in rows:
filtered.append(mode)
for x, value in enumerate(row):
left, up, corner = (row[x-channels] if x >= channels else 0,
prior[x], prior[x-channels] if x >= channels else 0)
p = left + up - corner
distances = [abs(p-left), abs(p-up), abs(p-corner)]
predictors = [0, left, up, (left+up)//2,
[left, up, corner][distances.index(min(distances))]]
filtered.append((value-predictors[mode]) % 256)
prior = row
header = struct.pack('>IIBBBBB', 2, 2, 8, 2 if channels == 3 else 6, 0, 0, 0)
return (b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', header)
+ chunk(b'IDAT', zlib.compress(filtered)) + chunk(b'IEND', b''))
def test_all_png_filters_rgb_and_rgba(self):
for mode in range(5):
for channels in (3, 4):
with self.subTest(mode=mode, channels=channels):
w, h, rows = check.png_pixels(self.png(mode, channels))
self.assertEqual((w, h), (2, 2))
self.assertEqual(rows[0][0], tuple([10, 20, 30, 40][:channels]))
self.assertEqual(rows[1][1], tuple([50, 60, 70, 80][:channels]))
def test_crc_and_trailing_bytes_rejected(self):
data = bytearray(self.png())
data[29] ^= 1
with self.assertRaisesRegex(ValueError, 'CRC mismatch'):
check.png_pixels(bytes(data))
with self.assertRaisesRegex(ValueError, 'invalid IEND'):
check.png_pixels(self.png() + b'extra')
def conversion(self):
raw, png = b'\xff\xd8synthetic-unit-test\xff\xd9', self.png()
digest = lambda b: hashlib.sha256(b).hexdigest()
rec = dict(raw_path='/raw.png', raw_sha256=digest(raw), raw_kind='jpeg',
tool_call_id='unit-test-call', converter='/usr/bin/sips', converter_sha256='a'*64,
argv=['/usr/bin/sips', '-s', 'format', 'png', '/raw.png', '--out', '/decoded.png'],
exit_code=0, stdout_sha256=digest(b''), stderr_sha256=digest(b''),
png_path='/decoded.png', png_sha256=digest(png), width=2, height=2)
cua = dict(raw_sha256=digest(raw), tool_call_id='unit-test-call')
return rec, cua, {'/raw.png': raw, '/decoded.png': png}
def test_conversion_chain_and_specific_forgery_deficits(self):
rec, cua, files = self.conversion()
helper = mock.Mock()
helper.jpeg_dimensions.return_value = (2, 2)
with mock.patch.object(Path, 'read_bytes', lambda p: files[str(p)]), \
mock.patch.object(check, 'module', return_value=helper):
self.assertEqual(check.inspect_conversion(rec, cua, 'a'*64)[:2], (2, 2))
for key, value, deficit in [('converter_sha256', 'b'*64, 'converter SHA mismatch'),
('argv', [], 'converter argv mismatch'),
('raw_sha256', 'b'*64, 'CUA raw hash/call mismatch'),
('width', 3, 'conversion dimensions mismatch')]:
with self.subTest(key=key):
bad = dict(rec, **{key: value})
with self.assertRaisesRegex(ValueError, deficit):
check.inspect_conversion(bad, cua, 'a'*64)
with self.assertRaisesRegex(ValueError, 'JPEG screenshot requires conversion record'):
check.screenshot_pixels('/raw.png')
class RestAuditTests(unittest.TestCase):
def fixture(self):
member = dict(staff_id='s', state='OFF_DUTY', health=100, current_task_id='', current_cell=[0, 0, 0])
facilities = [dict(instance_id=fid, definition_id='staff_waiting_room', origin=[0, 0, 0],
occupied_cells=[], state='OPEN', suspension_reason='') for fid in ('a', 'b')]
runtime = dict(staff=dict(staff=[member]), facilities=dict(instances=facilities),
defense=dict(raids=[]), events=dict(actor_locks={}), elevators=dict(trips=[]),
path=dict(cell_traffic=[dict(cell=[x, 0, 0]) for x in (-1, 0, 1)]),
world=dict(bounds=dict(min_x=-1, max_x=1, min_y=0, max_y=0), occupancies=[]))
routes = [dict(cell=[x, 0, 0], path=[[0, 0, 0], [x, 0, 0]] if x else [[0, 0, 0]],
edges=[dict(**{'from': [0, 0, 0], 'to': [x, 0, 0]}, total_cost=0)] if x else [],
calculate_path_cost=0) for x in (-1, 0, 1)]
observed = []
for f in facilities:
observed.append({k: f[k] for k in ('instance_id', 'definition_id', 'origin', 'occupied_cells')})
observed[-1].update(operation_state='OPERATING', probes=[dict(cell=[x, 0, 0], has_cell=True) for x in (0, -1, 1)],
ordered=[[x, 0, 0] for x in (-1, 0, 1)], routes=copy.deepcopy(routes))
selected = dict(reachable=True, resting=True, cell=[-1, 0, 0], facility_id='a', label='待機室で休憩中')
audit = dict(path_service_sha256=check.sha(check.ROOT/'scripts/world/path_service.gd'),
staff=[dict(member, defense_memberships=[], actor_lock=False, in_transit=False,
facilities=observed, comparison_only=selected)])
report = dict(resting_staff={'s': 'a'}, actor_drawings=[], layer=0, carried_patients={}, rooms={},
viewport=[1440, 810], zoom=1, pan=[0, 0])
return dict(systems=dict(runtime=runtime)), report, audit
def test_selection_ties_and_nonmutation(self):
state, report, audit = self.fixture()
before = copy.deepcopy((state, report, audit))
self.assertEqual(check.compare_rest(state, report, audit)['s']['cell'], [-1, 0, 0])
self.assertEqual((state, report, audit), before)
def test_rest_forgeries(self):
mutations = {
'selection': lambda a: a['staff'][0]['comparison_only'].update(facility_id='b'),
'tie': lambda a: a['staff'][0]['comparison_only'].update(cell=[0, 0, 0]),
'lock': lambda a: a['staff'][0].update(actor_lock=True),
'transit': lambda a: a['staff'][0].update(in_transit=True),
'label': lambda a: a['staff'][0]['comparison_only'].update(label='宿舎で休憩中'),
'cost': lambda a: a['staff'][0]['facilities'][0]['routes'][0]['edges'][0].update(total_cost=9),
'facility_order': lambda a: a['staff'][0]['facilities'].reverse(),
'candidate_order': lambda a: a['staff'][0]['facilities'][0]['ordered'].reverse(),
'empty_edge': lambda a: a['staff'][0]['facilities'][0]['routes'][0]['edges'][0].clear(),
}
for name, mutate in mutations.items():
with self.subTest(name=name):
state, report, audit = self.fixture()
mutate(audit)
with self.assertRaises(ValueError):
check.compare_rest(state, report, audit)
def test_ineligible_and_transit_recomputed(self):
state, report, audit = self.fixture()
state['systems']['runtime']['events']['actor_locks']['s'] = 'event'
audit['staff'][0].update(actor_lock=True, comparison_only={})
report['resting_staff'] = {}
self.assertEqual(check.compare_rest(state, report, audit), {'s': {}})
state, report, audit = self.fixture()
state['systems']['runtime']['elevators']['trips'] = [dict(actor_id='staff:s')]
audit['staff'][0]['in_transit'] = True
audit['staff'][0]['comparison_only'].update(resting=False, label='休憩先へ移動中')
report['resting_staff'] = {}
self.assertFalse(check.compare_rest(state, report, audit)['s']['resting'])
class InfrastructureTests(unittest.TestCase):
def test_matrix_requires_each_condition_and_each_category(self):
executed = {c: {k: set(v) for k, v in categories.items()} for c, categories in check.REQUIRED_CHECKS.items()}
self.assertTrue(all(r['status'] == 'passed' for r in check.condition_matrix(executed)))
for condition in check.CONDITIONS:
for category in check.CATEGORIES:
with self.subTest(condition=condition, category=category):
broken = copy.deepcopy(executed)
broken[condition][category].clear()
matrix = check.condition_matrix(broken)
self.assertEqual(next(r for r in matrix if r['condition'] == condition)['status'], 'pending')
self.assertIn(category, check.BLOCKERS(broken)[condition])
def test_distinct_pid_ack_and_formal_hash_negatives(self):
members = {name: 'a'*64 for name in ('world.bin', 'manifest.json', 'thumbnail.png', 'journal.log')}
writer = dict(actual_pid=1)
reader = dict(actual_pid=2, formal_input={k: dict(sha256=v) for k, v in members.items()})
saved = dict(pid=1, members=members)
records = [dict(request=dict(action='load_menu', target_pid=2, sequence=1, requested_ticks_usec=10, requested_unix_ns=90),
ack=dict(target_pid=2, sequence=1, request_sha256='b'*64, timestamp_ns=110),
observed=dict(pid=2, sequence=1, request_sha256='b'*64, ack_observed_ticks_usec=20, ack_observed_unix_ns=120, status='手動セーブを読み込みました。'),
cua=dict(target_pid=2, method='native_os', tool_call_id='actual-call', timestamp_ns=100),
request_sha256='b'*64)]
check.inspect_resume(writer, reader, saved, records, members)
for change in ('pid', 'ack', 'time', 'hash', 'id'):
with self.subTest(change=change):
r, q = copy.deepcopy(reader), copy.deepcopy(records)
if change == 'pid': r['actual_pid'] = 1
if change == 'ack': q.clear()
if change == 'time': q[0]['observed']['ack_observed_ticks_usec'] = 9
if change == 'hash': r['formal_input']['world.bin']['sha256'] = 'c'*64
if change == 'id': q[0]['ack']['sequence'] = 2
with self.assertRaises(ValueError): check.inspect_resume(writer, r, saved, q, members)
def test_interpolation_history_tampering(self):
state = dict(systems=dict(runtime=dict(guests=dict(guests=[]), staff=dict(staff=[]),
elevators=dict(shafts=[], trips=[], current_minute=0))))
report = dict(animation_time=0.0, paused=True, layer=0, zoom=1, pan=[0,0], viewport=[100,100],
actor_tracks={}, elevator_tracks={}, actor_drawings=[], cabins=[])
audit = dict(frames=[dict(frame=1, delta=.01, scaled_delta=0, display=copy.deepcopy(report)),
dict(frame=2, delta=.01, scaled_delta=0, display=copy.deepcopy(report))])
check.compare_motion(state, report, audit)
for change in ('delta', 'frame', 'decreasing_frame', 'no_frames', 'one_frame', 'display', 'report_binding'):
with self.subTest(change=change):
bad = copy.deepcopy(audit)
if change == 'delta': bad['frames'][1]['scaled_delta'] = 1
if change == 'frame': bad['frames'][1]['frame'] = 1
if change == 'decreasing_frame': bad['frames'][1]['frame'] = 0
if change == 'no_frames': bad['frames'].clear()
if change == 'one_frame': bad['frames'].pop()
if change == 'report_binding': bad['frames'][1]['display']['zoom'] = 2
if change == 'display': bad['frames'][1]['display']['animation_time'] = 1
with self.assertRaises(ValueError): check.compare_motion(state, report, bad)
def test_verify_only_missing_index_is_a_concrete_deficit(self):
with mock.patch.dict(check.os.environ, {'BUILD_OUTPUT_DIR': '/missing-p23-proof'}, clear=True):
with contextlib.redirect_stdout(io.StringIO()) as output:
self.assertEqual(check.main(['--verify-only']), 1)
result = json.loads(output.getvalue())
self.assertEqual(result['integrity'], 'fail')
self.assertEqual(result['acceptance'], 'pending')
self.assertIn('index.json', result['deficits'][0])
self.assertNotIn('blocked', result['deficits'][0])
def test_verify_only_requires_build_output(self):
with mock.patch.dict(check.os.environ, {}, clear=True):
with contextlib.redirect_stderr(io.StringIO()) as output:
self.assertEqual(check.main(['--verify-only']), 2)
self.assertIn('BUILD_OUTPUT_DIR is required', output.getvalue())
def test_normative_plan_change_invalidates_but_progress_does_not(self):
root = check.ROOT
text = (root / check.PLAN).read_text()
original = check.input_map(root)
progress = text.splitlines(keepends=True)
progress[2] = 'Progress-only test mutation\n'
with mock.patch.object(Path, 'read_text', return_value=''.join(progress)):
self.assertEqual(check.input_map(root), original)
changed = text.replace('同需要の動線改善を観察できる。', 'altered normative acceptance')
self.assertNotEqual(changed, text)
with mock.patch.object(Path, 'read_text', return_value=changed):
self.assertNotEqual(check.input_map(root), original)
self.assertNotIn(check.PLAN, original)
self.assertIn('full_plan_sha256', check.input_provenance(root))
for path in (root / 'tests/fixtures/p23-03').rglob('*'):
if path.is_file():
self.assertIn(path.relative_to(root).as_posix(), original)
def test_os_process_guards_reject_engine_profile_and_source_drift(self):
source = {'source.gd': 'a' * 64}
receipt = dict(engine_ended=True, passed=True, exit_code=0, error=None,
guard_errors=[], cleanup_errors=[], default_before={}, default_after={},
stage_before={}, stage_after={}, source_map=source,
source_after={'source.gd': {'sha256': 'a' * 64}},
owned_cleanup=[{'engine_ended': True}], ordinary_owner_proof={'present': True})
receipt.update(spec_sha256=check.SPEC_SHA, inputs={'spec': 'a'*64}, inputs_after={'spec': 'a'*64},
environment={'P23_LAYOUT': 'A'}, environment_after={'P23_LAYOUT': 'A'}, actual_pid=123,
profile='/private/test', profile_name='test', profile_before={'existed': False, 'files': {}}, profile_after={})
for field in ('engine_sha256', 'settings_sha256', 'environment_sha256'):
receipt[field] = receipt[field+'_after'] = 'a'*64
check.inspect_os_receipt(receipt, source)
for field, value in [('engine_ended', False), ('default_after', {'changed': True}),
('source_after', {'source.gd': {'sha256': 'b' * 64}}),
('stage_after', {'changed': True}), ('owned_cleanup', []),
('environment_after', {}), ('profile_before', {}),
('engine_sha256_after', 'b'*64), ('spec_sha256', 'b'*64)]:
with self.subTest(field=field):
altered = copy.deepcopy(receipt)
altered[field] = value
with self.assertRaises(ValueError):
check.inspect_os_receipt(altered, source)
class SemanticTests(unittest.TestCase):
def setUp(self):
self.guest = dict(guest_id='g', state='QUEUING', current_cell=[1, 0, 0],
target_facility_id='f', current_service_id='', queue_request_id='q')
self.staff = dict(staff_id='s', state='WORKING', current_cell=[2, 0, 1],
current_task_id='t', assigned_facility_id='f', role_id='porter',
carried_inventory_id='cargo')
self.task = dict(task_id='t', state='WORKING', task_type='delivery',
assigned_staff_id='s', target_entity_id='request', rescue_facility_id='')
self.snapshot = {'systems': {'runtime': {'guests': {'guests': [self.guest]},
'staff': {'staff': [self.staff], 'tasks': [self.task]}}}}
self.report = dict(guests=[dict(id='g', state='QUEUING', cell=[1, 0, 0], target='f', service='', queue='q')],
staff=[dict(id='s', state='WORKING', cell=[2, 0, 1], task='t', facility='f',
role='porter', carried_inventory_id='cargo')],
tasks=[dict(id='t', state='WORKING', type='delivery', staff='s',
target='request', rescue_facility='')])
def test_real_schema_projection(self):
self.assertEqual(check.compare_actor_rows(self.snapshot, self.report), ['guests', 'staff', 'tasks'])
def test_changed_state_position_target_task_and_goods_are_rejected(self):
for category, field, replacement in [('guests', 'cell', [8, 0, 0]), ('guests', 'target', 'other'),
('guests', 'state', 'MOVING'), ('staff', 'task', ''),
('staff', 'carried_inventory_id', ''), ('tasks', 'staff', 'other')]:
with self.subTest(category=category, field=field):
report = copy.deepcopy(self.report)
report[category][0][field] = replacement
with self.assertRaises(ValueError):
check.compare_actor_rows(self.snapshot, report)
def test_missing_extra_and_boolean_only_rows_are_rejected(self):
for bad in [[], self.report['guests'] * 2, [True]]:
report = copy.deepcopy(self.report)
report['guests'] = bad
with self.assertRaises(ValueError):
check.compare_actor_rows(self.snapshot, report)
def test_unknown_enum_and_duplicate_id_are_rejected(self):
self.guest['state'] = 'FICTIONAL'
with self.assertRaises(ValueError):
check.compare_actor_rows(self.snapshot, self.report)
self.guest['state'] = 'QUEUING'
self.snapshot['systems']['runtime']['guests']['guests'].append(copy.deepcopy(self.guest))
with self.assertRaises(ValueError):
check.compare_actor_rows(self.snapshot, self.report)
def test_typed_rectangle_and_duplicate_vector_key(self):
self.assertEqual(check.decode(dict(type='Rect2', text='Rect2(1, 2, 16, 24)')), [1, 2, 16, 24])
with self.assertRaises(ValueError):
check.decode(dict(type='Rect2', text='Rect2(1, nan, 16, 24)'))
key = dict(type='Vector3i', text='Vector3i(1, 2, 0)')
value = dict(type='int', text='1')
with self.assertRaises(ValueError):
check.decode(dict(type='Dictionary', entries=[[key, value], [key, value]]))
def test_immutable_typed_input_is_not_modified(self):
before = copy.deepcopy(self.snapshot)
check.compare_actor_rows(self.snapshot, self.report)
self.assertEqual(before, self.snapshot)
class SpatialTests(unittest.TestCase):
def setUp(self):
self.runtime = dict(world=dict(bounds=dict(min_x=0, max_x=1, min_y=0, max_y=0),
walkable_cells=[[0, 0, 0], [1, 0, 0]], occupancies=[]),
path=dict(cell_traffic=[dict(cell=[0, 0, 0], base_capacity=2,
current_density=3, dynamic_cost=0, temporary_block=False)]),
facilities=dict(instances=[], requests=[]), guests=dict(guests=[]),
staff=dict(staff=[], tasks=[]), logistics_requests=[],
elevators=dict(current_minute=0, shafts=[], trips=[]))
self.snapshot = dict(systems=dict(runtime=self.runtime))
self.report = dict(viewport=[184, 164], zoom=1, pan=[0, 0], layer=0,
traffic=[dict(cell=[0, 0, 0], rect=[78, 72, 12, 20],
traffic=dict(base_capacity=2, current_density=3,
dynamic_cost=0, temporary_block=False))],
queue_positions={}, queue_hidden={}, landing_badges=[], rooms={},
treated_patients={}, carried_patients={}, resting_staff={},
goods=dict(requests=[], deliveries=[]))
def test_density_and_pan_are_independently_recomputed(self):
check.compare_traffic(self.snapshot, self.report)
for key, value in [('current_density', 0), ('base_capacity', 9)]:
changed = copy.deepcopy(self.report)
changed['traffic'][0]['traffic'][key] = value
with self.assertRaises(ValueError):
check.compare_traffic(self.snapshot, changed)
self.report['pan'][0] = 20
with self.assertRaises(ValueError):
check.compare_traffic(self.snapshot, self.report)
def test_missing_queue_overflow_rejected(self):
saved = json.loads((check.ROOT / 'tests/fixtures/p23-03/queued_elevator.json').read_text())['saved']
self.runtime['elevators'] = saved
saved['trips'] = [dict(copy.deepcopy(saved['trips'][0]), actor_id='guest:g'+str(i),
request_id='trip'+str(i), enqueued_at=i) for i in range(3)]
self.report.update(queue_positions={'guest/g0': [100, 82]},
queue_hidden={'guest/g1': True, 'guest/g2': True}, landing_badges=[dict(at=[-4, 54],
text='待ち3人(他2人)', cell=[0, 0, 0],
members=['guest/g0', 'guest/g1', 'guest/g2'], visible_count=1, overflow=2)])
check.compare_queues(self.snapshot, self.report)
self.report['landing_badges'][0]['overflow'] = 0
with self.assertRaises(ValueError):
check.compare_queues(self.snapshot, self.report)
def test_fictional_goods_and_rooms_rejected(self):
check.compare_goods(self.snapshot, self.report)
check.compare_room_services(self.snapshot, self.report)
self.report['goods']['requests'].append(dict(stock=100))
with self.assertRaises(ValueError):
check.compare_goods(self.snapshot, self.report)
self.report['rooms']['invented'] = dict(count=0)
with self.assertRaises(ValueError):
check.compare_room_services(self.snapshot, self.report)
def test_room_reason_and_rescue_occupancy(self):
room = dict(instance_id='clinic', origin=[0, 0, 0], definition_id='infirmary',
state='NO_POWER', state_reasons=['NO_POWER'], suspension_reason='',
customer_capacity=2, active_staff_ids=[], active_services=[], occupied_cells=[])
self.runtime['facilities']['instances'] = [room]
self.runtime['staff']['tasks'] = [dict(task_id='rescue', task_type='rescue_transport',
state='WORKING', assigned_staff_id='carrier', target_entity_id='patient', rescue_facility_id='clinic')]
self.report['treated_patients'] = {'patient': 'clinic'}
self.report['rooms'] = {'clinic': dict(state=2, state_name='NO_POWER', reasons=['NO_POWER'],
operation=0, people=['patient'], count=1, limit=2, staff=[], suspension='')}
check.compare_room_services(self.snapshot, self.report)
for field, wrong in [('state', 6), ('operation', 1), ('people', []), ('count', 0)]:
changed = copy.deepcopy(self.report)
changed['rooms']['clinic'][field] = wrong
with self.assertRaises(ValueError):
check.compare_room_services(self.snapshot, changed)
def test_cabin_geometry_and_phase(self):
shaft = dict(config=dict(shaft_id='lift', stops=[[0, 0, 0]], width=2, capacity=4),
current_floor=0, phase='IDLE', operational=True, boarded=[])
self.runtime['elevators']['shafts'] = [shaft]
self.report.update(paused=True, animation_time=0, elevator_tracks={'lift': dict(floor=0, at=0)},
cabins=[dict(shaft_id='lift', rect=[80, 72, 24, 19], pixel=1, operational=True,
doors_open=True, badge_at=[80, 58], badge='0/4人', passengers=[])])
check.compare_cabin_geometry(self.snapshot, self.report)
for field, value in [('rect', [80, 70, 24, 19]), ('doors_open', False), ('badge', '4/4人')]:
changed = copy.deepcopy(self.report)
changed['cabins'][0][field] = value
with self.assertRaises(ValueError):
check.compare_cabin_geometry(self.snapshot, changed)
class ComparisonTests(unittest.TestCase):
def pair(self):
declaration = dict(metric='sum_destination_arrival_minutes_entire_cohort',
arrivals=[dict(id='g', offset=0)], window=2, to=[2, 1, 0],
improvement=dict(definition_id='guest_elevator', origin=[4, 0, 0]))
a = dict(declaration=declaration, initial=dict(seed=1))
a['arrival-g'] = dict(offset=0, payload=dict(guest_id='g'), result=dict(code='OK'))
for minute in range(3):
a['tick-%03d' % minute] = dict(minute=minute, guests=dict(guests=[dict(guest_id='g',
current_cell=[2, 1, 0] if minute == 2 else [2, 0, 0])]))
b = copy.deepcopy(a)
b['build-0'] = dict(payload=declaration['improvement'], result=dict(code='OK'))
b['tick-001']['guests']['guests'][0]['current_cell'] = [2, 1, 0]
return a, b
def test_strict_metric_from_typed_cells(self):
a, b = self.pair()
self.assertEqual(check.compare_layouts(a, b)['B'], 1)
for mutation in ('demand', 'incomplete', 'no_improvement', 'extra_build'):
with self.subTest(mutation=mutation):
a, b = self.pair()
if mutation == 'demand':
b['arrival-g']['payload']['guest_id'] = 'other'
elif mutation == 'incomplete':
for minute in (1, 2):
b['tick-%03d' % minute]['guests']['guests'][0]['current_cell'] = [2, 0, 0]
elif mutation == 'no_improvement':
b['tick-001'] = copy.deepcopy(a['tick-001'])
else:
b['build-1'] = copy.deepcopy(b['build-0'])
with self.assertRaises(ValueError):
check.compare_layouts(a, b)
class OfflineGeometryTests(unittest.TestCase):
"""Synthetic calibration examples; no OS or acceptance credit."""
def setUp(self):
self.calibration = dict(window_size=[100, 80], window_position=[240, 150],
screenshot_pixels=[200, 190], backing_scale=2,
canvas_stretch=1, titlebar_pixels=30)
self.request = dict(window_size=[100, 80], window_position=[240, 150],
screen_scale=2, content_scale_factor=1, target_pid=123)
self.clicks = [dict(target_pid=123, events=[dict(action='click',
coordinates=[20, 70], calibration=copy.deepcopy(self.calibration),
point=dict(screen=[10, 20], viewport=[10, 20],
viewport_to_screen=[1, 0, 0, 1, 0, 0]))])]
def transform(self):
return check.screenshot_transform(self.calibration, self.request, [200, 190], self.clicks)
def test_uses_measured_scale_origin_not_desktop_position(self):
self.assertEqual(check.affine_rect(self.transform(), [10, 20, 5, 7]), [20, 70, 10, 14])
def test_shifted_titlebar_fails_independent_click(self):
self.calibration['titlebar_pixels'] += 1
self.calibration['screenshot_pixels'][1] += 1
self.clicks[0]['events'][0]['calibration'] = copy.deepcopy(self.calibration)
with self.assertRaises(ValueError):
check.screenshot_transform(self.calibration, self.request, [200, 191], self.clicks)
def test_wrong_click_offset_fails(self):
self.clicks[0]['events'][0]['coordinates'][1] -= 30
with self.assertRaisesRegex(ValueError, 'click screenshot offset'):
self.transform()
def test_wrong_pid_cannot_calibrate(self):
self.clicks[0]['target_pid'] += 1
with self.assertRaisesRegex(ValueError, 'missing independent click'):
self.transform()
def test_nonfinite_and_false_scale_rejected(self):
for scale in (False, float('nan'), 0, -1):
self.calibration['backing_scale'] = scale
with self.assertRaisesRegex(ValueError, 'invalid screenshot calibration'):
self.transform()
def test_all_visibility_cases_are_accounted_for(self):
self.assertEqual(check.rectangle_eligibility([2, 3, 4, 5], [10, 10]),
('visible', [2, 3, 4, 5]))
self.assertEqual(check.rectangle_eligibility([-2, 3, 4, 5], [10, 10]),
('clipped', [0, 3, 2, 5]))
self.assertEqual(check.rectangle_eligibility([10, 3, 4, 5], [10, 10])[0], 'outside')
self.assertEqual(check.rectangle_eligibility([2, 3, 0, 5], [10, 10])[0], 'outside')
def test_invalid_rectangles_rejected(self):
for rect in ([0, 0, -1, 4], [float('nan'), 0, 1, 4]):
with self.assertRaisesRegex(ValueError, 'invalid clipping rectangle'):
check.rectangle_eligibility(rect, [10, 10])
def test_noise_is_measured_and_does_not_assert_class(self):
before = (2, 2, [[(10, 20, 30)]*2 for _ in range(2)])
after = copy.deepcopy(before)
after[2][1][1] = (10, 27, 30)
noise = check.paired_crop_noise(before, after, [0, 0, 2, 2])
self.assertEqual(noise, dict(samples=4, max_channel_delta=7,
mean_channel_delta=1.75, unchanged=3))
self.assertNotIn('pass', noise)
self.assertNotIn('state', noise)
def test_wrong_dimensions_and_empty_crop_rejected(self):
image = (1, 1, [[(0, 0, 0)]])
with self.assertRaisesRegex(ValueError, 'paired image dimensions'):
check.paired_crop_noise(image, (2, 1, []), [0, 0, 1, 1])
with self.assertRaisesRegex(ValueError, 'empty noise crop'):
check.paired_crop_noise(image, image, [1, 0, 1, 1])
def test_report_positions_and_source_provenance_are_recomputed(self):
source = 'scripts/ui/pixel_people.gd'
report = dict(rooms={}, landing_badges=[], cabins=[], resting_staff={}, badges=[],
actor_drawings=[dict(key='staff/s', staff=True, at=[1, 1], scale=1)])
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
audit = dict(rows=[dict(category='staff', id='staff/s', rect=[1, 1, 16, 18],
style_source=source, style_colors=colors)])
check.validate_drawing_rows(report, audit)
for change in ('shift', 'identity', 'missing', 'palette'):
tampered = copy.deepcopy(audit)
if change == 'shift': tampered['rows'][0]['rect'][0] += 1
if change == 'identity': tampered['rows'][0]['category'] = 'guest'
if change == 'missing': tampered['rows'] = []
if change == 'palette': tampered['rows'][0]['style_colors'] = ['000000']
with self.subTest(change=change), self.assertRaises(ValueError):
check.validate_drawing_rows(report, tampered)
class FrameReviewTests(unittest.TestCase):
def setUp(self):
OfflineGeometryTests.setUp(self)
self.request.update(local_to_viewport=[1, 0, 0, 1, 0, 0],
viewport_to_screen=[1, 0, 0, 1, 0, 0],
local_to_screen=[1, 0, 0, 1, 0, 0])
self.report = dict(layer=0, viewport=[100, 80], rooms={}, cabins=[],
landing_badges=[], badges=[], resting_staff={}, traffic=[],
actor_drawings=[dict(key='staff/s', staff=True, at=[1, 1], scale=1, state=0)])
source = 'scripts/ui/pixel_people.gd'
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
self.audit = dict(rows=[dict(category='staff', id='staff/s', rect=[1, 1, 16, 18],
viewport_rect=[1, 1, 16, 18], screen_rect=[1, 1, 16, 18],
style_source=source, style_colors=colors)])
self.image = (200, 190, [[(x % 256, y % 256, 0) for x in range(200)] for y in range(190)])
def frame(self):
return check.frame_rows(self.report, self.audit, self.request,
dict(calibration=self.calibration), [self.image], self.clicks)
def test_blank_crop_fails_without_threshold(self):
self.image = (200, 190, [[(0, 0, 0)] * 200 for _ in range(190)])
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertIn('blank crop', result['rows'][0]['failures'])
def test_missing_extra_and_unaudited_traffic_fail(self):
for change in ('missing', 'extra', 'traffic'):
with self.subTest(change=change):
original = copy.deepcopy(self.audit)
if change == 'missing': self.audit['rows'].clear()
if change == 'extra': self.audit['rows'] *= 2
if change == 'traffic':
self.report['traffic'] = [dict(cell=[-6, 2, 0], rect=[1, 1, 5, 5],
traffic=dict(current_density=1, temporary_block=False))]
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertEqual(len(result['rows']), len(self.audit['rows']))
self.assertIn('offline rectangle coverage', result['errors'])
self.audit = original
def test_dense_or_blocked_traffic_row_closes_audit_gap(self):
source = 'scenes/main/world_preview.gd'
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
for density, blocked in ((1, False), (0, True), (0, False)):
with self.subTest(density=density, blocked=blocked):
self.report['traffic'] = [dict(cell=[-6, 2, 0], rect=[1, 1, 5, 5],
traffic=dict(current_density=density, temporary_block=blocked))]
active = density > 0 or blocked
missing = self.frame()
self.assertEqual(missing['mechanical_pass'], not active)
if active:
self.assertIn('offline rectangle coverage', missing['errors'])
self.audit['rows'].append(dict(category='traffic', id='-6,2,0',
rect=[1, 1, 5, 5], viewport_rect=[1, 1, 5, 5],
screen_rect=[1, 1, 5, 5], style_source=source, style_colors=colors))
complete = self.frame()
self.assertTrue(complete['mechanical_pass'], complete['errors'])
self.audit['rows'].pop()
def test_wrong_state_enum_and_name_fail(self):
source = 'scripts/ui/pixel_tower_art.gd'
self.report['actor_drawings'] = []
room = dict(rect=[1, 1, 16, 18], state=3, state_name='NO_STAFF', operation=0)
self.report['rooms'] = {'r': room}
self.audit['rows'][0].update(category='room', id='r', style_source=source,
style_colors=list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text()))))
self.assertEqual(self.frame()['rows'][0]['operation'], 'INACTIVE')
for state, name in ((99, 'NO_STAFF'), (3, 'OPEN'), (True, 'NO_ACCESS')):
room.update(state=state, state_name=name)
with self.assertRaises(ValueError): self.frame()
def test_frame_rejects_affine_and_calibration_shift(self):
self.request['local_to_screen'][4] += 1
with self.assertRaisesRegex(ValueError, 'affine composition'): self.frame()
self.request['local_to_screen'][4] -= 1
self.clicks[0]['events'][0]['coordinates'][1] += 1
with self.assertRaisesRegex(ValueError, 'click screenshot offset'): self.frame()
def test_eligible_crop_fully_outside_image_fails(self):
for key in ('viewport_to_screen', 'local_to_screen'):
self.request[key][4] = 300
self.audit['rows'][0]['screen_rect'][0] += 300
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertIn('eligible crop outside image', result['rows'][0]['failures'])
def test_manifest_crop_and_independent_review_binding(self):
with tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
manifest, digest = check.write_frame_review(directory, self.frame(),
[dict(whole_image_sha256='a'*64, raw_sha256='b'*64, conversion_sha256='c'*64)])
self.assertEqual(check.sha(directory/'manifest.json'), digest)
crop = manifest['rows'][0]['crops'][0]
self.assertEqual(check.sha(directory/crop['path']), crop['sha256'])
self.assertEqual(check.png_pixels((directory/crop['path']).read_bytes())[:2], (32, 36))
verdict_path = directory/'independent-verdict.json'
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), set())
verdict = dict(manifest_sha256=digest, reviewer='independent-opus-direct-image',
rows=[dict(row_index=0, category=True, state=True, position=True)])
for change in ('wrong_sha', 'missing_row', 'extra_row', 'rejected_state'):
bad = copy.deepcopy(verdict)
if change == 'wrong_sha': bad['manifest_sha256'] = '0'*64
if change == 'missing_row': bad['rows'] = []
if change == 'extra_row': bad['rows'] *= 2
if change == 'rejected_state': bad['rows'][0]['state'] = False
verdict_path.write_text(json.dumps(bad))
with self.subTest(change=change), self.assertRaises(ValueError):
check.reviewed_pixel_categories(manifest, digest, verdict_path)
verdict_path.write_text(json.dumps(verdict))
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), {'staff'})
manifest['mechanical_pass'] = False
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), set())
if __name__ == '__main__':
unittest.main()