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

121 lines
7.4 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Synthetic tests for Phase-1.0AB nonblocking lifecycle traces."""
from __future__ import annotations
import argparse
import importlib.util
from pathlib import Path
import sys
def load(path: Path):
spec = importlib.util.spec_from_file_location("phase10ab_trace", path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec); sys.modules[spec.name] = module
spec.loader.exec_module(module); return module
def main() -> int:
parser = argparse.ArgumentParser(); parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args(); module = load(args.root.resolve() / "tools/phase10ab_nonblocking_trace_model.py")
def event(op, at, value=0): return module.TraceEvent(op, at, value)
def valid(pending=True, sends=(2, 3), waits=()):
values = [event(module.RECEIPT_CREATED, 0), event(module.SOCKET_CREATED, 0), event(module.SET_NONBLOCKING, 0)]
if pending:
values += [event(module.CONNECT_PENDING, .1), event(module.READY_WRITE, .2), event(module.SO_ERROR_ZERO, .2)]
else: values += [event(module.CONNECT_IMMEDIATE, .1)]
at = .3
for count in sends:
values += [event(module.READY_WRITE, at), event(module.SEND_BYTES, at, count)]; at += .1
for op in waits: values.append(event(op, at)); at += .1
values += [event(module.READY_READ, at), event(module.RECV_BYTES, at, 100), event(module.DEADLINE_REACHED, 10), event(module.SANITIZER_ACCEPTED, 10), event(module.LOCAL_CLOSE, 10), event(module.OUTPUT_CREATED, 10)]
return tuple(values)
def expect_failure(function):
try: function()
except module.TraceModelError: return
raise RuntimeError("invalid trace accepted")
cases = []
def case(name):
def register(function): cases.append((name, function)); return function
return register
@case("01 pending connect complete trace succeeds")
def _():
result = module.assess_nonblocking_trace(5, 10, valid()); assert result.batch_bytes_sent == 5
@case("02 immediate connect complete trace succeeds")
def _(): assert module.assess_nonblocking_trace(5, 10, valid(False)).classification == "OFFLINE_NONBLOCKING_SEQUENCE_FEASIBLE"
@case("03 partial sends require repeated readiness")
def _(): assert module.assess_nonblocking_trace(5, 10, valid(sends=(1, 1, 3))).complete_send_loop
@case("04 interrupted waits are recomputed")
def _(): assert module.assess_nonblocking_trace(5, 10, valid(waits=(module.WAIT_INTERRUPTED,))).deadline_only_completion
@case("05 timeout before deadline is not completion")
def _(): assert module.assess_nonblocking_trace(5, 10, valid(waits=(module.WAIT_TIMEOUT,))).local_close_observed
@case("06 receipt must precede creation")
def _(): expect_failure(lambda: module.assess_nonblocking_trace(5, 10, valid()[1:]))
@case("07 nonblocking must precede connect")
def _():
trace = tuple(e for e in valid() if e.operation != module.SET_NONBLOCKING); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("08 pending connect requires readiness")
def _():
trace = tuple(e for e in valid() if e.operation != module.READY_WRITE or e.at_seconds != .2); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("09 pending connect requires SO_ERROR")
def _():
trace = tuple(e for e in valid() if e.operation != module.SO_ERROR_ZERO); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("10 send requires write readiness")
def _():
trace = tuple(e for e in valid() if not (e.operation == module.READY_WRITE and e.at_seconds == .3)); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("11 send cannot exceed exact batch")
def _(): expect_failure(lambda: module.assess_nonblocking_trace(5, 10, valid(sends=(6,))))
@case("12 incomplete send fails")
def _(): expect_failure(lambda: module.assess_nonblocking_trace(5, 10, valid(sends=(2, 2))))
@case("13 receive requires read readiness")
def _():
trace = tuple(e for e in valid() if e.operation != module.READY_READ); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("14 receive bound is enforced")
def _():
trace = list(valid()); index = next(i for i,e in enumerate(trace) if e.operation == module.RECV_BYTES); trace[index] = event(module.RECV_BYTES, trace[index].at_seconds, 65537); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, tuple(trace)))
@case("15 EOF never completes")
def _():
trace = list(valid()); index = next(i for i,e in enumerate(trace) if e.operation == module.RECV_BYTES); trace[index] = event(module.RECV_EOF, trace[index].at_seconds); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, tuple(trace)))
@case("16 early deadline fails")
def _():
trace = tuple(event(e.operation, 9 if e.operation in {module.DEADLINE_REACHED,module.SANITIZER_ACCEPTED,module.LOCAL_CLOSE,module.OUTPUT_CREATED} else e.at_seconds, e.value) for e in valid()); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("17 data at deadline fails")
def _():
trace = list(valid()); index = next(i for i,e in enumerate(trace) if e.operation == module.RECV_BYTES); trace[index] = event(module.RECV_BYTES, 10, 100); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, tuple(trace)))
@case("18 deadline requires received data")
def _():
trace = tuple(e for e in valid() if e.operation not in {module.READY_READ,module.RECV_BYTES}); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("19 sanitizer must follow deadline")
def _():
trace = tuple(e for e in valid() if e.operation != module.DEADLINE_REACHED); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("20 close must follow sanitizer")
def _():
trace = tuple(e for e in valid() if e.operation != module.SANITIZER_ACCEPTED); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("21 output must follow close")
def _():
trace = tuple(e for e in valid() if e.operation != module.LOCAL_CLOSE); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, trace))
@case("22 backward time fails")
def _():
trace = list(valid()); trace[2] = event(module.SET_NONBLOCKING, -.0); trace[1] = event(module.SOCKET_CREATED, .1); expect_failure(lambda: module.assess_nonblocking_trace(5, 10, tuple(trace)))
@case("23 trace event bound is enforced")
def _(): expect_failure(lambda: module.assess_nonblocking_trace(5, 10, tuple(event(module.RECEIPT_CREATED, 0) for _ in range(513))))
@case("24 result never claims device proof")
def _():
result = module.assess_nonblocking_trace(5, 10, valid()); assert not result.device_behavior_proven and not result.live_transport_present
@case("25 no live API exists")
def _(): assert not ({"connect", "send", "recv", "main"} & set(dir(module)))
failures=[]
for name,function in cases:
try: function(); print(f"PASS {name}")
except Exception as error: failures.append(f"{name}: {error}"); print(f"FAIL {name}: {error}")
if failures: return 1
print(f"Phase-1.0AB nonblocking-trace tests passed: {len(cases)}"); return 0
if __name__ == "__main__": raise SystemExit(main())