test: Add tests for monitoring helper and normalize functions

- TestCloneStringFloatMap: Deep copy verification for float maps
- TestCloneStringMap: Deep copy verification for string maps
- TestNormalizeAgentVersion: Version prefix normalization
- TestNormalizePBSNamespacePath: PBS namespace path handling
- TestNamespacePathsForDatastore: Datastore namespace extraction
- TestNormalizeDockerHostID: Docker host ID normalization
Coverage: monitoring 42.2% → 42.5%
This commit is contained in:
rcourtman 2025-12-01 14:14:48 +00:00
parent b311625328
commit 512bf91bdd

View file

@ -893,3 +893,303 @@ func TestExtractGuestOSInfo(t *testing.T) {
})
}
}
func TestCloneStringFloatMap(t *testing.T) {
t.Parallel()
cases := []struct {
name string
input map[string]float64
want map[string]float64
}{
{name: "nil input", input: nil, want: nil},
{name: "empty map", input: map[string]float64{}, want: nil},
{name: "single entry", input: map[string]float64{"cpu": 42.5}, want: map[string]float64{"cpu": 42.5}},
{name: "multiple entries", input: map[string]float64{"temp1": 45.0, "temp2": 50.0}, want: map[string]float64{"temp1": 45.0, "temp2": 50.0}},
{name: "zero value", input: map[string]float64{"zero": 0.0}, want: map[string]float64{"zero": 0.0}},
{name: "negative value", input: map[string]float64{"neg": -10.5}, want: map[string]float64{"neg": -10.5}},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
got := cloneStringFloatMap(tc.input)
if tc.want == nil {
if got != nil {
t.Fatalf("cloneStringFloatMap(%v) = %v, want nil", tc.input, got)
}
return
}
if len(got) != len(tc.want) {
t.Fatalf("cloneStringFloatMap(%v) length = %d, want %d", tc.input, len(got), len(tc.want))
}
for k, v := range tc.want {
if got[k] != v {
t.Fatalf("cloneStringFloatMap(%v)[%q] = %v, want %v", tc.input, k, got[k], v)
}
}
// Verify it's a deep copy
if tc.input != nil && len(tc.input) > 0 {
for k := range tc.input {
tc.input[k] = 999.0
if got[k] == 999.0 {
t.Fatalf("cloneStringFloatMap() returned reference, not a copy")
}
break
}
}
})
}
}
func TestCloneStringMap(t *testing.T) {
t.Parallel()
cases := []struct {
name string
input map[string]string
want map[string]string
}{
{name: "nil input", input: nil, want: nil},
{name: "empty map", input: map[string]string{}, want: nil},
{name: "single entry", input: map[string]string{"key": "value"}, want: map[string]string{"key": "value"}},
{name: "multiple entries", input: map[string]string{"a": "1", "b": "2"}, want: map[string]string{"a": "1", "b": "2"}},
{name: "empty string value", input: map[string]string{"empty": ""}, want: map[string]string{"empty": ""}},
{name: "empty string key", input: map[string]string{"": "value"}, want: map[string]string{"": "value"}},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
got := cloneStringMap(tc.input)
if tc.want == nil {
if got != nil {
t.Fatalf("cloneStringMap(%v) = %v, want nil", tc.input, got)
}
return
}
if len(got) != len(tc.want) {
t.Fatalf("cloneStringMap(%v) length = %d, want %d", tc.input, len(got), len(tc.want))
}
for k, v := range tc.want {
if got[k] != v {
t.Fatalf("cloneStringMap(%v)[%q] = %q, want %q", tc.input, k, got[k], v)
}
}
// Verify it's a deep copy
if tc.input != nil && len(tc.input) > 0 {
for k := range tc.input {
tc.input[k] = "modified"
if got[k] == "modified" {
t.Fatalf("cloneStringMap() returned reference, not a copy")
}
break
}
}
})
}
}
func TestNormalizeAgentVersion(t *testing.T) {
t.Parallel()
cases := []struct {
input string
want string
}{
// Empty/whitespace
{"", ""},
{" ", ""},
{" \t ", ""},
// Already has v prefix
{"v1.0.0", "v1.0.0"},
{"V1.0.0", "v1.0.0"},
// Needs v prefix
{"1.0.0", "v1.0.0"},
{"4.35.0", "v4.35.0"},
// Multiple v prefixes trimmed
{"vv1.0.0", "v1.0.0"},
{"VVV1.0.0", "v1.0.0"},
{"vVv1.0.0", "v1.0.0"},
// Only v/V (edge case)
{"v", ""},
{"V", ""},
{"vV", ""},
// With whitespace
{" v1.0.0 ", "v1.0.0"},
{" 1.0.0 ", "v1.0.0"},
}
for _, tc := range cases {
tc := tc
t.Run(tc.input, func(t *testing.T) {
t.Parallel()
if got := normalizeAgentVersion(tc.input); got != tc.want {
t.Fatalf("normalizeAgentVersion(%q) = %q, want %q", tc.input, got, tc.want)
}
})
}
}
func TestNormalizePBSNamespacePath(t *testing.T) {
t.Parallel()
cases := []struct {
input string
want string
}{
// Root path normalizes to empty
{"/", ""},
// Other paths preserved
{"", ""},
{"backup", "backup"},
{"/backup", "/backup"},
{"backup/subdir", "backup/subdir"},
}
for _, tc := range cases {
tc := tc
t.Run(tc.input, func(t *testing.T) {
t.Parallel()
if got := normalizePBSNamespacePath(tc.input); got != tc.want {
t.Fatalf("normalizePBSNamespacePath(%q) = %q, want %q", tc.input, got, tc.want)
}
})
}
}
func TestNamespacePathsForDatastore(t *testing.T) {
t.Parallel()
cases := []struct {
name string
ds models.PBSDatastore
want []string
}{
{
name: "no namespaces returns empty string",
ds: models.PBSDatastore{Name: "ds1", Namespaces: nil},
want: []string{""},
},
{
name: "empty namespaces returns empty string",
ds: models.PBSDatastore{Name: "ds1", Namespaces: []models.PBSNamespace{}},
want: []string{""},
},
{
name: "single namespace",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: "backup"},
},
},
want: []string{"backup"},
},
{
name: "multiple namespaces",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: "backup"},
{Path: "archive"},
},
},
want: []string{"backup", "archive"},
},
{
name: "root namespace normalized",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: "/"},
},
},
want: []string{""},
},
{
name: "duplicate paths deduplicated",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: "backup"},
{Path: "backup"},
{Path: "archive"},
},
},
want: []string{"backup", "archive"},
},
{
name: "duplicate root paths deduplicated",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: "/"},
{Path: "/"},
},
},
want: []string{""},
},
{
name: "all empty paths result in single empty",
ds: models.PBSDatastore{
Name: "ds1",
Namespaces: []models.PBSNamespace{
{Path: ""},
{Path: ""},
},
},
want: []string{""},
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
got := namespacePathsForDatastore(tc.ds)
if len(got) != len(tc.want) {
t.Fatalf("namespacePathsForDatastore() = %v, want %v", got, tc.want)
}
for i, v := range tc.want {
if got[i] != v {
t.Fatalf("namespacePathsForDatastore()[%d] = %q, want %q", i, got[i], v)
}
}
})
}
}
func TestNormalizeDockerHostID(t *testing.T) {
t.Parallel()
cases := []struct {
input string
want string
}{
{"", ""},
{"host1", "host1"},
{" host1 ", "host1"},
{" ", ""},
{"\t\n", ""},
{"docker-host-123", "docker-host-123"},
}
for _, tc := range cases {
tc := tc
t.Run(tc.input, func(t *testing.T) {
t.Parallel()
if got := normalizeDockerHostID(tc.input); got != tc.want {
t.Fatalf("normalizeDockerHostID(%q) = %q, want %q", tc.input, got, tc.want)
}
})
}
}