Files
CLIProxyAPI/internal/runtime/executor/helps/claude_code_session_test.go
Luis Pater 7c390a7a2e feat(runtime): add Claude Code session handling with caching and tests
- Introduced `ClaudeCodeSessionID` resolution logic, preferring headers over payload metadata.
- Added `ClaudeCodePromptCache` to map sessions to stable prompt cache keys.
- Refactored existing logic to integrate `ClaudeCodePromptCache` for session-based handling.
- Included extensive unit tests to validate session ID extraction, cache reuse, and header prioritization.
2026-06-23 13:19:13 +08:00

62 lines
2.1 KiB
Go

package helps
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
func TestExtractClaudeCodeSessionIDFromPayloadJSON(t *testing.T) {
payload := []byte(`{"metadata":{"user_id":"{\"device_id\":\"d\",\"session_id\":\"cache-session-1\"}"}}`)
got := ExtractClaudeCodeSessionID(context.Background(), payload, nil)
if got != "cache-session-1" {
t.Fatalf("ExtractClaudeCodeSessionID() = %q, want cache-session-1", got)
}
}
func TestExtractClaudeCodeSessionIDFromHeader(t *testing.T) {
recorder := httptest.NewRecorder()
ginCtx, _ := gin.CreateTestContext(recorder)
ginCtx.Request = httptest.NewRequest(http.MethodPost, "/v1/messages", nil)
ginCtx.Request.Header.Set(ClaudeCodeSessionHeader, "header-session-1")
ctx := context.WithValue(context.Background(), "gin", ginCtx)
got := ExtractClaudeCodeSessionID(ctx, []byte(`{"model":"gpt-5.4"}`), nil)
if got != "header-session-1" {
t.Fatalf("ExtractClaudeCodeSessionID() = %q, want header-session-1", got)
}
}
func TestClaudeCodePromptCacheStableAcrossRequests(t *testing.T) {
ctx := context.Background()
payload := []byte(`{"metadata":{"user_id":"{\"session_id\":\"cache-session-2\"}"}}`)
first, ok, err := ClaudeCodePromptCache(ctx, "grok-composer-2.5-fast", payload, nil)
if err != nil {
t.Fatalf("ClaudeCodePromptCache first error: %v", err)
}
if !ok || first.ID == "" {
t.Fatalf("ClaudeCodePromptCache first = %#v, ok=%v, want cached id", first, ok)
}
second, ok, err := ClaudeCodePromptCache(ctx, "grok-composer-2.5-fast", payload, nil)
if err != nil {
t.Fatalf("ClaudeCodePromptCache second error: %v", err)
}
if !ok || second.ID != first.ID {
t.Fatalf("second cache id = %q, want %q", second.ID, first.ID)
}
}
func TestExtractClaudeCodeSessionIDPrefersHeaderOverPayload(t *testing.T) {
payload := []byte(`{"metadata":{"user_id":"{"session_id":"payload-session"}"}}`)
headers := http.Header{}
headers.Set(ClaudeCodeSessionHeader, "header-session")
got := ExtractClaudeCodeSessionID(context.Background(), payload, headers)
if got != "header-session" {
t.Fatalf("ExtractClaudeCodeSessionID() = %q, want header-session", got)
}
}