From 8f1752e59c40cdba757aa78d16ff24e686ab4f91 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 22 Jan 2026 08:59:50 -0600 Subject: [PATCH] feat: add more vendor modules and fix sensor discovery New vendor modules for WISP equipment: - Ruckus: ZoneDirector, SmartZone, Unleashed controllers - DragonWave: Horizon Compact/Duo/Quantum microwave - AirFiber: Ubiquiti AF 5/24/60 series (split from Airos) - Racom: RAy and RAy3 microwave radios - Exalt: ExtendAir microwave radios - SIAE: ALFO 80HD microwave radios Also fixes: - sensor_value -> last_value consistency in YAML sensor discovery - Test warnings (assert defs != [] -> assert [_ | _] = defs) Total: 17 vendor modules, 162 tests passing --- lib/towerops/snmp/profiles/dynamic.ex | 4 +- .../snmp/profiles/vendors/airfiber.ex | 97 ++++++++++++++++ lib/towerops/snmp/profiles/vendors/airos.ex | 5 +- .../snmp/profiles/vendors/dragonwave.ex | 77 +++++++++++++ lib/towerops/snmp/profiles/vendors/exalt.ex | 79 +++++++++++++ lib/towerops/snmp/profiles/vendors/racom.ex | 83 +++++++++++++ .../snmp/profiles/vendors/registry.ex | 26 ++++- lib/towerops/snmp/profiles/vendors/ruckus.ex | 79 +++++++++++++ lib/towerops/snmp/profiles/vendors/siae.ex | 71 ++++++++++++ .../snmp/profiles/vendors/airfiber_test.exs | 94 +++++++++++++++ .../snmp/profiles/vendors/cnpilot_test.exs | 2 +- .../snmp/profiles/vendors/dragonwave_test.exs | 109 ++++++++++++++++++ .../snmp/profiles/vendors/exalt_test.exs | 102 ++++++++++++++++ .../snmp/profiles/vendors/ligoos_test.exs | 2 +- .../snmp/profiles/vendors/mimosa_test.exs | 2 +- .../snmp/profiles/vendors/pmp_test.exs | 2 +- .../snmp/profiles/vendors/racom_test.exs | 105 +++++++++++++++++ .../snmp/profiles/vendors/radwin_test.exs | 2 +- .../snmp/profiles/vendors/registry_test.exs | 42 +++++++ .../snmp/profiles/vendors/ruckus_test.exs | 100 ++++++++++++++++ .../snmp/profiles/vendors/saf_test.exs | 2 +- .../snmp/profiles/vendors/siae_test.exs | 102 ++++++++++++++++ .../snmp/profiles/vendors/siklu_test.exs | 2 +- .../snmp/profiles/vendors/unifi_test.exs | 2 +- 24 files changed, 1176 insertions(+), 15 deletions(-) create mode 100644 lib/towerops/snmp/profiles/vendors/airfiber.ex create mode 100644 lib/towerops/snmp/profiles/vendors/dragonwave.ex create mode 100644 lib/towerops/snmp/profiles/vendors/exalt.ex create mode 100644 lib/towerops/snmp/profiles/vendors/racom.ex create mode 100644 lib/towerops/snmp/profiles/vendors/ruckus.ex create mode 100644 lib/towerops/snmp/profiles/vendors/siae.ex create mode 100644 test/towerops/snmp/profiles/vendors/airfiber_test.exs create mode 100644 test/towerops/snmp/profiles/vendors/dragonwave_test.exs create mode 100644 test/towerops/snmp/profiles/vendors/exalt_test.exs create mode 100644 test/towerops/snmp/profiles/vendors/racom_test.exs create mode 100644 test/towerops/snmp/profiles/vendors/ruckus_test.exs create mode 100644 test/towerops/snmp/profiles/vendors/siae_test.exs diff --git a/lib/towerops/snmp/profiles/dynamic.ex b/lib/towerops/snmp/profiles/dynamic.ex index 993ec37b..51f33565 100644 --- a/lib/towerops/snmp/profiles/dynamic.ex +++ b/lib/towerops/snmp/profiles/dynamic.ex @@ -233,7 +233,7 @@ defmodule Towerops.Snmp.Profiles.Dynamic do sensor_descr: build_sensor_descr(sensor_def, idx), sensor_unit: sensor_def[:sensor_unit] || "", sensor_divisor: sensor_def[:sensor_divisor] || 1, - sensor_value: value + last_value: value / 1 } end @@ -291,7 +291,7 @@ defmodule Towerops.Snmp.Profiles.Dynamic do sensor_descr: build_sensor_descr(sensor_def, idx), sensor_unit: "", sensor_divisor: 1, - sensor_value: value, + last_value: value / 1, state_descr: state_descr } end diff --git a/lib/towerops/snmp/profiles/vendors/airfiber.ex b/lib/towerops/snmp/profiles/vendors/airfiber.ex new file mode 100644 index 00000000..47ba7133 --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/airfiber.ex @@ -0,0 +1,97 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Airfiber do + @moduledoc """ + Ubiquiti AirFiber device-specific SNMP handling. + + Supports AirFiber 5, 5X, 5XHD, 24, 24HD, and 60 series. + + Supported devices: + - AirFiber 5/5X/5XHD + - AirFiber 24/24HD + - AirFiber 60/60 LR + - AirFiber 60 XG + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Profiles.Vendors.Vendor + + @impl true + def profile_names do + ["airos-af", "airos-af-ltu", "airos-af60"] + end + + @impl true + def detect_hardware(_client_opts) do + # Hardware detection handled by YAML profile + nil + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + # UBNT-AirFIBER-MIB OIDs + # Enterprise OID: 1.3.6.1.4.1.41112.1.3 + [ + # TX Frequency (MHz) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.6.1", + sensor_type: "frequency", + sensor_descr: "Tx Frequency", + sensor_unit: "MHz", + sensor_divisor: 1 + }, + # RX Frequency (MHz) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.7.1", + sensor_type: "frequency", + sensor_descr: "Rx Frequency", + sensor_unit: "MHz", + sensor_divisor: 1 + }, + # TX Power (dBm) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.8.1", + sensor_type: "power", + sensor_descr: "Tx Power", + sensor_unit: "dBm", + sensor_divisor: 1 + }, + # RX Power 0 (chain 0) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.13.1", + sensor_type: "rssi", + sensor_descr: "Rx Power Chain 0", + sensor_unit: "dBm", + sensor_divisor: 1 + }, + # RX Power 1 (chain 1) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.14.1", + sensor_type: "rssi", + sensor_descr: "Rx Power Chain 1", + sensor_unit: "dBm", + sensor_divisor: 1 + }, + # TX Capacity (Mbps) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.20.1", + sensor_type: "rate", + sensor_descr: "Tx Capacity", + sensor_unit: "Mbps", + sensor_divisor: 1 + }, + # RX Capacity (Mbps) + %{ + oid: "1.3.6.1.4.1.41112.1.3.2.1.21.1", + sensor_type: "rate", + sensor_descr: "Rx Capacity", + sensor_unit: "Mbps", + sensor_divisor: 1 + } + ] + end +end diff --git a/lib/towerops/snmp/profiles/vendors/airos.ex b/lib/towerops/snmp/profiles/vendors/airos.ex index 55ea9cb8..5087b04c 100644 --- a/lib/towerops/snmp/profiles/vendors/airos.ex +++ b/lib/towerops/snmp/profiles/vendors/airos.ex @@ -6,9 +6,6 @@ defmodule Towerops.Snmp.Profiles.Vendors.Airos do Supported devices: - AirMax (LiteBeam, PowerBeam, NanoStation, etc.) - - AirFiber - - AirFiber 60GHz - - AirFiber LTU """ @behaviour Towerops.Snmp.Profiles.Vendors.Vendor @@ -20,7 +17,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.Airos do @product_name_oid "1.2.840.10036.1.1.1.9.5" @impl true - def profile_names, do: ["airos", "airos-af", "airos-af60", "airos-af-ltu"] + def profile_names, do: ["airos"] @impl true def detect_hardware(client_opts) do diff --git a/lib/towerops/snmp/profiles/vendors/dragonwave.ex b/lib/towerops/snmp/profiles/vendors/dragonwave.ex new file mode 100644 index 00000000..ce6b25ec --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/dragonwave.ex @@ -0,0 +1,77 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Dragonwave do + @moduledoc """ + DragonWave Horizon device-specific SNMP handling. + + Supports Horizon Compact, CompactPlus, Duo, and Quantum series. + + Supported devices: + - Horizon Compact + - Horizon Compact Plus + - Horizon Duo + - Horizon Quantum + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Client + alias Towerops.Snmp.Profiles.Vendors.Vendor + + # Horizon ODU MIB - hardware info + @hardware_oid "1.3.6.1.4.1.7262.2.2.1.1.8.0" + + @impl true + def profile_names do + ["horizon-compact", "horizon-compactplus", "horizon-duo", "horizon-quantum"] + end + + @impl true + def detect_hardware(client_opts) do + case Client.get(client_opts, @hardware_oid) do + {:ok, hardware} when is_binary(hardware) -> hardware + _ -> nil + end + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + [ + # Radio Temperature (divide by 10) + %{ + oid: "1.3.6.1.4.1.7262.2.2.5.1.3.6.0", + sensor_type: "temperature", + sensor_descr: "Radio Temperature", + sensor_unit: "C", + sensor_divisor: 10 + }, + # Modem SNR (divide by 10) + %{ + oid: "1.3.6.1.4.1.7262.2.2.5.1.2.3.0", + sensor_type: "snr", + sensor_descr: "Modem SNR", + sensor_unit: "dB", + sensor_divisor: 10 + }, + # RSL (Receive Signal Level) + %{ + oid: "1.3.6.1.4.1.7262.2.2.5.1.2.2.0", + sensor_type: "rssi", + sensor_descr: "RSL", + sensor_unit: "dBm", + sensor_divisor: 10 + }, + # Transmit Power + %{ + oid: "1.3.6.1.4.1.7262.2.2.5.1.3.2.0", + sensor_type: "power", + sensor_descr: "Tx Power", + sensor_unit: "dBm", + sensor_divisor: 10 + } + ] + end +end diff --git a/lib/towerops/snmp/profiles/vendors/exalt.ex b/lib/towerops/snmp/profiles/vendors/exalt.ex new file mode 100644 index 00000000..7ff06a68 --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/exalt.ex @@ -0,0 +1,79 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Exalt do + @moduledoc """ + Exalt ExtendAir device-specific SNMP handling. + + Supports ExtendAir licensed and unlicensed microwave radios. + + Supported devices: + - ExtendAir series + - ExploreAir series + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Profiles.Vendors.Vendor + + @impl true + def profile_names do + ["extendair"] + end + + @impl true + def detect_hardware(_client_opts) do + # Hardware detection handled by YAML profile + nil + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + # EXALT-MIB OIDs + # Enterprise OID: 1.3.6.1.4.1.25651 + [ + # Tx Frequency (kHz, divide by 1000 for MHz) + %{ + oid: "1.3.6.1.4.1.25651.1.2.3.1.1.7.0", + sensor_type: "frequency", + sensor_descr: "Tx Frequency", + sensor_unit: "MHz", + sensor_divisor: 1000 + }, + # Rx Frequency (kHz, divide by 1000 for MHz) + %{ + oid: "1.3.6.1.4.1.25651.1.2.3.1.1.8.0", + sensor_type: "frequency", + sensor_descr: "Rx Frequency", + sensor_unit: "MHz", + sensor_divisor: 1000 + }, + # Tx Power (dBm * 10) + %{ + oid: "1.3.6.1.4.1.25651.1.2.3.1.1.9.0", + sensor_type: "power", + sensor_descr: "Tx Power", + sensor_unit: "dBm", + sensor_divisor: 10 + }, + # RSL (Receive Signal Level, dBm * 10) + %{ + oid: "1.3.6.1.4.1.25651.1.2.3.1.2.1.0", + sensor_type: "rssi", + sensor_descr: "RSL", + sensor_unit: "dBm", + sensor_divisor: 10 + }, + # SNR (dB * 10) + %{ + oid: "1.3.6.1.4.1.25651.1.2.3.1.2.3.0", + sensor_type: "snr", + sensor_descr: "SNR", + sensor_unit: "dB", + sensor_divisor: 10 + } + ] + end +end diff --git a/lib/towerops/snmp/profiles/vendors/racom.ex b/lib/towerops/snmp/profiles/vendors/racom.ex new file mode 100644 index 00000000..16e60fd4 --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/racom.ex @@ -0,0 +1,83 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Racom do + @moduledoc """ + Racom RAy device-specific SNMP handling. + + Supports RAy and RAy3 microwave radios. + + Supported devices: + - RAy series + - RAy3 series + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Client + alias Towerops.Snmp.Profiles.Vendors.Vendor + + # RAy MIB - product name + @product_name_oid "1.3.6.1.4.1.33555.1.1.1.3.0" + + @impl true + def profile_names do + ["ray", "ray3"] + end + + @impl true + def detect_hardware(client_opts) do + case Client.get(client_opts, @product_name_oid) do + {:ok, name} when is_binary(name) -> name + _ -> nil + end + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + [ + # Temperature (divide by 100) + %{ + oid: "1.3.6.1.4.1.33555.1.1.4.2.0", + sensor_type: "temperature", + sensor_descr: "Radio Temperature", + sensor_unit: "C", + sensor_divisor: 100 + }, + # Voltage (divide by 10) + %{ + oid: "1.3.6.1.4.1.33555.1.1.4.3.0", + sensor_type: "voltage", + sensor_descr: "Voltage", + sensor_unit: "V", + sensor_divisor: 10 + }, + # BER (Bit Error Rate) + %{ + oid: "1.3.6.1.4.1.33555.1.3.2.11.0", + sensor_type: "ber", + sensor_descr: "BER", + sensor_unit: "", + sensor_divisor: 1 + }, + # Tx Modulation Index + %{ + oid: "1.3.6.1.4.1.33555.1.2.1.7.0", + sensor_type: "state", + sensor_descr: "Tx Modulation", + sensor_unit: "", + sensor_divisor: 1 + }, + # Rx Modulation Index + %{ + oid: "1.3.6.1.4.1.33555.1.2.1.8.0", + sensor_type: "state", + sensor_descr: "Rx Modulation", + sensor_unit: "", + sensor_divisor: 1 + } + ] + end +end diff --git a/lib/towerops/snmp/profiles/vendors/registry.ex b/lib/towerops/snmp/profiles/vendors/registry.ex index c51c6852..db5b0bf4 100644 --- a/lib/towerops/snmp/profiles/vendors/registry.ex +++ b/lib/towerops/snmp/profiles/vendors/registry.ex @@ -7,19 +7,43 @@ defmodule Towerops.Snmp.Profiles.Vendors.Registry do """ alias Towerops.Snmp.Client + alias Towerops.Snmp.Profiles.Vendors.Airfiber alias Towerops.Snmp.Profiles.Vendors.Airos alias Towerops.Snmp.Profiles.Vendors.Cnpilot + alias Towerops.Snmp.Profiles.Vendors.Dragonwave alias Towerops.Snmp.Profiles.Vendors.Epmp + alias Towerops.Snmp.Profiles.Vendors.Exalt alias Towerops.Snmp.Profiles.Vendors.Ligoos alias Towerops.Snmp.Profiles.Vendors.Mimosa alias Towerops.Snmp.Profiles.Vendors.Pmp + alias Towerops.Snmp.Profiles.Vendors.Racom alias Towerops.Snmp.Profiles.Vendors.Radwin alias Towerops.Snmp.Profiles.Vendors.Routeros + alias Towerops.Snmp.Profiles.Vendors.Ruckus alias Towerops.Snmp.Profiles.Vendors.Saf + alias Towerops.Snmp.Profiles.Vendors.Siae alias Towerops.Snmp.Profiles.Vendors.Siklu alias Towerops.Snmp.Profiles.Vendors.Unifi - @vendors [Epmp, Airos, Routeros, Pmp, Mimosa, Siklu, Radwin, Unifi, Ligoos, Cnpilot, Saf] + @vendors [ + Epmp, + Airos, + Airfiber, + Routeros, + Pmp, + Mimosa, + Siklu, + Radwin, + Unifi, + Ligoos, + Cnpilot, + Saf, + Ruckus, + Dragonwave, + Racom, + Exalt, + Siae + ] @doc """ Get the vendor module for a given profile name. diff --git a/lib/towerops/snmp/profiles/vendors/ruckus.ex b/lib/towerops/snmp/profiles/vendors/ruckus.ex new file mode 100644 index 00000000..cae54525 --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/ruckus.ex @@ -0,0 +1,79 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Ruckus do + @moduledoc """ + Ruckus Wireless device-specific SNMP handling. + + Supports ZoneDirector (ZD), SmartZone (SZ), and Unleashed controllers. + + Supported devices: + - ZoneDirector 1000/1100/1200/3000/5000 + - SmartZone 100/144/300 + - Virtual SmartZone + - Unleashed APs + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Client + alias Towerops.Snmp.Profiles.Vendors.Vendor + + # ZoneDirector System MIB OIDs + # 1.3.6.1.4.1.25053.1.2.1.1.1 = ruckusZDSystemObjects + @zd_system_model "1.3.6.1.4.1.25053.1.2.1.1.1.1.9.0" + + @impl true + def profile_names do + ["ruckuswireless", "ruckuswireless-sz", "ruckuswireless-unleashed", "ruckuswireless-hotzone"] + end + + @impl true + def detect_hardware(client_opts) do + case Client.get(client_opts, @zd_system_model) do + {:ok, model} when is_binary(model) -> model + _ -> nil + end + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + [ + # ZoneDirector System Stats + # Number of connected APs + %{ + oid: "1.3.6.1.4.1.25053.1.2.1.1.1.15.1.0", + sensor_type: "ap-count", + sensor_descr: "Connected APs", + sensor_unit: "", + sensor_divisor: 1 + }, + # Number of authorized clients + %{ + oid: "1.3.6.1.4.1.25053.1.2.1.1.1.15.2.0", + sensor_type: "clients", + sensor_descr: "Wireless Clients", + sensor_unit: "", + sensor_divisor: 1 + }, + # Number of registered APs + %{ + oid: "1.3.6.1.4.1.25053.1.2.1.1.1.15.15.0", + sensor_type: "ap-count", + sensor_descr: "Registered APs", + sensor_unit: "", + sensor_divisor: 1 + }, + # Number of rogue APs detected + %{ + oid: "1.3.6.1.4.1.25053.1.2.1.1.1.15.3.0", + sensor_type: "count", + sensor_descr: "Rogue APs", + sensor_unit: "", + sensor_divisor: 1 + } + ] + end +end diff --git a/lib/towerops/snmp/profiles/vendors/siae.ex b/lib/towerops/snmp/profiles/vendors/siae.ex new file mode 100644 index 00000000..9df38459 --- /dev/null +++ b/lib/towerops/snmp/profiles/vendors/siae.ex @@ -0,0 +1,71 @@ +defmodule Towerops.Snmp.Profiles.Vendors.Siae do + @moduledoc """ + SIAE Microelettronica device-specific SNMP handling. + + Supports ALFO and ALFOplus series microwave radios. + + Supported devices: + - ALFO 80HD series + - ALFOplus series + """ + + @behaviour Towerops.Snmp.Profiles.Vendors.Vendor + + alias Towerops.Snmp.Profiles.Vendors.Vendor + + @impl true + def profile_names do + ["alfo80hd"] + end + + @impl true + def detect_hardware(_client_opts) do + # Hardware detection handled by YAML profile + nil + end + + @impl true + def discover_wireless_sensors(client_opts) do + Vendor.fetch_sensors(wireless_oid_defs(), client_opts) + end + + @impl true + def wireless_oid_defs do + # SIAE ALFO MIB OIDs + # Enterprise OID: 1.3.6.1.4.1.3373 + [ + # Tx Power + %{ + oid: "1.3.6.1.4.1.3373.1103.80.1.1.11.1", + sensor_type: "power", + sensor_descr: "Tx Power", + sensor_unit: "dBm", + sensor_divisor: 10 + }, + # Rx Power (RSL) + %{ + oid: "1.3.6.1.4.1.3373.1103.80.1.1.12.1", + sensor_type: "rssi", + sensor_descr: "Rx Power", + sensor_unit: "dBm", + sensor_divisor: 10 + }, + # SNR + %{ + oid: "1.3.6.1.4.1.3373.1103.80.1.1.14.1", + sensor_type: "snr", + sensor_descr: "SNR", + sensor_unit: "dB", + sensor_divisor: 10 + }, + # Frequency + %{ + oid: "1.3.6.1.4.1.3373.1103.80.1.1.3.1", + sensor_type: "frequency", + sensor_descr: "Tx Frequency", + sensor_unit: "MHz", + sensor_divisor: 1000 + } + ] + end +end diff --git a/test/towerops/snmp/profiles/vendors/airfiber_test.exs b/test/towerops/snmp/profiles/vendors/airfiber_test.exs new file mode 100644 index 00000000..61e143f9 --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/airfiber_test.exs @@ -0,0 +1,94 @@ +defmodule Towerops.Snmp.Profiles.Vendors.AirfiberTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Airfiber + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns airfiber profile names" do + assert Airfiber.profile_names() == ["airos-af", "airos-af-ltu", "airos-af60"] + end + end + + describe "detect_hardware/1" do + test "returns nil (hardware detection handled by YAML)" do + assert Airfiber.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Airfiber.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes frequency sensors" do + defs = Airfiber.wireless_oid_defs() + freq_sensors = Enum.filter(defs, &(&1.sensor_type == "frequency")) + + assert length(freq_sensors) == 2 + assert Enum.all?(freq_sensors, &(&1.sensor_unit == "MHz")) + end + + test "includes RSSI sensors" do + defs = Airfiber.wireless_oid_defs() + rssi_sensors = Enum.filter(defs, &(&1.sensor_type == "rssi")) + + assert length(rssi_sensors) == 2 + end + + test "includes rate sensors" do + defs = Airfiber.wireless_oid_defs() + rate_sensors = Enum.filter(defs, &(&1.sensor_type == "rate")) + + assert length(rate_sensors) == 2 + assert Enum.all?(rate_sensors, &(&1.sensor_unit == "Mbps")) + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 7, fn _, oid, _ -> + cond do + String.contains?(oid, "41112.1.3.2.1.6.1") -> {:ok, 5800} + String.contains?(oid, "41112.1.3.2.1.7.1") -> {:ok, 5800} + String.contains?(oid, "41112.1.3.2.1.8.1") -> {:ok, 25} + String.contains?(oid, "41112.1.3.2.1.13.1") -> {:ok, -55} + String.contains?(oid, "41112.1.3.2.1.14.1") -> {:ok, -56} + String.contains?(oid, "41112.1.3.2.1.20.1") -> {:ok, 450} + String.contains?(oid, "41112.1.3.2.1.21.1") -> {:ok, 450} + true -> {:error, :no_such_object} + end + end) + + sensors = Airfiber.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 7 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 7, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Airfiber.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/cnpilot_test.exs b/test/towerops/snmp/profiles/vendors/cnpilot_test.exs index 9c2fff98..036be70a 100644 --- a/test/towerops/snmp/profiles/vendors/cnpilot_test.exs +++ b/test/towerops/snmp/profiles/vendors/cnpilot_test.exs @@ -33,7 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.CnpilotTest do defs = Cnpilot.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes clients sensor" do diff --git a/test/towerops/snmp/profiles/vendors/dragonwave_test.exs b/test/towerops/snmp/profiles/vendors/dragonwave_test.exs new file mode 100644 index 00000000..0d2209b4 --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/dragonwave_test.exs @@ -0,0 +1,109 @@ +defmodule Towerops.Snmp.Profiles.Vendors.DragonwaveTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Dragonwave + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns dragonwave profile names" do + assert Dragonwave.profile_names() == [ + "horizon-compact", + "horizon-compactplus", + "horizon-duo", + "horizon-quantum" + ] + end + end + + describe "detect_hardware/1" do + test "detects hardware from assembly number OID" do + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.7262.2.2.1.1.8.0", _ -> + {:ok, "Horizon Compact+"} + end) + + assert Dragonwave.detect_hardware(@client_opts) == "Horizon Compact+" + end + + test "returns nil when OID unavailable" do + expect(SnmpMock, :get, fn _, _, _ -> + {:error, :no_such_object} + end) + + assert Dragonwave.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Dragonwave.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes temperature sensor with divisor" do + defs = Dragonwave.wireless_oid_defs() + temp = Enum.find(defs, &(&1.sensor_type == "temperature")) + + assert temp + assert temp.sensor_divisor == 10 + end + + test "includes SNR sensor" do + defs = Dragonwave.wireless_oid_defs() + snr = Enum.find(defs, &(&1.sensor_type == "snr")) + + assert snr + assert snr.sensor_unit == "dB" + end + + test "includes RSSI sensor" do + defs = Dragonwave.wireless_oid_defs() + rssi = Enum.find(defs, &(&1.sensor_type == "rssi")) + + assert rssi + assert rssi.sensor_descr == "RSL" + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 4, fn _, oid, _ -> + cond do + String.contains?(oid, "7262.2.2.5.1.3.6.0") -> {:ok, 450} + String.contains?(oid, "7262.2.2.5.1.2.3.0") -> {:ok, 280} + String.contains?(oid, "7262.2.2.5.1.2.2.0") -> {:ok, -550} + String.contains?(oid, "7262.2.2.5.1.3.2.0") -> {:ok, 180} + true -> {:error, :no_such_object} + end + end) + + sensors = Dragonwave.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 4 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 4, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Dragonwave.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/exalt_test.exs b/test/towerops/snmp/profiles/vendors/exalt_test.exs new file mode 100644 index 00000000..29ed233f --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/exalt_test.exs @@ -0,0 +1,102 @@ +defmodule Towerops.Snmp.Profiles.Vendors.ExaltTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Exalt + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns exalt profile name" do + assert Exalt.profile_names() == ["extendair"] + end + end + + describe "detect_hardware/1" do + test "returns nil (hardware detection handled by YAML)" do + assert Exalt.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Exalt.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes frequency sensors with kHz divisor" do + defs = Exalt.wireless_oid_defs() + freq_sensors = Enum.filter(defs, &(&1.sensor_type == "frequency")) + + assert length(freq_sensors) == 2 + # Exalt returns frequency in kHz + assert Enum.all?(freq_sensors, &(&1.sensor_divisor == 1000)) + end + + test "includes power sensor" do + defs = Exalt.wireless_oid_defs() + power = Enum.find(defs, &(&1.sensor_type == "power")) + + assert power + assert power.sensor_descr == "Tx Power" + end + + test "includes RSSI sensor" do + defs = Exalt.wireless_oid_defs() + rssi = Enum.find(defs, &(&1.sensor_type == "rssi")) + + assert rssi + assert rssi.sensor_descr == "RSL" + end + + test "includes SNR sensor" do + defs = Exalt.wireless_oid_defs() + snr = Enum.find(defs, &(&1.sensor_type == "snr")) + + assert snr + assert snr.sensor_unit == "dB" + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 5, fn _, oid, _ -> + cond do + String.contains?(oid, "25651.1.2.3.1.1.7.0") -> {:ok, 71_000_000} + String.contains?(oid, "25651.1.2.3.1.1.8.0") -> {:ok, 81_000_000} + String.contains?(oid, "25651.1.2.3.1.1.9.0") -> {:ok, 200} + String.contains?(oid, "25651.1.2.3.1.2.1.0") -> {:ok, -550} + String.contains?(oid, "25651.1.2.3.1.2.3.0") -> {:ok, 280} + true -> {:error, :no_such_object} + end + end) + + sensors = Exalt.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 5 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 5, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Exalt.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/ligoos_test.exs b/test/towerops/snmp/profiles/vendors/ligoos_test.exs index 1eefe91b..951dfddb 100644 --- a/test/towerops/snmp/profiles/vendors/ligoos_test.exs +++ b/test/towerops/snmp/profiles/vendors/ligoos_test.exs @@ -33,7 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.LigoosTest do defs = Ligoos.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes frequency sensor" do diff --git a/test/towerops/snmp/profiles/vendors/mimosa_test.exs b/test/towerops/snmp/profiles/vendors/mimosa_test.exs index 6f96c94f..284e5036 100644 --- a/test/towerops/snmp/profiles/vendors/mimosa_test.exs +++ b/test/towerops/snmp/profiles/vendors/mimosa_test.exs @@ -33,7 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.MimosaTest do defs = Mimosa.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes error-ratio sensors" do diff --git a/test/towerops/snmp/profiles/vendors/pmp_test.exs b/test/towerops/snmp/profiles/vendors/pmp_test.exs index 367e93a9..bab3b2ff 100644 --- a/test/towerops/snmp/profiles/vendors/pmp_test.exs +++ b/test/towerops/snmp/profiles/vendors/pmp_test.exs @@ -109,7 +109,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.PmpTest do defs = Pmp.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs # Verify structure of first definition first = hd(defs) diff --git a/test/towerops/snmp/profiles/vendors/racom_test.exs b/test/towerops/snmp/profiles/vendors/racom_test.exs new file mode 100644 index 00000000..04aa86aa --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/racom_test.exs @@ -0,0 +1,105 @@ +defmodule Towerops.Snmp.Profiles.Vendors.RacomTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Racom + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns racom profile names" do + assert Racom.profile_names() == ["ray", "ray3"] + end + end + + describe "detect_hardware/1" do + test "detects hardware from product name OID" do + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.33555.1.1.1.3.0", _ -> + {:ok, "RAy3-17"} + end) + + assert Racom.detect_hardware(@client_opts) == "RAy3-17" + end + + test "returns nil when OID unavailable" do + expect(SnmpMock, :get, fn _, _, _ -> + {:error, :no_such_object} + end) + + assert Racom.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Racom.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes temperature sensor with high divisor" do + defs = Racom.wireless_oid_defs() + temp = Enum.find(defs, &(&1.sensor_type == "temperature")) + + assert temp + assert temp.sensor_divisor == 100 + end + + test "includes voltage sensor" do + defs = Racom.wireless_oid_defs() + voltage = Enum.find(defs, &(&1.sensor_type == "voltage")) + + assert voltage + assert voltage.sensor_unit == "V" + end + + test "includes BER sensor" do + defs = Racom.wireless_oid_defs() + ber = Enum.find(defs, &(&1.sensor_type == "ber")) + + assert ber + assert ber.sensor_descr == "BER" + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 5, fn _, oid, _ -> + cond do + String.contains?(oid, "33555.1.1.4.2.0") -> {:ok, 4500} + String.contains?(oid, "33555.1.1.4.3.0") -> {:ok, 480} + String.contains?(oid, "33555.1.3.2.11.0") -> {:ok, 0} + String.contains?(oid, "33555.1.2.1.7.0") -> {:ok, 4} + String.contains?(oid, "33555.1.2.1.8.0") -> {:ok, 4} + true -> {:error, :no_such_object} + end + end) + + sensors = Racom.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 5 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 5, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Racom.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/radwin_test.exs b/test/towerops/snmp/profiles/vendors/radwin_test.exs index eb42b8a7..aa267081 100644 --- a/test/towerops/snmp/profiles/vendors/radwin_test.exs +++ b/test/towerops/snmp/profiles/vendors/radwin_test.exs @@ -33,7 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.RadwinTest do defs = Radwin.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes distance sensor with km unit" do diff --git a/test/towerops/snmp/profiles/vendors/registry_test.exs b/test/towerops/snmp/profiles/vendors/registry_test.exs index ad008da8..18f1a5b2 100644 --- a/test/towerops/snmp/profiles/vendors/registry_test.exs +++ b/test/towerops/snmp/profiles/vendors/registry_test.exs @@ -3,16 +3,22 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do import Mox + alias Towerops.Snmp.Profiles.Vendors.Airfiber alias Towerops.Snmp.Profiles.Vendors.Airos alias Towerops.Snmp.Profiles.Vendors.Cnpilot + alias Towerops.Snmp.Profiles.Vendors.Dragonwave alias Towerops.Snmp.Profiles.Vendors.Epmp + alias Towerops.Snmp.Profiles.Vendors.Exalt alias Towerops.Snmp.Profiles.Vendors.Ligoos alias Towerops.Snmp.Profiles.Vendors.Mimosa alias Towerops.Snmp.Profiles.Vendors.Pmp + alias Towerops.Snmp.Profiles.Vendors.Racom alias Towerops.Snmp.Profiles.Vendors.Radwin alias Towerops.Snmp.Profiles.Vendors.Registry alias Towerops.Snmp.Profiles.Vendors.Routeros + alias Towerops.Snmp.Profiles.Vendors.Ruckus alias Towerops.Snmp.Profiles.Vendors.Saf + alias Towerops.Snmp.Profiles.Vendors.Siae alias Towerops.Snmp.Profiles.Vendors.Siklu alias Towerops.Snmp.Profiles.Vendors.Unifi alias Towerops.Snmp.SnmpMock @@ -34,6 +40,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do assert is_list(vendors) assert Epmp in vendors assert Airos in vendors + assert Airfiber in vendors assert Routeros in vendors assert Pmp in vendors assert Mimosa in vendors @@ -43,6 +50,11 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do assert Ligoos in vendors assert Cnpilot in vendors assert Saf in vendors + assert Ruckus in vendors + assert Dragonwave in vendors + assert Racom in vendors + assert Exalt in vendors + assert Siae in vendors end end @@ -54,6 +66,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do # Check for some known profile names assert "epmp" in names assert "airos" in names + assert "airos-af" in names assert "routeros" in names assert "pmp" in names assert "mimosa" in names @@ -64,6 +77,11 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do assert "deliberant" in names assert "cnpilot" in names assert "saf" in names + assert "ruckuswireless" in names + assert "horizon-compact" in names + assert "ray" in names + assert "extendair" in names + assert "alfo80hd" in names end end @@ -116,6 +134,30 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do assert Registry.get_vendor("saf") == Saf end + test "returns Ruckus for ruckuswireless profile" do + assert Registry.get_vendor("ruckuswireless") == Ruckus + end + + test "returns Dragonwave for horizon-compact profile" do + assert Registry.get_vendor("horizon-compact") == Dragonwave + end + + test "returns Airfiber for airos-af profile" do + assert Registry.get_vendor("airos-af") == Airfiber + end + + test "returns Racom for ray profile" do + assert Registry.get_vendor("ray") == Racom + end + + test "returns Exalt for extendair profile" do + assert Registry.get_vendor("extendair") == Exalt + end + + test "returns Siae for alfo80hd profile" do + assert Registry.get_vendor("alfo80hd") == Siae + end + test "returns nil for unknown profile" do assert Registry.get_vendor("unknown_vendor") == nil end diff --git a/test/towerops/snmp/profiles/vendors/ruckus_test.exs b/test/towerops/snmp/profiles/vendors/ruckus_test.exs new file mode 100644 index 00000000..52b49095 --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/ruckus_test.exs @@ -0,0 +1,100 @@ +defmodule Towerops.Snmp.Profiles.Vendors.RuckusTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Ruckus + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns ruckus profile names" do + assert Ruckus.profile_names() == [ + "ruckuswireless", + "ruckuswireless-sz", + "ruckuswireless-unleashed", + "ruckuswireless-hotzone" + ] + end + end + + describe "detect_hardware/1" do + test "detects hardware from system model OID" do + expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.25053.1.2.1.1.1.1.9.0", _ -> + {:ok, "ZD3000"} + end) + + assert Ruckus.detect_hardware(@client_opts) == "ZD3000" + end + + test "returns nil when OID unavailable" do + expect(SnmpMock, :get, fn _, _, _ -> + {:error, :no_such_object} + end) + + assert Ruckus.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Ruckus.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes AP count sensors" do + defs = Ruckus.wireless_oid_defs() + ap_sensors = Enum.filter(defs, &(&1.sensor_type == "ap-count")) + + assert length(ap_sensors) == 2 + end + + test "includes clients sensor" do + defs = Ruckus.wireless_oid_defs() + clients = Enum.find(defs, &(&1.sensor_type == "clients")) + + assert clients + assert clients.sensor_descr == "Wireless Clients" + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 4, fn _, oid, _ -> + cond do + String.contains?(oid, "25053.1.2.1.1.1.15.1.0") -> {:ok, 5} + String.contains?(oid, "25053.1.2.1.1.1.15.2.0") -> {:ok, 150} + String.contains?(oid, "25053.1.2.1.1.1.15.15.0") -> {:ok, 6} + String.contains?(oid, "25053.1.2.1.1.1.15.3.0") -> {:ok, 2} + true -> {:error, :no_such_object} + end + end) + + sensors = Ruckus.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 4 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 4, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Ruckus.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/saf_test.exs b/test/towerops/snmp/profiles/vendors/saf_test.exs index 60db751f..5e96f8e7 100644 --- a/test/towerops/snmp/profiles/vendors/saf_test.exs +++ b/test/towerops/snmp/profiles/vendors/saf_test.exs @@ -33,7 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.SafTest do defs = Saf.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes frequency sensors with correct divisor" do diff --git a/test/towerops/snmp/profiles/vendors/siae_test.exs b/test/towerops/snmp/profiles/vendors/siae_test.exs new file mode 100644 index 00000000..eaf9f186 --- /dev/null +++ b/test/towerops/snmp/profiles/vendors/siae_test.exs @@ -0,0 +1,102 @@ +defmodule Towerops.Snmp.Profiles.Vendors.SiaeTest do + use Towerops.DataCase, async: true + + import Mox + + alias Towerops.Snmp.Profiles.Vendors.Siae + alias Towerops.Snmp.SnmpMock + + setup :verify_on_exit! + + @client_opts [ + ip: "192.168.1.1", + community: "public", + version: "2c", + port: 161, + timeout: 5000 + ] + + describe "profile_names/0" do + test "returns siae profile name" do + assert Siae.profile_names() == ["alfo80hd"] + end + end + + describe "detect_hardware/1" do + test "returns nil (hardware detection handled by YAML)" do + assert Siae.detect_hardware(@client_opts) == nil + end + end + + describe "wireless_oid_defs/0" do + test "returns list of wireless sensor definitions" do + defs = Siae.wireless_oid_defs() + + assert is_list(defs) + assert [_ | _] = defs + end + + test "includes power sensor" do + defs = Siae.wireless_oid_defs() + power = Enum.find(defs, &(&1.sensor_type == "power")) + + assert power + assert power.sensor_descr == "Tx Power" + assert power.sensor_divisor == 10 + end + + test "includes RSSI sensor" do + defs = Siae.wireless_oid_defs() + rssi = Enum.find(defs, &(&1.sensor_type == "rssi")) + + assert rssi + assert rssi.sensor_descr == "Rx Power" + end + + test "includes SNR sensor" do + defs = Siae.wireless_oid_defs() + snr = Enum.find(defs, &(&1.sensor_type == "snr")) + + assert snr + assert snr.sensor_unit == "dB" + end + + test "includes frequency sensor" do + defs = Siae.wireless_oid_defs() + freq = Enum.find(defs, &(&1.sensor_type == "frequency")) + + assert freq + # SIAE frequency in kHz + assert freq.sensor_divisor == 1000 + end + end + + describe "discover_wireless_sensors/1" do + test "discovers sensors when SNMP responds" do + expect(SnmpMock, :get, 4, fn _, oid, _ -> + cond do + String.contains?(oid, "3373.1103.80.1.1.11.1") -> {:ok, 180} + String.contains?(oid, "3373.1103.80.1.1.12.1") -> {:ok, -450} + String.contains?(oid, "3373.1103.80.1.1.14.1") -> {:ok, 250} + String.contains?(oid, "3373.1103.80.1.1.3.1") -> {:ok, 71_000_000} + true -> {:error, :no_such_object} + end + end) + + sensors = Siae.discover_wireless_sensors(@client_opts) + + assert is_list(sensors) + assert length(sensors) == 4 + end + + test "returns empty list when no sensors respond" do + expect(SnmpMock, :get, 4, fn _, _, _ -> + {:error, :no_such_object} + end) + + sensors = Siae.discover_wireless_sensors(@client_opts) + + assert sensors == [] + end + end +end diff --git a/test/towerops/snmp/profiles/vendors/siklu_test.exs b/test/towerops/snmp/profiles/vendors/siklu_test.exs index 3e49dff9..e1a3147b 100644 --- a/test/towerops/snmp/profiles/vendors/siklu_test.exs +++ b/test/towerops/snmp/profiles/vendors/siklu_test.exs @@ -69,7 +69,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.SikluTest do defs = Siklu.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes frequency sensor" do diff --git a/test/towerops/snmp/profiles/vendors/unifi_test.exs b/test/towerops/snmp/profiles/vendors/unifi_test.exs index 6d499cca..82b69188 100644 --- a/test/towerops/snmp/profiles/vendors/unifi_test.exs +++ b/test/towerops/snmp/profiles/vendors/unifi_test.exs @@ -53,7 +53,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.UnifiTest do defs = Unifi.wireless_oid_defs() assert is_list(defs) - assert defs != [] + assert [_ | _] = defs end test "includes client count sensors for both radios" do