Files
arcrun-collector/cmd/arcrun-tray/main_test.go
T
Leo 0deef3dbd9 fix(t86 🔴): 換知識庫實例時清空看守資料夾——堵個資外洩
leo 07-28 實測坐實:youlin 時代的資料夾被原封同步進 geek6688 新實例
(「假如我把個人的同步到官方去就很危險,個資外泄」)。
修:instanceChanged(old,new) 比 host;連線精靈成功後若換了實例→清空
WatchFolders/WatchFolder,成功對話框改為說明「因為換了知識庫,為避免把舊資料夾
誤傳到新知識庫,請重新用『+新增知識資料夾…』選擇」;同實例改密碼行為照舊。
測試(main_test.go):host 異同判定含大小寫/尾斜線/scheme 差異。tray go test 綠。
(實作=子 CC;審查+commit=總管。⚠️ manifest 沿用=t86b 另案未含)
2026-07-28 12:03:20 +08:00

186 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"encoding/json"
"strings"
"testing"
)
// t26:暱稱 > email > 未設定(leo 07-24 拍板:CF 全程隱形,這條邏輯不該提到 cypher/CF)。
func TestConnectionStatusLabel(t *testing.T) {
cases := []struct {
name string
instanceName string
email string
want string
}{
{"暱稱優先於email", "我的書房", "leo21c@gmail.com", "連線中:我的書房"},
{"無暱稱退回email", "", "leo21c@gmail.com", "連線中:leo21c@gmail.com"},
{"兩者皆空顯示未設定", "", "", "連線中:未設定"},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := connectionStatusLabel(c.instanceName, c.email)
if got != c.want {
t.Errorf("connectionStatusLabel(%q, %q) = %q, want %q", c.instanceName, c.email, got, c.want)
}
})
}
}
func TestShortCypherHost(t *testing.T) {
cases := []struct {
name string
in string
want string
}{
{"完整URL取host", "https://arcrun-cypher-executor.someacct.workers.dev/path", "arcrun-cypher-executor.someacct.workers.dev"},
{"空字串回空字串", "", ""},
{"無法解析出host則原樣回傳", "not-a-url", "not-a-url"},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := shortCypherHost(c.in)
if got != c.want {
t.Errorf("shortCypherHost(%q) = %q, want %q", c.in, got, c.want)
}
})
}
}
// config 序列化含新欄(emailinstance_name)——t26 施工面一驗收項。
func TestDirectConfigJSONRoundTrip(t *testing.T) {
c := &directConfig{
CypherURL: "https://example.workers.dev",
Namespace: "demo",
Email: "leo21c@gmail.com",
InstanceName: "我的書房",
}
data, err := json.Marshal(c)
if err != nil {
t.Fatalf("marshal 失敗:%v", err)
}
s := string(data)
if !strings.Contains(s, `"email":"leo21c@gmail.com"`) {
t.Errorf("序列化結果缺 email 欄:%s", s)
}
if !strings.Contains(s, `"instance_name":"我的書房"`) {
t.Errorf("序列化結果缺 instance_name 欄:%s", s)
}
var back directConfig
if err := json.Unmarshal(data, &back); err != nil {
t.Fatalf("unmarshal 失敗:%v", err)
}
if back.Email != c.Email || back.InstanceName != c.InstanceName {
t.Errorf("round-trip 不一致:got email=%q instance_name=%q", back.Email, back.InstanceName)
}
}
// 暱稱空時 config JSON 不應寫出 instance_name 欄(omitempty;對齊面二 installer 端「空就不寫欄位」的約定)。
func TestDirectConfigJSONOmitsEmptyInstanceName(t *testing.T) {
c := &directConfig{
CypherURL: "https://example.workers.dev",
Namespace: "demo",
Email: "leo21c@gmail.com",
}
data, err := json.Marshal(c)
if err != nil {
t.Fatalf("marshal 失敗:%v", err)
}
if strings.Contains(string(data), "instance_name") {
t.Errorf("暱稱空時不該序列化出 instance_name 欄:%s", data)
}
}
// ── t86instanceChanged ─────────────────────────────────────────────────────
func TestInstanceChanged(t *testing.T) {
cases := []struct {
name string
oldURL string
newURL string
want bool
}{
{
"同 host 同實例改密碼不觸發清空",
"https://arcrun-cypher-executor.youlin.workers.dev",
"https://arcrun-cypher-executor.youlin.workers.dev",
false,
},
{
"不同 host 換實例觸發清空",
"https://arcrun-cypher-executor.youlin.workers.dev",
"https://arcrun-cypher-executor.geek6688.workers.dev",
true,
},
{
"舊 URL 空(首次設定)不觸發清空",
"",
"https://arcrun-cypher-executor.geek6688.workers.dev",
false,
},
{
"新 URL 空(異常值)不觸發清空",
"https://arcrun-cypher-executor.youlin.workers.dev",
"",
false,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := instanceChanged(c.oldURL, c.newURL)
if got != c.want {
t.Errorf("instanceChanged(%q, %q) = %v, want %v", c.oldURL, c.newURL, got, c.want)
}
})
}
}
// t86:換實例後 applyRemoteConfig 清空資料夾清單
func TestApplyRemoteConfigClearsFoldersOnInstanceSwitch(t *testing.T) {
cfg := &directConfig{
CypherURL: "https://arcrun-cypher-executor.youlin.workers.dev",
Namespace: "youlin",
WatchFolder: "/Users/youlin/KnowledgeBase",
WatchFolders: []string{"/Users/youlin/KnowledgeBase", "/Users/youlin/Finance"},
}
r := &daemonConfigResp{}
r.Config.CypherURL = "https://arcrun-cypher-executor.geek6688.workers.dev"
r.Config.Namespace = "geek6688"
switched := applyRemoteConfig(cfg, r)
if !switched {
t.Error("換了不同 host 應回傳 switched=true")
}
if cfg.WatchFolder != "" {
t.Errorf("換實例後 WatchFolder 應清空,got %q", cfg.WatchFolder)
}
if len(cfg.WatchFolders) != 0 {
t.Errorf("換實例後 WatchFolders 應清空,got %v", cfg.WatchFolders)
}
}
// t86:同實例改密碼不清空資料夾清單
func TestApplyRemoteConfigKeepsFoldersOnSameInstance(t *testing.T) {
cfg := &directConfig{
CypherURL: "https://arcrun-cypher-executor.youlin.workers.dev",
Namespace: "youlin",
WatchFolder: "/Users/youlin/KnowledgeBase",
WatchFolders: []string{"/Users/youlin/KnowledgeBase"},
}
r := &daemonConfigResp{}
r.Config.CypherURL = "https://arcrun-cypher-executor.youlin.workers.dev"
r.Config.Namespace = "youlin"
switched := applyRemoteConfig(cfg, r)
if switched {
t.Error("同 host 不應回傳 switched=true")
}
if cfg.WatchFolder == "" || len(cfg.WatchFolders) == 0 {
t.Error("同實例不應清空資料夾清單")
}
}