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:
parent
8291c6092a
commit
00ebe0c5fe
1 changed files with 488 additions and 0 deletions
488
test/towerops/proto/agent_pb_test.exs
Normal file
488
test/towerops/proto/agent_pb_test.exs
Normal 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
|
||||
Loading…
Add table
Reference in a new issue