Files
chimera-gfx-Public/tests/test_phase10ai_mapping_model.py
T
Chimera GFX release export a6037502d7
phase0-ci / build-and-audit (push) Successful in 2m14s
Publish Chimera GFX source
2026-09-03 03:27:14 +02:00

134 lines
6.0 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Failure-injection tests for Phase-1.0AI mapping transactions."""
from __future__ import annotations
import argparse
from pathlib import Path
import sys
import unittest
PARSER = argparse.ArgumentParser()
PARSER.add_argument("--root", type=Path, required=True)
ROOT = PARSER.parse_args().root
sys.path.insert(0, str(ROOT / "tools"))
from phase10ag_bounded_elf import LoadSegment, PF_R, PF_W, PF_X # noqa: E402
from phase10ai_mapping_model import * # noqa: E402,F403
def plan() -> MappingPlan:
return MappingPlan((
LoadSegment(PF_R | PF_X, 0x4000, 0, 0x1800, 0x1800, 0x4000),
LoadSegment(PF_R, 0x8000, 0x8000, 0x1000, 0x1000, 0x4000),
LoadSegment(PF_R | PF_W, 0xc000, 0xc000, 0x800, 0x1800, 0x4000),
), 7)
def happy(mapping: MappingPlan | None = None) -> list[FakeMappingEvent]:
mapping = mapping or plan()
events = [FakeMappingEvent(RESERVE_CHILD, OK, value=mapping.region_size),
FakeMappingEvent(CREATE_MIRROR, OK, value=mapping.region_size)]
for index, segment in enumerate(mapping.segments):
if segment.file_size:
events.append(FakeMappingEvent(COPY_FILE_BYTES, OK, index,
segment.file_size))
if segment.memory_size > segment.file_size:
events.append(FakeMappingEvent(ZERO_BSS, OK, index,
segment.memory_size - segment.file_size))
events.append(FakeMappingEvent(APPLY_RELATIVE, OK,
value=mapping.relative_relocations))
events.append(FakeMappingEvent(COPY_MIRROR_TO_CHILD, OK,
value=mapping.region_size))
for index, segment in enumerate(mapping.segments):
events.append(FakeMappingEvent(SET_FINAL_PROTECTION, OK, index,
segment.flags))
events += [FakeMappingEvent(SYNC_IMAGE, OK, value=mapping.region_size),
FakeMappingEvent(RELEASE_MIRROR, OK)]
return events
class MappingModelTests(unittest.TestCase):
def test_success(self) -> None:
mapping = plan()
result = run_mapping(mapping, FakeMappingFacade(tuple(happy(mapping))))
self.assertTrue(result.success and result.child_region_retained)
self.assertTrue(result.mirror_released)
self.assertFalse(result.child_region_unmapped or result.target_mapping_performed)
self.assertEqual(result.zeroed_bss_bytes, 0x1000)
def test_reserve_failure_has_no_cleanup(self) -> None:
mapping = plan()
events = (FakeMappingEvent(RESERVE_CHILD, ERROR, value=mapping.region_size),)
result = run_mapping(mapping, FakeMappingFacade(events))
self.assertFalse(result.success or result.child_region_unmapped)
def test_mirror_creation_failure_unmaps_child(self) -> None:
mapping = plan()
events = (FakeMappingEvent(RESERVE_CHILD, OK, value=mapping.region_size),
FakeMappingEvent(CREATE_MIRROR, ERROR, value=mapping.region_size),
FakeMappingEvent(UNMAP_CHILD, OK, value=mapping.region_size))
result = run_mapping(mapping, FakeMappingFacade(events))
self.assertFalse(result.success)
self.assertTrue(result.child_region_unmapped)
def test_every_post_mirror_failure_releases_and_unmaps(self) -> None:
mapping = plan()
baseline = happy(mapping)
for index in range(2, len(baseline)):
failed = baseline[:index + 1]
event = failed[index]
failed[index] = FakeMappingEvent(event.operation, ERROR,
event.segment_index, event.value)
failed += [FakeMappingEvent(RELEASE_MIRROR, OK),
FakeMappingEvent(UNMAP_CHILD, OK, value=mapping.region_size)]
with self.subTest(operation=event.operation, index=index):
result = run_mapping(mapping, FakeMappingFacade(tuple(failed)))
self.assertFalse(result.success)
self.assertTrue(result.mirror_released)
self.assertTrue(result.child_region_unmapped)
def test_cleanup_failure_is_hard_error(self) -> None:
mapping = plan()
events = happy(mapping)[:3]
event = events[-1]
events[-1] = FakeMappingEvent(event.operation, ERROR,
event.segment_index, event.value)
events.append(FakeMappingEvent(RELEASE_MIRROR, ERROR))
with self.assertRaises(MappingModelError):
run_mapping(mapping, FakeMappingFacade(tuple(events)))
def test_tick_budget_is_enforced_and_rolled_back(self) -> None:
mapping = plan()
events = happy(mapping)[:2]
first = events[0]
events[0] = FakeMappingEvent(first.operation, OK, value=first.value,
ticks=128)
events += [FakeMappingEvent(UNMAP_CHILD, OK, value=mapping.region_size)]
result = run_mapping(mapping, FakeMappingFacade(tuple(events)))
self.assertFalse(result.success)
self.assertTrue(result.child_region_unmapped)
def test_plan_rejects_wx_and_page_protection_overlap(self) -> None:
with self.assertRaises(MappingModelError):
MappingPlan((LoadSegment(PF_R | PF_W | PF_X, 0, 0, 1, 1, 0x4000),), 1)
with self.assertRaises(MappingModelError):
MappingPlan((LoadSegment(PF_R | PF_X, 0, 0, 1, 0x3000, 0x4000),
LoadSegment(PF_R | PF_W, 0x3000, 0x3000, 1, 1, 0x4000)), 1)
def test_wrong_binding_and_unused_events_are_rejected(self) -> None:
mapping = plan()
events = happy(mapping)
events[2] = FakeMappingEvent(COPY_FILE_BYTES, OK, 0, 1)
with self.assertRaises(MappingModelError):
run_mapping(mapping, FakeMappingFacade(tuple(events)))
with self.assertRaises(MappingModelError):
run_mapping(mapping, FakeMappingFacade(tuple(
happy(mapping) + [FakeMappingEvent(RELEASE_MIRROR, OK)])))
if __name__ == "__main__":
unittest.main(argv=[__file__])