113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"git.pcux.cn/xuans/Smail/dto/parsemail"
|
|
)
|
|
|
|
type weChatRoundTripFunc func(*http.Request) (*http.Response, error)
|
|
|
|
func (f weChatRoundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) {
|
|
return f(request)
|
|
}
|
|
|
|
func TestBuildWeChatMessageLimitsContent(t *testing.T) {
|
|
message := buildWeChatMessage(&parsemail.Email{
|
|
Subject: strings.Repeat("\u754c", maxWeChatMessageBytes),
|
|
Text: []byte(strings.Repeat("body", maxWeChatMessageBytes)),
|
|
})
|
|
if len(message) > maxWeChatMessageBytes {
|
|
t.Fatalf("message length = %d, want at most %d", len(message), maxWeChatMessageBytes)
|
|
}
|
|
if !utf8.ValidString(message) {
|
|
t.Fatal("message is not valid UTF-8")
|
|
}
|
|
if message := buildWeChatMessage(nil); message != "" {
|
|
t.Fatalf("nil email message = %q", message)
|
|
}
|
|
}
|
|
|
|
func TestSendUserMsgLimitsOutboundContent(t *testing.T) {
|
|
originalClient := weChatHTTPClient
|
|
t.Cleanup(func() { weChatHTTPClient = originalClient })
|
|
|
|
var captured sendMsgRequest
|
|
weChatHTTPClient = &http.Client{Transport: weChatRoundTripFunc(func(request *http.Request) (*http.Response, error) {
|
|
body, err := io.ReadAll(request.Body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := json.Unmarshal(body, &captured); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Header: make(http.Header),
|
|
Body: io.NopCloser(strings.NewReader(`{}`)),
|
|
}, nil
|
|
})}
|
|
|
|
hook := &WeChatPushHook{
|
|
token: "test-token",
|
|
tokenExpires: time.Now().Add(time.Minute).Unix(),
|
|
templateId: "template",
|
|
webDomain: "mail.example.com",
|
|
}
|
|
hook.sendUserMsg(nil, "user", strings.Repeat("x", maxWeChatMessageBytes+100))
|
|
if len(captured.Data.Content.Value) != maxWeChatMessageBytes {
|
|
t.Fatalf("outbound content length = %d, want %d", len(captured.Data.Content.Value), maxWeChatMessageBytes)
|
|
}
|
|
}
|
|
|
|
func TestGetWxAccessTokenConcurrentRefresh(t *testing.T) {
|
|
originalClient := weChatHTTPClient
|
|
t.Cleanup(func() { weChatHTTPClient = originalClient })
|
|
|
|
var requestCount atomic.Int32
|
|
weChatHTTPClient = &http.Client{Transport: weChatRoundTripFunc(func(request *http.Request) (*http.Response, error) {
|
|
requestCount.Add(1)
|
|
time.Sleep(20 * time.Millisecond)
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Header: make(http.Header),
|
|
Body: io.NopCloser(strings.NewReader(`{"access_token":"shared-token","expires_in":7200}`)),
|
|
}, nil
|
|
})}
|
|
|
|
hook := &WeChatPushHook{appId: "test-app-id", secret: "test-secret"}
|
|
const workerCount = 32
|
|
start := make(chan struct{})
|
|
results := make(chan string, workerCount)
|
|
var workers sync.WaitGroup
|
|
workers.Add(workerCount)
|
|
for range workerCount {
|
|
go func() {
|
|
defer workers.Done()
|
|
<-start
|
|
results <- hook.getWxAccessToken()
|
|
}()
|
|
}
|
|
|
|
close(start)
|
|
workers.Wait()
|
|
close(results)
|
|
|
|
for token := range results {
|
|
if token != "shared-token" {
|
|
t.Fatalf("token = %q, want shared-token", token)
|
|
}
|
|
}
|
|
if got := requestCount.Load(); got != 1 {
|
|
t.Fatalf("token request count = %d, want 1", got)
|
|
}
|
|
}
|