172 lines
5.4 KiB
Go
172 lines
5.4 KiB
Go
package pack
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPublishProviderManifestWritesProviderBumpsPackAndCommits(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if _, err := exec.LookPath("git"); err != nil {
|
|
t.Skip("git is required for publish test")
|
|
}
|
|
|
|
repoRoot := t.TempDir()
|
|
packDir := filepath.Join(repoRoot, "packs", "openai-cn-pack")
|
|
createPackFixtureAt(t, packDir, map[string]string{
|
|
"pack.json": `{
|
|
"pack_id": "openai-cn-pack",
|
|
"version": "1.1.4",
|
|
"vendor": "YourTeam",
|
|
"target_host": "sub2api",
|
|
"min_host_version": "0.1.126",
|
|
"max_host_version": "0.2.x",
|
|
"providers_dir": "providers",
|
|
"checksum_file": "checksums.txt"
|
|
}`,
|
|
"providers/minimax-53hk.json": `{
|
|
"provider_id": "minimax-53hk",
|
|
"display_name": "MiniMax 53hk 中转兼容",
|
|
"base_url": "https://api.53hk.cn/v1",
|
|
"platform": "openai",
|
|
"account_type": "apikey",
|
|
"default_models": ["MiniMax-M2.7-highspeed"],
|
|
"smoke_test_model": "MiniMax-M2.7-highspeed",
|
|
"group_template": {"name": "g", "rate_multiplier": 1.0},
|
|
"channel_template": {"name": "c", "model_mapping": {"MiniMax-M2.7-highspeed": "MiniMax-M2.7-highspeed"}},
|
|
"plan_template": {"name": "p", "price": 1, "validity_days": 30, "validity_unit": "day"},
|
|
"import": {"supports_multi_key": true, "supports_strict": true, "supports_partial": true}
|
|
}`,
|
|
})
|
|
initGitRepo(t, repoRoot)
|
|
|
|
result, err := PublishProviderManifest(context.Background(), PublishProviderManifestRequest{
|
|
RepoRoot: repoRoot,
|
|
PackID: "openai-cn-pack",
|
|
Manifest: ProviderManifest{
|
|
ProviderID: "openai-zhongzhuan",
|
|
DisplayName: "OpenAI 中转",
|
|
BaseURL: "https://api.example.com/v1",
|
|
Platform: "openai",
|
|
SmokeTestModel: "gpt-5.4",
|
|
DefaultModels: []string{"gpt-5.4", "gpt-5.4-mini"},
|
|
},
|
|
CommitMessage: "feat(pack): publish openai-zhongzhuan",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("PublishProviderManifest() error = %v", err)
|
|
}
|
|
|
|
if result.PublishMode != "created" {
|
|
t.Fatalf("PublishMode = %q, want created", result.PublishMode)
|
|
}
|
|
if result.PackVersionBefore != "1.1.4" || result.PackVersionAfter != "1.1.5" {
|
|
t.Fatalf("pack versions = %q -> %q, want 1.1.4 -> 1.1.5", result.PackVersionBefore, result.PackVersionAfter)
|
|
}
|
|
if strings.TrimSpace(result.CommitSHA) == "" {
|
|
t.Fatal("CommitSHA is empty")
|
|
}
|
|
|
|
publishedPack, err := LoadDir(packDir)
|
|
if err != nil {
|
|
t.Fatalf("LoadDir() after publish error = %v", err)
|
|
}
|
|
if publishedPack.Manifest.Version != "1.1.5" {
|
|
t.Fatalf("published pack version = %q, want 1.1.5", publishedPack.Manifest.Version)
|
|
}
|
|
|
|
body, err := readFileString(filepath.Join(packDir, "providers", "openai-zhongzhuan.json"))
|
|
if err != nil {
|
|
t.Fatalf("readFileString() provider error = %v", err)
|
|
}
|
|
var provider ProviderManifest
|
|
if err := json.Unmarshal([]byte(body), &provider); err != nil {
|
|
t.Fatalf("json.Unmarshal() provider error = %v", err)
|
|
}
|
|
if provider.AccountType != "apikey" {
|
|
t.Fatalf("AccountType = %q, want apikey", provider.AccountType)
|
|
}
|
|
if provider.ChannelTemplate.ModelMapping["gpt-5.4-mini"] != "gpt-5.4-mini" {
|
|
t.Fatalf("ChannelTemplate.ModelMapping = %+v, want identity mapping for gpt-5.4-mini", provider.ChannelTemplate.ModelMapping)
|
|
}
|
|
|
|
checksums, err := readFileString(filepath.Join(packDir, "checksums.txt"))
|
|
if err != nil {
|
|
t.Fatalf("readFileString() checksums error = %v", err)
|
|
}
|
|
if !strings.Contains(checksums, "providers/openai-zhongzhuan.json") {
|
|
t.Fatalf("checksums.txt = %q, want providers/openai-zhongzhuan.json entry", checksums)
|
|
}
|
|
}
|
|
|
|
func TestPublishProviderManifestRejectsMissingRepoRoot(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
_, err := PublishProviderManifest(context.Background(), PublishProviderManifestRequest{
|
|
PackID: "openai-cn-pack",
|
|
Manifest: ProviderManifest{
|
|
ProviderID: "deepseek",
|
|
DisplayName: "DeepSeek",
|
|
BaseURL: "https://api.deepseek.com",
|
|
Platform: "openai",
|
|
SmokeTestModel: "deepseek-chat",
|
|
DefaultModels: []string{"deepseek-chat"},
|
|
},
|
|
})
|
|
if err == nil || !strings.Contains(err.Error(), "repo root") {
|
|
t.Fatalf("PublishProviderManifest() error = %v, want repo root detail", err)
|
|
}
|
|
}
|
|
|
|
func createPackFixtureAt(t *testing.T, packDir string, files map[string]string) {
|
|
t.Helper()
|
|
|
|
var lines []string
|
|
for relativePath, content := range files {
|
|
absolutePath := filepath.Join(packDir, relativePath)
|
|
mustWrite(t, absolutePath, content)
|
|
sum := sha256Sum(content)
|
|
lines = append(lines, sum+" "+relativePath)
|
|
}
|
|
mustWrite(t, filepath.Join(packDir, "checksums.txt"), strings.Join(lines, "\n")+"\n")
|
|
}
|
|
|
|
func sha256Sum(content string) string {
|
|
sum := sha256.Sum256([]byte(content))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
func initGitRepo(t *testing.T, repoRoot string) {
|
|
t.Helper()
|
|
runGitTest(t, repoRoot, "init")
|
|
runGitTest(t, repoRoot, "config", "user.name", "Test User")
|
|
runGitTest(t, repoRoot, "config", "user.email", "test@example.com")
|
|
runGitTest(t, repoRoot, "add", ".")
|
|
runGitTest(t, repoRoot, "commit", "-m", "chore: seed pack fixture")
|
|
}
|
|
|
|
func runGitTest(t *testing.T, repoRoot string, args ...string) {
|
|
t.Helper()
|
|
cmd := exec.Command("git", append([]string{"-C", repoRoot}, args...)...)
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git %v error = %v: %s", args, err, strings.TrimSpace(string(output)))
|
|
}
|
|
}
|
|
|
|
func readFileString(path string) (string, error) {
|
|
body, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(body), nil
|
|
}
|