package plugin import ( "encoding/base64" "encoding/json" "fmt" "path/filepath" "sync" "testing" ) func lifecycleRequest(t *testing.T, schema uint32, config string) []byte { t.Helper() raw, err := json.Marshal(LifecycleRequest{ConfigYAML: []byte(config), SchemaVersion: schema}) if err != nil { t.Fatal(err) } return raw } func testConfig(t *testing.T, config string) string { t.Helper() return fmt.Sprintf("database_path: %q\n%s", filepath.Join(t.TempDir(), "usage.db"), config) } func TestRegisterNegotiatesSchemaAndDeclaresManagedAccessCapabilities(t *testing.T) { app := NewApp() raw, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, 99, testConfig(t, "enabled: true\ncodex_only: true\n"))) if err != nil { t.Fatal(err) } var env Envelope if err := json.Unmarshal(raw, &env); err != nil { t.Fatal(err) } if !env.OK { t.Fatalf("register failed: %s", raw) } var got Registration if err := json.Unmarshal(env.Result, &got); err != nil { t.Fatal(err) } if got.SchemaVersion != SchemaVersion || !got.Capabilities.FrontendAuthProvider || !got.Capabilities.FrontendAuthProviderExclusive || !got.Capabilities.Scheduler || !got.Capabilities.RequestInterceptor || !got.Capabilities.RequestLifecyclePlugin || !got.Capabilities.UsagePlugin || !got.Capabilities.ManagementAPI { t.Fatalf("unexpected registration: %+v", got) } } func TestLifecycleConfigYAMLUsesBase64WireEncoding(t *testing.T) { raw := lifecycleRequest(t, SchemaVersion, "enabled: true\n") if !json.Valid(raw) { t.Fatal("invalid JSON") } var wire map[string]any _ = json.Unmarshal(raw, &wire) want := base64.StdEncoding.EncodeToString([]byte("enabled: true\n")) if wire["config_yaml"] != want { t.Fatalf("config_yaml = %v, want %q", wire["config_yaml"], want) } } func TestReconfigureIsAtomicAndFiltersUsage(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: true\n"))); err != nil { t.Fatal(err) } for _, record := range []UsageRecord{{Provider: "codex", Model: "gpt-5.5"}, {Provider: "gemini", Model: "gemini-pro"}} { raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } } if got := app.Seen(); got != 1 { t.Fatalf("seen = %d, want 1", got) } if _, err := app.HandleMethod(MethodPluginReconfigure, lifecycleRequest(t, SchemaVersion, "enabled: [invalid")); err == nil { t.Fatal("invalid reconfiguration unexpectedly succeeded") } raw, _ := json.Marshal(UsageRecord{Provider: "codex", Model: "gpt-5.5"}) _, _ = app.HandleMethod(MethodUsageHandle, raw) if got := app.Seen(); got != 2 { t.Fatalf("last valid config was not retained: seen = %d", got) } } func TestConcurrentUsage(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: true\n"))); err != nil { t.Fatal(err) } raw, _ := json.Marshal(UsageRecord{Provider: "codex", Model: "gpt-5.5"}) var wg sync.WaitGroup for range 100 { wg.Add(1) go func() { defer wg.Done() if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Errorf("handle usage: %v", err) } }() } wg.Wait() if got := app.Seen(); got != 100 { t.Fatalf("seen = %d, want 100", got) } } func TestUnknownMethodReturnsErrorEnvelope(t *testing.T) { raw, err := NewApp().HandleMethod("missing", nil) if err != nil { t.Fatal(err) } var env Envelope if err := json.Unmarshal(raw, &env); err != nil { t.Fatal(err) } if env.OK || env.Error == nil || env.Error.Code != "unknown_method" { t.Fatalf("unexpected envelope: %s", raw) } } func TestUsageRequestTypeMatchesKeeperEndpointSemantics(t *testing.T) { tests := []struct { endpoint string want string }{ {endpoint: "POST /v1/responses", want: "SSE"}, {endpoint: "POST /v1/chat/completions", want: "SSE"}, {endpoint: "GET /v1/responses", want: "WS"}, {endpoint: "/v1/responses", want: ""}, } for _, test := range tests { if got := usageRequestType(test.endpoint); got != test.want { t.Fatalf("usageRequestType(%q) = %q, want %q", test.endpoint, got, test.want) } } }