Ctrl K
ComunidadGuías…

internal/pluginhost/adapters_auth_body_slots_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package pluginhost

import (
	"bytes"
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/router-for-me/CLIProxyAPI/v8/internal/config"
)

// With every decode slot taken, a decoding request waits and gives up with its context.
func TestAccessAdapterDecodeWaitsForSlot(t *testing.T) {
	saved := authDecodeSlots
	authDecodeSlots = make(chan struct{}, 1)
	authDecodeSlots <- struct{}{}
	defer func() { authDecodeSlots = saved }()
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	_, calls, _, authErr := authenticateWithBody(ctx, t, http.MethodPost, "/v1/responses", zstdCompress(t, []byte(`{"model":"gpt-5"}`)), "zstd", 0)
	if authErr == nil || calls != 0 || len(authDecodeSlots) != 1 {
		t.Fatalf("err %v, plugin calls %d, slots held %d", authErr, calls, len(authDecodeSlots))
	}
}

// When a client cancels while a guarded RPC auth call is still running, the decode slot stays
// held until the underlying inner plugin call finishes.
func TestAccessAdapterCanceledRPCKeepsSlotUntilInnerCallFinishes(t *testing.T) {
	saved := authDecodeSlots
	authDecodeSlots = make(chan struct{}, 1)
	defer func() { authDecodeSlots = saved }()

	inner := &blockingGuardPluginClient{
		started: make(chan struct{}),
		release: make(chan struct{}),
	}
	guarded := newGuardedPluginClient(inner)
	host := New()
	host.runtimeConfig = &config.Config{}
	adapter := newAccessAdapterForTest(host, "auth-plugin", rpcFrontendAuthProvider{
		rpcPluginAdapter: &rpcPluginAdapter{
			id:     "auth-plugin",
			host:   host,
			client: guarded,
		},
	})

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	compressed := zstdCompress(t, []byte(`{"model":"gpt-5"}`))
	req := httptest.NewRequest(http.MethodPost, "/v1/responses", bytes.NewReader(compressed))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Content-Encoding", "zstd")

	authDone := make(chan struct{})
	go func() {
		_, _ = adapter.Authenticate(ctx, req)
		close(authDone)
	}()

	<-inner.started
	if len(authDecodeSlots) != 1 {
		t.Fatalf("slots held while inner call active = %d, want 1", len(authDecodeSlots))
	}

	cancel()
	<-authDone
	if len(authDecodeSlots) != 1 {
		t.Fatalf("slots held after canceled Authenticate returned while inner call still blocked = %d, want 1", len(authDecodeSlots))
	}

	close(inner.release)
	guarded.Shutdown()
	if len(authDecodeSlots) != 0 {
		t.Fatalf("slots held after inner call finished = %d, want 0", len(authDecodeSlots))
	}
}