java-topology/defects/ryujinx-0001/test/test_ryujinx_0001.py
russell@unturf.com 8e1b8b1694 ryujinx: 1 CWE-407 defect, MOAD 0002-0005 CLEAN
ryujinx-0001: ManagedSocketPollManager Poll()/Select() List<Socket>.Contains()
inside loop after Socket.Select() trims lists to ready sockets. O(E*S) -> O(E+S)
with HashSet<Socket> conversion. 49.8x speedup at E=500. MOAD 0002-0005 CLEAN.
2026-03-31 18:06:01 -04:00

119 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""
ryujinx-0001: ManagedSocketPollManager Poll()/Select() ready-set lookup
CWE-407: List<Socket>.Contains() inside loop after Socket.Select()
Fix: convert to HashSet<Socket> after Socket.Select() trims the lists.
Complexity:
Before: O(E * S) -- E events, S ready sockets, list.Contains is O(S)
After: O(E + S) -- set lookup is O(1) amortized
This test validates correctness and performance of our HashSet-based
ready-set lookup using a Python simulation of the C# pattern.
Python list.count(x)==... mirrors C# List<T>.Contains; Python set membership
mirrors C# HashSet<T>.Contains.
Run: python3 test_ryujinx_0001.py
"""
import time
import sys
# Simulate the BEFORE (defective) pattern: list.Contains() in a loop
def count_ready_before(ready_list, all_sockets):
"""O(E * S) - list membership check per event"""
count = 0
for socket in all_sockets:
if socket in ready_list: # O(S) per call (linear scan over list)
count += 1
return count
# Simulate the AFTER (fixed) pattern: set lookup in a loop
def count_ready_after(ready_list, all_sockets):
"""O(E + S) - O(S) set build once, O(1) lookup per event"""
ready_set = set(ready_list) # O(S) once
count = 0
for socket in all_sockets:
if socket in ready_set: # O(1) per call
count += 1
return count
def assert_equal(a, b, msg):
if a != b:
print(f"FAIL: {msg}: expected {b}, got {a}", file=sys.stderr)
sys.exit(1)
def assert_true(cond, msg):
if not cond:
print(f"FAIL: {msg}", file=sys.stderr)
sys.exit(1)
def main():
print("ryujinx-0001: ManagedSocketPollManager ready-set lookup test")
print("=============================================================")
# Correctness: 10 events, 3 ready
all_sockets = list(range(10))
ready = [1, 4, 7]
assert_equal(count_ready_before(ready, all_sockets), 3, "before correctness (10/3)")
assert_equal(count_ready_after(ready, all_sockets), 3, "after correctness (10/3)")
print(" PASS: correctness check (10 events, 3 ready)")
# Correctness: no ready sockets
all_sockets = list(range(20))
ready = []
assert_equal(count_ready_before(ready, all_sockets), 0, "before correctness (20/0)")
assert_equal(count_ready_after(ready, all_sockets), 0, "after correctness (20/0)")
print(" PASS: correctness check (20 events, 0 ready)")
# Correctness: all ready
all_sockets = list(range(15))
ready = list(range(15))
assert_equal(count_ready_before(ready, all_sockets), 15, "before correctness (15/15)")
assert_equal(count_ready_after(ready, all_sockets), 15, "after correctness (15/15)")
print(" PASS: correctness check (15 events, all ready)")
# Benchmark: E=500, S~250 (heavy multiplayer game server socket poll)
E = 500
all_sockets = list(range(E))
ready = list(range(E // 2)) # half ready
# Warmup
WARMUP = 50
for _ in range(WARMUP):
count_ready_before(ready, all_sockets)
count_ready_after(ready, all_sockets)
RUNS = 500
t0 = time.perf_counter()
checksum_before = sum(count_ready_before(ready, all_sockets) for _ in range(RUNS))
t_before = time.perf_counter() - t0
t0 = time.perf_counter()
checksum_after = sum(count_ready_after(ready, all_sockets) for _ in range(RUNS))
t_after = time.perf_counter() - t0
assert_equal(checksum_before, checksum_after, "checksums match")
ratio = t_before / max(t_after, 1e-9)
ms_before = t_before * 1000
ms_after = t_after * 1000
print(f" BENCHMARK E={E}, S={E//2}: "
f"before={ms_before:.1f}ms after={ms_after:.1f}ms ratio={ratio:.1f}x")
# At E=500, S=250 the list scan does ~125,000 comparisons per call.
# HashSet/set is O(1). Expect at least 5x speedup on any hardware.
assert_true(
ratio >= 5.0 or (ms_before < 5 and ms_after < 5),
f"Expected >=5x speedup or both <5ms, got ratio={ratio:.1f}x "
f"before={ms_before:.1f}ms after={ms_after:.1f}ms"
)
print(" PASS: benchmark (>= 5x speedup measured)")
print()
print("ALL TESTS PASSED")
if __name__ == "__main__":
main()