aprs.me/test/aprsme/encoding_test.exs
Graham McIntire 7b488e9fd7
Fix code review findings batch 2: dead code, encoding, correctness
- Delete dead modules: Archiver, PacketPipelineSetup, SystemMonitor
- Encoding: fast-path for clean ASCII, fix latin1 C1 control chars (128-159)
- SpatialPubSub: fix date line grid cell wrapping
- QueryBuilder: use indexed has_weather column instead of 10-way OR
- PacketProcessor/HistoricalLoader: wire up heat map via DisplayManager
- MapLive: add PacketBatcher crash recovery with Process.monitor
- MapLive: fix time display re-render by touching assign
- DeviceCache: remove unreachable outer try/rescue
- Remove dead stubs: RateLimiterWrapper count/reset, DeviceIdentification enqueue_refresh_job
- Simplify Application.pubsub_config/0
- Add tests for SpatialPubSub, PacketBatcher, encoding, weather_only
2026-02-20 07:29:27 -06:00

86 lines
2.8 KiB
Elixir

defmodule Aprsme.EncodingTest do
use ExUnit.Case
alias Aprsme.Encoding
describe "sanitize_string/1 fast-path for clean strings" do
test "returns clean ASCII string unchanged" do
input = "VALID1>APRS,WIDE1-1:Test packet"
assert Encoding.sanitize_string(input) == input
end
test "returns clean ASCII string with allowed whitespace unchanged" do
input = "Hello\tWorld\nNew line\r\nCRLF"
result = Encoding.sanitize_string(input)
assert result == input
end
test "still cleans strings with control characters" do
# String with null byte (control character that should be removed)
input = "Hello\x00World"
result = Encoding.sanitize_string(input)
assert result == "HelloWorld"
end
test "still cleans strings with DEL character" do
input = "Hello\x7FWorld"
result = Encoding.sanitize_string(input)
assert result == "HelloWorld"
end
test "handles empty string" do
assert Encoding.sanitize_string("") == ""
end
test "handles non-binary input" do
assert Encoding.sanitize_string(nil) == ""
assert Encoding.sanitize_string(123) == ""
end
test "handles valid UTF-8 multi-byte characters" do
input = "Café résumé"
result = Encoding.sanitize_string(input)
assert String.valid?(result)
assert String.contains?(result, "Caf")
end
test "handles latin1 encoded binary" do
# Latin1 bytes for accented characters (>= 160, valid Latin1 printable)
invalid_binary = <<85, 78, 73, 211, 78, 32, 80, 65, 78, 65, 77, 69, 209, 65>>
result = Encoding.sanitize_string(invalid_binary)
assert String.valid?(result)
# 211 = Ó, 209 = Ñ — both above 159, so they convert to real characters
assert result == "UNIÓN PANAMEÑA"
end
end
describe "sanitize_string/1 C1 control range (128-159)" do
test "latin1 bytes 128-159 become replacement characters instead of being silently deleted" do
input = <<72, 101, 108, 108, 111, 130>>
result = Encoding.sanitize_string(input)
assert String.valid?(result)
assert String.contains?(result, "\uFFFD")
end
test "latin1 byte 128 becomes replacement character" do
input = <<65, 128, 66>>
result = Encoding.sanitize_string(input)
assert String.valid?(result)
assert result == "A\uFFFDB"
end
test "latin1 byte 159 becomes replacement character" do
input = <<65, 159, 66>>
result = Encoding.sanitize_string(input)
assert String.valid?(result)
assert result == "A\uFFFDB"
end
test "latin1 bytes above 159 still convert to proper characters" do
input = <<67, 97, 102, 233>>
result = Encoding.sanitize_string(input)
assert String.valid?(result)
assert result == "Café"
end
end
end