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) } }