Files
NianAIGC/backend/internal/billing/catalog_test.go

107 lines
5.2 KiB
Go

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)
}
}