返回 DeepSeek-Reasonix
opencode_go_selection_test.go
根目录 / internal / config / opencode_go_selection_test.go
1 package config
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8 )
9
10 func migratedSelectionConfig(t *testing.T) *Config {
11 t.Helper()
12 c := &Config{ConfigVersion: 9, Providers: []ProviderEntry{{
13 Name: "go", Kind: "anthropic", BaseURL: "https://opencode.ai/zen/go",
14 APIKeyEnv: "SELECTION_TEST_KEY", Models: []string{"deepseek-v4-flash", "deepseek-v4-pro"}, Default: "deepseek-v4-flash",
15 }}}
16 j, _ := planOpenCodeGoUpgrade(c)
17 c.openCodeGoJournal = &j
18 c.ConfigVersion = 10
19 return c
20 }
21
22 func TestOpenCodeGoCurrentSelectionAfterConnectionEdit(t *testing.T) {
23 for _, tc := range []struct {
24 name string
25 edit func(*ProviderEntry)
26 }{
27 {"proxy", func(p *ProviderEntry) { p.NoProxy = true }},
28 {"headers", func(p *ProviderEntry) { p.Headers = map[string]string{"X-User": "changed"} }},
29 {"credential reference", func(p *ProviderEntry) { p.APIKeyEnv = "NEW_SELECTION_TEST_KEY" }},
30 } {
31 t.Run(tc.name, func(t *testing.T) {
32 c := migratedSelectionConfig(t)
33 tc.edit(&c.Providers[0])
34 for _, ref := range []string{"go/deepseek-v4-flash", "go", "deepseek-v4-flash"} {
35 if err := c.ModelReferenceError(ref); err != nil {
36 t.Fatal(err)
37 }
38 if e, ok := c.ResolveModel(ref); !ok || e.Model != "deepseek-v4-flash" {
39 t.Fatalf("current selection %q failed: %+v", ref, e)
40 }
41 if _, err := c.ResolveHistoricalModel(ref); err == nil || !strings.Contains(err.Error(), "MIGRATED_MODEL_UNAVAILABLE") {
42 t.Fatalf("historical identity was not protected: %v", err)
43 }
44 }
45 })
46 }
47 }
48
49 func TestOpenCodeGoCurrentDefaultAndHistoricalDefault(t *testing.T) {
50 c := migratedSelectionConfig(t)
51 c.Providers[0].Default = "deepseek-v4-pro"
52 if e, ok := c.ResolveModel("go"); !ok || e.Model != "deepseek-v4-pro" {
53 t.Fatalf("current default ignored: %+v", e)
54 }
55 if ref, err := c.ResolveHistoricalModel("go"); err != nil || ref != "go/deepseek-v4-flash" {
56 t.Fatalf("historical default changed: %q, %v", ref, err)
57 }
58 c.Providers[0].Models = []string{"deepseek-v4-pro"}
59 if e, ok := c.ResolveModel("go"); !ok || e.Model != "deepseek-v4-pro" {
60 t.Fatalf("deleted old default blocked new default: %+v", e)
61 }
62 if _, err := c.ResolveHistoricalModel("go"); err == nil {
63 t.Fatal("deleted historical model must fail closed")
64 }
65 }
66
67 func TestOpenCodeGoSelectionEditSaveReload(t *testing.T) {
68 path := filepath.Join(t.TempDir(), "config.toml")
69 if err := os.WriteFile(path, []byte(`config_version = 9
70 [[providers]]
71 name = "go"
72 kind = "anthropic"
73 base_url = "https://opencode.ai/zen/go"
74 api_key_env = "SELECTION_TEST_KEY"
75 models = ["deepseek-v4-flash", "deepseek-v4-pro"]
76 default = "deepseek-v4-flash"
77 `), 0600); err != nil {
78 t.Fatal(err)
79 }
80 if _, err := ApplyUserConfigUpgradesOnStartup(path); err != nil {
81 t.Fatal(err)
82 }
83 c := LoadForEdit(path)
84 if c.openCodeGoJournal == nil {
85 t.Fatal("missing durable migration journal")
86 }
87 c.Providers[0].NoProxy = true
88 c.Providers[0].Default = "deepseek-v4-pro"
89 if err := c.SaveToScope(path, RenderScopeFull); err != nil {
90 t.Fatal(err)
91 }
92 c = LoadForEdit(path)
93 if e, ok := c.ResolveModel("go"); !ok || e.Model != "deepseek-v4-pro" || !e.NoProxy {
94 t.Fatalf("selection edit did not survive reload: %+v", e)
95 }
96 if _, err := c.ResolveHistoricalModel("go"); err == nil {
97 t.Fatal("save erased the historical identity guard")
98 }
99 }
100
101 func TestOpenCodeGoExplicitSelectionIdentity(t *testing.T) {
102 c := migratedSelectionConfig(t)
103 c.Providers[0].NoProxy = true
104 ref := "go/deepseek-v4-flash"
105 identity := c.ModelSelectionIdentity(ref)
106 if len(identity) != 64 || strings.Contains(identity, "SELECTION_TEST_KEY") {
107 t.Fatal("selection must contain only an identity digest")
108 }
109 if _, err := c.ResolveSavedModel(ref, ""); err == nil {
110 t.Fatal("legacy selection adopted edited connection")
111 }
112 if got, err := c.ResolveSavedModel(ref, identity); err != nil || got != ref {
113 t.Fatalf("acknowledged selection failed: %q, %v", got, err)
114 }
115 c.Providers[0].Default = "deepseek-v4-pro"
116 if _, err := c.ResolveSavedModel(ref, identity); err != nil {
117 t.Fatalf("default edit changed explicit model identity: %v", err)
118 }
119 c.Providers[0].APIKeyEnv = "OTHER_KEY"
120 if _, err := c.ResolveSavedModel(ref, identity); err == nil {
121 t.Fatal("acknowledgement silently followed a later account edit")
122 }
123 }
124
125 func TestOpenCodeGoAutomaticSearchNeverUsesAnotherAccountAfterEdit(t *testing.T) {
126 c := migratedSelectionConfig(t)
127 c.Providers[0].NoProxy = true
128 c.Providers = append(c.Providers, ProviderEntry{Name: "other", Kind: "anthropic", BaseURL: "https://opencode.ai/zen/go", Model: "deepseek-v4-flash", APIKeyEnv: "OTHER_KEY", WebSearch: boolPointer(true)})
129 for i := range c.Providers {
130 c.Providers[i].resolvedAPIKey = "test-key"
131 }
132 chat, _ := c.ResolveModel("go/deepseek-v4-flash")
133 if got := c.ResolveWebSearch(chat); got.Entry != nil {
134 t.Fatalf("automatic search crossed accounts: %s", got.Entry.Name)
135 }
136 if got, err := c.ResolveWebSearchModel("other/deepseek-v4-flash"); err != nil || got.Name != "other" {
137 t.Fatalf("explicit search choice blocked: %v", err)
138 }
139 }
140
140 lines GO