72 lines
3.3 KiB
Python
72 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
"""Mutation guardrails for Phase-1.0Z passive-batch evidence."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from copy import deepcopy
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
def load(path: Path):
|
|
spec = importlib.util.spec_from_file_location("phase10z_validator", 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()
|
|
root = args.root.resolve()
|
|
validator = load(root / "tools/validate_retroarch_phase10z.py")
|
|
original = validator.load_json(
|
|
root / "manifests/retroarch/phase-1.0z-passive-batch.json")
|
|
cases = []
|
|
|
|
def mutation(name, function):
|
|
cases.append((name, function))
|
|
|
|
mutation("01 active record rejected", lambda r: r["activation"].update(active=True))
|
|
mutation("02 target rejected", lambda r: r["activation"].update(target_address="device.invalid"))
|
|
mutation("03 connection authority rejected", lambda r: r["authorizations"].update(ps5_connection_authorized=True))
|
|
mutation("04 request authority rejected", lambda r: r["authorizations"].update(device_request_authorized=True))
|
|
mutation("05 receive authority rejected", lambda r: r["authorizations"].update(result_receive_authorized=True))
|
|
mutation("06 retry rejected", lambda r: r["authorizations"].update(automatic_retry=True))
|
|
mutation("07 reconnect rejected", lambda r: r["authorizations"].update(reconnect_authorized=True))
|
|
mutation("08 second outbound batch rejected", lambda r: r["batch_contract"].update(outbound_batches=2))
|
|
mutation("09 CR framing rejected", lambda r: r["batch_contract"].update(cr_allowed=True))
|
|
mutation("10 IAC framing rejected", lambda r: r["batch_contract"].update(iac_allowed=True))
|
|
mutation("11 prompt completion rejected", lambda r: r["receive_contract"].update(prompt_completion_used=True))
|
|
mutation("12 EOF completion rejected", lambda r: r["receive_contract"].update(remote_eof_completion_used=True))
|
|
mutation("13 nondeadline completion rejected", lambda r: r["receive_contract"].update(completion_event="PROMPT"))
|
|
mutation("14 partial acceptance rejected", lambda r: r["receive_contract"].update(partial_result="ACCEPT"))
|
|
mutation("15 source-family promotion rejected", lambda r: r["receive_contract"].update(source_family_selected=True))
|
|
mutation("16 hardware proof rejected", lambda r: r["tests"].update(hardware_claim_from_host_test=True))
|
|
mutation("17 device action rejected", lambda r: r["performed_actions"].update(ps5_connected=True))
|
|
mutation("18 live next step rejected", lambda r: r["decision"].update(next_step="LIVE_CLIENT"))
|
|
|
|
failures = []
|
|
for name, mutate in cases:
|
|
value = deepcopy(original)
|
|
mutate(value)
|
|
errors = validator.validate_record(value)
|
|
if errors:
|
|
print(f"PASS {name}")
|
|
else:
|
|
failures.append(name); print(f"FAIL {name}: mutation accepted")
|
|
if failures:
|
|
return 1
|
|
print(f"Phase-1.0Z guardrails passed: {len(cases)}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|