Files
llm-intelligence/scripts/import_azure_openai_pricing_test.go

147 lines
4.1 KiB
Go
Raw Normal View History

//go:build llm_script
package main
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
)
func TestParseAzureOpenAIPricingCatalogBuildsRecords(t *testing.T) {
raw, err := os.ReadFile(filepath.Join("testdata", "azure_openai_pricing_sample.json"))
if err != nil {
t.Fatalf("读取 fixture 失败: %v", err)
}
records, err := parseAzureOpenAIPricingCatalog(string(raw))
if err != nil {
t.Fatalf("parseAzureOpenAIPricingCatalog 返回错误: %v", err)
}
if len(records) != 2 {
t.Fatalf("期望 2 条 Azure OpenAI 价格记录,实际 %d", len(records))
}
if records[0].InputPrice != 2.2 || records[0].OutputPrice != 8.8 {
t.Fatalf("gpt-4.1 价格换算错误: %v / %v", records[0].InputPrice, records[0].OutputPrice)
}
if records[1].ModelName != "GPT-5" {
t.Fatalf("第二条模型名错误: %q", records[1].ModelName)
}
}
func TestRunAzureOpenAIPricingImportDryRunPrintsSummary(t *testing.T) {
var out bytes.Buffer
err := runAzureOpenAIPricingImport(azureOpenAIPricingImportConfig{
URL: defaultAzureOpenAIPricingURL,
Fixture: filepath.Join("testdata", "azure_openai_pricing_sample.json"),
DryRun: true,
}, nil, &out)
if err != nil {
t.Fatalf("runAzureOpenAIPricingImport 返回错误: %v", err)
}
output := out.String()
for _, want := range []string{
"source=azure-openai-pricing-import",
"models=2",
"operator=Microsoft Azure",
"dry_run=true",
} {
if !strings.Contains(output, want) {
t.Fatalf("输出缺少 %q实际: %q", want, output)
}
}
}
func TestRunAzureOpenAIPricingImportDryRunFollowsNextPageLink(t *testing.T) {
pageTwoPath := "/page-2"
var server *httptest.Server
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
response := azureRetailPriceResponse{}
switch r.URL.Path {
case "/":
response = azureRetailPriceResponse{
Items: []azureRetailPriceItem{
{
CurrencyCode: "USD",
UnitPrice: 0.0022,
Location: "US East",
MeterName: "gpt 4.1 Inp regnl Tokens",
ProductName: "Azure OpenAI",
SkuName: "gpt 4.1 Inp regnl",
ServiceName: "Foundry Models",
UnitOfMeasure: "1K",
Type: "Consumption",
ArmSkuName: "gpt 4.1 Inp regnl",
},
{
CurrencyCode: "USD",
UnitPrice: 0.0088,
Location: "US East",
MeterName: "gpt 4.1 Outp regnl Tokens",
ProductName: "Azure OpenAI",
SkuName: "gpt 4.1 Outp regnl",
ServiceName: "Foundry Models",
UnitOfMeasure: "1K",
Type: "Consumption",
ArmSkuName: "gpt 4.1 Outp regnl",
},
},
NextPageLink: server.URL + pageTwoPath,
}
case pageTwoPath:
response = azureRetailPriceResponse{
Items: []azureRetailPriceItem{
{
CurrencyCode: "USD",
UnitPrice: 1.25,
Location: "US West",
MeterName: "GPT 5 inp Glbl 1M Tokens",
ProductName: "Azure OpenAI GPT5",
SkuName: "GPT 5 inp Glbl",
ServiceName: "Foundry Models",
UnitOfMeasure: "1M",
Type: "Consumption",
ArmSkuName: "GPT 5 inp Glbl",
},
{
CurrencyCode: "USD",
UnitPrice: 10,
Location: "US West",
MeterName: "GPT 5 outpt Glbl 1M Tokens",
ProductName: "Azure OpenAI GPT5",
SkuName: "GPT 5 outpt Glbl",
ServiceName: "Foundry Models",
UnitOfMeasure: "1M",
Type: "Consumption",
ArmSkuName: "GPT 5 outpt Glbl",
},
},
}
default:
t.Fatalf("unexpected path: %s", r.URL.Path)
}
if err := json.NewEncoder(w).Encode(response); err != nil {
t.Fatalf("encode response: %v", err)
}
}))
defer server.Close()
var out bytes.Buffer
err := runAzureOpenAIPricingImport(azureOpenAIPricingImportConfig{
URL: server.URL,
DryRun: true,
}, nil, &out)
if err != nil {
t.Fatalf("runAzureOpenAIPricingImport 返回错误: %v", err)
}
if !strings.Contains(out.String(), "models=2") {
t.Fatalf("分页结果未聚合,输出: %q", out.String())
}
}