Add comprehensive Agent protobuf module tests

Added 37 tests covering all 12 protobuf modules:
- AgentConfig, Equipment, SnmpConfig
- Sensor, Sensor.MetadataEntry, Interface
- MetricBatch, Metric (with oneof field handling)
- SensorReading, InterfaceStat
- HeartbeatMetadata, HeartbeatResponse

Tests cover struct creation, default values, and encode/decode cycles.
All protobuf modules now at 100% coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2026-01-13 08:39:02 -06:00
parent 8291c6092a
commit 00ebe0c5fe
No known key found for this signature in database

View file

@ -0,0 +1,488 @@
defmodule Towerops.Proto.AgentPbTest do
use ExUnit.Case, async: true
alias Towerops.Agent.AgentConfig
alias Towerops.Agent.Equipment
alias Towerops.Agent.HeartbeatMetadata
alias Towerops.Agent.HeartbeatResponse
alias Towerops.Agent.Interface
alias Towerops.Agent.InterfaceStat
alias Towerops.Agent.Metric
alias Towerops.Agent.MetricBatch
alias Towerops.Agent.Sensor
alias Towerops.Agent.SensorReading
alias Towerops.Agent.SnmpConfig
describe "AgentConfig" do
test "creates struct with default values" do
config = %AgentConfig{}
assert config.version == ""
assert config.poll_interval_seconds == 0
assert config.equipment == []
end
test "creates struct with values" do
equipment = %Equipment{id: "eq1", name: "Router"}
config = %AgentConfig{
version: "1.0.0",
poll_interval_seconds: 60,
equipment: [equipment]
}
assert config.version == "1.0.0"
assert config.poll_interval_seconds == 60
assert length(config.equipment) == 1
assert hd(config.equipment).id == "eq1"
end
test "encodes and decodes" do
config = %AgentConfig{
version: "1.0.0",
poll_interval_seconds: 60
}
encoded = AgentConfig.encode(config)
assert is_binary(encoded)
decoded = AgentConfig.decode(encoded)
assert decoded.version == "1.0.0"
assert decoded.poll_interval_seconds == 60
end
end
describe "Equipment" do
test "creates struct with default values" do
equipment = %Equipment{}
assert equipment.id == ""
assert equipment.name == ""
assert equipment.ip_address == ""
assert equipment.snmp == nil
assert equipment.poll_interval_seconds == 0
assert equipment.sensors == []
assert equipment.interfaces == []
end
test "creates struct with SNMP config" do
snmp = %SnmpConfig{
enabled: true,
version: "2c",
community: "public",
port: 161
}
equipment = %Equipment{
id: "eq1",
name: "Router 1",
ip_address: "192.168.1.1",
snmp: snmp,
poll_interval_seconds: 60
}
assert equipment.id == "eq1"
assert equipment.name == "Router 1"
assert equipment.ip_address == "192.168.1.1"
assert equipment.snmp.enabled == true
assert equipment.poll_interval_seconds == 60
end
test "creates struct with sensors and interfaces" do
sensor = %Sensor{id: "s1", type: "temperature", oid: "1.3.6.1.2.1"}
interface = %Interface{id: "i1", if_index: 1, if_name: "eth0"}
equipment = %Equipment{
id: "eq1",
sensors: [sensor],
interfaces: [interface]
}
assert length(equipment.sensors) == 1
assert length(equipment.interfaces) == 1
assert hd(equipment.sensors).id == "s1"
assert hd(equipment.interfaces).id == "i1"
end
test "encodes and decodes" do
equipment = %Equipment{
id: "eq1",
name: "Router 1",
ip_address: "192.168.1.1"
}
encoded = Equipment.encode(equipment)
decoded = Equipment.decode(encoded)
assert decoded.id == "eq1"
assert decoded.name == "Router 1"
assert decoded.ip_address == "192.168.1.1"
end
end
describe "SnmpConfig" do
test "creates struct with default values" do
snmp = %SnmpConfig{}
assert snmp.enabled == false
assert snmp.version == ""
assert snmp.community == ""
assert snmp.port == 0
end
test "creates struct with values" do
snmp = %SnmpConfig{
enabled: true,
version: "2c",
community: "public",
port: 161
}
assert snmp.enabled == true
assert snmp.version == "2c"
assert snmp.community == "public"
assert snmp.port == 161
end
test "encodes and decodes" do
snmp = %SnmpConfig{
enabled: true,
version: "2c",
community: "public",
port: 161
}
encoded = SnmpConfig.encode(snmp)
decoded = SnmpConfig.decode(encoded)
assert decoded.enabled == true
assert decoded.version == "2c"
assert decoded.community == "public"
assert decoded.port == 161
end
end
describe "Sensor" do
test "creates struct with default values" do
sensor = %Sensor{}
assert sensor.id == ""
assert sensor.type == ""
assert sensor.oid == ""
assert sensor.divisor == 0.0
assert sensor.unit == ""
assert sensor.metadata == %{}
end
test "creates struct with values" do
sensor = %Sensor{
id: "s1",
type: "temperature",
oid: "1.3.6.1.2.1.99.1.1.1.4.1",
divisor: 10.0,
unit: "°C",
metadata: [%{key: "location", value: "CPU"}]
}
assert sensor.id == "s1"
assert sensor.type == "temperature"
assert sensor.oid == "1.3.6.1.2.1.99.1.1.1.4.1"
assert sensor.divisor == 10.0
assert sensor.unit == "°C"
assert length(sensor.metadata) == 1
end
test "encodes and decodes" do
sensor = %Sensor{
id: "s1",
type: "temperature",
oid: "1.3.6.1.2.1",
divisor: 10.0,
unit: "°C"
}
encoded = Sensor.encode(sensor)
decoded = Sensor.decode(encoded)
assert decoded.id == "s1"
assert decoded.type == "temperature"
assert decoded.divisor == 10.0
end
end
describe "Sensor.MetadataEntry" do
test "creates struct with default values" do
entry = %Sensor.MetadataEntry{}
assert entry.key == ""
assert entry.value == ""
end
test "creates struct with values" do
entry = %Sensor.MetadataEntry{key: "location", value: "CPU"}
assert entry.key == "location"
assert entry.value == "CPU"
end
end
describe "Interface" do
test "creates struct with default values" do
interface = %Interface{}
assert interface.id == ""
assert interface.if_index == 0
assert interface.if_name == ""
end
test "creates struct with values" do
interface = %Interface{
id: "i1",
if_index: 1,
if_name: "eth0"
}
assert interface.id == "i1"
assert interface.if_index == 1
assert interface.if_name == "eth0"
end
test "encodes and decodes" do
interface = %Interface{
id: "i1",
if_index: 1,
if_name: "eth0"
}
encoded = Interface.encode(interface)
decoded = Interface.decode(encoded)
assert decoded.id == "i1"
assert decoded.if_index == 1
assert decoded.if_name == "eth0"
end
end
describe "MetricBatch" do
test "creates struct with default values" do
batch = %MetricBatch{}
assert batch.metrics == []
end
test "creates struct with metrics" do
reading = %SensorReading{sensor_id: "s1", value: 45.5}
metric = %Metric{metric_type: {:sensor_reading, reading}}
batch = %MetricBatch{metrics: [metric]}
assert length(batch.metrics) == 1
assert {:sensor_reading, reading} = hd(batch.metrics).metric_type
assert reading.sensor_id == "s1"
end
test "encodes and decodes" do
reading = %SensorReading{sensor_id: "s1", value: 45.5}
metric = %Metric{metric_type: {:sensor_reading, reading}}
batch = %MetricBatch{metrics: [metric]}
encoded = MetricBatch.encode(batch)
decoded = MetricBatch.decode(encoded)
assert length(decoded.metrics) == 1
end
end
describe "Metric" do
test "creates struct with sensor_reading" do
reading = %SensorReading{
sensor_id: "s1",
value: 45.5,
status: "ok",
timestamp: 1_640_000_000
}
metric = %Metric{metric_type: {:sensor_reading, reading}}
assert {:sensor_reading, reading} = metric.metric_type
assert reading.sensor_id == "s1"
assert reading.value == 45.5
end
test "creates struct with interface_stat" do
stat = %InterfaceStat{
interface_id: "i1",
if_in_octets: 1000,
if_out_octets: 2000,
timestamp: 1_640_000_000
}
metric = %Metric{metric_type: {:interface_stat, stat}}
assert {:interface_stat, stat} = metric.metric_type
assert stat.interface_id == "i1"
end
test "encodes and decodes sensor_reading" do
reading = %SensorReading{sensor_id: "s1", value: 45.5}
metric = %Metric{metric_type: {:sensor_reading, reading}}
encoded = Metric.encode(metric)
decoded = Metric.decode(encoded)
assert {:sensor_reading, decoded_reading} = decoded.metric_type
assert decoded_reading.sensor_id == "s1"
end
test "encodes and decodes interface_stat" do
stat = %InterfaceStat{interface_id: "i1", if_in_octets: 1000}
metric = %Metric{metric_type: {:interface_stat, stat}}
encoded = Metric.encode(metric)
decoded = Metric.decode(encoded)
assert {:interface_stat, decoded_stat} = decoded.metric_type
assert decoded_stat.interface_id == "i1"
end
end
describe "SensorReading" do
test "creates struct with default values" do
reading = %SensorReading{}
assert reading.sensor_id == ""
assert reading.value == 0.0
assert reading.status == ""
assert reading.timestamp == 0
end
test "creates struct with values" do
reading = %SensorReading{
sensor_id: "s1",
value: 45.5,
status: "ok",
timestamp: 1_640_000_000
}
assert reading.sensor_id == "s1"
assert reading.value == 45.5
assert reading.status == "ok"
assert reading.timestamp == 1_640_000_000
end
test "encodes and decodes" do
reading = %SensorReading{
sensor_id: "s1",
value: 45.5,
status: "ok",
timestamp: 1_640_000_000
}
encoded = SensorReading.encode(reading)
decoded = SensorReading.decode(encoded)
assert decoded.sensor_id == "s1"
assert decoded.value == 45.5
assert decoded.status == "ok"
assert decoded.timestamp == 1_640_000_000
end
end
describe "InterfaceStat" do
test "creates struct with default values" do
stat = %InterfaceStat{}
assert stat.interface_id == ""
assert stat.if_in_octets == 0
assert stat.if_out_octets == 0
assert stat.if_in_errors == 0
assert stat.if_out_errors == 0
assert stat.if_in_discards == 0
assert stat.if_out_discards == 0
assert stat.timestamp == 0
end
test "creates struct with values" do
stat = %InterfaceStat{
interface_id: "i1",
if_in_octets: 1000,
if_out_octets: 2000,
if_in_errors: 1,
if_out_errors: 2,
if_in_discards: 3,
if_out_discards: 4,
timestamp: 1_640_000_000
}
assert stat.interface_id == "i1"
assert stat.if_in_octets == 1000
assert stat.if_out_octets == 2000
assert stat.if_in_errors == 1
assert stat.if_out_errors == 2
assert stat.if_in_discards == 3
assert stat.if_out_discards == 4
assert stat.timestamp == 1_640_000_000
end
test "encodes and decodes" do
stat = %InterfaceStat{
interface_id: "i1",
if_in_octets: 1000,
if_out_octets: 2000,
timestamp: 1_640_000_000
}
encoded = InterfaceStat.encode(stat)
decoded = InterfaceStat.decode(encoded)
assert decoded.interface_id == "i1"
assert decoded.if_in_octets == 1000
assert decoded.if_out_octets == 2000
assert decoded.timestamp == 1_640_000_000
end
end
describe "HeartbeatMetadata" do
test "creates struct with default values" do
metadata = %HeartbeatMetadata{}
assert metadata.version == ""
assert metadata.hostname == ""
assert metadata.uptime_seconds == 0
end
test "creates struct with values" do
metadata = %HeartbeatMetadata{
version: "1.0.0",
hostname: "agent-1",
uptime_seconds: 3600
}
assert metadata.version == "1.0.0"
assert metadata.hostname == "agent-1"
assert metadata.uptime_seconds == 3600
end
test "encodes and decodes" do
metadata = %HeartbeatMetadata{
version: "1.0.0",
hostname: "agent-1",
uptime_seconds: 3600
}
encoded = HeartbeatMetadata.encode(metadata)
decoded = HeartbeatMetadata.decode(encoded)
assert decoded.version == "1.0.0"
assert decoded.hostname == "agent-1"
assert decoded.uptime_seconds == 3600
end
end
describe "HeartbeatResponse" do
test "creates struct with default values" do
response = %HeartbeatResponse{}
assert response.status == ""
end
test "creates struct with values" do
response = %HeartbeatResponse{status: "ok"}
assert response.status == "ok"
end
test "encodes and decodes" do
response = %HeartbeatResponse{status: "ok"}
encoded = HeartbeatResponse.encode(response)
decoded = HeartbeatResponse.decode(encoded)
assert decoded.status == "ok"
end
end
end