| 37 | } |
| 38 | |
| 39 | func TestConvert(t *testing.T) { |
| 40 | t.Parallel() |
| 41 | |
| 42 | const upstreamJSON = `{ |
| 43 | "anthropic": { |
| 44 | "models": { |
| 45 | "claude-sonnet-4-7": { |
| 46 | "cost": {"input": 3, "output": 15, "cache_read": 0.3, "cache_write": 3.75} |
| 47 | }, |
| 48 | "claude-haiku": { |
| 49 | "cost": {"input": 0.8, "output": 4} |
| 50 | } |
| 51 | } |
| 52 | }, |
| 53 | "openai": { |
| 54 | "models": { |
| 55 | "gpt-4o": {"cost": {"input": 2.5, "output": 10, "cache_read": 1.25}}, |
| 56 | "gpt-no-prices": {} |
| 57 | } |
| 58 | }, |
| 59 | "alibaba": { |
| 60 | "models": { |
| 61 | "should-be-ignored": {"cost": {"input": 1, "output": 1}} |
| 62 | } |
| 63 | } |
| 64 | }` |
| 65 | |
| 66 | var upstream map[string]upstreamProvider |
| 67 | require.NoError(t, json.Unmarshal([]byte(upstreamJSON), &upstream)) |
| 68 | |
| 69 | rows, err := convert(upstream, []string{"anthropic", "openai"}) |
| 70 | require.NoError(t, err) |
| 71 | |
| 72 | // alibaba is dropped (not a supported provider) and gpt-no-prices is |
| 73 | // dropped (no per-token pricing), leaving three priced rows. |
| 74 | require.Len(t, rows, 3) |
| 75 | |
| 76 | // Sorted (provider, model). |
| 77 | require.Equal(t, "anthropic", rows[0].Provider) |
| 78 | require.Equal(t, "claude-haiku", rows[0].Model) |
| 79 | require.Equal(t, "anthropic", rows[1].Provider) |
| 80 | require.Equal(t, "claude-sonnet-4-7", rows[1].Model) |
| 81 | require.Equal(t, "openai", rows[2].Provider) |
| 82 | require.Equal(t, "gpt-4o", rows[2].Model) |
| 83 | |
| 84 | // All four prices populated for Anthropic Sonnet. |
| 85 | sonnet := rows[1] |
| 86 | require.Equal(t, int64(3_000_000), *sonnet.InputPrice) |
| 87 | require.Equal(t, int64(15_000_000), *sonnet.OutputPrice) |
| 88 | require.Equal(t, int64(300_000), *sonnet.CacheReadPrice) |
| 89 | require.Equal(t, int64(3_750_000), *sonnet.CacheWritePrice) |
| 90 | |
| 91 | // Missing keys stay nil for OpenAI gpt-4o. |
| 92 | gpt := rows[2] |
| 93 | require.Equal(t, int64(2_500_000), *gpt.InputPrice) |
| 94 | require.Equal(t, int64(10_000_000), *gpt.OutputPrice) |
| 95 | require.Equal(t, int64(1_250_000), *gpt.CacheReadPrice) |
| 96 | require.Nil(t, gpt.CacheWritePrice) |