package billing import ( "encoding/json" "errors" "os" "testing" ) func TestBillingCoreFixtureIsConsumedByGo(t *testing.T) { data, err := os.ReadFile("../../../contracts/billing/core-v1.json") if err != nil { t.Fatal(err) } var fixture struct { Currency string `json:"currency"` MoneyUnit string `json:"moneyUnit"` Statuses struct { InsufficientBalance int `json:"insufficientBalance"` IdempotencyConflict int `json:"idempotencyConflict"` } `json:"statuses"` IdempotencyKeys struct { Charge string `json:"charge"` Refund string `json:"refund"` } `json:"idempotencyKeys"` } if err := json.Unmarshal(data, &fixture); err != nil { t.Fatal(err) } if fixture.Currency != CurrencyCNY || fixture.MoneyUnit != "fen" || fixture.Statuses.InsufficientBalance != 402 || fixture.Statuses.IdempotencyConflict != 409 || fixture.IdempotencyKeys.Charge != "job-charge:{jobId}" || fixture.IdempotencyKeys.Refund != "job-refund:{jobId}" { t.Fatalf("fixture = %#v", fixture) } } func TestCatalogQuotesMostSpecificRuleWithCeiledQuantityAndTierFactors(t *testing.T) { catalog := Catalog{Rules: []PriceRule{ {ID: "generic", Provider: "evolink", Capability: "image.generate", Unit: UnitImage, StandardUnitPriceFen: 10, MarkupMultiplier: 1.2, Enabled: true}, {ID: "specific", Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2", Unit: UnitImage, QuantitySource: QuantityImageCount, StandardUnitPriceFen: 34, MarkupMultiplier: 1.2, Enabled: true, Conditions: Conditions{"quality": "high"}, Dimensions: []ParameterDimension{ {Key: "quality", Tiers: []ParameterTier{{Value: "high", StandardFactor: 4, MarkupMultiplier: 1.5, Enabled: true}}}, {Key: "resolution", DefaultValue: "1K", Tiers: []ParameterTier{{Value: "1K", StandardFactor: 2, MarkupMultiplier: 1.8, Enabled: true}}}, }}, }} quote, err := catalog.Quote(QuoteInput{Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2", Parameters: Parameters{"quality": "HIGH", "imageCount": 1.2}}) if err != nil { t.Fatal(err) } if quote.PriceRuleID != "specific" || quote.Quantity != 2 || quote.StandardUnitPriceFen != 272 || quote.MarkupMultiplier != 1.8 || quote.AmountFen != 980 || quote.Currency != CurrencyCNY { t.Fatalf("quote = %#v", quote) } } func TestCatalogRejectsAmbiguousWinners(t *testing.T) { rules := []PriceRule{ {ID: "a", Provider: "bailian", Capability: "image.generate", Unit: UnitRequest, StandardUnitPriceFen: 1, MarkupMultiplier: 1, Enabled: true}, {ID: "b", Provider: "bailian", Capability: "image.generate", Unit: UnitRequest, StandardUnitPriceFen: 2, MarkupMultiplier: 1, Enabled: true}, } _, err := (Catalog{Rules: rules}).Quote(QuoteInput{Provider: "bailian", Capability: "image.generate"}) if !errors.Is(err, ErrAmbiguousPriceRule) { t.Fatalf("error = %v", err) } } func TestCatalogExemptsDisabledMockAndSuperAdmin(t *testing.T) { rule := PriceRule{ID: "r", Provider: "bailian", Capability: "image.generate", Unit: UnitRequest, StandardUnitPriceFen: 10, MarkupMultiplier: 1, Enabled: true} for _, input := range []QuoteInput{ {BillingDisabled: true, Provider: "bailian", Capability: "image.generate"}, {Provider: "mock", Capability: "image.generate"}, } { quote, err := (Catalog{Rules: []PriceRule{rule}}).Quote(input) if err != nil || quote != nil { t.Fatalf("Quote(%#v) = %#v, %v", input, quote, err) } } quote, err := (Catalog{Rules: []PriceRule{rule}}).Quote(QuoteInput{Provider: "bailian", Capability: "image.generate", Source: "platform", Role: "super_admin"}) if err != nil || quote == nil || !quote.QuotaExempt { t.Fatalf("quote = %#v, %v", quote, err) } } func TestCatalogMatchesLegacyVariantKeyAsEffectiveConditions(t *testing.T) { rules := []PriceRule{ {ID: "720", Provider: "seedance", Capability: "video.generate", ReqKey: "seedance-2", VariantKey: "resolution=720p", Unit: UnitVideoSecond, StandardUnitPriceFen: 99, MarkupMultiplier: 1.2, Enabled: true}, {ID: "1080", Provider: "seedance", Capability: "video.generate", ReqKey: "seedance-2", VariantKey: "resolution=1080p", Unit: UnitVideoSecond, StandardUnitPriceFen: 248, MarkupMultiplier: 1.2, Enabled: true}, } quote, err := (Catalog{Rules: rules}).Quote(QuoteInput{ Provider: "seedance", Capability: "video.generate", ReqKey: "seedance-2", Parameters: Parameters{"resolution": " 720P ", "duration": 5.0}, }) if err != nil { t.Fatal(err) } if quote.PriceRuleID != "720" || quote.VariantKey != "resolution=720p" || quote.AmountFen != 594 { t.Fatalf("quote = %#v", quote) } if quote.Conditions["resolution"] != "720p" { t.Fatalf("effective conditions = %#v", quote.Conditions) } } func TestCatalogExplicitConditionsOverrideLegacyVariantKey(t *testing.T) { rule := PriceRule{ID: "override", Provider: "seedance", Capability: "video.generate", VariantKey: "resolution=720p", Conditions: Conditions{"resolution": "1080p"}, Unit: UnitRequest, StandardUnitPriceFen: 1, MarkupMultiplier: 1, Enabled: true} quote, err := (Catalog{Rules: []PriceRule{rule}}).Quote(QuoteInput{Provider: "seedance", Capability: "video.generate", Parameters: Parameters{"resolution": "1080P"}}) if err != nil || quote == nil || quote.Conditions["resolution"] != "1080p" { t.Fatalf("quote = %#v, err = %v", quote, err) } }