package billing import ( "encoding/json" "testing" ) func TestCalculateTextPointsRoundsUpToPointCent(t *testing.T) { pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "100.0000", OutputPerM: "300.0000"} amount, err := CalculateTextPoints(pricing, TextUsage{Input: 120, Output: 30}) if err != nil { t.Fatal(err) } if amount != "0.03" { t.Fatalf("expected 0.03 points, got %s", amount) } amount, err = CalculateTextPoints(pricing, TextUsage{Input: 1}) if err != nil { t.Fatal(err) } if amount != "0.01" { t.Fatalf("expected minimum positive charge 0.01, got %s", amount) } } func TestTextPricingSnapshot(t *testing.T) { pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "1250.0000", OutputPerM: "2500.0000"} parsed, err := ParseTextPricingSnapshot(pricing.MarshalSnapshot()) if err != nil { t.Fatal(err) } if parsed != pricing { t.Fatalf("unexpected snapshot: %s", json.RawMessage(pricing.MarshalSnapshot())) } } func TestTextPricingSnapshotRejectsLegacyThousandTokenRates(t *testing.T) { _, err := ParseTextPricingSnapshot(json.RawMessage(`{"mode":"per_token","input_per_k":"0.1000","output_per_k":"0.3000","max_output_tokens":1000}`)) if err == nil { t.Fatal("expected legacy thousand-token snapshot to be rejected") } } func TestCalculateTextPointsUsesMillionTokens(t *testing.T) { pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "10", OutputPerM: "20"} amount, err := CalculateTextPoints(pricing, TextUsage{Input: 1_000_000}) if err != nil { t.Fatal(err) } if amount != "10.00" { t.Fatalf("expected 10.00 points for one million input tokens, got %s", amount) } } func TestCalculateTextReservePointsUsesDoubleInputAsEstimatedOutput(t *testing.T) { pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "10", OutputPerM: "20"} amount, err := CalculateTextReservePoints(pricing, 1_000_000) if err != nil { t.Fatal(err) } if amount != "50.00" { t.Fatalf("expected 50.00 points for input plus double-input output estimate, got %s", amount) } } func TestEstimateTextTokens(t *testing.T) { if got := EstimateTextTokens("中文ABCD"); got != 3 { t.Fatalf("expected 3 estimated tokens, got %d", got) } }