yao/openapi/oauth/acl/scope_test.go
Max 976eb2769d Refactor test case structure for path matching in ACL tests
- Adjusted the formatting of the test case struct in scope_test.go for improved readability.
- No functional changes were made; this commit focuses on code style consistency.
2025-10-23 10:54:48 +08:00

149 lines
3.9 KiB
Go

package acl
import (
"testing"
)
func TestNormalizePath(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "path with trailing slash",
input: "/user/teams/",
expected: "/user/teams",
},
{
name: "path without trailing slash",
input: "/user/teams",
expected: "/user/teams",
},
{
name: "root path",
input: "/",
expected: "/",
},
{
name: "empty path",
input: "",
expected: "",
},
{
name: "nested path with trailing slash",
input: "/user/teams/members/",
expected: "/user/teams/members",
},
{
name: "nested path without trailing slash",
input: "/user/teams/members",
expected: "/user/teams/members",
},
{
name: "path with multiple trailing slashes",
input: "/user/teams//",
expected: "/user/teams/",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := normalizePath(tt.input)
if result != tt.expected {
t.Errorf("normalizePath(%q) = %q, want %q", tt.input, result, tt.expected)
}
})
}
}
// TestPathMatchingWithTrailingSlash tests that paths match correctly regardless of trailing slashes
func TestPathMatchingWithTrailingSlash(t *testing.T) {
manager := &ScopeManager{
endpointIndex: make(map[string]*PathMatcher),
publicPaths: make(map[string]struct{}),
}
// Add a test endpoint without trailing slash
err := manager.addEndpointRule("POST", "/user/teams", "require-scopes", []string{"teams:write:own"})
if err != nil {
t.Fatalf("Failed to add endpoint rule: %v", err)
}
// Test that matching works with trailing slash
endpoint, pattern := manager.matchEndpoint("POST", "/user/teams/")
if endpoint == nil {
t.Errorf("Expected to match endpoint POST /user/teams/, but got nil")
}
if pattern != "/user/teams" {
t.Errorf("Expected pattern /user/teams, got %s", pattern)
}
// Test that matching works without trailing slash
endpoint, pattern = manager.matchEndpoint("POST", "/user/teams")
if endpoint == nil {
t.Errorf("Expected to match endpoint POST /user/teams, but got nil")
}
if pattern != "/user/teams" {
t.Errorf("Expected pattern /user/teams, got %s", pattern)
}
}
// TestPathMatchingExactPaths tests exact path matching with normalization
func TestPathMatchingExactPaths(t *testing.T) {
manager := &ScopeManager{
endpointIndex: make(map[string]*PathMatcher),
publicPaths: make(map[string]struct{}),
}
// Add endpoints with different trailing slash patterns
testCases := []struct {
method string
definedPath string
requestPaths []string
shouldMatch bool
}{
{
method: "POST",
definedPath: "/user/teams",
requestPaths: []string{"/user/teams", "/user/teams/"},
shouldMatch: true,
},
{
method: "GET",
definedPath: "/user/teams/",
requestPaths: []string{"/user/teams", "/user/teams/"},
shouldMatch: true,
},
{
method: "DELETE",
definedPath: "/user/profile",
requestPaths: []string{"/user/profile", "/user/profile/"},
shouldMatch: true,
},
}
for _, tc := range testCases {
// Add the endpoint
err := manager.addEndpointRule(tc.method, tc.definedPath, "allow", nil)
if err != nil {
t.Fatalf("Failed to add endpoint rule %s %s: %v", tc.method, tc.definedPath, err)
}
// Test all request paths
for _, requestPath := range tc.requestPaths {
endpoint, pattern := manager.matchEndpoint(tc.method, requestPath)
if tc.shouldMatch && endpoint == nil {
t.Errorf("Expected %s %s to match defined path %s, but got nil",
tc.method, requestPath, tc.definedPath)
} else if tc.shouldMatch && endpoint != nil {
// Both paths should normalize to the same pattern
expectedPattern := normalizePath(tc.definedPath)
if pattern != expectedPattern {
t.Errorf("Expected pattern %s, got %s (defined: %s, request: %s)",
expectedPattern, pattern, tc.definedPath, requestPath)
}
}
}
}
}