353 lines
11 KiB
Elixir
353 lines
11 KiB
Elixir
defmodule SnmpKit.SnmpLib.ErrorTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias SnmpKit.SnmpLib.Error
|
|
|
|
doctest Error
|
|
|
|
describe "Error.no_error/0" do
|
|
test "returns correct error code" do
|
|
assert Error.no_error() == 0
|
|
end
|
|
end
|
|
|
|
describe "Error.too_big/0" do
|
|
test "returns correct error code" do
|
|
assert Error.too_big() == 1
|
|
end
|
|
end
|
|
|
|
describe "Error.no_such_name/0" do
|
|
test "returns correct error code" do
|
|
assert Error.no_such_name() == 2
|
|
end
|
|
end
|
|
|
|
describe "Error.bad_value/0" do
|
|
test "returns correct error code" do
|
|
assert Error.bad_value() == 3
|
|
end
|
|
end
|
|
|
|
describe "Error.read_only/0" do
|
|
test "returns correct error code" do
|
|
assert Error.read_only() == 4
|
|
end
|
|
end
|
|
|
|
describe "Error.gen_err/0" do
|
|
test "returns correct error code" do
|
|
assert Error.gen_err() == 5
|
|
end
|
|
end
|
|
|
|
describe "Error.error_name/1" do
|
|
test "returns correct names for numeric codes" do
|
|
assert Error.error_name(0) == "no_error"
|
|
assert Error.error_name(1) == "too_big"
|
|
assert Error.error_name(2) == "no_such_name"
|
|
assert Error.error_name(3) == "bad_value"
|
|
assert Error.error_name(4) == "read_only"
|
|
assert Error.error_name(5) == "gen_err"
|
|
end
|
|
|
|
test "returns correct names for atom codes" do
|
|
assert Error.error_name(:no_error) == "no_error"
|
|
assert Error.error_name(:too_big) == "too_big"
|
|
assert Error.error_name(:no_such_name) == "no_such_name"
|
|
assert Error.error_name(:bad_value) == "bad_value"
|
|
assert Error.error_name(:read_only) == "read_only"
|
|
assert Error.error_name(:gen_err) == "gen_err"
|
|
end
|
|
|
|
test "returns correct names for SNMPv2c codes" do
|
|
assert Error.error_name(6) == "no_access"
|
|
assert Error.error_name(7) == "wrong_type"
|
|
assert Error.error_name(8) == "wrong_length"
|
|
assert Error.error_name(18) == "inconsistent_name"
|
|
end
|
|
|
|
test "returns unknown_error for invalid codes" do
|
|
assert Error.error_name(999) == "unknown_error"
|
|
assert Error.error_name(-1) == "unknown_error"
|
|
assert Error.error_name(:invalid) == "unknown_error"
|
|
end
|
|
end
|
|
|
|
describe "Error.error_atom/1" do
|
|
test "converts numeric codes to atoms" do
|
|
assert Error.error_atom(0) == :no_error
|
|
assert Error.error_atom(2) == :no_such_name
|
|
assert Error.error_atom(5) == :gen_err
|
|
end
|
|
|
|
test "returns atom as-is" do
|
|
assert Error.error_atom(:too_big) == :too_big
|
|
assert Error.error_atom(:bad_value) == :bad_value
|
|
end
|
|
|
|
test "converts unknown codes to unknown_error atom" do
|
|
assert Error.error_atom(999) == :unknown_error
|
|
end
|
|
end
|
|
|
|
describe "Error.error_code/1" do
|
|
test "converts atoms to numeric codes" do
|
|
assert Error.error_code(:no_error) == 0
|
|
assert Error.error_code(:too_big) == 1
|
|
assert Error.error_code(:no_such_name) == 2
|
|
assert Error.error_code(:bad_value) == 3
|
|
assert Error.error_code(:read_only) == 4
|
|
assert Error.error_code(:gen_err) == 5
|
|
end
|
|
|
|
test "converts strings to numeric codes" do
|
|
assert Error.error_code("no_error") == 0
|
|
assert Error.error_code("too_big") == 1
|
|
assert Error.error_code("no_such_name") == 2
|
|
end
|
|
|
|
test "converts SNMPv2c atoms to codes" do
|
|
assert Error.error_code(:no_access) == 6
|
|
assert Error.error_code(:wrong_type) == 7
|
|
assert Error.error_code(:inconsistent_name) == 18
|
|
end
|
|
|
|
test "returns gen_err for unknown values" do
|
|
assert Error.error_code(:unknown) == 5
|
|
assert Error.error_code("invalid") == 5
|
|
end
|
|
end
|
|
|
|
describe "Error.format_error/3" do
|
|
test "formats basic error without varbinds" do
|
|
result = Error.format_error(2, 1, [])
|
|
assert result == "SNMP Error: no_such_name (2) at index 1"
|
|
end
|
|
|
|
test "formats error with atom status" do
|
|
result = Error.format_error(:bad_value, 2, [])
|
|
assert result == "SNMP Error: bad_value (3) at index 2"
|
|
end
|
|
|
|
test "formats error with varbind information" do
|
|
varbinds = [
|
|
{[1, 3, 6, 1, 2, 1, 1, 1, 0], "test"},
|
|
{[1, 3, 6, 1, 2, 1, 1, 2, 0], "value"}
|
|
]
|
|
|
|
result = Error.format_error(:no_such_name, 1, varbinds)
|
|
assert result == "SNMP Error: no_such_name (2) at index 1 - OID: 1.3.6.1.2.1.1.1.0"
|
|
|
|
result2 = Error.format_error(:bad_value, 2, varbinds)
|
|
assert result2 == "SNMP Error: bad_value (3) at index 2 - OID: 1.3.6.1.2.1.1.2.0"
|
|
end
|
|
|
|
test "handles invalid error index gracefully" do
|
|
varbinds = [{[1, 3, 6, 1, 2, 1, 1, 1, 0], "test"}]
|
|
|
|
result = Error.format_error(:no_such_name, 5, varbinds)
|
|
assert result == "SNMP Error: no_such_name (2) at index 5"
|
|
end
|
|
|
|
test "handles zero error index" do
|
|
varbinds = [{[1, 3, 6, 1, 2, 1, 1, 1, 0], "test"}]
|
|
|
|
result = Error.format_error(:gen_err, 0, varbinds)
|
|
assert result == "SNMP Error: gen_err (5) at index 0"
|
|
end
|
|
end
|
|
|
|
describe "Error.retriable_error?/1" do
|
|
test "identifies retriable errors" do
|
|
assert Error.retriable_error?(:too_big) == true
|
|
assert Error.retriable_error?(:gen_err) == true
|
|
assert Error.retriable_error?(:resource_unavailable) == true
|
|
assert Error.retriable_error?(1) == true
|
|
assert Error.retriable_error?(5) == true
|
|
end
|
|
|
|
test "identifies non-retriable errors" do
|
|
assert Error.retriable_error?(:no_error) == false
|
|
assert Error.retriable_error?(:no_such_name) == false
|
|
assert Error.retriable_error?(:bad_value) == false
|
|
assert Error.retriable_error?(:read_only) == false
|
|
assert Error.retriable_error?(:no_access) == false
|
|
assert Error.retriable_error?(:authorization_error) == false
|
|
assert Error.retriable_error?(0) == false
|
|
assert Error.retriable_error?(2) == false
|
|
end
|
|
|
|
test "handles unknown errors as non-retriable" do
|
|
assert Error.retriable_error?(999) == false
|
|
assert Error.retriable_error?(:unknown) == false
|
|
end
|
|
end
|
|
|
|
describe "Error.create_error_response/3" do
|
|
test "creates error response from request PDU" do
|
|
request_pdu = %{
|
|
type: :get_request,
|
|
request_id: 12_345,
|
|
varbinds: [
|
|
{[1, 3, 6, 1, 2, 1, 1, 1, 0], :null},
|
|
{[1, 3, 6, 1, 2, 1, 1, 2, 0], :null}
|
|
]
|
|
}
|
|
|
|
{:ok, error_response} = Error.create_error_response(request_pdu, :no_such_name, 1)
|
|
|
|
assert error_response.type == :get_response
|
|
assert error_response.request_id == 12_345
|
|
assert error_response.error_status == 2
|
|
assert error_response.error_index == 1
|
|
assert error_response.varbinds == request_pdu.varbinds
|
|
end
|
|
|
|
test "creates error response with numeric error code" do
|
|
request_pdu = %{
|
|
type: :set_request,
|
|
request_id: 54_321,
|
|
varbinds: []
|
|
}
|
|
|
|
{:ok, error_response} = Error.create_error_response(request_pdu, 3, 2)
|
|
|
|
assert error_response.error_status == 3
|
|
assert error_response.error_index == 2
|
|
assert error_response.request_id == 54_321
|
|
end
|
|
|
|
test "handles missing request_id gracefully" do
|
|
request_pdu = %{
|
|
type: :get_request,
|
|
varbinds: []
|
|
}
|
|
|
|
{:ok, error_response} = Error.create_error_response(request_pdu, :gen_err, 1)
|
|
|
|
assert error_response.request_id == 0
|
|
end
|
|
|
|
test "handles missing varbinds gracefully" do
|
|
request_pdu = %{
|
|
type: :get_request,
|
|
request_id: 999
|
|
}
|
|
|
|
{:ok, error_response} = Error.create_error_response(request_pdu, :gen_err, 1)
|
|
|
|
assert error_response.varbinds == []
|
|
end
|
|
|
|
test "returns error for invalid request PDU" do
|
|
invalid_pdu = "not a map"
|
|
|
|
{:error, reason} = Error.create_error_response(invalid_pdu, :gen_err, 1)
|
|
assert reason == :invalid_request_pdu
|
|
end
|
|
end
|
|
|
|
describe "Error.valid_error_status?/1" do
|
|
test "validates numeric error codes" do
|
|
assert Error.valid_error_status?(0) == true
|
|
assert Error.valid_error_status?(1) == true
|
|
assert Error.valid_error_status?(18) == true
|
|
assert Error.valid_error_status?(999) == false
|
|
assert Error.valid_error_status?(-1) == false
|
|
end
|
|
|
|
test "validates atom error codes" do
|
|
assert Error.valid_error_status?(:no_error) == true
|
|
assert Error.valid_error_status?(:too_big) == true
|
|
assert Error.valid_error_status?(:inconsistent_name) == true
|
|
assert Error.valid_error_status?(:invalid_atom) == false
|
|
end
|
|
|
|
test "rejects invalid types" do
|
|
assert Error.valid_error_status?("string") == false
|
|
assert Error.valid_error_status?([1, 2, 3]) == false
|
|
assert Error.valid_error_status?(nil) == false
|
|
end
|
|
end
|
|
|
|
describe "Error.all_error_codes/0" do
|
|
test "returns all standard error codes" do
|
|
codes = Error.all_error_codes()
|
|
|
|
assert 0 in codes
|
|
assert 5 in codes
|
|
assert 18 in codes
|
|
assert length(codes) == 19
|
|
end
|
|
end
|
|
|
|
describe "Error.all_error_atoms/0" do
|
|
test "returns all standard error atoms" do
|
|
atoms = Error.all_error_atoms()
|
|
|
|
assert :no_error in atoms
|
|
assert :gen_err in atoms
|
|
assert :inconsistent_name in atoms
|
|
assert length(atoms) == 19
|
|
end
|
|
end
|
|
|
|
describe "Error.error_severity/1" do
|
|
test "categorizes no_error as info" do
|
|
assert Error.error_severity(:no_error) == :info
|
|
assert Error.error_severity(0) == :info
|
|
end
|
|
|
|
test "categorizes retriable errors as warning" do
|
|
assert Error.error_severity(:too_big) == :warning
|
|
assert Error.error_severity(:gen_err) == :warning
|
|
assert Error.error_severity(:resource_unavailable) == :warning
|
|
assert Error.error_severity(1) == :warning
|
|
end
|
|
|
|
test "categorizes non-retriable errors as error" do
|
|
assert Error.error_severity(:no_such_name) == :error
|
|
assert Error.error_severity(:bad_value) == :error
|
|
assert Error.error_severity(:authorization_error) == :error
|
|
assert Error.error_severity(2) == :error
|
|
end
|
|
|
|
test "categorizes unknown errors as error" do
|
|
assert Error.error_severity(999) == :error
|
|
assert Error.error_severity(:unknown) == :error
|
|
end
|
|
end
|
|
|
|
describe "integration with other modules" do
|
|
test "error codes work with PDU module concepts" do
|
|
# Test that error responses have correct structure for PDU encoding
|
|
request_pdu = %{
|
|
type: :get_request,
|
|
request_id: 123,
|
|
varbinds: [{[1, 3, 6, 1, 2, 1, 1, 1, 0], :null}]
|
|
}
|
|
|
|
{:ok, error_response} = Error.create_error_response(request_pdu, :no_such_name, 1)
|
|
|
|
# Verify structure matches what PDU module expects
|
|
assert Map.has_key?(error_response, :type)
|
|
assert Map.has_key?(error_response, :request_id)
|
|
assert Map.has_key?(error_response, :error_status)
|
|
assert Map.has_key?(error_response, :error_index)
|
|
assert Map.has_key?(error_response, :varbinds)
|
|
end
|
|
|
|
test "error formatting works with OID module concepts" do
|
|
# Test that OID lists are properly formatted in error messages
|
|
varbinds = [
|
|
{[1, 3, 6, 1, 2, 1, 1, 1, 0], "sysDescr"},
|
|
{[1, 3, 6, 1, 2, 1, 1, 3, 0], "sysUpTime"}
|
|
]
|
|
|
|
result = Error.format_error(:no_such_name, 2, varbinds)
|
|
|
|
assert String.contains?(result, "1.3.6.1.2.1.1.3.0")
|
|
end
|
|
end
|
|
end
|