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

158 lines
6.3 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only tests for the Phase-1.0Y shsrv framing model."""
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("phase10y_framing", 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 require(value: bool, message: str) -> None:
if not value:
raise RuntimeError(message)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
model = load(args.root.resolve() / "tools/phase10y_shsrv_framing_model.py")
cases = []
def case(name):
def register(function):
cases.append((name, function))
return function
return register
def decode(family, chunks):
decoder = model.ClientWireDecoder(family)
for chunk in chunks:
decoder.feed(chunk)
return decoder.finalize()
@case("01 legacy family passes raw bytes")
def _(): require(decode(model.LEGACY_RAW, [b"help\r\n"]).application == b"help\r\n", "legacy transformed")
@case("02 legacy family passes Telnet controls to shell")
def _():
raw = bytes((model.IAC, model.WILL, 1))
value = decode(model.LEGACY_RAW, [raw])
require(value.application == raw and not value.negotiation_replies, "legacy negotiated")
@case("03 current family maps CRLF to LF")
def _(): require(decode(model.LIBTELNET_NVT, [b"help\r\n"]).application == b"help\n", "CRLF mismatch")
@case("04 current family maps CRNUL to CR")
def _(): require(decode(model.LIBTELNET_NVT, [b"x\r\x00"]).application == b"x\r", "CRNUL mismatch")
@case("05 current family preserves CR followed by data")
def _(): require(decode(model.LIBTELNET_NVT, [b"x\ry"]).application == b"x\ry", "CR data mismatch")
@case("06 doubled IAC becomes one application byte")
def _():
value = decode(model.LIBTELNET_NVT, [bytes((model.IAC, model.IAC))])
require(value.application == bytes((model.IAC,)), "IAC escape mismatch")
@case("07 WILL receives DONT")
def _():
value = decode(model.LIBTELNET_NVT, [bytes((model.IAC, model.WILL, 1))])
require(value.negotiation_replies == (bytes((model.IAC, model.DONT, 1)),), "WILL reply mismatch")
@case("08 DO receives WONT")
def _():
value = decode(model.LIBTELNET_NVT, [bytes((model.IAC, model.DO, 3))])
require(value.negotiation_replies == (bytes((model.IAC, model.WONT, 3)),), "DO reply mismatch")
@case("09 initial WONT produces no reply")
def _(): require(not decode(model.LIBTELNET_NVT, [bytes((model.IAC, model.WONT, 1))]).negotiation_replies, "WONT replied")
@case("10 initial DONT produces no reply")
def _(): require(not decode(model.LIBTELNET_NVT, [bytes((model.IAC, model.DONT, 1))]).negotiation_replies, "DONT replied")
@case("11 fragmented negotiation is modeled")
def _():
value = decode(model.LIBTELNET_NVT, [bytes((model.IAC,)), bytes((model.WILL,)), b"\x01"])
require(value.negotiation_replies == (bytes((model.IAC, model.DONT, 1)),), "fragment reply mismatch")
@case("12 subnegotiation is removed")
def _():
frame = bytes((model.IAC, model.SB, 31, 0, 80, model.IAC, model.SE))
require(decode(model.LIBTELNET_NVT, [frame[:2], frame[2:]]).application == b"", "subnegotiation leaked")
@case("13 incomplete control fails closed")
def _():
decoder = model.ClientWireDecoder(model.LIBTELNET_NVT); decoder.feed(bytes((model.IAC,)))
try: decoder.finalize()
except model.FramingError: return
raise RuntimeError("incomplete control accepted")
@case("14 outgoing newline becomes CRLF only in current family")
def _():
require(model.encode_server_text(model.LIBTELNET_NVT, b"x\n") == b"x\r\n" and model.encode_server_text(model.LEGACY_RAW, b"x\n") == b"x\n", "newline encoding mismatch")
@case("15 outgoing CR becomes CRNUL")
def _(): require(model.encode_server_text(model.LIBTELNET_NVT, b"x\r") == b"x\r\x00", "CR encoding mismatch")
@case("16 outgoing IAC is doubled")
def _(): require(model.encode_server_text(model.LIBTELNET_NVT, bytes((model.IAC,))) == bytes((model.IAC, model.IAC)), "outgoing IAC mismatch")
@case("17 neither family proactively negotiates")
def _(): require(all(model.initial_server_bytes(family) == b"" for family in model.SOURCE_FAMILIES), "proactive bytes invented")
@case("18 source-shaped prompt remains candidate only")
def _():
value = model.assess_prompt_candidates(b"greeting\r\n/$ ")
require(value.classification == "SOURCE_SHAPE_CANDIDATE_ONLY" and value.exact_completion_proven is False, "prompt promoted")
@case("19 embedded prompt shape is ambiguous")
def _():
value = model.assess_prompt_candidates(b"/tmp/$ embedded$ ")
require(value.classification == "AMBIGUOUS_PROMPT_CANDIDATES" and len(value.candidate_offsets) == 2, "ambiguity missed")
@case("20 nonterminal prompt shape is incomplete")
def _():
value = model.assess_prompt_candidates(b"/$ output")
require(value.classification == "NO_TERMINAL_PROMPT_CANDIDATE", "nonterminal candidate accepted")
@case("21 model byte bound fails closed")
def _():
decoder = model.ClientWireDecoder(model.LEGACY_RAW)
try: decoder.feed(b"x" * (model.MAX_MODEL_BYTES + 1))
except model.FramingError: return
raise RuntimeError("oversize wire accepted")
@case("22 IAC command is recorded, not application data")
def _():
value = decode(model.LIBTELNET_NVT, [bytes((model.IAC, 244))])
require(value.application == b"" and value.iac_commands == (244,), "IAC command mismatch")
failures = []
for name, function in cases:
try:
function()
print(f"PASS {name}")
except Exception as error: # noqa: BLE001 - test harness
failures.append(f"{name}: {error}")
print(f"FAIL {name}: {error}")
if failures:
return 1
print(f"Phase-1.0Y framing-model tests passed: {len(cases)}")
return 0
if __name__ == "__main__":
raise SystemExit(main())