Files
chimera-gfx-Public/tests/test_phase10af_bigapp_lifecycle_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

109 lines
4.6 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Failure-injection tests for the Phase-1.0AF lifecycle model."""
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 phase10af_bigapp_lifecycle_model import * # noqa: E402,F403
def happy() -> list[FakeEvent]:
return [FakeEvent(CHECK_NO_BIGAPP, NONE), FakeEvent(ATTACH_PARENT, OK),
FakeEvent(ARM_FORK, OK), FakeEvent(CONTINUE_PARENT, OK),
FakeEvent(LAUNCH_FIXED_TITLE, OK),
FakeEvent(AWAIT_UNIQUE_CHILD, CHILD, child_id=4242),
FakeEvent(DETACH_PARENT, OK), FakeEvent(ARM_EXEC, OK),
FakeEvent(CONTINUE_CHILD, OK), FakeEvent(AWAIT_EXEC, OK),
FakeEvent(REPLACE_EXACT_PAYLOAD, OK),
FakeEvent(RESTORE_MUTATIONS, OK), FakeEvent(DETACH_CHILD, OK),
FakeEvent(EMIT_RESULT, OK)]
class LifecycleTests(unittest.TestCase):
def test_success(self) -> None:
result = run_lifecycle(FakeLifecycleFacade(tuple(happy())))
self.assertTrue(result.success)
self.assertEqual(result.child_id, 4242)
self.assertTrue(result.parent_detached and result.child_detached)
self.assertTrue(result.mutations_restored)
self.assertFalse(result.child_terminated or result.existing_bigapp_killed)
def test_existing_bigapp_fails_without_kill(self) -> None:
result = run_lifecycle(FakeLifecycleFacade((FakeEvent(CHECK_NO_BIGAPP, EXISTS),)))
self.assertFalse(result.success)
self.assertFalse(result.existing_bigapp_killed)
self.assertEqual(result.child_id, 0)
def test_parent_stage_failures_detach(self) -> None:
for index in range(2, 5):
events = happy()[:index + 1]
events[index] = FakeEvent(events[index].operation, ERROR)
events = events[:index + 1] + [FakeEvent(DETACH_PARENT, OK)]
with self.subTest(index=index):
result = run_lifecycle(FakeLifecycleFacade(tuple(events)))
self.assertFalse(result.success)
self.assertTrue(result.parent_detached)
def test_child_stage_failures_terminate_only_child(self) -> None:
for index in range(7, 10):
events = happy()[:index + 1]
events[index] = FakeEvent(events[index].operation, ERROR)
events = events[:index + 1] + [FakeEvent(TERMINATE_CHILD, OK)]
with self.subTest(index=index):
result = run_lifecycle(FakeLifecycleFacade(tuple(events)))
self.assertFalse(result.success)
self.assertEqual(result.child_id, 4242)
self.assertTrue(result.child_terminated)
def test_replace_failure_restores_then_terminates(self) -> None:
events = happy()[:11]
events[10] = FakeEvent(REPLACE_EXACT_PAYLOAD, ERROR)
events += [FakeEvent(RESTORE_MUTATIONS, OK), FakeEvent(TERMINATE_CHILD, OK)]
result = run_lifecycle(FakeLifecycleFacade(tuple(events)))
self.assertFalse(result.success)
self.assertTrue(result.mutations_restored and result.child_terminated)
self.assertLess(result.trace.index("RESTORE_MUTATIONS:OK"),
result.trace.index("TERMINATE_CHILD:OK"))
def test_timeout_is_failure(self) -> None:
events = happy()[:6]
events[5] = FakeEvent(AWAIT_UNIQUE_CHILD, TIMEOUT)
events += [FakeEvent(DETACH_PARENT, OK)]
result = run_lifecycle(FakeLifecycleFacade(tuple(events)))
self.assertFalse(result.success)
def test_main_tick_budget(self) -> None:
events = happy()
events[0] = FakeEvent(CHECK_NO_BIGAPP, NONE, ticks=64)
events = events[:2] + [FakeEvent(DETACH_PARENT, OK)]
with self.assertRaises(LifecycleModelError):
run_lifecycle(FakeLifecycleFacade(tuple(events)))
def test_cleanup_failure_is_hard_error(self) -> None:
events = happy()[:3]
events[2] = FakeEvent(ARM_FORK, ERROR)
events += [FakeEvent(DETACH_PARENT, ERROR)]
with self.assertRaises(LifecycleModelError):
run_lifecycle(FakeLifecycleFacade(tuple(events)))
def test_unused_or_wrong_order_is_rejected(self) -> None:
result = run_lifecycle(FakeLifecycleFacade((FakeEvent(ATTACH_PARENT, OK),)))
self.assertFalse(result.success)
with self.assertRaises(LifecycleModelError):
run_lifecycle(FakeLifecycleFacade(tuple(happy() + [FakeEvent(EMIT_RESULT, OK)])))
if __name__ == "__main__":
unittest.main(argv=[__file__])