215 lines
4.6 KiB
Go
215 lines
4.6 KiB
Go
package middleware
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestNormalizeEndpoint(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Simple path",
|
|
input: "/api/users",
|
|
expected: "/api/users",
|
|
},
|
|
{
|
|
name: "Path with UUID",
|
|
input: "/api/users/abcdef12345",
|
|
expected: "/api/users/{id}",
|
|
},
|
|
{
|
|
name: "Path with UUID and trailing slash",
|
|
input: "/api/users/abcdef12345/",
|
|
expected: "/api/users/{id}/",
|
|
},
|
|
{
|
|
name: "Path with UUID in middle",
|
|
input: "/api/users/abcdef12345/profile",
|
|
expected: "/api/users/{id}/profile",
|
|
},
|
|
{
|
|
name: "Path with query params",
|
|
input: "/api/users?page=1&limit=10",
|
|
expected: "/api/users",
|
|
},
|
|
{
|
|
name: "Path with UUID and query params",
|
|
input: "/api/users/abcdef12345?detail=full",
|
|
expected: "/api/users/abcdef12345", // Query params removed first, then UUID not matched
|
|
},
|
|
{
|
|
name: "Multiple UUIDs",
|
|
input: "/api/users/abc12345678/posts/def87654321",
|
|
expected: "/api/users/{id}/posts/{id}",
|
|
},
|
|
{
|
|
name: "Root path",
|
|
input: "/",
|
|
expected: "/",
|
|
},
|
|
{
|
|
name: "Empty path",
|
|
input: "",
|
|
expected: "",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := normalizeEndpoint(tc.input)
|
|
if result != tc.expected {
|
|
t.Errorf("Expected '%s', got '%s'", tc.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizeEndpointUUIDFormats(t *testing.T) {
|
|
uuidFormats := []string{
|
|
"abcdef12345",
|
|
"ABCDEF12345",
|
|
"abc_def1234",
|
|
"abc-def1234",
|
|
"mixedCase12",
|
|
}
|
|
|
|
for _, uuid := range uuidFormats {
|
|
t.Run(uuid, func(t *testing.T) {
|
|
input := "/api/users/" + uuid
|
|
result := normalizeEndpoint(input)
|
|
expected := "/api/users/{id}"
|
|
|
|
if result != expected {
|
|
t.Errorf("Expected '%s', got '%s' for UUID format '%s'", expected, result, uuid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizeEndpointComplexQueryStrings(t *testing.T) {
|
|
testCases := []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"/api/users?a=1&b=2&c=3", "/api/users"},
|
|
{"/api/users?filter=active&sort=name&order=asc", "/api/users"},
|
|
{"/api/users?search=john+doe", "/api/users"},
|
|
{"/api/users?tags[]=tag1&tags[]=tag2", "/api/users"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := normalizeEndpoint(tc.input)
|
|
if result != tc.expected {
|
|
t.Errorf("Input '%s': expected '%s', got '%s'", tc.input, tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeEndpointEdgeCases(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Just query string",
|
|
input: "?param=value",
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "Double slashes",
|
|
input: "/api//users",
|
|
expected: "/api//users",
|
|
},
|
|
{
|
|
name: "Trailing query without params",
|
|
input: "/api/users?",
|
|
expected: "/api/users",
|
|
},
|
|
{
|
|
name: "UUID at end without slash",
|
|
input: "/users/abc12345678",
|
|
expected: "/users/{id}",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := normalizeEndpoint(tc.input)
|
|
if result != tc.expected {
|
|
t.Errorf("Expected '%s', got '%s'", tc.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizeEndpointPreservesNonUUID(t *testing.T) {
|
|
testCases := []string{
|
|
"/api/users/all",
|
|
"/api/users/active",
|
|
"/api/sessions/current",
|
|
"/health",
|
|
"/metrics",
|
|
}
|
|
|
|
for _, input := range testCases {
|
|
t.Run(input, func(t *testing.T) {
|
|
result := normalizeEndpoint(input)
|
|
if result != input {
|
|
t.Errorf("Non-UUID path should be preserved. Input: '%s', got '%s'", input, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizeEndpointUUIDLength(t *testing.T) {
|
|
// UUIDs must be exactly 11 characters
|
|
testCases := []struct {
|
|
name string
|
|
uuid string
|
|
shouldNormalize bool
|
|
}{
|
|
{"10 chars", "abcdefghij", false},
|
|
{"11 chars", "abcdefghijk", true},
|
|
{"12 chars", "abcdefghijkl", false},
|
|
{"5 chars", "abcde", false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
input := "/api/users/" + tc.uuid
|
|
result := normalizeEndpoint(input)
|
|
|
|
if tc.shouldNormalize {
|
|
expected := "/api/users/{id}"
|
|
if result != expected {
|
|
t.Errorf("Expected '%s', got '%s'", expected, result)
|
|
}
|
|
} else {
|
|
if result != input {
|
|
t.Errorf("Should not normalize, expected '%s', got '%s'", input, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkNormalizeEndpoint(b *testing.B) {
|
|
testPaths := []string{
|
|
"/api/users",
|
|
"/api/users/abc12345678",
|
|
"/api/users/abc12345678/profile",
|
|
"/api/users?page=1&limit=10",
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for _, path := range testPaths {
|
|
normalizeEndpoint(path)
|
|
}
|
|
}
|
|
}
|