Add coverage tests for MixUnused.Analyzer and HistoricalLoader edge cases
This commit is contained in:
parent
aa809976ab
commit
b2a1d8e7e9
2 changed files with 151 additions and 0 deletions
|
|
@ -444,6 +444,109 @@ defmodule AprsmeWeb.MapLive.HistoricalLoaderTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "low zoom heat map path with string-keyed packet ids" do
|
||||
test "string-keyed :id packet uses get_packet_key string-key clause" do
|
||||
now = DateTime.utc_now()
|
||||
|
||||
Mox.stub(Aprsme.PacketsMock, :get_recent_packets, fn _opts ->
|
||||
[
|
||||
%{
|
||||
"id" => "str-keyed-1",
|
||||
"sender" => "STR-1",
|
||||
"callsign" => "STR-1",
|
||||
"received_at" => now,
|
||||
"lat" => 33.0,
|
||||
"lon" => -96.0,
|
||||
has_position: true,
|
||||
symbol_table_id: "/",
|
||||
symbol_code: ">",
|
||||
path: ""
|
||||
}
|
||||
]
|
||||
end)
|
||||
|
||||
socket =
|
||||
build_socket(%{
|
||||
map_bounds: %{north: 34.0, south: 32.0, east: -95.0, west: -97.0},
|
||||
map_zoom: 5,
|
||||
historical_loading: true,
|
||||
loading_generation: 1,
|
||||
total_batches: 3
|
||||
})
|
||||
|
||||
result = HistoricalLoader.load_historical_batch(socket, 0, nil)
|
||||
# The string-keyed id was placed into historical_packets via the
|
||||
# get_packet_key/1 string-key clause.
|
||||
assert is_map(result.assigns.historical_packets)
|
||||
end
|
||||
end
|
||||
|
||||
describe "very zoomed out (zoom < 5) get_loading_params_for_zoom fallback" do
|
||||
test "zoom 2 uses the catch-all params {50, 5}" do
|
||||
Mox.stub(Aprsme.PacketsMock, :get_recent_packets, fn _opts -> [] end)
|
||||
|
||||
socket =
|
||||
build_socket(%{
|
||||
map_bounds: %{north: 34.0, south: 32.0, east: -95.0, west: -97.0},
|
||||
map_zoom: 2,
|
||||
loading_generation: 0
|
||||
})
|
||||
|
||||
result = HistoricalLoader.start_progressive_historical_loading(socket)
|
||||
# Catch-all clause produces 5 batches.
|
||||
assert result.assigns.total_batches == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe "apply_memory_limit pruning path" do
|
||||
test "exceeds @max_historical_packets and triggers prune_oldest_packets" do
|
||||
now = DateTime.utc_now()
|
||||
# Pre-populate historical_packets with > 5000 entries (the cap).
|
||||
historical_packets =
|
||||
for i <- 1..5_001, into: %{} do
|
||||
{to_string(i),
|
||||
%{
|
||||
id: "old-#{i}",
|
||||
received_at: DateTime.add(now, -i, :second),
|
||||
lat: 33.0,
|
||||
lon: -96.0
|
||||
}}
|
||||
end
|
||||
|
||||
Mox.stub(Aprsme.PacketsMock, :get_recent_packets, fn _opts ->
|
||||
[
|
||||
%{
|
||||
id: "newcomer",
|
||||
sender: "NEW-1",
|
||||
base_callsign: "NEW",
|
||||
ssid: "1",
|
||||
lat: 33.5,
|
||||
lon: -96.5,
|
||||
has_position: true,
|
||||
symbol_table_id: "/",
|
||||
symbol_code: ">",
|
||||
received_at: now,
|
||||
path: ""
|
||||
}
|
||||
]
|
||||
end)
|
||||
|
||||
socket =
|
||||
build_socket(%{
|
||||
map_bounds: %{north: 34.0, south: 32.0, east: -95.0, west: -97.0},
|
||||
map_zoom: 5,
|
||||
historical_loading: true,
|
||||
historical_packets: historical_packets,
|
||||
loading_generation: 1,
|
||||
total_batches: 3
|
||||
})
|
||||
|
||||
result = HistoricalLoader.load_historical_batch(socket, 0, nil)
|
||||
# After pruning, the historical_packets size should be <= 5000.
|
||||
assert map_size(result.assigns.historical_packets) <= 5_000
|
||||
end
|
||||
end
|
||||
|
||||
describe "schedules next batch when not final" do
|
||||
test "saturated batch with more rows triggers maybe_schedule_next_batch" do
|
||||
now = DateTime.utc_now()
|
||||
|
|
|
|||
|
|
@ -103,5 +103,53 @@ defmodule MixUnused.AnalyzerTest do
|
|||
result = Analyzer.analyze(app: :no_such_app_for_real)
|
||||
assert result == []
|
||||
end
|
||||
|
||||
test "honors :compile_path option pointing to an empty directory" do
|
||||
tmp = Path.join(System.tmp_dir!(), "mu_empty_#{System.unique_integer([:positive])}")
|
||||
File.mkdir_p!(tmp)
|
||||
|
||||
try do
|
||||
result = Analyzer.analyze(compile_path: tmp)
|
||||
assert result == []
|
||||
after
|
||||
File.rm_rf(tmp)
|
||||
end
|
||||
end
|
||||
|
||||
test "honors :compile_path option pointing to a non-existent directory" do
|
||||
result = Analyzer.analyze(compile_path: "/nonexistent/path/for/test/#{System.unique_integer([:positive])}")
|
||||
assert result == []
|
||||
end
|
||||
|
||||
test "exclude with both module atoms and MFA tuples filters both kinds" do
|
||||
[first, second | _] = Analyzer.analyze()
|
||||
|
||||
excluded =
|
||||
Analyzer.analyze(exclude: [first.module, {second.module, second.name, second.arity}])
|
||||
|
||||
refute Enum.any?(excluded, &(&1.module == first.module))
|
||||
|
||||
refute Enum.any?(
|
||||
excluded,
|
||||
&(&1.module == second.module and &1.name == second.name and &1.arity == second.arity)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "format/1 with grouped multiple-modules and missing line metadata" do
|
||||
test "formats a mix of present and missing line numbers" do
|
||||
entries = [
|
||||
%{module: A, name: :one, arity: 1, file: "lib/a.ex", line: 5},
|
||||
%{module: A, name: :two, arity: 0, file: "lib/a.ex", line: nil},
|
||||
%{module: B, name: :three, arity: 2, file: nil, line: nil}
|
||||
]
|
||||
|
||||
out = Analyzer.format(entries)
|
||||
assert out =~ "A"
|
||||
assert out =~ "B"
|
||||
assert out =~ "lib/a.ex:5"
|
||||
assert out =~ "(lib/a.ex)"
|
||||
assert out =~ "(?)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue