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)
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
"""
|
|
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.")
|