- Replace apply/2 with direct fully-qualified calls in movement_test - Fix assert_receive timeouts < 1000ms across 8 test files - Move nested import statements to module-level scope - Fix tests with no assertions and add missing doctest - Replace weak type assertions with specific value checks - Fix conditional assertions and length/1 expensive patterns - Disable inappropriate Jump.CredoChecks.AvoidSocketAssignsInTest - Fix tests not calling application code with credo:disable - Add various credo:disable comments for legitimate patterns
134 lines
4.8 KiB
Elixir
134 lines
4.8 KiB
Elixir
defmodule Aprsme.GeoUtilsTest do
|
|
use ExUnit.Case, async: true
|
|
use ExUnitProperties
|
|
|
|
alias Aprsme.GeoUtils
|
|
|
|
doctest GeoUtils
|
|
|
|
describe "haversine_distance/4" do
|
|
test "calculates zero distance for same point" do
|
|
assert GeoUtils.haversine_distance(33.16961, -96.4921, 33.16961, -96.4921) == 0.0
|
|
end
|
|
|
|
test "calculates small distances accurately" do
|
|
# About 1.1 meters north
|
|
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.16962, -96.4921)
|
|
assert_in_delta distance, 1.11, 0.1
|
|
end
|
|
|
|
test "calculates GPS drift-like distances" do
|
|
# Typical GPS drift of ~5 meters
|
|
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.169655, -96.4921)
|
|
assert_in_delta distance, 5.0, 0.5
|
|
end
|
|
|
|
test "calculates larger distances" do
|
|
# About 100 meters
|
|
distance = GeoUtils.haversine_distance(33.16961, -96.4921, 33.17061, -96.4921)
|
|
assert_in_delta distance, 111.2, 1.0
|
|
end
|
|
|
|
test "handles nil inputs" do
|
|
assert GeoUtils.haversine_distance(nil, -96.4921, 33.16962, -96.4921) == nil
|
|
assert GeoUtils.haversine_distance(33.16961, nil, 33.16962, -96.4921) == nil
|
|
assert GeoUtils.haversine_distance(33.16961, -96.4921, nil, -96.4921) == nil
|
|
assert GeoUtils.haversine_distance(33.16961, -96.4921, 33.16962, nil) == nil
|
|
end
|
|
|
|
test "handles non-numeric inputs" do
|
|
assert GeoUtils.haversine_distance("33.16961", -96.4921, 33.16962, -96.4921) == nil
|
|
assert GeoUtils.haversine_distance(33.16961, "invalid", 33.16962, -96.4921) == nil
|
|
end
|
|
end
|
|
|
|
describe "significant_movement?/5" do
|
|
test "returns false for no movement" do
|
|
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.16961, -96.4921)
|
|
end
|
|
|
|
test "returns false for GPS drift under default threshold" do
|
|
# About 5 meters - typical GPS drift
|
|
refute GeoUtils.significant_movement?(33.16961, -96.4921, 33.169655, -96.4921)
|
|
end
|
|
|
|
test "returns true for movement over default threshold" do
|
|
# About 55 meters movement (over 50m default threshold)
|
|
assert GeoUtils.significant_movement?(33.16961, -96.4921, 33.1701, -96.4921)
|
|
end
|
|
|
|
test "respects custom threshold" do
|
|
# About 5 meters movement
|
|
lat1 = 33.16961
|
|
lon1 = -96.4921
|
|
lat2 = 33.169655
|
|
lon2 = -96.4921
|
|
|
|
# With 3 meter threshold, should be significant
|
|
assert GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 3)
|
|
|
|
# With 10 meter threshold (default), should not be significant
|
|
refute GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 10)
|
|
|
|
# With 20 meter threshold, definitely not significant
|
|
refute GeoUtils.significant_movement?(lat1, lon1, lat2, lon2, 20)
|
|
end
|
|
|
|
test "handles nil inputs" do
|
|
refute GeoUtils.significant_movement?(nil, -96.4921, 33.16962, -96.4921)
|
|
refute GeoUtils.significant_movement?(33.16961, nil, 33.16962, -96.4921)
|
|
refute GeoUtils.significant_movement?(33.16961, -96.4921, nil, -96.4921)
|
|
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
|