towerops/test/snmpkit/snmp_mgr/format_test.exs
2026-06-15 11:15:46 -05:00

263 lines
9 KiB
Elixir

defmodule SnmpKit.SnmpMgr.FormatTest do
use ExUnit.Case, async: true
alias SnmpKit.SnmpMgr.Format
doctest Format
describe "pretty_print/1 - new functionality" do
test "formats 3-tuple results with type-aware formatting" do
# Test timeticks formatting (delegates to SnmpKit.SnmpLib.Types)
result = {"1.3.6.1.2.1.1.3.0", :timeticks, 12_345_678}
{oid, type, formatted} = Format.pretty_print(result)
assert oid == "1.3.6.1.2.1.1.3.0"
assert type == :timeticks
assert String.contains?(formatted, "day")
end
test "formats large counter types as speed" do
# Counter32 values > 1,000,000 are formatted as speed
result = {"1.3.6.1.2.1.2.2.1.10.1", :counter32, 42_000_000}
{_oid, _type, formatted} = Format.pretty_print(result)
assert formatted == "42.0 Mbps"
end
test "formats small counter types as integers" do
# Counter32 values <= 1,000,000 are formatted as plain integers
result = {"1.3.6.1.2.1.2.2.1.10.1", :counter32, 500_000}
{_oid, _type, formatted} = Format.pretty_print(result)
assert formatted == "500000"
end
test "formats large gauge types as bytes" do
# Gauge32 values > 1,000,000 are formatted as bytes
result = {"1.3.6.1.2.1.2.2.1.5.1", :gauge32, 100_000_000}
{_oid, _type, formatted} = Format.pretty_print(result)
assert formatted == "95.4 MB"
end
test "formats small gauge types as integers" do
# Gauge32 values <= 1,000,000 are formatted as plain integers
result = {"1.3.6.1.2.1.2.2.1.5.1", :gauge32, 500_000}
{_oid, _type, formatted} = Format.pretty_print(result)
assert formatted == "500000"
end
test "formats object identifiers" do
# Test with OID list
result = {"1.3.6.1.2.1.1.2.0", :object_identifier, [1, 3, 6, 1, 4, 1, 9]}
{_oid, _type, formatted} = Format.pretty_print(result)
assert formatted == "1.3.6.1.4.1.9"
# Test with OID string
result2 = {"1.3.6.1.2.1.1.2.0", :object_identifier, "1.3.6.1.4.1.9"}
{_oid, _type, formatted2} = Format.pretty_print(result2)
assert formatted2 == "1.3.6.1.4.1.9"
end
test "handles unknown types gracefully" do
result = {"1.3.6.1.2.1.1.1.0", :unknown_type, "test value"}
{_oid, _type, formatted} = Format.pretty_print(result)
# Unknown types with printable binary values are returned as-is
assert formatted == "test value"
end
end
describe "pretty_print_all/1 - new functionality" do
test "formats list of SNMP results" do
results = [
{"1.3.6.1.2.1.1.3.0", :timeticks, 12_345},
{"1.3.6.1.2.1.2.2.1.10.1", :counter32, 42_000_000}
]
formatted = Format.pretty_print_all(results)
assert length(formatted) == 2
assert Enum.all?(formatted, fn {_oid, _type, value} -> is_binary(value) end)
end
end
describe "bytes/1 - new functionality" do
test "formats byte counts into human-readable sizes" do
assert Format.bytes(512) == "512 bytes"
assert Format.bytes(1024) == "1.0 KB"
assert Format.bytes(1_048_576) == "1.0 MB"
assert Format.bytes(1_073_741_824) == "1.0 GB"
assert Format.bytes(1_099_511_627_776) == "1.0 TB"
end
test "handles edge cases" do
assert Format.bytes(0) == "0 bytes"
assert Format.bytes(1023) == "1023 bytes"
assert Format.bytes(1536) == "1.5 KB"
end
test "handles non-integer input gracefully" do
result = Format.bytes("not a number")
assert String.contains?(result, "not a number")
end
end
describe "speed/1 - new functionality" do
test "formats network speeds into human-readable rates" do
assert Format.speed(100) == "100 bps"
assert Format.speed(1000) == "1.0 Kbps"
assert Format.speed(1_000_000) == "1.0 Mbps"
assert Format.speed(1_000_000_000) == "1.0 Gbps"
assert Format.speed(1_000_000_000_000) == "1.0 Tbps"
end
test "handles common network speeds" do
assert Format.speed(10_000_000) == "10.0 Mbps"
assert Format.speed(100_000_000) == "100.0 Mbps"
assert Format.speed(1_000_000_000) == "1.0 Gbps"
end
test "handles non-integer input gracefully" do
result = Format.speed("fast")
assert String.contains?(result, "fast")
end
end
describe "interface_status/1 - new functionality" do
test "formats standard interface status codes" do
assert Format.interface_status(1) == "up"
assert Format.interface_status(2) == "down"
assert Format.interface_status(3) == "testing"
assert Format.interface_status(4) == "unknown"
assert Format.interface_status(5) == "dormant"
assert Format.interface_status(6) == "notPresent"
assert Format.interface_status(7) == "lowerLayerDown"
end
test "handles unknown status codes" do
assert Format.interface_status(99) == "unknown(99)"
assert Format.interface_status(0) == "unknown(0)"
end
end
describe "interface_type/1 - new functionality" do
test "formats common interface types" do
assert Format.interface_type(1) == "other"
assert Format.interface_type(6) == "ethernetCsmacd"
assert Format.interface_type(24) == "softwareLoopback"
assert Format.interface_type(131) == "tunnel"
assert Format.interface_type(161) == "ieee80211"
end
test "handles unknown interface types" do
assert Format.interface_type(999) == "type999"
assert Format.interface_type(42) == "type42"
end
end
describe "mac_address/1" do
test "formats binary MAC address" do
mac_binary = <<0x00, 0x1B, 0x21, 0x3C, 0x4D, 0x5E>>
result = Format.mac_address(mac_binary)
assert result == "00:1b:21:3c:4d:5e"
end
test "formats list MAC address" do
mac_list = [0, 27, 33, 60, 77, 94]
result = Format.mac_address(mac_list)
assert result == "00:1b:21:3c:4d:5e"
end
test "handles uppercase hex values" do
mac_list = [255, 255, 255, 255, 255, 255]
result = Format.mac_address(mac_list)
assert result == "ff:ff:ff:ff:ff:ff"
end
test "handles all zeros" do
mac_binary = <<0, 0, 0, 0, 0, 0>>
result = Format.mac_address(mac_binary)
assert result == "00:00:00:00:00:00"
end
test "handles invalid input gracefully" do
result = Format.mac_address("invalid")
assert byte_size(result) > 0
end
end
describe "format_by_type/2 with MAC addresses" do
test "formats explicit MAC address type correctly" do
mac_binary = <<0x00, 0x1B, 0x21, 0x3C, 0x4D, 0x5E>>
result = Format.format_by_type(:mac_address, mac_binary)
assert result == "00:1b:21:3c:4d:5e"
end
test "formats non-printable octet strings as spaced hex with hex: prefix" do
short_binary = <<0x00, 0x1B>>
result = Format.format_by_type(:octet_string, short_binary)
assert result == "hex:00 1B"
six_byte_binary = <<0x00, 0x1B, 0x21, 0x3C, 0x4D, 0x5E>>
result2 = Format.format_by_type(:octet_string, six_byte_binary)
assert result2 == "hex:00 1B 21 3C 4D 5E"
end
test "formats explicit MAC addresses correctly" do
mac_string = "00:1b:21:3c:4d:5e"
result = Format.mac_address(mac_string)
assert result == "00:1b:21:3c:4d:5e"
end
end
describe "format_by_type/2 object identifier formatting" do
test "formats object identifier list as dotted decimal string" do
result = Format.format_by_type(:object_identifier, [1, 3, 6, 1, 4, 1, 14_988, 1])
assert result == "1.3.6.1.4.1.14988.1"
end
test "passes through object identifier string unchanged" do
result = Format.format_by_type(:object_identifier, "1.3.6.1.4.1.14988.1")
assert result == "1.3.6.1.4.1.14988.1"
end
test "handles single element object identifier" do
result = Format.format_by_type(:object_identifier, [1])
assert result == "1"
end
test "handles empty object identifier" do
result = Format.format_by_type(:object_identifier, [])
assert result == ""
end
end
describe "format_by_type/2 explicit type handling" do
test "formats explicit MAC address type as MAC" do
# Explicit MAC address type
mac_bytes = <<0x00, 0x1B, 0x21, 0x3C, 0x4D, 0x5E>>
result = Format.format_by_type(:mac_address, mac_bytes)
assert result == "00:1b:21:3c:4d:5e"
end
test "keeps octet strings as strings regardless of length" do
# Interface names should remain as strings
assert Format.format_by_type(:octet_string, "ether1") == "ether1"
assert Format.format_by_type(:octet_string, "ether2") == "ether2"
assert Format.format_by_type(:octet_string, "wifi1 ") == "wifi1 "
assert Format.format_by_type(:octet_string, "bridge") == "bridge"
assert Format.format_by_type(:octet_string, "wlan01") == "wlan01"
end
test "formats binary octet strings as spaced hex when non-printable" do
# Even 6-byte binary data should render as hex when not printable UTF-8
binary_data = <<0x00, 0x1B, 0x21, 0x3C, 0x4D, 0x5E>>
result = Format.format_by_type(:octet_string, binary_data)
assert result == "hex:00 1B 21 3C 4D 5E"
end
end
end