@mytec: feat: Phase 3.0 Architecture Refactor ✅
Major refactoring of RFCP backend: - Modular propagation models (8 models) - SharedMemoryManager for terrain data - ProcessPoolExecutor parallel processing - WebSocket progress streaming - Building filtering pipeline (351k → 15k) - 82 unit tests Performance: Standard preset 38s → 5s (7.6x speedup) Known issue: Detailed preset timeout (fix in 3.1.0)
This commit is contained in:
60
backend/tests/test_geometry/test_diffraction.py
Normal file
60
backend/tests/test_geometry/test_diffraction.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
Unit tests for knife-edge diffraction calculations.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
|
||||
from app.geometry.diffraction import knife_edge_loss
|
||||
|
||||
|
||||
def freq_to_wl(freq_mhz):
|
||||
return 300.0 / freq_mhz
|
||||
|
||||
|
||||
class TestKnifeEdgeLoss:
|
||||
def test_no_obstruction_low_loss(self):
|
||||
"""Negative h means clearance above LOS — loss should be small."""
|
||||
loss = knife_edge_loss(d1_m=500, d2_m=500, h_m=-10, wavelength_m=freq_to_wl(1800))
|
||||
assert loss >= 0
|
||||
assert loss < 3
|
||||
|
||||
def test_grazing_obstruction(self):
|
||||
"""h=0 means exactly at LOS line — ~6 dB loss."""
|
||||
loss = knife_edge_loss(d1_m=500, d2_m=500, h_m=0, wavelength_m=freq_to_wl(1800))
|
||||
assert 5 < loss < 8
|
||||
|
||||
def test_obstruction_increases_loss(self):
|
||||
wl = freq_to_wl(1800)
|
||||
loss_low = knife_edge_loss(d1_m=500, d2_m=500, h_m=1, wavelength_m=wl)
|
||||
loss_high = knife_edge_loss(d1_m=500, d2_m=500, h_m=10, wavelength_m=wl)
|
||||
assert loss_high > loss_low
|
||||
|
||||
def test_higher_freq_more_loss(self):
|
||||
"""Higher frequency = shorter wavelength = more diffraction loss."""
|
||||
loss_low_f = knife_edge_loss(d1_m=500, d2_m=500, h_m=5, wavelength_m=freq_to_wl(450))
|
||||
loss_high_f = knife_edge_loss(d1_m=500, d2_m=500, h_m=5, wavelength_m=freq_to_wl(1800))
|
||||
assert loss_high_f > loss_low_f
|
||||
|
||||
def test_zero_distance_safe(self):
|
||||
"""Should not crash on zero distances."""
|
||||
loss = knife_edge_loss(d1_m=0, d2_m=500, h_m=5, wavelength_m=freq_to_wl(900))
|
||||
assert loss >= 0
|
||||
|
||||
def test_large_clearance(self):
|
||||
"""Very deep clearance (large negative h) should have near-zero loss."""
|
||||
loss = knife_edge_loss(d1_m=500, d2_m=500, h_m=-50, wavelength_m=freq_to_wl(900))
|
||||
assert loss < 1.0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
instance = TestKnifeEdgeLoss()
|
||||
for method_name in [m for m in dir(instance) if m.startswith("test_")]:
|
||||
try:
|
||||
getattr(instance, method_name)()
|
||||
print(f" PASS {method_name}")
|
||||
except Exception as e:
|
||||
print(f" FAIL {method_name}: {e}")
|
||||
print("\nAll tests completed.")
|
||||
Reference in New Issue
Block a user