prop/test/microwaveprop/geo_test.exs
Graham McIntire cb2937f12c
test: cover geo, qrz record, callsign client
34 characterization tests for pure/wrapper modules. Documents existing
behavior — no production code changes.
2026-04-16 14:09:44 -05:00

98 lines
3.2 KiB
Elixir

defmodule Microwaveprop.GeoTest do
use ExUnit.Case, async: true
alias Microwaveprop.Geo
alias Microwaveprop.Radio.Maidenhead
describe "haversine_km/4" do
test "returns 0.0 for identical points" do
assert Geo.haversine_km(32.9, -96.8, 32.9, -96.8) == 0.0
end
test "matches a known long-distance pair (DFW to Newington, CT)" do
assert_in_delta Geo.haversine_km(32.9, -96.8, 41.714, -72.727), 2333.3, 1.0
end
test "computes a half-circumference for antipodal equator points" do
# Half the Earth's circumference at R = 6371 km is ~20015 km.
assert_in_delta Geo.haversine_km(0.0, 0.0, 0.0, 180.0), 20_015.0, 1.0
end
test "is symmetric in its arguments" do
forward = Geo.haversine_km(32.9, -96.8, 41.714, -72.727)
reverse = Geo.haversine_km(41.714, -72.727, 32.9, -96.8)
assert_in_delta forward, reverse, 0.0001
end
test "one degree of latitude is roughly 111 km" do
assert_in_delta Geo.haversine_km(32.0, -96.0, 33.0, -96.0), 111.195, 0.1
end
end
describe "bearing_deg/4" do
test "returns 0.0 for due north" do
assert Geo.bearing_deg(32.0, -96.0, 33.0, -96.0) == 0.0
end
test "returns ~90 for due east at the equator" do
assert_in_delta Geo.bearing_deg(0.0, 0.0, 0.0, 1.0), 90.0, 0.1
end
test "returns 180.0 for due south" do
assert Geo.bearing_deg(32.0, -96.0, 31.0, -96.0) == 180.0
end
test "returns a bearing in the range [0, 360)" do
bearing = Geo.bearing_deg(32.0, -96.0, 32.0, -97.0)
assert bearing >= 0.0 and bearing < 360.0
assert_in_delta bearing, 270.0, 1.0
end
test "rounds to one decimal place" do
# DFW to Newington - pick any pair, the result must have at most 1 decimal.
bearing = Geo.bearing_deg(32.9, -96.8, 41.714, -72.727)
assert Float.round(bearing, 1) == bearing
end
end
describe "maidenhead_center/1" do
test "returns the center of a 4-character grid" do
# EM12 is lat 32-33, lon -98 to -96, center (32.5, -97.0).
assert Geo.maidenhead_center("EM12") == {32.5, -97.0}
end
test "returns the center of a 6-character grid at higher precision" do
{lat, lon} = Geo.maidenhead_center("EM12kp")
assert_in_delta lat, 32.6458, 0.001
assert_in_delta lon, -97.125, 0.001
end
test "accepts lowercase grids" do
assert Geo.maidenhead_center("em12") == {32.5, -97.0}
end
test "returns nil for invalid grid characters" do
assert Geo.maidenhead_center("ZZZZ") == nil
end
end
describe "latlon_to_grid4/2" do
test "encodes the DFW area as EM12" do
assert Geo.latlon_to_grid4(32.9, -96.8) == "EM12"
end
test "encodes Newington, CT as FN31" do
assert Geo.latlon_to_grid4(41.714, -72.727) == "FN31"
end
test "encodes the prime-meridian/equator origin as JJ00" do
assert Geo.latlon_to_grid4(0.0, 0.0) == "JJ00"
end
test "agrees with Maidenhead.from_latlon/3 at precision 4 for typical US coords" do
for {lat, lon} <- [{32.9, -96.8}, {41.714, -72.727}, {40.0, -105.0}, {47.6, -122.3}] do
assert Geo.latlon_to_grid4(lat, lon) == Maidenhead.from_latlon(lat, lon, 4)
end
end
end
end