""" Unit tests for the passive p0f-lite OS fingerprint lookup. Covers: - initial_ttl() TTL → bucket rounding - hop_distance() upper-bound clamping - guess_os() signature matching for Linux, Windows, macOS, nmap, embedded, and the unknown fallback """ from __future__ import annotations from decnet.sniffer.p0f import guess_os, hop_distance, initial_ttl # ─── initial_ttl ──────────────────────────────────────────────────────────── class TestInitialTtl: def test_linux_bsd(self): assert initial_ttl(64) == 64 assert initial_ttl(59) == 64 assert initial_ttl(33) == 64 def test_windows(self): assert initial_ttl(128) == 128 assert initial_ttl(120) == 128 assert initial_ttl(65) == 128 def test_embedded(self): assert initial_ttl(255) == 255 assert initial_ttl(254) == 255 assert initial_ttl(200) == 255 def test_very_short(self): # anything <= 32 rounds to 32 assert initial_ttl(32) == 32 assert initial_ttl(1) == 32 def test_out_of_range(self): # Packets with TTL > 255 (should never happen) still bucket. assert initial_ttl(300) == 255 # ─── hop_distance ─────────────────────────────────────────────────────────── class TestHopDistance: def test_zero_when_local(self): assert hop_distance(64) == 0 assert hop_distance(128) == 0 assert hop_distance(255) == 0 def test_typical(self): assert hop_distance(60) == 4 # 4 hops from Linux assert hop_distance(120) == 8 # 8 hops from Windows def test_negative_or_weird_still_bucketed(self): # TTL=0 is anomalous but we still return a non-negative distance. # TTL 0 bucket is 32 → distance = 32 - 0 = 32. assert hop_distance(0) == 32 # ─── guess_os ─────────────────────────────────────────────────────────────── class TestGuessOs: def test_linux_default(self): # Modern Linux: TTL 64, window 29200+, WScale 7, full options result = guess_os( ttl=64, window=29200, mss=1460, wscale=7, options_sig="M,S,T,N,W", ) assert result == "linux" def test_windows_default(self): # Windows 10: TTL 128, window 64240, WScale 8, MSS 1460 result = guess_os( ttl=128, window=64240, mss=1460, wscale=8, options_sig="M,N,W,N,N,T,S", ) assert result == "windows" def test_macos_ios(self): # macOS default: TTL 64, window 65535, WScale 6, ends with EOL result = guess_os( ttl=64, window=65535, mss=1460, wscale=6, options_sig="M,N,W,N,N,T,S,E", ) assert result == "macos_ios" def test_nmap_sYn(self): # nmap -sS uses tiny/distinctive windows like 1024 or 4096 result = guess_os( ttl=64, window=1024, mss=1460, wscale=10, options_sig="M,W,T,S,S", ) assert result == "nmap" def test_nmap_alt_window(self): result = guess_os( ttl=64, window=31337, mss=1460, wscale=10, options_sig="M,W,T,S,S", ) assert result == "nmap" def test_embedded_ttl255(self): # Any TTL bucket 255 → embedded result = guess_os( ttl=250, window=4128, mss=536, wscale=None, options_sig="M", ) assert result == "embedded" def test_unknown(self): # Bizarre combo nothing matches result = guess_os( ttl=50, window=100, mss=0, wscale=None, options_sig="", ) assert result == "unknown"