package core import ( "os" "path/filepath" "testing" ) // Qoder 的设备身份两个头**必须成对**出现:参考用抓包 + 消融实验定位过 —— // 缺任一个,服务端就不下发「可领取」的活动(只回 VIEW_DETAILS), // 症状是用户报的「没领过却显示今日已领取」。 // 同时:拿不到身份时必须**保守降级**(照常发请求、不带这两个头), // 不能让纯插件登录(未装桌面端)的账号整个积分功能报错。 func TestQoderMachineIdentityPairingAndDegradation(t *testing.T) { t.Run("行1 有 machine_token.json → 成对带上两个头", func(t *testing.T) { dir := t.TempDir() p := filepath.Join(dir, "machine_token.json") if err := os.WriteFile(p, []byte(`{"token":"T-abc","type":"TY-def","updateAt":1}`), 0o644); err != nil { t.Fatal(err) } t.Setenv("QODER_MACHINE_TOKEN_PATH", p) c := kernelTestCore(t) ps := c.Plugins() src, err := readBundledChannels(t) if err != nil { t.Fatal(err) } if err := ps.LoadSource("channels", src); err != nil { t.Fatal(err) } got, err := ps.Call("channels", "__qoder_machine_probe", map[string]interface{}{}) if err != nil { t.Fatalf("probe: %v", err) } w, _ := got.(map[string]interface{}) m, _ := w["json"].(map[string]interface{}) if m == nil { t.Fatalf("无 json: %#v", got) } if m["token"] != "T-abc" || m["type"] != "TY-def" { t.Fatalf("应从磁盘缓存读出 token/type,实得 %v", m) } if m["client_type"] != "10" { t.Fatalf("Cosy-ClientType 应为 10(参考实测值),实得 %v", m["client_type"]) } }) t.Run("行2 无任何来源 → 降级:不带这两个头,且不报错", func(t *testing.T) { // 指向不存在的路径,且把 HOME 指到空目录(找不到 runtime-info) t.Setenv("QODER_MACHINE_TOKEN_PATH", filepath.Join(t.TempDir(), "nope.json")) t.Setenv("HOME", t.TempDir()) t.Setenv("APPDATA", "") c := kernelTestCore(t) ps := c.Plugins() src, err := readBundledChannels(t) if err != nil { t.Fatal(err) } if err := ps.LoadSource("channels", src); err != nil { t.Fatal(err) } got, err := ps.Call("channels", "__qoder_machine_probe", map[string]interface{}{}) if err != nil { t.Fatalf("probe 不应报错(必须保守降级): %v", err) } w, _ := got.(map[string]interface{}) m, _ := w["json"].(map[string]interface{}) if m == nil { t.Fatalf("无 json: %#v", got) } if m["token"] != nil && m["token"] != "" { t.Errorf("拿不到身份时不应带 token,实得 %v", m["token"]) } if m["type"] != nil && m["type"] != "" { t.Errorf("拿不到身份时不应带 type,实得 %v", m["type"]) } // 头仍然要有 clienttype(那是必要但不充分条件,与身份无关) if m["client_type"] != "10" { t.Errorf("降级时仍应带 Cosy-ClientType=10,实得 %v", m["client_type"]) } }) }