test: cover PacketConsumer init and process_batch callbacks

This commit is contained in:
Graham McIntire 2026-04-23 16:55:59 -05:00
parent f0db8f711e
commit e3dfdf03ba
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 188 additions and 0 deletions

View file

@ -7,6 +7,76 @@ defmodule Aprsme.PacketConsumerTest do
alias Aprsme.PacketConsumer
alias Aprsme.StreamingPacketsPubSub
describe "init/1" do
test "returns a :consumer tuple with default configuration" do
# Start an isolated consumer with no subscription to avoid contaminating
# the global packet pipeline. We skip the auto-subscribe by using :manual.
assert {:consumer, state, opts} =
PacketConsumer.init(
batch_size: 50,
batch_timeout: 500,
max_batch_size: 123,
subscribe_to: []
)
assert state.batch == []
assert state.batch_length == 0
assert state.batch_size == 50
assert state.batch_timeout == 500
assert state.max_batch_size == 123
assert is_reference(state.timer)
assert opts[:subscribe_to] == []
# Cancel the timer to avoid stray :process_batch messages later.
Process.cancel_timer(state.timer)
end
test "applies default batch sizing when not provided" do
assert {:consumer, state, _opts} = PacketConsumer.init(subscribe_to: [])
assert state.batch_size == 100
assert state.batch_timeout == 1000
assert state.max_batch_size == 1000
Process.cancel_timer(state.timer)
end
end
describe "handle_info(:process_batch, state)" do
test "empty batch just restarts the timer" do
{:consumer, state, _} = PacketConsumer.init(subscribe_to: [])
Process.cancel_timer(state.timer)
state = %{state | timer: nil}
assert {:noreply, [], new_state} = PacketConsumer.handle_info(:process_batch, state)
assert new_state.batch == []
assert new_state.batch_length == 0
assert is_reference(new_state.timer)
Process.cancel_timer(new_state.timer)
end
test "non-empty batch processes and then resets timer" do
{:consumer, state, _} = PacketConsumer.init(subscribe_to: [])
Process.cancel_timer(state.timer)
# A packet with minimal required fields. process_batch will try to
# insert — that may fail, but handle_info should still return :noreply.
packet = %{
sender: "UNIT-1",
base_callsign: "UNIT",
ssid: "1",
raw_packet: "UNIT-1>APRS:>test",
received_at: DateTime.utc_now()
}
state = %{state | batch: [packet], batch_length: 1, timer: nil}
assert {:noreply, [], new_state} = PacketConsumer.handle_info(:process_batch, state)
assert new_state.batch == []
assert new_state.batch_length == 0
assert is_reference(new_state.timer)
Process.cancel_timer(new_state.timer)
end
end
describe "object broadcast with correct identifier" do
test "broadcasts object packets using object_name instead of sender" do
# Subscribe to packets in test bounds

View file

@ -291,5 +291,123 @@ defmodule AprsmeWeb.MapLive.IndexTest do
send(view.pid, :cleanup_old_packets)
assert render(view) =~ "aprs-map"
end
test "responds to :reload_historical_packets", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
send(view.pid, :reload_historical_packets)
assert render(view) =~ "aprs-map"
end
test "responds to a postgres_packet message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
packet = %{
id: "123",
sender: "TEST-1",
base_callsign: "TEST",
ssid: "1",
lat: 35.0,
lon: -90.0,
symbol_table_id: "/",
symbol_code: ">",
comment: "test packet",
received_at: DateTime.utc_now(),
path: "WIDE1-1"
}
send(view.pid, {:postgres_packet, packet})
assert render(view) =~ "aprs-map"
end
test "responds to a spatial_packet message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
packet = %{
id: "789",
sender: "SPATIAL",
base_callsign: "SPATIAL",
ssid: "0",
lat: 41.0,
lon: -97.0,
symbol_table_id: "/",
symbol_code: "-",
comment: nil,
received_at: DateTime.utc_now(),
path: ""
}
send(view.pid, {:spatial_packet, packet})
assert render(view) =~ "aprs-map"
end
test "responds to a packet_batch message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
packets =
for i <- 1..3 do
%{
id: "batch-#{i}",
sender: "BATCH-#{i}",
base_callsign: "BATCH",
ssid: "#{i}",
lat: 40.0 + i * 0.1,
lon: -98.0 + i * 0.1,
symbol_table_id: "/",
symbol_code: ">",
comment: "batch #{i}",
received_at: DateTime.utc_now(),
path: ""
}
end
send(view.pid, {:packet_batch, packets})
assert render(view) =~ "aprs-map"
end
test "responds to a streaming_packet message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
packet = %{
id: "stream-1",
sender: "STREAM",
base_callsign: "STREAM",
ssid: "0",
lat: 39.0,
lon: -98.0,
symbol_table_id: "/",
symbol_code: ">",
comment: nil,
received_at: DateTime.utc_now(),
path: ""
}
send(view.pid, {:streaming_packet, packet})
assert render(view) =~ "aprs-map"
end
test "responds to a drain_connections message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
send(view.pid, {:drain_connections, 5})
assert render(view) =~ "aprs-map"
end
test "responds to load_rf_path_station_packets message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
send(view.pid, {:load_rf_path_station_packets, ["K1ABC", "W5XYZ"]})
assert render(view) =~ "aprs-map"
end
test "responds to show_error message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
send(view.pid, {:show_error, "something went wrong"})
assert render(view)
end
test "responds to historical_loading_timeout message", %{conn: conn} do
{:ok, view, _html} = live(conn, "/", on_error: :warn)
# Use a stale generation — should skip without side effects.
send(view.pid, {:historical_loading_timeout, -999})
assert render(view) =~ "aprs-map"
end
end
end