返回 DeepSeek-Reasonix
provider_connection_isolation_test.go
根目录 / desktop / provider_connection_isolation_test.go
1 package main
2
3 import (
4 "reasonix/internal/config"
5 "testing"
6 )
7
8 func TestIndependentConnectionCredentials(t *testing.T) {
9 isolateDesktopUserDirs(t)
10 app := &App{}
11 if _, err := app.AddProviderConnection("", "deepseek-flash", "personal-test-key"); err != nil {
12 t.Fatal(err)
13 }
14 cfg, _, err := app.loadDesktopUserConfigForView()
15 if err != nil {
16 t.Fatal(err)
17 }
18 var first string
19 for _, p := range cfg.Providers {
20 if p.Name != "deepseek-flash" && p.APIKey() == "personal-test-key" {
21 first = p.Name
22 break
23 }
24 }
25 if first == "" {
26 t.Fatal("new connection not found")
27 }
28 if _, err := app.AddProviderConnection("", first, ""); err != nil {
29 t.Fatal(err)
30 }
31 cfg, _, err = app.loadDesktopUserConfigForView()
32 if err != nil {
33 t.Fatal(err)
34 }
35 var second string
36 for _, p := range cfg.Providers {
37 if p.Name != first && len(p.Name) > len(first) && p.Name[:len(first)] == first {
38 second = p.Name
39 if p.APIKey() != "" {
40 t.Fatal("copy inherited secret")
41 }
42 break
43 }
44 }
45 if second == "" {
46 t.Fatal("copy missing")
47 }
48 if _, err := app.SetConnectionKey(second, "work-test-key"); err != nil {
49 t.Fatal(err)
50 }
51 cfg, _, err = app.loadDesktopUserConfigForView()
52 if err != nil {
53 t.Fatal(err)
54 }
55 for _, p := range cfg.Providers {
56 if p.Name == first && p.APIKey() != "personal-test-key" {
57 t.Fatal("first key changed")
58 }
59 if p.Name == second && p.APIKey() != "work-test-key" {
60 t.Fatal("second key missing")
61 }
62 }
63 if _, err := app.SetConnectionKey(second, ""); err != nil {
64 t.Fatal(err)
65 }
66 cfg, _, err = app.loadDesktopUserConfigForView()
67 if err != nil {
68 t.Fatal(err)
69 }
70 for _, p := range cfg.Providers {
71 if p.Name == first && p.APIKey() != "personal-test-key" {
72 t.Fatal("clear changed sibling")
73 }
74 if p.Name == second && p.APIKey() != "" {
75 t.Fatal("clear failed")
76 }
77 }
78 }
79
80 func TestLegacyConnectionKeyDetachesSharedSecret(t *testing.T) {
81 isolateDesktopUserDirs(t)
82 if err := upsertDotEnv("DEEPSEEK_API_KEY", "legacy-test-key"); err != nil {
83 t.Fatal(err)
84 }
85 app := &App{}
86 if _, err := app.SetConnectionKey("deepseek-flash", "private-test-key"); err != nil {
87 t.Fatal(err)
88 }
89 cfg, _, err := app.loadDesktopUserConfigForView()
90 if err != nil {
91 t.Fatal(err)
92 }
93 for _, p := range cfg.Providers {
94 if p.Name == "deepseek-flash" && (p.APIKeyEnv == "DEEPSEEK_API_KEY" || p.APIKey() != "private-test-key") {
95 t.Fatal("legacy connection was not detached")
96 }
97 }
98 if _, err := app.AddProviderConnection("", "deepseek-pro", ""); err != nil {
99 t.Fatal(err)
100 }
101 for _, p := range config.Default().Providers {
102 if p.Name == "deepseek-pro" && p.APIKey() != "legacy-test-key" {
103 t.Fatal("shared sibling credential changed")
104 }
105 }
106
107 }
108
109 func TestNewConnectionURLDoesNotChangeTemplate(t *testing.T) {
110 isolateDesktopUserDirs(t)
111 a := &App{}
112 if _, err := a.AddProviderConnectionWithURL("", "deepseek-flash", "", "https://gateway.example/v1"); err != nil {
113 t.Fatal(err)
114 }
115 if _, err := a.AddProviderConnection("", "deepseek-flash", ""); err != nil {
116 t.Fatal(err)
117 }
118 cfg, _, err := a.loadDesktopUserConfigForView()
119 if err != nil {
120 t.Fatal(err)
121 }
122 custom, defaults := 0, 0
123 for _, p := range cfg.Providers {
124 if p.Name == "deepseek-flash" {
125 continue
126 }
127 if p.BaseURL == "https://gateway.example/v1" {
128 custom++
129 } else if p.BaseURL == config.Default().Providers[0].BaseURL {
130 defaults++
131 }
132 }
133 if custom != 1 || defaults == 0 {
134 t.Fatalf("custom=%d defaults=%d", custom, defaults)
135 }
136 if _, err := a.AddProviderConnectionWithURL("", "deepseek-flash", "", "file:///tmp/key"); err == nil {
137 t.Fatal("invalid URL accepted")
138 }
139 }
140
141 func TestNewConnectionProtocolOverride(t *testing.T) {
142 isolateDesktopUserDirs(t)
143 a := &App{}
144 for _, kind := range []string{"openai", "responses", "anthropic"} {
145 if _, err := a.AddProviderConnectionWithOptions("glm-cn", "", "", "https://gateway.example/v1", kind); err != nil {
146 t.Fatal(err)
147 }
148 }
149 if _, err := a.AddProviderConnection("glm-cn", "", ""); err != nil {
150 t.Fatal(err)
151 }
152 cfg, _, err := a.loadDesktopUserConfigForView()
153 if err != nil {
154 t.Fatal(err)
155 }
156 kinds := map[string]bool{}
157 defaults := false
158 for _, p := range cfg.Providers {
159 if p.BaseURL == "https://gateway.example/v1" {
160 kinds[p.Kind] = true
161 if p.RequestURL != "" || p.ChatURL != "" || p.ModelsURL != "" {
162 t.Fatal("stale endpoint")
163 }
164 }
165 if p.BaseURL == "https://open.bigmodel.cn/api/paas/v4" && p.Kind == "openai" {
166 defaults = true
167 }
168 }
169 if len(kinds) != 3 || !defaults {
170 t.Fatalf("protocols=%v defaults=%v", kinds, defaults)
171 }
172 if _, err := a.AddProviderConnectionWithOptions("glm-cn", "", "", "", "invalid"); err == nil {
173 t.Fatal("invalid protocol accepted")
174 }
175 }
176
177 func TestDocumentedProtocolConnectionOptions(t *testing.T) {
178 isolateDesktopUserDirs(t)
179 a := &App{}
180 for _, tc := range []struct{ id, kind, url string }{
181 {"qiniu", "anthropic", "https://api.qnaigc.com"},
182 {"mimo-api", "responses", "https://api.xiaomimimo.com/v1"},
183 } {
184 if _, err := a.AddProviderConnectionWithOptions(tc.id, "", "", tc.url, tc.kind); err != nil {
185 t.Fatal(err)
186 }
187 }
188 cfg, _, err := a.loadDesktopUserConfigForView()
189 if err != nil {
190 t.Fatal(err)
191 }
192 bearer, stateless := false, false
193 for _, p := range cfg.Providers {
194 if p.Kind == "anthropic" && p.BaseURL == "https://api.qnaigc.com" {
195 bearer = p.AuthHeader
196 }
197 if p.Kind == "responses" && p.BaseURL == "https://api.xiaomimimo.com/v1" {
198 stateless = p.ResponsesMode == "stateless"
199 }
200 }
201 if !bearer || !stateless {
202 t.Fatalf("bearer=%v stateless=%v", bearer, stateless)
203 }
204 }
205
205 lines GO