first commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,70 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_healthcheck() -> None:
|
||||
response = client.get("/health")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
||||
|
||||
def test_openapi_contains_expected_paths() -> None:
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
paths = response.json()["paths"]
|
||||
assert "/api/v1/terrain/profile" in paths
|
||||
assert "/api/v1/terrain/los" in paths
|
||||
assert "/api/v1/link/budget" in paths
|
||||
assert "/api/v1/coverage" in paths
|
||||
|
||||
|
||||
def test_profile_endpoint_returns_geodesic_samples() -> None:
|
||||
response = client.post(
|
||||
"/api/v1/terrain/profile",
|
||||
json={
|
||||
"start": {"lat": 60.17, "lon": 24.94},
|
||||
"end": {"lat": 60.25, "lon": 25.10},
|
||||
"samples": 4,
|
||||
"include_buildings": True,
|
||||
"include_canopy": True,
|
||||
"k_factor": 1.333,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["distance_m"] > 0
|
||||
assert len(data["samples"]) == 4
|
||||
assert data["path_geojson"]["type"] == "LineString"
|
||||
|
||||
|
||||
def test_elevation_returns_not_implemented_without_dem() -> None:
|
||||
response = client.get("/api/v1/terrain/elevation", params={"lat": 60.17, "lon": 24.94})
|
||||
assert response.status_code == 501
|
||||
|
||||
|
||||
def test_manual_link_budget_endpoint() -> None:
|
||||
response = client.post(
|
||||
"/api/v1/link/budget",
|
||||
json={
|
||||
"tx": {"lat": 60.17, "lon": 24.94, "height_agl": 30, "power_dbm": 37, "gain_dbi": 8},
|
||||
"rx": {
|
||||
"lat": 60.25,
|
||||
"lon": 25.10,
|
||||
"height_agl": 2,
|
||||
"gain_dbi": 2,
|
||||
"sensitivity_dbm": -110,
|
||||
},
|
||||
"frequency_mhz": 433,
|
||||
"model": "manual",
|
||||
"include_buildings": True,
|
||||
"include_vegetation": True,
|
||||
"k_factor": 1.333,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["fspl_db"] > 0
|
||||
assert data["link_viable"] is True
|
||||
@@ -0,0 +1,56 @@
|
||||
from math import isclose
|
||||
|
||||
import pytest
|
||||
|
||||
from app.core.antenna import AntennaPattern, gain
|
||||
from app.core.diffraction import knife_edge_loss
|
||||
from app.core.fresnel import earth_bulge, fresnel_radius, wavelength
|
||||
from app.core.propagation import fspl
|
||||
from app.core.vegetation import P833Coefficients, p833_attenuation
|
||||
|
||||
|
||||
def test_fspl_reference_value() -> None:
|
||||
assert isclose(fspl(433, 12.45), 107.08, abs_tol=0.05)
|
||||
|
||||
|
||||
def test_fresnel_radius_reference_value() -> None:
|
||||
lmbda = wavelength(433_000_000)
|
||||
assert isclose(fresnel_radius(lmbda, 6_225, 6_225), 46.45, abs_tol=0.05)
|
||||
|
||||
|
||||
def test_earth_bulge_reference_value() -> None:
|
||||
assert isclose(earth_bulge(6_225, 6_225, 1.333), 2.28, abs_tol=0.02)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("v", "expected"),
|
||||
[
|
||||
(-0.79, 0.0),
|
||||
(0.0, 6.03),
|
||||
(1.0, 13.93),
|
||||
],
|
||||
)
|
||||
def test_knife_edge_loss_reference_values(v: float, expected: float) -> None:
|
||||
assert isclose(knife_edge_loss(v), expected, abs_tol=0.05)
|
||||
|
||||
|
||||
def test_p833_formula_with_supplied_coefficients() -> None:
|
||||
attenuation = p833_attenuation(
|
||||
depth_m=100,
|
||||
freq_hz=433_000_000,
|
||||
forest_type="coniferous",
|
||||
coefficients=P833Coefficients(gamma_db_per_m=0.2, max_attenuation_db=30),
|
||||
)
|
||||
assert isclose(attenuation, 14.60, abs_tol=0.05)
|
||||
|
||||
|
||||
def test_sector_antenna_gain_peaks_at_boresight() -> None:
|
||||
pattern = AntennaPattern(
|
||||
pattern="sector",
|
||||
azimuth_deg=90,
|
||||
gain_dbi=8,
|
||||
beamwidth_h=65,
|
||||
beamwidth_v=15,
|
||||
)
|
||||
assert gain(pattern, 90, 0) == 8
|
||||
assert gain(pattern, 270, 0) < 8
|
||||
Reference in New Issue
Block a user