mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
新增 10 个真实厂商平台(端点/模型/流程逐字照抄参考 channel-pack):
device-poll(已有执行器):
minimax 保留(MiniMax 形态:看 status 字段,slow_down +5s)
cline WorkOS 设备码(判据看 error 字段、HTTP 可非 2xx;slow_down +1s;
access_denied/invalid_grant 同组失败;成功后 register 第二跳
/api/v1/auth/register 换 Cline token)。新增 deviceRegister。
state-poll(新流程):
buddy CodeBuddy(腾讯)。POST /v2/plugin/auth/state → authUrl+state;
轮询 GET /v2/plugin/auth/token?state=,业务码 11217 = 未就绪继续等
(对齐参考 loopGetToken:网络错误同样继续不中断);token 就绪后
拿账号(失败不阻塞)。
callback:
gemini 标准 OAuth code 交换(oauth2.googleapis.com/token,六 scope 照抄);
oauth_callback 增 code→token 交换分支(Gemini/LobsterAI 复用)。
lobsterai 本地回调 + authCode 换 token(lobsterai-server.youdao.com)。
trae 保留(token 直传 + ExchangeToken,已 8938574)。
paste:
opencode 直接贴 API key(无登录流)。
codearts 企业凭据 + SDK-HMAC-SHA256 签到(claim_fn 钩子,canonical request
+ 派生密钥链 kDate→kNonce→kSigning→signature)。
manual(后端给 manual_hint,明确说明而非假装成功):
qoder WASM 签名头(纯 Lua 无法生成)
zcode captcha 求解
loomy 微信扫码
raccoon 图片二维码
WebUI(之前只覆盖 vnc/url+轮询/device-poll):
chLogin 增 manual / paste 两个分支:manual_hint 展示 + 凭据粘贴框 +
提交按钮。新增 chComplete 调 channels/login/complete 落保险库,
凭据不回显、失败给可读错误不重载页面。node --check 过。
set_endpoints 增 register/state 覆盖(运维能力 + 测试缝,与 device/checkin 同语义)。
行为测试(照参考逐行):
TestClineWorkOSBehavior 5 行:非200 authorization_pending 继续等 /
slow_down 退避 1s(interval=2)/ access_denied 失败 / 成功 register 凭据
是 CLINE-AT-1(不是 WorkOS token)/ 非200无 error 失败。
TestBuddyStatePollBehavior 3 行:state 申请给 authUrl / 首拍 11217 pending
次拍 token completed / account 查询失败不阻塞回退默认名。
变异测试修复(deviceOneStep 拆 workos/minimax 两分支后幸存体暴露):
锚点 +step / authorization_pending 现两处同形,strings.Replace(,,1) 只改
workos 分支、minimax 决策表没杀到 → 改 ReplaceAll 全改;删冗余第 6 变异体。
5 变异体全杀。回归:channels/device/cline/buddy/trae/legacy/保险库/e2e 全绿。
74 lines
2.6 KiB
Go
74 lines
2.6 KiB
Go
package core
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// TestDevicePollMutants 是 device-poll 执行器的变异测试。
|
||
//
|
||
// 用户要求:移植要照参考实现的行为形成测试项,且要变异验证测试真的能杀掉
|
||
// 「行为走样」的代码。每个用例把 channels 源里的一个决策分支做语义变异,
|
||
// 断言决策表**会失败**(变异体被杀)。变异体幸存 = 该分支没有覆盖。
|
||
func TestDevicePollMutants(t *testing.T) {
|
||
src, err := readBundledChannels(t)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
// 锚点会命中 deviceOneStep 里两处同形代码(workos 分支 + minimax 分支),
|
||
// 全部替换:两个决策表(minimax + workos)都会杀,任一幸存即失败。
|
||
muts := []struct {
|
||
name string
|
||
from string
|
||
to string
|
||
}{
|
||
{
|
||
name: "slow_down 不再加 interval",
|
||
from: `sess.device_interval = (sess.device_interval or d.interval or 5) + step`,
|
||
to: `sess.device_interval = (sess.device_interval or d.interval or 5)`,
|
||
},
|
||
{
|
||
name: "denied 被当成继续等待",
|
||
from: `if resp.status == 200 and (status == "denied" or status == "access_denied") then`,
|
||
to: `if resp.status == 200 and (status == "denied_x" or status == "access_denied") then`,
|
||
},
|
||
{
|
||
name: "expired_token 不被识别",
|
||
from: `if resp.status == 200 and (status == "expired" or status == "expired_token") then`,
|
||
to: `if resp.status == 200 and (status == "expired" or status == "expired_token_x") then`,
|
||
},
|
||
{
|
||
name: "authorization_pending 被当成失败",
|
||
from: `if ecode == "authorization_pending" then return false end`,
|
||
to: `if ecode == "authorization_pending_x" then return false end`,
|
||
},
|
||
{
|
||
name: "成功分支被禁用",
|
||
from: `if resp.status == 200 and rec.access_token then`,
|
||
to: `if resp.status == 200 and rec.access_token and false then`,
|
||
},
|
||
}
|
||
|
||
for _, mu := range muts {
|
||
t.Run(mu.name, func(t *testing.T) {
|
||
if !strings.Contains(src, mu.from) {
|
||
t.Fatalf("锚点丢失,先更新实现与锚点:%q", mu.from)
|
||
}
|
||
// 锚点在 deviceOneStep 的 workos/minimax 两个分支各有一份同形代码,
|
||
// 全部替换:任一分支的变异体被任一决策表杀掉才算有覆盖。
|
||
mutated := strings.ReplaceAll(src, mu.from, mu.to)
|
||
if mutated == src {
|
||
t.Fatal("变异未生效")
|
||
}
|
||
// 基准必须全过(测试自身有效),变异体必须被杀(有覆盖)
|
||
if !newDeviceHarness(t, src).runDecisionTable() {
|
||
t.Fatal("基准决策表未全过 —— 测试自身失效")
|
||
}
|
||
if newDeviceHarness(t, mutated).runDecisionTable() {
|
||
t.Fatalf("★ 变异体幸存(%s)—— 该分支无覆盖", mu.name)
|
||
}
|
||
})
|
||
}
|
||
}
|