Add unit tests for diagnostic snapshot key generation functions

32 test cases covering makeNodeSnapshotKey and makeGuestSnapshotKey
utility functions used for diagnostic memory snapshot storage. Tests
cover simple inputs, edge cases (empty strings, negative VMIDs),
special characters, and key uniqueness verification. Also includes
struct field tests for NodeMemoryRaw and VMMemoryRaw.

First test file for diagnostic_snapshots.go. Coverage 36.7% → 36.8%.
This commit is contained in:
rcourtman 2025-11-30 22:34:09 +00:00
parent c1fdb77b2c
commit fe4db29941

View file

@ -0,0 +1,332 @@
package monitoring
import (
"testing"
)
func TestMakeNodeSnapshotKey(t *testing.T) {
tests := []struct {
name string
instance string
node string
expected string
}{
{
name: "simple instance and node",
instance: "pve1",
node: "node1",
expected: "pve1|node1",
},
{
name: "instance with port",
instance: "pve.example.com:8006",
node: "pve-node",
expected: "pve.example.com:8006|pve-node",
},
{
name: "IP address instance",
instance: "192.168.1.100",
node: "server01",
expected: "192.168.1.100|server01",
},
{
name: "empty instance",
instance: "",
node: "node1",
expected: "|node1",
},
{
name: "empty node",
instance: "pve1",
node: "",
expected: "pve1|",
},
{
name: "both empty",
instance: "",
node: "",
expected: "|",
},
{
name: "special characters in node name",
instance: "pve1",
node: "node-with-dashes_and_underscores",
expected: "pve1|node-with-dashes_and_underscores",
},
{
name: "FQDN instance",
instance: "proxmox.datacenter.example.com",
node: "pve-cluster-node-01",
expected: "proxmox.datacenter.example.com|pve-cluster-node-01",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := makeNodeSnapshotKey(tc.instance, tc.node)
if got != tc.expected {
t.Errorf("makeNodeSnapshotKey(%q, %q) = %q, want %q",
tc.instance, tc.node, got, tc.expected)
}
})
}
}
func TestMakeGuestSnapshotKey(t *testing.T) {
tests := []struct {
name string
instance string
guestType string
node string
vmid int
expected string
}{
{
name: "VM guest",
instance: "pve1",
guestType: "qemu",
node: "node1",
vmid: 100,
expected: "pve1|qemu|node1|100",
},
{
name: "LXC container",
instance: "pve1",
guestType: "lxc",
node: "node1",
vmid: 200,
expected: "pve1|lxc|node1|200",
},
{
name: "high VMID",
instance: "pve1",
guestType: "qemu",
node: "node1",
vmid: 999999,
expected: "pve1|qemu|node1|999999",
},
{
name: "zero VMID",
instance: "pve1",
guestType: "qemu",
node: "node1",
vmid: 0,
expected: "pve1|qemu|node1|0",
},
{
name: "negative VMID",
instance: "pve1",
guestType: "qemu",
node: "node1",
vmid: -1,
expected: "pve1|qemu|node1|-1",
},
{
name: "instance with port",
instance: "pve.example.com:8006",
guestType: "lxc",
node: "pve-node",
vmid: 101,
expected: "pve.example.com:8006|lxc|pve-node|101",
},
{
name: "empty instance",
instance: "",
guestType: "qemu",
node: "node1",
vmid: 100,
expected: "|qemu|node1|100",
},
{
name: "empty guest type",
instance: "pve1",
guestType: "",
node: "node1",
vmid: 100,
expected: "pve1||node1|100",
},
{
name: "empty node",
instance: "pve1",
guestType: "qemu",
node: "",
vmid: 100,
expected: "pve1|qemu||100",
},
{
name: "all empty except VMID",
instance: "",
guestType: "",
node: "",
vmid: 42,
expected: "|||42",
},
{
name: "FQDN with complex node name",
instance: "proxmox.datacenter.example.com",
guestType: "qemu",
node: "pve-cluster-node-01",
vmid: 12345,
expected: "proxmox.datacenter.example.com|qemu|pve-cluster-node-01|12345",
},
{
name: "IP address instance",
instance: "192.168.1.100",
guestType: "lxc",
node: "server01",
vmid: 500,
expected: "192.168.1.100|lxc|server01|500",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := makeGuestSnapshotKey(tc.instance, tc.guestType, tc.node, tc.vmid)
if got != tc.expected {
t.Errorf("makeGuestSnapshotKey(%q, %q, %q, %d) = %q, want %q",
tc.instance, tc.guestType, tc.node, tc.vmid, got, tc.expected)
}
})
}
}
func TestMakeSnapshotKey_Uniqueness(t *testing.T) {
// Test that different inputs produce different keys
t.Run("node keys with different instances are unique", func(t *testing.T) {
key1 := makeNodeSnapshotKey("pve1", "node1")
key2 := makeNodeSnapshotKey("pve2", "node1")
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
t.Run("node keys with different nodes are unique", func(t *testing.T) {
key1 := makeNodeSnapshotKey("pve1", "node1")
key2 := makeNodeSnapshotKey("pve1", "node2")
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
t.Run("guest keys with different VMIDs are unique", func(t *testing.T) {
key1 := makeGuestSnapshotKey("pve1", "qemu", "node1", 100)
key2 := makeGuestSnapshotKey("pve1", "qemu", "node1", 101)
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
t.Run("guest keys with different guest types are unique", func(t *testing.T) {
key1 := makeGuestSnapshotKey("pve1", "qemu", "node1", 100)
key2 := makeGuestSnapshotKey("pve1", "lxc", "node1", 100)
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
t.Run("guest keys with different nodes are unique", func(t *testing.T) {
key1 := makeGuestSnapshotKey("pve1", "qemu", "node1", 100)
key2 := makeGuestSnapshotKey("pve1", "qemu", "node2", 100)
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
t.Run("guest keys with different instances are unique", func(t *testing.T) {
key1 := makeGuestSnapshotKey("pve1", "qemu", "node1", 100)
key2 := makeGuestSnapshotKey("pve2", "qemu", "node1", 100)
if key1 == key2 {
t.Errorf("Keys should be unique: %q == %q", key1, key2)
}
})
}
func TestDiagnosticSnapshotSet_Fields(t *testing.T) {
// Test struct field initialization
set := DiagnosticSnapshotSet{
Nodes: []NodeMemorySnapshot{},
Guests: []GuestMemorySnapshot{},
}
if set.Nodes == nil {
t.Error("Nodes should not be nil")
}
if set.Guests == nil {
t.Error("Guests should not be nil")
}
if len(set.Nodes) != 0 {
t.Errorf("Nodes length = %d, want 0", len(set.Nodes))
}
if len(set.Guests) != 0 {
t.Errorf("Guests length = %d, want 0", len(set.Guests))
}
}
func TestNodeMemoryRaw_Fields(t *testing.T) {
raw := NodeMemoryRaw{
Total: 16000000000,
Used: 8000000000,
Free: 8000000000,
Available: 10000000000,
Buffers: 500000000,
Cached: 2000000000,
ProxmoxMemorySource: "rrd-available",
}
if raw.Total != 16000000000 {
t.Errorf("Total = %d, want 16000000000", raw.Total)
}
if raw.Used != 8000000000 {
t.Errorf("Used = %d, want 8000000000", raw.Used)
}
if raw.Free != 8000000000 {
t.Errorf("Free = %d, want 8000000000", raw.Free)
}
if raw.Available != 10000000000 {
t.Errorf("Available = %d, want 10000000000", raw.Available)
}
if raw.Buffers != 500000000 {
t.Errorf("Buffers = %d, want 500000000", raw.Buffers)
}
if raw.Cached != 2000000000 {
t.Errorf("Cached = %d, want 2000000000", raw.Cached)
}
if raw.ProxmoxMemorySource != "rrd-available" {
t.Errorf("ProxmoxMemorySource = %q, want %q", raw.ProxmoxMemorySource, "rrd-available")
}
}
func TestVMMemoryRaw_Fields(t *testing.T) {
raw := VMMemoryRaw{
ListingMem: 2000000000,
ListingMaxMem: 4000000000,
StatusMem: 2100000000,
StatusMaxMem: 4000000000,
Balloon: 3000000000,
BalloonMin: 1000000000,
Agent: 1,
}
if raw.ListingMem != 2000000000 {
t.Errorf("ListingMem = %d, want 2000000000", raw.ListingMem)
}
if raw.ListingMaxMem != 4000000000 {
t.Errorf("ListingMaxMem = %d, want 4000000000", raw.ListingMaxMem)
}
if raw.StatusMem != 2100000000 {
t.Errorf("StatusMem = %d, want 2100000000", raw.StatusMem)
}
if raw.StatusMaxMem != 4000000000 {
t.Errorf("StatusMaxMem = %d, want 4000000000", raw.StatusMaxMem)
}
if raw.Balloon != 3000000000 {
t.Errorf("Balloon = %d, want 3000000000", raw.Balloon)
}
if raw.BalloonMin != 1000000000 {
t.Errorf("BalloonMin = %d, want 1000000000", raw.BalloonMin)
}
if raw.Agent != 1 {
t.Errorf("Agent = %d, want 1", raw.Agent)
}
}