Files
FabledSteward/tests/plugins/snmp/test_readings.py
T
bvandeusenandClaude Opus 5.5 f035a3b14a fix(snmp): a UPS on mains reads "On battery: No, on mains", not "0s" (#5214)
UPS-MIB upsSecondsOnBattery is zero whenever the UPS is on mains power, so
"On battery for 0s" read as a timer that had just started. The reading gets
its own unit, battery_seconds: zero says "No, on mains", anything else
"for <span>". The metric key stays on_battery_for, so stored history keeps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:16:24 -04:00

70 lines
2.8 KiB
Python

"""What an SNMP device is asked for and how each answer reads (milestone 491)."""
import pytest
from plugins.snmp.readings import (device_readings, format_value, interface_readings, parse_custom,
parse_interfaces, stored_unit)
def test_interface_numbers_read_as_a_list():
assert parse_interfaces("1, 2 5-7,2") == [1, 2, 5, 6, 7]
assert parse_interfaces("") == []
for bad in ("eth0", "7-3", "1-100"):
with pytest.raises(ValueError):
parse_interfaces(bad)
def test_interfaces_read_64_bit_counters_except_on_v1():
v2 = {r.key: r for r in interface_readings([3], "2c")}
v1 = {r.key: r for r in interface_readings([3], "1")}
assert set(v2) == {"if3_status", "if3_in", "if3_out"}
assert v2["if3_in"].oid == "1.3.6.1.2.1.31.1.1.1.6.3" and v2["if3_in"].counter
assert v1["if3_in"].oid == "1.3.6.1.2.1.2.2.1.10.3"
assert stored_unit(v2["if3_out"]) == "bits_per_second" and not v2["if3_status"].counter
def test_a_custom_line_is_an_oid_a_name_and_a_unit():
got = parse_custom("# a comment\n.1.3.6.1.4.1.9.1.0 fan_speed\n1.3.6.1.4.1.9.2.0 inlet_temp celsius\n")
assert [(r.oid, r.key, r.name, r.unit) for r in got] == [
("1.3.6.1.4.1.9.1.0", "fan_speed", "Fan speed", "number"),
("1.3.6.1.4.1.9.2.0", "inlet_temp", "Inlet temp", "celsius")]
@pytest.mark.parametrize("line, says", [
("1.3.6.1", "OID name"),
("sysUpTime uptime", "is not an OID"),
("1.3.6.1.2 Bad-Name", "must start with a letter"),
("1.3.6.1.2 temp furlongs", "is not a unit"),
])
def test_a_custom_line_that_does_not_read_says_which_and_why(line, says):
with pytest.raises(ValueError, match="Line 1") as exc:
parse_custom(line)
assert says in str(exc.value)
def test_presets_come_in_order_and_names_may_not_repeat():
keys = [r.key for r in device_readings(["ups", "system", "interfaces"], [1], "", "2c")]
assert keys[:4] == ["uptime", "if1_status", "if1_in", "if1_out"] and "battery_charge" in keys
with pytest.raises(ValueError, match="uptime"):
device_readings(["system"], [], "1.3.6.1.2.1.1.3.0 uptime", "2c")
@pytest.mark.parametrize("unit, value, text", [
("centiseconds", 105_120_000, "12d 4h"),
("percent", 99.6, "100%"),
("volts", 121.0, "121 V"),
("decivolts", 1203, "120.3 V"),
("minutes", 45, "45m"),
("battery_seconds", 0, "No, on mains"),
("battery_seconds", 300, "for 5m"),
("kilobytes", 2048, "2.0 MiB"),
("bits_per_second", 12_345_678, "12.3 Mbit/s"),
("bits_per_second", 950, "950 bit/s"),
("if_status", 2, "down"),
("ups_battery", 3, "low"),
("if_status", 99, "code 99"),
("number", 41.25, "41.25"),
("number", None, "—"),
])
def test_a_value_reads_in_its_unit(unit, value, text):
assert format_value(unit, value) == text