""" 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.")