Files
CosmicClash/server/api/admission_test.go
T
2026-09-01 19:14:28 +01:00

91 lines
2.7 KiB
Go

package api
import (
"net/http"
"net/http/httptest"
"strings"
"sync"
"testing"
)
func TestAdmissionGateDefaultsToAllowAndBlocksOnlyNewWork(t *testing.T) {
gate := NewAdmissionGate(false)
for _, operation := range []string{"login", "queue", "proposal", "allocation", "result", "events"} {
if !gate.Allow(operation) {
t.Fatalf("normal mode rejected %q", operation)
}
}
gate.SetDegraded(true)
for _, operation := range []string{"login", "queue", "proposal", "allocation"} {
if gate.Allow(operation) {
t.Fatalf("degraded mode allowed %q", operation)
}
}
for _, operation := range []string{"result", "events", "read", ""} {
if !gate.Allow(operation) {
t.Fatalf("degraded mode rejected live-safe operation %q", operation)
}
}
}
func TestAdmissionOperationClassifiesOnlyMutations(t *testing.T) {
tests := []struct {
path, method, want string
}{
{"/v1/session/steam", http.MethodPost, "login"},
{"/api/v1/session/steam/", http.MethodPost, "login"},
{"/v1/queue", http.MethodPost, "queue"},
{"/api/v1/queue/tickets/abc/heartbeat", http.MethodPost, "queue"},
{"/v1/proposals/abc/accept", http.MethodPost, "proposal"},
{"/api/v1/proposals/abc", http.MethodDelete, "proposal"},
{"/v1/queue", http.MethodGet, ""},
{"/v1/queue-not-a-route", http.MethodPost, ""},
{"/v1/servers/abc/result", http.MethodPost, ""},
{"/v1/events", http.MethodPost, ""},
}
for _, test := range tests {
if got := admissionOperation(test.path, test.method); got != test.want {
t.Errorf("admissionOperation(%q, %q) = %q, want %q", test.path, test.method, got, test.want)
}
}
}
func TestAdmissionGateConcurrentToggle(t *testing.T) {
gate := NewAdmissionGate(false)
var wg sync.WaitGroup
for i := 0; i < 8; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 1000; j++ {
gate.SetDegraded(j%2 == 0)
_ = gate.Allow("queue")
}
}()
}
wg.Wait()
}
func TestHandlerReturnsDegradedOnlyForNewMatchmakingMutations(t *testing.T) {
service := &Service{Admission: NewAdmissionGate(true)}
tests := []struct {
path, want string
}{
{"/v1/queue", "service_degraded"},
{"/api/v1/proposals/proposal-1/accept", "service_degraded"},
{"/v1/servers/server-1/result", "server_unavailable"},
{"/v1/events", ""},
}
for _, test := range tests {
req := httptest.NewRequest(http.MethodPost, test.path, strings.NewReader(`{}`))
rec := httptest.NewRecorder()
service.Handler().ServeHTTP(rec, req)
if test.want != "" && !strings.Contains(rec.Body.String(), test.want) {
t.Errorf("%s body = %q, want %q", test.path, rec.Body.String(), test.want)
}
if test.want == "service_degraded" && rec.Code != http.StatusServiceUnavailable {
t.Errorf("%s status = %d, want 503", test.path, rec.Code)
}
}
}