test: add StreamData properties for Aprsme.GeoUtils

Four properties exercise haversine_distance / significant_movement?:

- non-negativity across any in-range coordinate pair
- symmetry: d(a, b) == d(b, a) within a tight tolerance
- identity: d(p, p) == 0.0
- significance agrees with (haversine > threshold) for any integer
  threshold in 1..1000

Total: +4 properties, coverage stays clean (dialyzer: 0 new errors).
This commit is contained in:
Graham McIntire 2026-04-23 15:14:05 -05:00
parent 8edc4bb4c7
commit ab0204f3dc
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59

View file

@ -1,5 +1,6 @@
defmodule Aprsme.GeoUtilsTest do
use ExUnit.Case, async: true
use ExUnitProperties
alias Aprsme.GeoUtils
@ -78,4 +79,54 @@ defmodule Aprsme.GeoUtilsTest do
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.16962, nil)
end
end
describe "property: haversine_distance" do
property "is always non-negative for numeric inputs" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0)
) do
assert GeoUtils.haversine_distance(lat1, lon1, lat2, lon2) >= 0
end
end
property "is symmetric: d(a,b) == d(b,a)" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0)
) do
a = GeoUtils.haversine_distance(lat1, lon1, lat2, lon2)
b = GeoUtils.haversine_distance(lat2, lon2, lat1, lon1)
assert_in_delta a, b, 0.01
end
end
property "d(p, p) == 0" do
check all(
lat <- float(min: -89.0, max: 89.0),
lon <- float(min: -179.0, max: 179.0)
) do
assert GeoUtils.haversine_distance(lat, lon, lat, lon) == 0.0
end
end
end
describe "property: significant_movement?" do
property "agrees with the haversine + threshold check" do
check all(
lat1 <- float(min: -89.0, max: 89.0),
lon1 <- float(min: -179.0, max: 179.0),
lat2 <- float(min: -89.0, max: 89.0),
lon2 <- float(min: -179.0, max: 179.0),
threshold <- integer(1..1000)
) do
d = GeoUtils.haversine_distance(lat1, lon1, lat2, lon2)
assert GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, threshold) == d > threshold
end
end
end
end