diff --git a/fifa17-recon/tools/test_capability_negotiation.py b/fifa17-recon/tools/test_capability_negotiation.py index f4ad645..1c6c6f2 100755 --- a/fifa17-recon/tools/test_capability_negotiation.py +++ b/fifa17-recon/tools/test_capability_negotiation.py @@ -28,6 +28,7 @@ Matrix (docs/plans/FIFA17_PATCHED_CLIENT_CAPABILITY.md): O session cleanup / TTL expiry -> capability gone, sentinel P duplicate registration for a session -> idempotent; no post-freeze change Q register-before-login (pending consumed) -> clean + R topology freeze immutable per SID -> no flip either way; new SID fresh Standalone unit test in the project style: `python3 test_capability_negotiation.py`. """ @@ -266,10 +267,33 @@ def main(): assert mode_of("sidQ") == CLEAN print("Q register-before-login pending consumed -> clean: OK") + # ---- R. topology freeze immutable per SID; new SID decides fresh ---- + # F3 invariant: once a SID's store topology is decided it NEVER flips, + # in either direction, and a different SID may decide differently. + reset_state(); set_zero_packs() + IP = "10.0.2.8" + # frozen Sentinel never becomes Clean, even if a capability appears later + auth("sidR_s", IP) + assert SENTINEL_ID in store("sidR_s", IP) # freeze Sentinel + register(IP, 1) + us._FIFA17_SESSIONS["sidR_s"]["resolver"] = 1 # force-present capability + assert SENTINEL_ID in store("sidR_s", IP) # STILL Sentinel + assert mode_of("sidR_s") == SENT + # frozen Clean never becomes Sentinel, even if the capability is wiped + auth("sidR_c", IP); register(IP, 1) + assert SENTINEL_ID not in store("sidR_c", IP) # freeze Clean + us._FIFA17_SESSIONS["sidR_c"]["resolver"] = None # capability vanishes + assert SENTINEL_ID not in store("sidR_c", IP) # STILL Clean + assert mode_of("sidR_c") == CLEAN + # a fresh SID (same IP) decides independently + auth("sidR_new", IP) + assert SENTINEL_ID in store("sidR_new", IP) + print("R topology freeze immutable per SID; new SID fresh: OK") + finally: us.visible_unopened_packs = _orig_visible - print("capability negotiation matrix A-Q: OK") + print("capability negotiation matrix A-R: OK") return 0