Files
new-api-custom/setting/billing_setting/builtin_billing_test.go
T
cneicy a5f7b8e586
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 1m40s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 42m16s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
feat: sync deployed v1.0.0-rc.38-custom.42
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
2026-09-26 04:49:11 +08:00

151 lines
6.9 KiB
Go

package billing_setting_test
import (
"net/http/httptest"
"testing"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/controller"
"github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/pkg/billingexpr"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/setting/billing_setting"
"github.com/QuantumNous/new-api/setting/config"
"github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGPT6AstraBuiltinBilling(t *testing.T) {
settings := config.GlobalConfig.Get("billing_setting").(*billing_setting.BillingSetting)
saved := *settings
savedRatios, savedPrices := ratio_setting.ModelRatio2JSONString(), ratio_setting.ModelPrice2JSONString()
savedOptions := common.OptionMap
t.Cleanup(func() {
*settings, common.OptionMap = saved, savedOptions
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(savedRatios))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(savedPrices))
})
common.OptionMap = map[string]string{"billing_setting.billing_mode": `{}`, "billing_setting.billing_expr": `{}`}
require.NoError(t, config.GlobalConfig.LoadFromDB(common.OptionMap))
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(`{}`))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(`{}`))
assert.Equal(t, billing_setting.BillingModeTieredExpr, billing_setting.GetBillingMode("gpt-6-astra"))
expression, ok := billing_setting.GetBillingExpr("gpt-6-astra")
require.True(t, ok)
for _, tc := range []struct {
name string
input, output, cached, written int
request string
quota int
}{
{"standard", 1000, 100, 0, 0, `{}`, 7500},
{"client flex cannot discount standard pricing", 1000, 100, 0, 0, `{"service_tier":"flex"}`, 7500},
{"cache at context boundary", 272000, 1000, 200000, 20000, `{}`, 510000},
{"whole request above boundary", 272001, 1000, 200000, 20000, `{}`, 1007510},
} {
t.Run(tc.name, func(t *testing.T) {
usage := &dto.Usage{
PromptTokens: tc.input, CompletionTokens: tc.output,
PromptTokensDetails: dto.InputTokenDetails{CachedTokens: tc.cached, CacheWriteTokens: tc.written},
}
params := service.BuildTieredTokenParams(usage, false, billingexpr.UsedVars(expression))
result, err := billingexpr.ComputeTieredQuotaWithRequest(&billingexpr.BillingSnapshot{
ExprString: expression, GroupRatio: 1, QuotaPerUnit: 500000,
}, params, billingexpr.RequestInput{Body: []byte(tc.request)})
require.NoError(t, err)
assert.Equal(t, tc.quota, result.ActualQuotaAfterGroup)
})
}
t.Run("admin options expose defaults without persisting them", func(t *testing.T) {
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
controller.GetOptions(ctx)
var response struct {
Success bool
Data []model.Option
}
require.NoError(t, common.Unmarshal(recorder.Body.Bytes(), &response))
require.True(t, response.Success)
found := map[string]string{}
for _, option := range response.Data {
if _, ok := common.OptionMap[option.Key]; ok {
assert.NotContains(t, found, option.Key)
var values map[string]string
require.NoError(t, common.UnmarshalJsonStr(option.Value, &values))
found[option.Key] = values["gpt-6-astra"]
assert.Equal(t, `{}`, common.OptionMap[option.Key])
}
}
assert.Equal(t, map[string]string{"billing_setting.billing_mode": "tiered_expr", "billing_setting.billing_expr": expression}, found)
})
for _, tc := range []struct {
name, mode, expr, ratios, prices, wantMode string
}{
{"custom expression overrides legacy price", "tiered_expr", "p * 7", `{"gpt-6-astra":8}`, `{}`, "tiered_expr"},
{"explicit ratio mode", "ratio", "", `{}`, `{}`, "ratio"},
{"existing free token price", "", "", `{"gpt-6-astra":0}`, `{}`, "ratio"},
{"existing per-call price", "", "", `{}`, `{"gpt-6-astra":0.1}`, "ratio"},
} {
t.Run(tc.name, func(t *testing.T) {
*settings = billing_setting.BillingSetting{BillingMode: map[string]string{}, BillingExpr: map[string]string{}}
if tc.mode != "" {
settings.BillingMode["gpt-6-astra"] = tc.mode
}
if tc.expr != "" {
settings.BillingExpr["gpt-6-astra"] = tc.expr
}
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(tc.ratios))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(tc.prices))
assert.Equal(t, tc.wantMode, billing_setting.GetBillingMode("gpt-6-astra"))
actual, ok := billing_setting.GetBillingExpr("gpt-6-astra")
assert.Equal(t, tc.expr, actual)
assert.Equal(t, tc.expr != "", ok)
})
}
}
func TestImageModelBuiltinPricesAndOverrides(t *testing.T) {
settings := config.GlobalConfig.Get("billing_setting").(*billing_setting.BillingSetting)
saved := *settings
savedRatios, savedPrices := ratio_setting.ModelRatio2JSONString(), ratio_setting.ModelPrice2JSONString()
t.Cleanup(func() {
*settings = saved
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(savedRatios))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(savedPrices))
})
for _, name := range []string{"gpt-image-2", "gpt-image-2.5-sunburst", "gpt-image-2.5-flare"} {
t.Run(name, func(t *testing.T) {
*settings = billing_setting.BillingSetting{BillingMode: map[string]string{}, BillingExpr: map[string]string{}}
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(`{}`))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(`{}`))
expression, ok := billing_setting.GetBillingExpr(name)
require.True(t, ok)
usage := &dto.Usage{PromptTokens: 1000, CompletionTokens: 100, PromptTokensDetails: dto.InputTokenDetails{
CachedTokens: 300, ImageTokens: 600, CachedTokensDetails: &dto.CachedTokenDetails{ImageTokens: common.GetPointer(200)},
}}
result, err := billingexpr.ComputeTieredQuota(&billingexpr.BillingSnapshot{ExprString: expression, ExprHash: billingexpr.ExprHashString(expression), GroupRatio: 1, QuotaPerUnit: 500000},
service.BuildTieredTokenParams(usage, false, billingexpr.UsedVars(expression)))
require.NoError(t, err)
assert.Equal(t, 4113, result.ActualQuotaAfterGroup)
encoded, err := common.Marshal(map[string]float64{name: 0})
require.NoError(t, err)
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(string(encoded)))
assert.Equal(t, "ratio", billing_setting.GetBillingMode(name))
require.NoError(t, ratio_setting.UpdateModelRatioByJSONString(`{}`))
require.NoError(t, ratio_setting.UpdateModelPriceByJSONString(string(encoded)))
assert.Equal(t, "ratio", billing_setting.GetBillingMode(name))
settings.BillingMode[name] = "tiered_expr"
settings.BillingExpr[name] = `tier("custom", p * 7)`
actual, ok := billing_setting.GetBillingExpr(name)
require.True(t, ok)
assert.Equal(t, settings.BillingExpr[name], actual)
})
}
}