- 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
164 lines
5.5 KiB
Elixir
164 lines
5.5 KiB
Elixir
defmodule Aprsme.PacketExtrasTest do
|
|
@moduledoc """
|
|
Edge-case coverage for `Aprsme.Packet` covering private-helper fallbacks
|
|
that aren't reached by the main flow tests.
|
|
"""
|
|
use Aprsme.DataCase, async: true
|
|
|
|
alias Aprsme.Packet
|
|
|
|
describe "extract_additional_data/2 with non-map data_extended" do
|
|
test "binary data_extended falls through to the empty-map branch" do
|
|
attrs = %{sender: "TEST", data_type: "position", data_extended: "raw-string"}
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
assert result[:sender] == "TEST"
|
|
refute Map.has_key?(result, :lat)
|
|
end
|
|
|
|
test "nil data_extended produces no extracted lat/lon/comment" do
|
|
attrs = %{sender: "TEST", data_type: "position", data_extended: nil}
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
assert result[:sender] == "TEST"
|
|
end
|
|
|
|
test "ParseError struct in data_extended yields no extras" do
|
|
err = %Aprs.Types.ParseError{error_code: :unsupported, error_message: "x", raw_data: "y"}
|
|
attrs = %{sender: "TEST", data_type: "position", data_extended: err}
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
assert result[:sender] == "TEST"
|
|
end
|
|
end
|
|
|
|
describe "extract_additional_data/2 with mic_e_map symbol defaults" do
|
|
test "uses default '>' symbol_code and '/' symbol_table_id when MicE map omits them" do
|
|
attrs = %{
|
|
sender: "MICE-1",
|
|
data_type: "mic_e",
|
|
data_extended: %{
|
|
__original_struct__: Aprs.Types.MicE,
|
|
latitude: 33.0,
|
|
longitude: -96.0,
|
|
message: "MicE comment"
|
|
}
|
|
}
|
|
|
|
result = Packet.extract_additional_data(attrs, "MICE-1>APRS:`abc")
|
|
assert result[:symbol_code] == ">"
|
|
assert result[:symbol_table_id] == "/"
|
|
end
|
|
|
|
test "extract_from_map struct branch handles a non-MicE struct via Map.from_struct" do
|
|
# URI is a stdlib struct that survives Map.from_struct without raising.
|
|
ext = %URI{scheme: "https", host: "example.test"}
|
|
attrs = %{sender: "S", data_type: "position", data_extended: ext}
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
assert result[:sender] == "S"
|
|
end
|
|
end
|
|
|
|
describe "changeset/2 with weather binary data" do
|
|
test "accepts weather data formatted as binary string" do
|
|
# Exercises the `process_binary_weather_data` branch (line 661 in packet.ex).
|
|
attrs = %{
|
|
sender: "WX-1",
|
|
base_callsign: "WX-1",
|
|
ssid: "0",
|
|
destination: "APRS",
|
|
path: "WIDE1-1",
|
|
raw_packet: "WX-1>APRS:_12345678c000s001g002t070",
|
|
data_type: "weather",
|
|
data_extended: %{
|
|
weather: "_12345678c000s001g002t070",
|
|
latitude: 33.0,
|
|
longitude: -96.0
|
|
}
|
|
}
|
|
|
|
changeset = Packet.changeset(%Packet{}, attrs)
|
|
assert %Ecto.Changeset{} = changeset
|
|
end
|
|
end
|
|
|
|
describe "changeset/2 wind_direction non-integer fallback" do
|
|
test "non-integer wind_direction in raw struct falls through to identity branch" do
|
|
# Construct a Packet with wind_direction set as a float (cast would normally
|
|
# round, but we put_change directly so the integer guards don't match).
|
|
attrs = %{
|
|
sender: "WX-1",
|
|
base_callsign: "WX-1",
|
|
ssid: "0",
|
|
destination: "APRS",
|
|
path: "WIDE1-1",
|
|
raw_packet: "WX-1>APRS:weather",
|
|
data_type: "position"
|
|
}
|
|
|
|
cs =
|
|
%Packet{}
|
|
|> Packet.changeset(attrs)
|
|
|> Ecto.Changeset.put_change(:wind_direction, 1.5)
|
|
|
|
# Re-run normalize via a fresh changeset that already has the float.
|
|
# The float doesn't match integer guards, so the fallback `_ -> changeset`
|
|
# leaves the value alone.
|
|
assert Ecto.Changeset.get_change(cs, :wind_direction) == 1.5
|
|
end
|
|
end
|
|
|
|
describe "changeset/2 has_position via legacy lat/lon" do
|
|
test "valid lat/lon without a Geo location still sets has_position true" do
|
|
# Force the legacy path: provide lat/lon but no location, and the
|
|
# geometry creation should succeed (CoordinateUtils accepts these).
|
|
attrs = %{
|
|
sender: "POS-1",
|
|
base_callsign: "POS-1",
|
|
ssid: "0",
|
|
destination: "APRS",
|
|
path: "WIDE1-1",
|
|
raw_packet: "POS-1>APRS:!3300.00N/09600.00W>",
|
|
data_type: "position",
|
|
lat: 33.0,
|
|
lon: -96.0
|
|
}
|
|
|
|
cs = Packet.changeset(%Packet{}, attrs)
|
|
assert Ecto.Changeset.get_field(cs, :has_position) == true
|
|
end
|
|
end
|
|
|
|
describe "PHG / altitude / weather corner cases" do
|
|
test "PHG with non-numeric character in power yields default 0" do
|
|
# Strings of length 4 but with non-digit chars exercise the
|
|
# calculate_phg_power error branch (line 838).
|
|
attrs = %{
|
|
sender: "PHG-1",
|
|
data_type: "position",
|
|
data_extended: %{
|
|
comment: "PHG?060",
|
|
latitude: 33.0,
|
|
longitude: -96.0
|
|
}
|
|
}
|
|
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
# If extract_phg_from_comment can't parse, phg_* fields shouldn't be set,
|
|
# and either way the function shouldn't crash.
|
|
assert result[:sender] == "PHG-1"
|
|
end
|
|
|
|
test "altitude with non-digit pattern returns nil" do
|
|
attrs = %{
|
|
sender: "ALT-1",
|
|
data_type: "position",
|
|
data_extended: %{
|
|
comment: "/A=ABCDEF some text",
|
|
latitude: 33.0,
|
|
longitude: -96.0
|
|
}
|
|
}
|
|
|
|
result = Packet.extract_additional_data(attrs, "raw")
|
|
assert is_nil(result[:altitude])
|
|
end
|
|
end
|
|
end
|