mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 11:30:15 +00:00
227 lines
4.8 KiB
Go
227 lines
4.8 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
func TestSanitizeNodeLabel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
}{
|
|
// Basic cases
|
|
{
|
|
name: "simple hostname",
|
|
input: "node1",
|
|
want: "node1",
|
|
},
|
|
{
|
|
name: "hostname with hyphen",
|
|
input: "node-1",
|
|
want: "node-1",
|
|
},
|
|
{
|
|
name: "hostname with underscore",
|
|
input: "node_1",
|
|
want: "node_1",
|
|
},
|
|
{
|
|
name: "hostname with dot",
|
|
input: "node.local",
|
|
want: "node.local",
|
|
},
|
|
{
|
|
name: "fqdn",
|
|
input: "node1.example.com",
|
|
want: "node1.example.com",
|
|
},
|
|
|
|
// Case conversion
|
|
{
|
|
name: "uppercase converted to lowercase",
|
|
input: "Node1",
|
|
want: "node1",
|
|
},
|
|
{
|
|
name: "mixed case",
|
|
input: "MyNode-Server",
|
|
want: "mynode-server",
|
|
},
|
|
{
|
|
name: "all uppercase",
|
|
input: "PRODSERVER01",
|
|
want: "prodserver01",
|
|
},
|
|
|
|
// Special character handling
|
|
{
|
|
name: "space replaced with underscore",
|
|
input: "node 1",
|
|
want: "node_1",
|
|
},
|
|
{
|
|
name: "colon replaced with underscore",
|
|
input: "node:1",
|
|
want: "node_1",
|
|
},
|
|
{
|
|
name: "at sign replaced with underscore",
|
|
input: "user@node",
|
|
want: "user_node",
|
|
},
|
|
{
|
|
name: "forward slash replaced",
|
|
input: "path/to/node",
|
|
want: "path_to_node",
|
|
},
|
|
{
|
|
name: "multiple special chars",
|
|
input: "node!@#$%^&*()+=[]{}|\\:;<>,?/~`",
|
|
want: "node___________________________",
|
|
},
|
|
{
|
|
name: "unicode replaced with underscore",
|
|
input: "节点1",
|
|
want: "__1",
|
|
},
|
|
{
|
|
name: "emoji replaced",
|
|
input: "server🔥hot",
|
|
want: "server_hot",
|
|
},
|
|
|
|
// Length limits
|
|
{
|
|
name: "exactly 63 chars preserved",
|
|
input: "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0",
|
|
want: "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0",
|
|
},
|
|
{
|
|
name: "longer than 63 chars truncated",
|
|
input: "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789",
|
|
want: "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0",
|
|
},
|
|
{
|
|
name: "very long hostname truncated",
|
|
input: "this-is-a-very-long-hostname-that-exceeds-the-prometheus-label-value-limit-of-sixty-three-characters",
|
|
want: "this-is-a-very-long-hostname-that-exceeds-the-prometheus-label-",
|
|
},
|
|
|
|
// Edge cases
|
|
{
|
|
name: "empty string returns unknown",
|
|
input: "",
|
|
want: "unknown",
|
|
},
|
|
{
|
|
name: "all special chars returns unknown",
|
|
input: "!@#$%",
|
|
want: "_____",
|
|
},
|
|
{
|
|
name: "single char",
|
|
input: "a",
|
|
want: "a",
|
|
},
|
|
{
|
|
name: "numbers only",
|
|
input: "12345",
|
|
want: "12345",
|
|
},
|
|
{
|
|
name: "hyphen start preserved",
|
|
input: "-node",
|
|
want: "-node",
|
|
},
|
|
{
|
|
name: "underscore start preserved",
|
|
input: "_node",
|
|
want: "_node",
|
|
},
|
|
{
|
|
name: "dot start preserved",
|
|
input: ".hidden",
|
|
want: ".hidden",
|
|
},
|
|
|
|
// Realistic node names
|
|
{
|
|
name: "proxmox node style",
|
|
input: "pve-node1",
|
|
want: "pve-node1",
|
|
},
|
|
{
|
|
name: "ip address style",
|
|
input: "192.168.1.100",
|
|
want: "192.168.1.100",
|
|
},
|
|
{
|
|
name: "kubernetes node",
|
|
input: "k8s-worker-01.cluster.local",
|
|
want: "k8s-worker-01.cluster.local",
|
|
},
|
|
{
|
|
name: "docker container id prefix",
|
|
input: "abc123def456",
|
|
want: "abc123def456",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := sanitizeNodeLabel(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("sanitizeNodeLabel(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSanitizeNodeLabel_MaxLength(t *testing.T) {
|
|
// Test that all outputs are <= 63 chars
|
|
longInputs := []string{
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"very-long-hostname-with-many-hyphens-and-lots-of-segments-here",
|
|
"node123456789012345678901234567890123456789012345678901234567890",
|
|
}
|
|
|
|
for _, input := range longInputs {
|
|
result := sanitizeNodeLabel(input)
|
|
if len(result) > 63 {
|
|
t.Errorf("sanitizeNodeLabel(%q) length = %d, want <= 63", input, len(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSanitizeNodeLabel_NeverEmpty(t *testing.T) {
|
|
// Test that output is never empty
|
|
emptyishInputs := []string{
|
|
"",
|
|
" ",
|
|
}
|
|
|
|
for _, input := range emptyishInputs {
|
|
result := sanitizeNodeLabel(input)
|
|
if result == "" {
|
|
t.Errorf("sanitizeNodeLabel(%q) returned empty string, should return 'unknown' or sanitized value", input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSanitizeNodeLabel_Idempotent(t *testing.T) {
|
|
// Applying sanitize twice should give same result as once
|
|
inputs := []string{
|
|
"node1",
|
|
"Node@Server",
|
|
"test.node.local",
|
|
"mixed-CASE_name.123",
|
|
}
|
|
|
|
for _, input := range inputs {
|
|
once := sanitizeNodeLabel(input)
|
|
twice := sanitizeNodeLabel(once)
|
|
if once != twice {
|
|
t.Errorf("sanitizeNodeLabel is not idempotent: sanitizeNodeLabel(%q) = %q, sanitizeNodeLabel(%q) = %q",
|
|
input, once, once, twice)
|
|
}
|
|
}
|
|
}
|