chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package billing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestValidatePriceInput(t *testing.T) {
|
||||
input := CreatePriceBookInput{
|
||||
TenantID: "10000000-0000-0000-0000-000000000010", Provider: "mock", Currency: "CNY",
|
||||
SourceRef: "contract://mock/2026-v1", ChangeSummary: "本地回归单价", EffectiveFrom: time.Now().UTC(),
|
||||
Rates: []RateInput{{UsageCategory: "LLM", MetricCode: "input_tokens", Unit: "token", UnitPriceMicros: 2}},
|
||||
}
|
||||
if err := validatePriceInput(input); err != nil {
|
||||
t.Fatalf("valid price input rejected: %v", err)
|
||||
}
|
||||
input.Rates = append(input.Rates, input.Rates[0])
|
||||
if err := validatePriceInput(input); !errors.Is(err, ErrInvalid) {
|
||||
t.Fatalf("duplicate rate error = %v, want ErrInvalid", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateQuotaInput(t *testing.T) {
|
||||
valid := QuotaInput{ScopeType: "TENANT", BillingTimezone: "Asia/Shanghai", Currency: "CNY", DailyLimitMicros: 10_000_000, MonthlyLimitMicros: 100_000_000, MaxConcurrentCalls: 10, MaxCallDurationSec: 3600, InProgressAction: "COMPLETE_CURRENT_TURN", ChangeSummary: "家庭试点额度"}
|
||||
if err := validateQuotaInput(valid); err != nil {
|
||||
t.Fatalf("valid quota rejected: %v", err)
|
||||
}
|
||||
for name, mutate := range map[string]func(*QuotaInput){
|
||||
"tenant scope id": func(item *QuotaInput) { item.ScopeID = "10000000-0000-0000-0000-000000000511" },
|
||||
"monthly below daily": func(item *QuotaInput) { item.MonthlyLimitMicros = item.DailyLimitMicros - 1 },
|
||||
"invalid timezone": func(item *QuotaInput) { item.BillingTimezone = "China/Unknown" },
|
||||
"short duration": func(item *QuotaInput) { item.MaxCallDurationSec = 59 },
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
item := valid
|
||||
mutate(&item)
|
||||
if err := validateQuotaInput(item); !errors.Is(err, ErrInvalid) {
|
||||
t.Fatalf("error = %v, want ErrInvalid", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsageQuantityPrecision(t *testing.T) {
|
||||
for _, value := range []string{"0", "1", "1000", "0.000001", "999999999999999999.999999"} {
|
||||
if !quantityPattern.MatchString(value) {
|
||||
t.Fatalf("valid quantity %q rejected", value)
|
||||
}
|
||||
}
|
||||
for _, value := range []string{"-1", "01", "1.0000001", "1e3", "9999999999999999999"} {
|
||||
if quantityPattern.MatchString(value) {
|
||||
t.Fatalf("invalid quantity %q accepted", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordProviderUsageValidation(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
if _, err := RecordProviderUsageTx(ctx, nil, "", "", "", "", "", time.Time{}, nil); !errors.Is(err, ErrInvalid) {
|
||||
t.Fatalf("empty usage error=%v", err)
|
||||
}
|
||||
metrics := []UsageMetricInput{
|
||||
{UsageCategory: " llm ", MetricCode: " INPUT_TOKENS ", Quantity: "12", Unit: " TOKEN "},
|
||||
{UsageCategory: "LLM", MetricCode: "input_tokens", Quantity: "13", Unit: "token"},
|
||||
}
|
||||
if _, err := RecordProviderUsageTx(ctx, nil,
|
||||
"10000000-0000-0000-0000-000000000001", "10000000-0000-0000-0000-000000000901",
|
||||
"10000000-0000-0000-0000-000000000902", "mock", "usage-validation", time.Now().UTC(), metrics,
|
||||
); !errors.Is(err, ErrInvalid) {
|
||||
t.Fatalf("duplicate metric error=%v", err)
|
||||
}
|
||||
metrics = []UsageMetricInput{{UsageCategory: "UNKNOWN", MetricCode: "input_tokens", Quantity: "1", Unit: "token"}}
|
||||
if _, err := RecordProviderUsageTx(ctx, nil,
|
||||
"10000000-0000-0000-0000-000000000001", "10000000-0000-0000-0000-000000000901",
|
||||
"10000000-0000-0000-0000-000000000902", "mock", "usage-validation", time.Now().UTC(), metrics,
|
||||
); !errors.Is(err, ErrInvalid) {
|
||||
t.Fatalf("invalid category error=%v", err)
|
||||
}
|
||||
if _, err := NewService(nil, nil); err == nil {
|
||||
t.Fatal("invalid billing service dependencies were accepted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user