Files
Pulse/cmd/pulse-sensor-proxy/http_server_test.go
rcourtman 48af5615b9 Add unit tests for pulse-sensor-proxy utility functions
- hashIPToUID: 11 test cases covering IP hashing for rate limiting
  (determinism, range bounds, collision detection, boundary values)
- extractNodesFromYAML: 17 test cases covering YAML node list parsing
  (map format, list format, mixed types, edge cases)

First test files for config_cmd.go and http_server.go utilities.
2025-11-30 14:19:43 +00:00

144 lines
2.9 KiB
Go

package main
import (
"testing"
)
func TestHashIPToUID(t *testing.T) {
tests := []struct {
name string
ip string
wantMin uint32
wantMax uint32
wantSame bool // if true, verify determinism by checking same IP gives same result
}{
{
name: "IPv4 localhost",
ip: "127.0.0.1",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "IPv4 standard",
ip: "192.168.1.100",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "IPv4 another address",
ip: "10.0.0.1",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "IPv6 localhost",
ip: "::1",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "IPv6 full address",
ip: "2001:db8::1",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "empty string",
ip: "",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "single character",
ip: "a",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
{
name: "long string",
ip: "this-is-a-very-long-hostname-that-might-be-used.example.com",
wantMin: 100000,
wantMax: 999999,
wantSame: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := hashIPToUID(tc.ip)
// Check range
if result < tc.wantMin || result > tc.wantMax {
t.Errorf("hashIPToUID(%q) = %d, want in range [%d, %d]",
tc.ip, result, tc.wantMin, tc.wantMax)
}
// Check determinism
if tc.wantSame {
result2 := hashIPToUID(tc.ip)
if result != result2 {
t.Errorf("hashIPToUID(%q) not deterministic: got %d then %d",
tc.ip, result, result2)
}
}
})
}
}
func TestHashIPToUID_DifferentInputsProduceDifferentHashes(t *testing.T) {
ips := []string{
"127.0.0.1",
"192.168.1.1",
"192.168.1.2",
"10.0.0.1",
"::1",
"2001:db8::1",
}
hashes := make(map[uint32]string)
collisions := 0
for _, ip := range ips {
hash := hashIPToUID(ip)
if existing, found := hashes[hash]; found {
// Collision found - not necessarily an error but worth noting
collisions++
t.Logf("Hash collision: %q and %q both produce %d", ip, existing, hash)
}
hashes[hash] = ip
}
// With only 6 inputs and 900000 possible outputs, collisions should be rare
if collisions > 1 {
t.Errorf("Too many collisions (%d) for %d inputs", collisions, len(ips))
}
}
func TestHashIPToUID_BoundaryValues(t *testing.T) {
// Test that the function correctly produces values in the expected range
// even for edge cases
tests := []string{
"", // empty
"\x00", // null byte
"\xff\xff\xff", // high bytes
"0.0.0.0",
"255.255.255.255",
}
for _, ip := range tests {
result := hashIPToUID(ip)
if result < 100000 || result > 999999 {
t.Errorf("hashIPToUID(%q) = %d, out of expected range [100000, 999999]",
ip, result)
}
}
}