Files
AskaEth 95f97f5df3
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
docs(comments): 注释中文化 · plugins/channels/weixin_ilink(20 文件,纯替换)
- 只翻注释/文档字符串:剥掉行尾注释后,每条「-」都有逐字节相同的「+」对应行(8 组,代码零改动)
- 保留协议/线上标识符原文:errcode、bot_token、context_token、getupdates、binded_redirect、PKCS#7、ECB 等
- 术语对齐既有译法:owner→主人、peer→对端、long poll→长轮询、backoff→退避、sentinel error→哨兵错误
- 已知既有欠债(未顺手修):login_reuse_test.go 在 HEAD 上就未 gofmt 干净;login_test.go 的 TestStartLogin_ScanStatusTransition 91 行 >80(HEAD 同为 91 行)
2026-10-04 12:29:05 +08:00

146 lines
4.3 KiB
Go

package weixin_ilink
import (
"bytes"
"context"
"crypto/aes"
"errors"
"testing"
)
func TestDeriveInboundKey(t *testing.T) {
t.Parallel()
key := bytes.Repeat([]byte{0x7F}, aes.BlockSize)
token := encodeToken(key)
got, err := deriveInboundKey(token)
if err != nil {
t.Fatalf("deriveInboundKey: %v", err)
}
if !bytes.Equal(got, key) {
t.Fatalf("key = %x, want %x", got, key)
}
}
func TestDeriveInboundKey_Errors(t *testing.T) {
t.Parallel()
t.Run("empty token", func(t *testing.T) {
t.Parallel()
if _, err := deriveInboundKey(""); !errors.Is(err, ErrInvalidConfig) {
t.Fatalf("err = %v, want ErrInvalidConfig", err)
}
})
t.Run("not base64", func(t *testing.T) {
t.Parallel()
if _, err := deriveInboundKey("@not-base64@"); err == nil {
t.Fatal("err = nil, want decode error")
}
})
t.Run("token too short", func(t *testing.T) {
t.Parallel()
if _, err := deriveInboundKey(encodeToken([]byte("short"))); !errors.Is(err, ErrKeyTooShort) {
t.Fatalf("err = %v, want ErrKeyTooShort", err)
}
})
}
func TestDownloadMedia_DecryptsFromTokenDerivedKey(t *testing.T) {
t.Parallel()
key := bytes.Repeat([]byte{0x11}, aes.BlockSize)
plain := []byte("the quick brown fox jumps over the lazy dog")
enc, err := aesECBEncrypt(key, plain)
if err != nil {
t.Fatalf("aesECBEncrypt: %v", err)
}
token := encodeToken(key)
srv := newJSONServer(t, nil, func(req recordedReq) handlerResult {
if req.path == "/media/1" {
return handlerResult{ctype: "application/octet-stream", body: enc}
}
return handlerResult{status: 404}
})
ad := newAdapter(t, Config{BaseURL: srv.URL, CDNBaseURL: srv.URL, BotToken: token}, srv)
got, err := ad.DownloadMedia(context.Background(), srv.URL+"/media/1")
if err != nil {
t.Fatalf("DownloadMedia: %v", err)
}
if !bytes.Equal(got, plain) {
t.Fatalf("decrypted = %q, want %q", got, plain)
}
}
func TestDownloadMediaWithKey_ExplicitKey(t *testing.T) {
t.Parallel()
key := bytes.Repeat([]byte{0x22}, aes.BlockSize)
plain := []byte("explicit key path")
enc, err := aesECBEncrypt(key, plain)
if err != nil {
t.Fatalf("aesECBEncrypt: %v", err)
}
srv := newJSONServer(t, nil, func(req recordedReq) handlerResult {
if req.path == "/media/2" {
return handlerResult{ctype: "application/octet-stream", body: enc}
}
return handlerResult{status: 404}
})
ad := newAdapter(t, Config{BaseURL: srv.URL, CDNBaseURL: srv.URL, BotToken: "unused"}, srv)
got, err := ad.DownloadMediaWithKey(context.Background(), srv.URL+"/media/2", key)
if err != nil {
t.Fatalf("DownloadMediaWithKey: %v", err)
}
if !bytes.Equal(got, plain) {
t.Fatalf("decrypted = %q, want %q", got, plain)
}
}
func TestDownloadMedia_RejectsOversize(t *testing.T) {
t.Parallel()
big := bytes.Repeat([]byte{0x01}, 256)
srv := newJSONServer(t, nil, func(req recordedReq) handlerResult {
if req.path == "/media/big" {
return handlerResult{ctype: "application/octet-stream", body: big}
}
return handlerResult{status: 404}
})
ad := newAdapter(t, Config{
BaseURL: srv.URL, CDNBaseURL: srv.URL,
BotToken: encodeToken(bytes.Repeat([]byte{1}, aes.BlockSize)),
MaxMediaSize: 64,
}, srv)
_, err := ad.DownloadMedia(context.Background(), srv.URL+"/media/big")
if !errors.Is(err, ErrMediaTooLarge) {
t.Fatalf("err = %v, want ErrMediaTooLarge", err)
}
}
func TestDownloadMedia_RejectsDecryptFailure(t *testing.T) {
t.Parallel()
// 返回不构成合法 AES 分组序列的字节。
srv := newJSONServer(t, nil, func(req recordedReq) handlerResult {
if req.path == "/media/bad" {
return handlerResult{ctype: "application/octet-stream", body: []byte("not-a-block")}
}
return handlerResult{status: 404}
})
ad := newAdapter(t, Config{
BaseURL: srv.URL, CDNBaseURL: srv.URL,
BotToken: encodeToken(bytes.Repeat([]byte{1}, aes.BlockSize)),
}, srv)
if _, err := ad.DownloadMedia(context.Background(), srv.URL+"/media/bad"); err == nil {
t.Fatal("err = nil, want decrypt failure")
}
}
func TestCDNURL_JoinsRelativeAndPassesAbsolute(t *testing.T) {
t.Parallel()
ad, _ := New(Config{BaseURL: "https://api.example.com", CDNBaseURL: "https://cdn.example.com/c2c"}, nil, nil)
if got := ad.cdnURL("media/1.jpg"); got != "https://cdn.example.com/c2c/media/1.jpg" {
t.Fatalf("cdnURL(relative) = %q", got)
}
if got := ad.cdnURL("https://other.example.com/x"); got != "https://other.example.com/x" {
t.Fatalf("cdnURL(absolute) = %q", got)
}
}