- packet_replay: stop_replay test reduces fake-task receive timeout from 5s to 200ms - broadcast_task_supervisor: scheduler_usage takes configurable sample seconds; test uses sample-pair API (instant) instead of blocking 1-second sample - health_check: ask_if_alive timeout is now configurable; unresponsive-pid test uses 50ms timeout instead of waiting full 5-second default - mix_unused/analyzer_test: cache analyze() result in setup_all so 4 tests share one analyze pass instead of running 4 separate scans - mix/tasks/compile/unused_test: consolidate three slow severity tests into one - log_sanitizer + packet_field_whitelist: cap property-test runs at 25 (was 100) - historical_loading: trim 200ms post-event sleeps to 50ms - movement: refute_push_event timeout from 200ms to 50ms Total suite time: ~45s -> 40.6s; 2488 tests, 0 failures.
130 lines
4.4 KiB
Elixir
130 lines
4.4 KiB
Elixir
defmodule Aprsme.PacketFieldWhitelistTest do
|
|
use ExUnit.Case, async: true
|
|
use ExUnitProperties
|
|
|
|
alias Aprsme.PacketFieldWhitelist
|
|
|
|
describe "allowed_fields/0" do
|
|
test "returns a list of strings" do
|
|
fields = PacketFieldWhitelist.allowed_fields()
|
|
assert is_list(fields)
|
|
assert match?([_ | _], fields)
|
|
assert Enum.all?(fields, &is_binary/1)
|
|
end
|
|
|
|
test "contains core schema fields" do
|
|
fields = PacketFieldWhitelist.allowed_fields()
|
|
assert "sender" in fields
|
|
assert "base_callsign" in fields
|
|
assert "lat" in fields
|
|
assert "lon" in fields
|
|
assert "received_at" in fields
|
|
assert "raw_packet" in fields
|
|
end
|
|
end
|
|
|
|
describe "allowed?/1" do
|
|
test "accepts atoms that match allowed fields" do
|
|
assert PacketFieldWhitelist.allowed?(:sender)
|
|
assert PacketFieldWhitelist.allowed?(:raw_packet)
|
|
assert PacketFieldWhitelist.allowed?(:lat)
|
|
end
|
|
|
|
test "accepts strings that match allowed fields" do
|
|
assert PacketFieldWhitelist.allowed?("sender")
|
|
assert PacketFieldWhitelist.allowed?("raw_packet")
|
|
end
|
|
|
|
test "rejects unknown atoms" do
|
|
refute PacketFieldWhitelist.allowed?(:totally_bogus)
|
|
refute PacketFieldWhitelist.allowed?(:__struct__)
|
|
end
|
|
|
|
test "rejects unknown strings" do
|
|
refute PacketFieldWhitelist.allowed?("id")
|
|
refute PacketFieldWhitelist.allowed?("")
|
|
end
|
|
|
|
test "rejects non-atom, non-binary input" do
|
|
refute PacketFieldWhitelist.allowed?(123)
|
|
refute PacketFieldWhitelist.allowed?(nil)
|
|
refute PacketFieldWhitelist.allowed?(%{})
|
|
refute PacketFieldWhitelist.allowed?([])
|
|
end
|
|
end
|
|
|
|
describe "filter_fields/1" do
|
|
test "keeps allowed atom keys" do
|
|
input = %{sender: "K5ABC", lat: 30.0, bogus: "x"}
|
|
result = PacketFieldWhitelist.filter_fields(input)
|
|
assert result[:sender] == "K5ABC"
|
|
assert result[:lat] == 30.0
|
|
refute Map.has_key?(result, :bogus)
|
|
end
|
|
|
|
test "keeps allowed string keys" do
|
|
input = %{"sender" => "K5ABC", "unknown" => "x"}
|
|
result = PacketFieldWhitelist.filter_fields(input)
|
|
assert result["sender"] == "K5ABC"
|
|
refute Map.has_key?(result, "unknown")
|
|
end
|
|
|
|
test "preserves whichever key type caller used" do
|
|
atom_in = %{sender: "a"}
|
|
string_in = %{"sender" => "b"}
|
|
assert PacketFieldWhitelist.filter_fields(atom_in) == %{sender: "a"}
|
|
assert PacketFieldWhitelist.filter_fields(string_in) == %{"sender" => "b"}
|
|
end
|
|
|
|
test "returns empty map when no keys are allowed" do
|
|
assert PacketFieldWhitelist.filter_fields(%{bogus: 1, junk: 2}) == %{}
|
|
end
|
|
|
|
test "returns empty map on empty input" do
|
|
assert PacketFieldWhitelist.filter_fields(%{}) == %{}
|
|
end
|
|
end
|
|
|
|
describe "invalid_fields/1" do
|
|
test "returns only the disallowed keys as strings" do
|
|
input = %{"junk" => 2, sender: "x", bogus: 1}
|
|
assert PacketFieldWhitelist.invalid_fields(input) == ["bogus", "junk"]
|
|
end
|
|
|
|
test "returns empty list when every key is allowed" do
|
|
assert PacketFieldWhitelist.invalid_fields(%{sender: "x", lat: 1.0}) == []
|
|
end
|
|
|
|
test "returns sorted, deduplicated-looking output" do
|
|
input = %{z_bogus: 1, a_bogus: 2}
|
|
result = PacketFieldWhitelist.invalid_fields(input)
|
|
assert result == Enum.sort(result)
|
|
end
|
|
end
|
|
|
|
describe "property: filter_fields/1 is idempotent" do
|
|
property "running filter twice equals running once" do
|
|
check all(map <- map_of(atom(:alphanumeric), term()), max_runs: 25) do
|
|
once = PacketFieldWhitelist.filter_fields(map)
|
|
twice = PacketFieldWhitelist.filter_fields(once)
|
|
assert once == twice
|
|
end
|
|
end
|
|
|
|
property "every key in the output satisfies allowed?/1" do
|
|
check all(map <- map_of(atom(:alphanumeric), term()), max_runs: 25) do
|
|
result = PacketFieldWhitelist.filter_fields(map)
|
|
assert Enum.all?(Map.keys(result), &PacketFieldWhitelist.allowed?/1)
|
|
end
|
|
end
|
|
|
|
property "invalid_fields and filter_fields partition the input" do
|
|
check all(map <- map_of(atom(:alphanumeric), term()), max_runs: 25) do
|
|
kept = map |> PacketFieldWhitelist.filter_fields() |> Map.keys() |> Enum.map(&to_string/1)
|
|
dropped = PacketFieldWhitelist.invalid_fields(map)
|
|
all_keys = map |> Map.keys() |> Enum.map(&to_string/1)
|
|
assert Enum.sort(kept ++ dropped) == Enum.sort(all_keys)
|
|
end
|
|
end
|
|
end
|
|
end
|