towerops/test/integration/snmp_integration_test.exs
2026-06-15 11:15:46 -05:00

138 lines
4.1 KiB
Elixir

defmodule Towerops.Integration.SnmpIntegrationTest do
@moduledoc """
Integration tests for SNMP functionality against real devices.
These tests are excluded from the main test suite by default.
To run them: mix test --only integration
Requirements:
- Network access to test devices
- SNMP-enabled devices (configure IP/community below)
"""
use ExUnit.Case, async: false
import Towerops.AccountsFixtures
alias Towerops.Snmp.Client
alias Towerops.Snmp.Poller
alias Towerops.Snmp.Profiles.Base
alias Towerops.Workers.DeviceMonitorWorker
@moduletag :real_device
setup do
# Skip these tests - they require real SNMP devices
# To run: mix test --include real_device
:ok
end
# Configure your test device here
@test_device_opts [
ip: "10.0.19.254",
community: "kdyyJrT0Mm",
version: "2c",
port: 161,
timeout: 5000
]
describe "SNMP Client against real device" do
test "can perform GET operation" do
case Client.get(@test_device_opts, "1.3.6.1.2.1.1.3.0") do
{:ok, uptime} ->
assert is_integer(uptime)
{:error, reason} ->
flunk("SNMP GET failed: #{inspect(reason)}")
end
end
test "can perform WALK operation" do
case Client.walk(@test_device_opts, "1.3.6.1.2.1.2.2.1.1") do
{:ok, results} ->
assert map_size(results) > 0
{:error, reason} ->
flunk("SNMP WALK failed: #{inspect(reason)}")
end
end
test "can test connection" do
assert {:ok, _message} = Client.test_connection(@test_device_opts)
end
end
describe "SNMP Poller against real device" do
test "can check device reachability" do
case Poller.check_device(@test_device_opts) do
{:ok, response_time} ->
assert is_float(response_time)
assert response_time > 0
{:error, reason} ->
flunk("Poller check failed: #{inspect(reason)}")
end
end
end
describe "Discovery against real device" do
@tag :full_discovery
test "can discover device using Base profile" do
# Discover system info using Base profile
{:ok, system_info} = Base.discover_system_info(@test_device_opts)
assert byte_size(system_info.sys_descr) > 0
assert byte_size(system_info.sys_name) > 0
# Discover interfaces
{:ok, interfaces} = Base.discover_interfaces(@test_device_opts)
refute Enum.empty?(interfaces)
# Discover sensors (may be empty if device doesn't support ENTITY-SENSOR-MIB)
{:ok, _sensors} = Base.discover_sensors(@test_device_opts)
# Identify device
device_info = Base.identify_device(system_info)
assert byte_size(device_info.manufacturer) > 0
assert byte_size(device_info.model) > 0
end
end
describe "Device Monitor with SNMP" do
test "creates SNMP-specific alert messages when device goes down" do
# This test makes real SNMP calls to an unreachable IP to verify timeout handling
user = user_fixture()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
{:ok, site} =
Towerops.Sites.create_site(%{
name: "Test Site",
organization_id: organization.id
})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "SNMP Router",
ip_address: "192.0.2.1",
site_id: site.id,
organization_id: organization.id,
snmp_enabled: true,
snmp_version: "2c",
snmp_community: "public",
snmp_port: 161,
monitoring_enabled: true
})
# Set to up first so status change will trigger
{:ok, device} = Towerops.Devices.update_device_status(device, :up)
# Trigger check - will timeout trying to reach 192.0.2.1
DeviceMonitorWorker.perform(%Oban.Job{args: %{"device_id" => device.id}})
alerts = Towerops.Alerts.list_devices_alerts(device.id)
refute Enum.empty?(alerts)
alert = hd(alerts)
assert alert.alert_type == :device_down
assert String.contains?(alert.message, "SNMP")
end
end
end