package gateway import ( "testing" "llmsproxy/internal/types" ) // TestMergeUsageKeepsZeroCacheDetails locks the streaming counterpart of the // "distinguish missed from not reported" contract: a usage chunk that reports // prompt_tokens_details with 0 cached tokens must survive the merge, otherwise // streaming rows lose cache_reported and the UI shows "—" instead of 0%. func TestMergeUsageKeepsZeroCacheDetails(t *testing.T) { t.Run("zero-hit details survive merge", func(t *testing.T) { prev := &types.TokenUsage{Prompt: 10, Completion: 1, Total: 11} cur := &types.TokenUsage{ Prompt: 10, Completion: 5, Total: 15, PromptTokensDetails: &types.PromptTokensDetails{CachedTokens: 0}, } got := mergeUsage(prev, cur) if got.PromptTokensDetails == nil { t.Fatal("zero-hit prompt_tokens_details was dropped by mergeUsage") } if got.PromptTokensDetails.CachedTokens != 0 { t.Fatalf("cached_tokens = %d, want 0", got.PromptTokensDetails.CachedTokens) } }) t.Run("non-zero hit still wins", func(t *testing.T) { prev := &types.TokenUsage{Prompt: 10, Completion: 1, Total: 11} cur := &types.TokenUsage{ Prompt: 10, Completion: 5, Total: 15, PromptTokensDetails: &types.PromptTokensDetails{CachedTokens: 64}, } got := mergeUsage(prev, cur) if got.PromptTokensDetails == nil || got.PromptTokensDetails.CachedTokens != 64 { t.Fatalf("cached_tokens lost: %+v", got.PromptTokensDetails) } }) t.Run("absent details do not overwrite an earlier report", func(t *testing.T) { prev := &types.TokenUsage{ Prompt: 10, Completion: 1, Total: 11, PromptTokensDetails: &types.PromptTokensDetails{CachedTokens: 32}, } cur := &types.TokenUsage{Prompt: 10, Completion: 5, Total: 15} got := mergeUsage(prev, cur) if got.PromptTokensDetails == nil || got.PromptTokensDetails.CachedTokens != 32 { t.Fatalf("earlier cache report clobbered by a later chunk without details: %+v", got.PromptTokensDetails) } }) t.Run("no cache data anywhere stays nil", func(t *testing.T) { prev := &types.TokenUsage{Prompt: 10, Completion: 1, Total: 11} cur := &types.TokenUsage{Prompt: 10, Completion: 5, Total: 15} got := mergeUsage(prev, cur) if got.PromptTokensDetails != nil { t.Fatalf("fabricated cache details: %+v", got.PromptTokensDetails) } }) }