proxy-pool/api/openapi/openapi_test.go
2026-07-29 10:14:56 +08:00

85 lines
2.2 KiB
Go

package openapi
import (
"os"
"testing"
"go.yaml.in/yaml/v4"
)
type document struct {
OpenAPI string `yaml:"openapi"`
Paths map[string]map[string]any `yaml:"paths"`
}
func TestDistributionContract(t *testing.T) {
spec := readDocument(t, "proxy-pool.yaml")
if spec.OpenAPI != "3.1.0" {
t.Fatalf("openapi version = %q, want 3.1.0", spec.OpenAPI)
}
extraction, ok := spec.Paths["/api/v1/proxies/extract"]
if !ok {
t.Fatal("exclusive extraction path is missing")
}
post, ok := extraction["post"]
if !ok {
t.Fatal("exclusive extraction must use POST")
}
requireResponses(t, post, "200", "400", "409", "413", "415", "422", "429", "500", "503")
for path := range spec.Paths {
if path == "/api/v1/leases" || path == "/api/v1/proxies/release" || path == "/api/v1/proxies/renew" {
t.Fatalf("lease/release path is forbidden: %s", path)
}
}
}
func TestAdminContract(t *testing.T) {
spec := readDocument(t, "admin.yaml")
for _, path := range []string{
"/api/v1/status",
"/api/v1/upstreams/{name}/enable",
"/api/v1/upstreams/{name}/disable",
"/api/v1/routing/{name}/switch",
"/api/v1/config/reload",
} {
if _, ok := spec.Paths[path]; !ok {
t.Errorf("admin path is missing: %s", path)
}
}
requireResponses(t, spec.Paths["/api/v1/routing/{name}/switch"]["post"],
"200", "400", "401", "403", "404", "405", "409", "413", "415", "422", "500", "503")
}
func requireResponses(t *testing.T, operation any, codes ...string) {
t.Helper()
operationMap, ok := operation.(map[string]any)
if !ok {
t.Fatalf("operation has type %T, want map", operation)
}
responses, ok := operationMap["responses"].(map[string]any)
if !ok {
t.Fatalf("responses has type %T, want map", operationMap["responses"])
}
for _, code := range codes {
if _, ok := responses[code]; !ok {
t.Errorf("response %s is missing", code)
}
}
}
func readDocument(t *testing.T, path string) document {
t.Helper()
content, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read %s: %v", path, err)
}
var spec document
if err := yaml.Unmarshal(content, &spec); err != nil {
t.Fatalf("parse %s: %v", path, err)
}
if spec.OpenAPI != "3.1.0" {
t.Fatalf("%s openapi version = %q, want 3.1.0", path, spec.OpenAPI)
}
return spec
}