usage_contract_test.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. //go:build unit
  2. package antigravity
  3. import (
  4. "strings"
  5. "testing"
  6. "github.com/stretchr/testify/require"
  7. )
  8. // Gemini usageMetadata 只有 cachedContentTokenCount(缓存命中),没有缓存写入的 token 类别:
  9. // 两条转换路径产出的 Claude usage 中 cache_creation_input_tokens 恒为 0,缓存命中计入
  10. // cache_read_input_tokens 并从 input_tokens 中扣除。
  11. func TestGeminiUsageMapping_NoCacheCreationTokens(t *testing.T) {
  12. const geminiBody = `{"candidates":[{"content":{"parts":[{"text":"hi"}],"role":"model"},"finishReason":"STOP"}],` +
  13. `"usageMetadata":{"promptTokenCount":100,"candidatesTokenCount":20,"cachedContentTokenCount":30,"thoughtsTokenCount":5}}`
  14. t.Run("non-stream", func(t *testing.T) {
  15. _, usage, err := TransformGeminiToClaude([]byte(geminiBody), "gemini-3.1-pro-preview")
  16. require.NoError(t, err)
  17. require.NotNil(t, usage)
  18. require.Equal(t, 70, usage.InputTokens)
  19. require.Equal(t, 25, usage.OutputTokens)
  20. require.Equal(t, 30, usage.CacheReadInputTokens)
  21. require.Zero(t, usage.CacheCreationInputTokens)
  22. })
  23. t.Run("stream", func(t *testing.T) {
  24. p := NewStreamingProcessor("gemini-3.1-pro-preview")
  25. out := p.ProcessLine(`data: {"response":` + geminiBody + `}`)
  26. require.True(t, strings.Contains(string(out), `"message_start"`))
  27. require.NotContains(t, string(out), `"cache_creation_input_tokens"`, "message_start 的 usage 不应携带缓存写入分项")
  28. _, usage := p.Finish()
  29. require.NotNil(t, usage)
  30. require.Equal(t, 70, usage.InputTokens)
  31. require.Equal(t, 30, usage.CacheReadInputTokens)
  32. require.Zero(t, usage.CacheCreationInputTokens)
  33. })
  34. }