Files
llm-intelligence/cmd/server/main_test.go
phamnazage-jpg 5c5578a19b
Some checks failed
CI / go-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / docker-build (push) Has been cancelled
feat(region_pricing): 扩展非 token 统一计费字段,支持语音按字符/秒计费
- 新增 region_pricing.pricing_mode / price_unit / flat_price 字段
- 新增 migration 016_region_pricing_non_token_units.sql
- officialPricingRecord 新增 PricingMode/PriceUnit/FlatPrice 字段
- detectModality 新增 audio 模态检测(voice/audio/speech)
- providerMetadata 新增 BAAI/ByteDance/China Mobile 元数据
- import_mobile_cloud_pricing.go: 解析语音计费表(CosyVoice/SenseVoice)
  - CosyVoice: 2元/万字符 → pricingMode=flat, priceUnit=10k_characters
  - SenseVoice: 0.0007元/秒 → pricingMode=flat, priceUnit=second
- mobileCloudProviderName 新增 cosyvoice/sensevoice → Alibaba 映射
- cmd/server: modelResponse 新增 pricingMode/priceUnit/flatPrice,API 字段说明同步更新
- 新增 TestModelsHandlerReturnsFlatPricingFields 测试
2026-05-22 14:51:38 +08:00

214 lines
5.9 KiB
Go

package main
import (
"context"
"database/sql"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
)
func TestModelsHandlerReturnsFlatPricingFields(t *testing.T) {
mux := newMux(
&sql.DB{},
func(context.Context, *sql.DB) ([]modelResponse, error) {
return []modelResponse{{
ID: "mobile-cloud-huabei-huhehaote-cosyvoice",
Name: "CosyVoice",
Provider: "Alibaba",
ProviderCN: "阿里云",
Modality: "audio",
PricingMode: "flat",
PriceUnit: "10k_characters",
FlatPrice: 2,
Currency: "CNY",
IsFree: false,
DataConfidence: "official",
}}, nil
},
func(context.Context, *sql.DB) ([]subscriptionPlanResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) (*latestReportResponse, error) {
return nil, sql.ErrNoRows
},
)
req := httptest.NewRequest(http.MethodGet, "/api/v1/models", nil)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d", rec.Code)
}
var payload struct {
Data []modelResponse `json:"data"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal response: %v", err)
}
if len(payload.Data) != 1 {
t.Fatalf("expected 1 model, got %d", len(payload.Data))
}
got := payload.Data[0]
if got.PricingMode != "flat" || got.PriceUnit != "10k_characters" || got.FlatPrice != 2 {
t.Fatalf("unexpected flat pricing payload: %+v", got)
}
}
func TestSubscriptionPlansHandlerReturnsEnvelope(t *testing.T) {
mux := newMux(
&sql.DB{},
func(context.Context, *sql.DB) ([]modelResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) ([]subscriptionPlanResponse, error) {
return []subscriptionPlanResponse{
{
PlanFamily: "token_plan",
PlanCode: "token-plan-lite",
PlanName: "通用 Token Plan Lite",
Tier: "Lite",
Provider: "Tencent",
ProviderCN: "腾讯",
Operator: "Tencent Cloud",
OperatorCN: "腾讯云",
Currency: "CNY",
ListPrice: 39,
PriceUnit: "CNY/month",
QuotaValue: 35000000,
QuotaUnit: "tokens/month",
ContextWindow: 0,
ModelScope: []string{"tc-code-latest", "glm-5", "glm-5.1"},
SourceURL: "https://cloud.tencent.com/document/product/1823/130060",
EffectiveDate: "2026-04-27",
},
}, nil
},
func(context.Context, *sql.DB) (*latestReportResponse, error) {
return nil, sql.ErrNoRows
},
)
req := httptest.NewRequest(http.MethodGet, "/api/v1/subscription-plans", nil)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d", rec.Code)
}
var payload struct {
Data []subscriptionPlanResponse `json:"data"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal response: %v", err)
}
if len(payload.Data) != 1 {
t.Fatalf("expected 1 plan, got %d", len(payload.Data))
}
got := payload.Data[0]
if got.PlanCode != "token-plan-lite" {
t.Fatalf("unexpected plan code: %q", got.PlanCode)
}
if got.ProviderCN != "腾讯" {
t.Fatalf("unexpected providerCN: %q", got.ProviderCN)
}
if got.OperatorCN != "腾讯云" {
t.Fatalf("unexpected operatorCN: %q", got.OperatorCN)
}
if got.ListPrice != 39 {
t.Fatalf("unexpected list price: %v", got.ListPrice)
}
if len(got.ModelScope) != 3 {
t.Fatalf("unexpected model scope length: %d", len(got.ModelScope))
}
}
func TestLatestReportHandlerReturnsEnvelope(t *testing.T) {
mux := newMux(
&sql.DB{},
func(context.Context, *sql.DB) ([]modelResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) ([]subscriptionPlanResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) (*latestReportResponse, error) {
return &latestReportResponse{
ReportDate: "2026-05-13",
Status: "generated",
ModelCount: 504,
MarkdownPath: "reports/daily/daily_report_2026-05-13.md",
HTMLPath: "reports/daily/html/daily_report_2026-05-13.html",
MarkdownURL: "/api/v1/reports/latest/markdown",
HTMLURL: "/api/v1/reports/latest/html",
}, nil
},
)
req := httptest.NewRequest(http.MethodGet, "/api/v1/reports/latest", nil)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d", rec.Code)
}
var payload struct {
Data latestReportResponse `json:"data"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal response: %v", err)
}
if payload.Data.ReportDate != "2026-05-13" {
t.Fatalf("unexpected report date: %q", payload.Data.ReportDate)
}
if payload.Data.HTMLURL != "/api/v1/reports/latest/html" {
t.Fatalf("unexpected html url: %q", payload.Data.HTMLURL)
}
}
func TestLatestReportHTMLHandlerServesArtifact(t *testing.T) {
tempDir := t.TempDir()
htmlPath := tempDir + "/daily_report_2026-05-13.html"
if err := os.WriteFile(htmlPath, []byte("<html><body>ok</body></html>"), 0644); err != nil {
t.Fatalf("write temp html: %v", err)
}
mux := newMux(
&sql.DB{},
func(context.Context, *sql.DB) ([]modelResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) ([]subscriptionPlanResponse, error) {
return nil, nil
},
func(context.Context, *sql.DB) (*latestReportResponse, error) {
return &latestReportResponse{
ReportDate: "2026-05-13",
Status: "generated",
MarkdownPath: tempDir + "/daily_report_2026-05-13.md",
HTMLPath: htmlPath,
}, nil
},
)
req := httptest.NewRequest(http.MethodGet, "/api/v1/reports/latest/html", nil)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d", rec.Code)
}
if body := rec.Body.String(); body != "<html><body>ok</body></html>" {
t.Fatalf("unexpected body: %q", body)
}
}