2026-06-12 00:35:14 +08:00

134 lines
4.4 KiB
Go

package gamemanagement
import (
"context"
"encoding/base64"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"unicode"
)
type fakeRobotAvatarUploader struct {
key string
contentType string
data []byte
}
func (u *fakeRobotAvatarUploader) PutObject(_ context.Context, key string, reader io.Reader, _ int64, contentType string) (string, error) {
data, err := io.ReadAll(reader)
if err != nil {
return "", err
}
u.key = key
u.contentType = contentType
u.data = data
return "https://media.example.com/" + key, nil
}
func TestUploadRobotAvatarFromSourceUploadsDownloadedImageToCOS(t *testing.T) {
imageBytes, err := base64.StdEncoding.DecodeString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=")
if err != nil {
t.Fatalf("decode png: %v", err)
}
avatarServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "image/png")
_, _ = w.Write(imageBytes)
}))
defer avatarServer.Close()
uploader := &fakeRobotAvatarUploader{}
handler := New(nil, nil, nil, WithRobotAvatarUploader(uploader, "admin"), WithRobotAvatarHTTPClient(avatarServer.Client()))
got, err := handler.uploadRobotAvatarFromSource(t.Context(), 42, avatarServer.URL+"/avatar.png")
if err != nil {
t.Fatalf("uploadRobotAvatarFromSource failed: %v", err)
}
if !strings.HasPrefix(got, "https://media.example.com/admin/game-robots/avatars/42/") {
t.Fatalf("uploaded url = %q", got)
}
if uploader.contentType != "image/png" {
t.Fatalf("contentType = %q, want image/png", uploader.contentType)
}
if string(uploader.data) != string(imageBytes) {
t.Fatalf("uploaded bytes mismatch")
}
}
func TestRobotNicknameUsesSingleLanguagePresetWithoutDigits(t *testing.T) {
// 预设池是批量创建机器人的基础数据,数量变化会直接影响后台一次创建 1000 个机器人时的去重效果。
if len(defaultArabicRobotNicknames) != robotPresetTargetCount {
t.Fatalf("arabic nickname preset count = %d, want %d", len(defaultArabicRobotNicknames), robotPresetTargetCount)
}
if len(defaultEnglishRobotNicknames) != robotPresetTargetCount {
t.Fatalf("english nickname preset count = %d, want %d", len(defaultEnglishRobotNicknames), robotPresetTargetCount)
}
if len(defaultRobotAvatarSources) != robotPresetTargetCount {
t.Fatalf("avatar preset count = %d, want %d", len(defaultRobotAvatarSources), robotPresetTargetCount)
}
if uniqueCount(defaultRobotAvatarSources) != robotPresetTargetCount {
t.Fatalf("avatar preset must keep %d unique source urls", robotPresetTargetCount)
}
englishNames := make([]string, 0, robotPresetTargetCount)
arabicNames := make([]string, 0, robotPresetTargetCount)
for index := 0; index < robotPresetTargetCount; index++ {
english := robotNickname(index, "english")
if !isPureEnglishNickname(english) {
t.Fatalf("english nickname[%d] = %q, want letters only", index, english)
}
englishNames = append(englishNames, english)
arabic := robotNickname(index, "arabic")
if !isPureArabicNickname(arabic) {
t.Fatalf("arabic nickname[%d] = %q, want arabic letters only", index, arabic)
}
arabicNames = append(arabicNames, arabic)
}
if uniqueCount(englishNames) != len(englishNames) {
t.Fatalf("english nickname presets and overflow combinations must keep %d unique names", robotPresetTargetCount)
}
if uniqueCount(arabicNames) != len(arabicNames) {
t.Fatalf("arabic nickname presets and overflow combinations must keep %d unique names", robotPresetTargetCount)
}
if got := robotNickname(robotPresetTargetCount, "english"); !isPureEnglishNickname(got) {
t.Fatalf("english overflow nickname = %q, want pure english combined name", got)
}
if got := robotNickname(robotPresetTargetCount, "arabic"); !isPureArabicNickname(got) {
t.Fatalf("arabic overflow nickname = %q, want pure arabic combined name", got)
}
}
func isPureEnglishNickname(value string) bool {
if value == "" {
return false
}
for _, item := range value {
if (item < 'A' || item > 'Z') && (item < 'a' || item > 'z') {
return false
}
}
return true
}
func isPureArabicNickname(value string) bool {
if value == "" {
return false
}
for _, item := range value {
if !unicode.Is(unicode.Arabic, item) {
return false
}
}
return true
}
func uniqueCount(values []string) int {
seen := make(map[string]struct{}, len(values))
for _, value := range values {
seen[value] = struct{}{}
}
return len(seen)
}