Files
mc-gateway/internal/adminhttp/api_test.go
tursom f508ecc1b9
Some checks failed
Go / build (.exe, 386, windows, windows-386) (push) Has been cancelled
Go / build (.exe, amd64, windows, windows-amd64) (push) Has been cancelled
Go / build (.exe, arm64, windows, windows-arm64) (push) Has been cancelled
Go / build (386, freebsd, freebsd-386) (push) Has been cancelled
Go / build (386, linux, linux-386) (push) Has been cancelled
Go / build (386, netbsd, netbsd-386) (push) Has been cancelled
Go / build (386, openbsd, openbsd-386) (push) Has been cancelled
Go / build (386, plan9, plan9-386) (push) Has been cancelled
Go / build (amd64, darwin, darwin-amd64) (push) Has been cancelled
Go / build (amd64, dragonfly, dragonfly-amd64) (push) Has been cancelled
Go / build (amd64, freebsd, freebsd-amd64) (push) Has been cancelled
Go / build (amd64, illumos, illumos-amd64) (push) Has been cancelled
Go / build (amd64, linux, linux-amd64) (push) Has been cancelled
Go / build (amd64, netbsd, netbsd-amd64) (push) Has been cancelled
Go / build (amd64, openbsd, openbsd-amd64) (push) Has been cancelled
Go / build (amd64, plan9, plan9-amd64) (push) Has been cancelled
Go / build (amd64, solaris, solaris-amd64) (push) Has been cancelled
Go / build (arm, 6, linux, linux-armv6) (push) Has been cancelled
Go / build (arm, 7, linux, linux-armv7) (push) Has been cancelled
Go / build (arm, freebsd, freebsd-arm) (push) Has been cancelled
Go / build (arm, netbsd, netbsd-arm) (push) Has been cancelled
Go / build (arm, openbsd, openbsd-arm) (push) Has been cancelled
Go / build (arm, plan9, plan9-arm) (push) Has been cancelled
Go / build (arm64, darwin, darwin-arm64) (push) Has been cancelled
Go / build (arm64, freebsd, freebsd-arm64) (push) Has been cancelled
Go / build (arm64, linux, linux-arm64) (push) Has been cancelled
Go / build (arm64, netbsd, netbsd-arm64) (push) Has been cancelled
Go / build (arm64, openbsd, openbsd-arm64) (push) Has been cancelled
Go / build (loong64, linux, linux-loong64) (push) Has been cancelled
Go / build (mips, linux, linux-mips) (push) Has been cancelled
Go / build (mips64, linux, linux-mips64) (push) Has been cancelled
Go / build (mips64le, linux, linux-mips64le) (push) Has been cancelled
Go / build (mipsle, linux, linux-mipsle) (push) Has been cancelled
Go / build (ppc64, aix, aix-ppc64) (push) Has been cancelled
Go / build (ppc64, linux, linux-ppc64) (push) Has been cancelled
Go / build (ppc64, openbsd, openbsd-ppc64) (push) Has been cancelled
Go / build (ppc64le, linux, linux-ppc64le) (push) Has been cancelled
Go / build (riscv64, freebsd, freebsd-riscv64) (push) Has been cancelled
Go / build (riscv64, linux, linux-riscv64) (push) Has been cancelled
Go / build (riscv64, openbsd, openbsd-riscv64) (push) Has been cancelled
Go / build (s390x, linux, linux-s390x) (push) Has been cancelled
Docker Image / docker (push) Has been cancelled
Go / merge-artifacts (push) Has been cancelled
docs: 补充中文代码注释
2026-06-27 20:15:29 +08:00

168 lines
10 KiB
Go

// internal/adminhttp/api_test.go 包含用于约束 api 行为的测试。
package adminhttp
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestNewAPIHandlerRoutesRequests(t *testing.T) {
tests := []struct {
name string
method string
path string
wantCall string
wantSegment string
}{
{name: "setup status", method: http.MethodGet, path: "/admin/api/setup", wantCall: "setup_status"},
{name: "setup", method: http.MethodPost, path: "/admin/api/setup", wantCall: "setup"},
{name: "login", method: http.MethodPost, path: "/admin/api/auth/login", wantCall: "login"},
{name: "logout", method: http.MethodPost, path: "/admin/api/auth/logout", wantCall: "logout"},
{name: "me", method: http.MethodGet, path: "/admin/api/me", wantCall: "me"},
{name: "status", method: http.MethodGet, path: "/admin/api/status", wantCall: "status"},
{name: "routes list", method: http.MethodGet, path: "/admin/api/routes", wantCall: "routes_list"},
{name: "route item", method: http.MethodPut, path: "/admin/api/routes/play.example", wantCall: "route_item", wantSegment: "play.example"},
{name: "services list", method: http.MethodGet, path: "/admin/api/services", wantCall: "services_list"},
{name: "service restart", method: http.MethodPost, path: "/admin/api/services/kcp/restart", wantCall: "service_item", wantSegment: "kcp/restart"},
{name: "metrics", method: http.MethodGet, path: "/admin/api/metrics", wantCall: "metrics"},
{name: "users list", method: http.MethodGet, path: "/admin/api/users", wantCall: "users_list"},
{name: "users create", method: http.MethodPost, path: "/admin/api/users", wantCall: "users_create"},
{name: "user item", method: http.MethodPatch, path: "/admin/api/users/member", wantCall: "user_item", wantSegment: "member"},
{name: "audit logs", method: http.MethodGet, path: "/admin/api/audit-logs", wantCall: "audit_logs"},
{name: "plugin artifacts", method: http.MethodGet, path: "/admin/api/plugin-artifacts", wantCall: "plugin_artifacts"},
{name: "plugin artifact", method: http.MethodGet, path: "/admin/api/plugin-artifacts/abc", wantCall: "plugin_artifact", wantSegment: "abc"},
{name: "plugin sources", method: http.MethodGet, path: "/admin/api/plugin-sources", wantCall: "plugin_sources"},
{name: "plugin builds", method: http.MethodGet, path: "/admin/api/plugin-builds", wantCall: "plugin_builds"},
{name: "plugin build", method: http.MethodGet, path: "/admin/api/plugin-builds/7", wantCall: "plugin_build", wantSegment: "7"},
{name: "plugin build retry", method: http.MethodPost, path: "/admin/api/plugin-builds/7/retry", wantCall: "plugin_build", wantSegment: "7/retry"},
{name: "plugin gc", method: http.MethodGet, path: "/admin/api/plugin-gc", wantCall: "plugin_gc"},
{name: "plugin operations gc", method: http.MethodGet, path: "/admin/api/plugin-operations-gc", wantCall: "plugin_operations_gc"},
{name: "plugins list", method: http.MethodGet, path: "/admin/api/plugins", wantCall: "plugins_list"},
{name: "plugin item", method: http.MethodPut, path: "/admin/api/plugins/upstream-rewrite", wantCall: "plugin_item", wantSegment: "upstream-rewrite"},
{name: "plugin action", method: http.MethodPost, path: "/admin/api/plugins/upstream-rewrite/enable", wantCall: "plugin_action", wantSegment: "upstream-rewrite/enable"},
{name: "plugin config", method: http.MethodPut, path: "/admin/api/plugins/upstream-rewrite/config", wantCall: "plugin_config", wantSegment: "upstream-rewrite/config"},
{name: "plugin config dry-run", method: http.MethodPost, path: "/admin/api/plugins/upstream-rewrite/config/dry-run", wantCall: "plugin_config", wantSegment: "upstream-rewrite/config/dry-run"},
{name: "plugin secrets", method: http.MethodGet, path: "/admin/api/plugins/upstream-rewrite/secrets", wantCall: "plugin_secrets", wantSegment: "upstream-rewrite/secrets"},
{name: "plugin rollback artifact", method: http.MethodPost, path: "/admin/api/plugins/upstream-rewrite/rollback/artifact", wantCall: "plugin_rollback", wantSegment: "upstream-rewrite/rollback/artifact"},
{name: "plugin governance", method: http.MethodGet, path: "/admin/api/plugins/upstream-rewrite/governance", wantCall: "plugin_governance", wantSegment: "upstream-rewrite/governance"},
{name: "plugin governance review", method: http.MethodPost, path: "/admin/api/plugins/upstream-rewrite/governance/review", wantCall: "plugin_governance", wantSegment: "upstream-rewrite/governance/review"},
{name: "plugin operations", method: http.MethodGet, path: "/admin/api/plugins/upstream-rewrite/operations", wantCall: "plugin_operations", wantSegment: "upstream-rewrite/operations"},
{name: "plugin operations task trigger", method: http.MethodPost, path: "/admin/api/plugins/upstream-rewrite/operations/tasks/sync/trigger", wantCall: "plugin_operations", wantSegment: "upstream-rewrite/operations/tasks/sync/trigger"},
{name: "plugin diagnostics", method: http.MethodGet, path: "/admin/api/plugins/upstream-rewrite/diagnostics", wantCall: "plugin_diagnostics", wantSegment: "upstream-rewrite"},
{name: "plugin draining force close", method: http.MethodPost, path: "/admin/api/plugins/mc-auth-proxy/draining/force-close", wantCall: "plugin_draining", wantSegment: "mc-auth-proxy"},
{name: "plugin dispatch", method: http.MethodGet, path: "/admin/api/plugins/dispatch-plan", wantCall: "plugin_dispatch"},
{name: "plugin advisories", method: http.MethodGet, path: "/admin/api/plugin-advisories", wantCall: "plugin_advisories"},
{name: "plugin service", method: http.MethodGet, path: "/admin/api/plugin-service", wantCall: "plugin_service"},
{name: "plugin repositories", method: http.MethodGet, path: "/admin/api/plugin-repositories/imports", wantCall: "plugin_repositories"},
{name: "plugin supply chain", method: http.MethodGet, path: "/admin/api/plugin-supply-chain", wantCall: "plugin_supply_chain"},
{name: "plugin instrumentation", method: http.MethodGet, path: "/admin/api/plugin-instrumentation", wantCall: "plugin_instrumentation"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var gotCall, gotSegment string
handler := NewAPIHandler("/admin/api", APIHandlers{
SetupStatus: recordCall(&gotCall, "setup_status"),
Setup: recordCall(&gotCall, "setup"),
Login: recordCall(&gotCall, "login"),
Logout: recordCall(&gotCall, "logout"),
Me: recordCall(&gotCall, "me"),
Status: recordCall(&gotCall, "status"),
RoutesList: recordCall(&gotCall, "routes_list"),
RouteItem: recordSegmentCall(&gotCall, &gotSegment, "route_item"),
ServicesList: recordCall(&gotCall, "services_list"),
ServiceItem: recordSegmentCall(&gotCall, &gotSegment, "service_item"),
Metrics: recordCall(&gotCall, "metrics"),
UsersList: recordCall(&gotCall, "users_list"),
UsersCreate: recordCall(&gotCall, "users_create"),
UserItem: recordSegmentCall(&gotCall, &gotSegment, "user_item"),
AuditLogs: recordCall(&gotCall, "audit_logs"),
PluginArtifacts: recordCall(&gotCall, "plugin_artifacts"),
PluginArtifact: recordSegmentCall(&gotCall, &gotSegment, "plugin_artifact"),
PluginSources: recordCall(&gotCall, "plugin_sources"),
PluginBuilds: recordCall(&gotCall, "plugin_builds"),
PluginBuild: recordSegmentCall(&gotCall, &gotSegment, "plugin_build"),
PluginGC: recordCall(&gotCall, "plugin_gc"),
PluginOperationsGC: recordCall(&gotCall, "plugin_operations_gc"),
PluginsList: recordCall(&gotCall, "plugins_list"),
PluginItem: recordSegmentCall(&gotCall, &gotSegment, "plugin_item"),
PluginAction: recordSegmentCall(&gotCall, &gotSegment, "plugin_action"),
PluginConfig: recordSegmentCall(&gotCall, &gotSegment, "plugin_config"),
PluginSecrets: recordSegmentCall(&gotCall, &gotSegment, "plugin_secrets"),
PluginRollback: recordSegmentCall(&gotCall, &gotSegment, "plugin_rollback"),
PluginOperations: recordSegmentCall(&gotCall, &gotSegment, "plugin_operations"),
PluginDraining: recordSegmentCall(&gotCall, &gotSegment, "plugin_draining"),
PluginDispatch: recordCall(&gotCall, "plugin_dispatch"),
PluginGovernance: recordSegmentCall(&gotCall, &gotSegment, "plugin_governance"),
PluginAdvisories: recordCall(&gotCall, "plugin_advisories"),
PluginDiagnostics: recordSegmentCall(&gotCall, &gotSegment, "plugin_diagnostics"),
PluginService: recordCall(&gotCall, "plugin_service"),
PluginRepositories: recordCall(&gotCall, "plugin_repositories"),
PluginSupplyChain: recordCall(&gotCall, "plugin_supply_chain"),
PluginInstrumentation: recordCall(&gotCall, "plugin_instrumentation"),
})
resp := httptest.NewRecorder()
req := httptest.NewRequest(tt.method, tt.path, nil)
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusNoContent {
t.Fatalf("status = %d, want %d; body=%s", resp.Code, http.StatusNoContent, resp.Body.String())
}
if gotCall != tt.wantCall {
t.Fatalf("call = %q, want %q", gotCall, tt.wantCall)
}
if gotSegment != tt.wantSegment {
t.Fatalf("segment = %q, want %q", gotSegment, tt.wantSegment)
}
if got := resp.Header().Get("Cache-Control"); got != "no-store" {
t.Fatalf("Cache-Control = %q, want no-store", got)
}
})
}
}
func TestNewAPIHandlerWritesNotFound(t *testing.T) {
handler := NewAPIHandler("/admin/api", APIHandlers{})
resp := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/admin/api/auth/login", nil)
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusNotFound {
t.Fatalf("wrong method status = %d, want %d", resp.Code, http.StatusNotFound)
}
if strings.TrimSpace(resp.Body.String()) != `{"error":"not found"}` {
t.Fatalf("wrong method body = %q", resp.Body.String())
}
resp = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/admin/api/missing", nil)
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusNotFound {
t.Fatalf("missing status = %d, want %d", resp.Code, http.StatusNotFound)
}
}
func recordCall(got *string, call string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
*got = call
w.WriteHeader(http.StatusNoContent)
}
}
func recordSegmentCall(gotCall, gotSegment *string, call string) SegmentHandlerFunc {
return func(w http.ResponseWriter, r *http.Request, segment string) {
*gotCall = call
*gotSegment = segment
w.WriteHeader(http.StatusNoContent)
}
}