289 lines
8.6 KiB
Go
289 lines
8.6 KiB
Go
package regionimgroup
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
"testing"
|
||
"time"
|
||
|
||
"chatapp3-golang/internal/config"
|
||
"chatapp3-golang/internal/model"
|
||
|
||
"gorm.io/driver/sqlite"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
func TestCreateRegionIMGroupSavesActiveGroup(t *testing.T) {
|
||
service, db := newRegionIMGroupTestService(t)
|
||
fakeIM := &fakeIMGateway{}
|
||
service.im = fakeIM
|
||
|
||
resp, err := service.CreateRegionIMGroup(context.Background(), RegionIMGroupRequest{
|
||
SysOrigin: "LIKEI",
|
||
RegionCode: "AR",
|
||
RegionName: "Arab",
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("CreateRegionIMGroup() error = %v", err)
|
||
}
|
||
if resp.Status != imGroupStatusActive || resp.GroupID != defaultRegionIMGroupID("LIKEI", "AR") {
|
||
t.Fatalf("CreateRegionIMGroup() response = %+v", resp)
|
||
}
|
||
if len(fakeIM.created) != 1 || fakeIM.created[0].groupID != resp.GroupID {
|
||
t.Fatalf("created groups = %+v, want one %s", fakeIM.created, resp.GroupID)
|
||
}
|
||
var row model.VoiceRoomRegionIMGroup
|
||
if err := db.Where("sys_origin = ? AND region_code = ?", "LIKEI", "AR").First(&row).Error; err != nil {
|
||
t.Fatalf("load im group: %v", err)
|
||
}
|
||
if row.Status != imGroupStatusActive || row.GroupID != resp.GroupID {
|
||
t.Fatalf("stored im group = %+v", row)
|
||
}
|
||
}
|
||
|
||
func TestDefaultRegionIMGroupIDKeepsASCIIRegionReadable(t *testing.T) {
|
||
got := defaultRegionIMGroupID("LIKEI", "IR")
|
||
if got != "VRRP_LIKEI_IR" {
|
||
t.Fatalf("defaultRegionIMGroupID() = %s, want VRRP_LIKEI_IR", got)
|
||
}
|
||
}
|
||
|
||
func TestDefaultRegionIMGroupIDKeepsNonASCIIRegionsDistinct(t *testing.T) {
|
||
middleEast := defaultRegionIMGroupID("LIKEI", "\u4e2d\u4e1c")
|
||
southAsia := defaultRegionIMGroupID("LIKEI", "\u5357\u4e9a\u533a\u57df")
|
||
if middleEast == southAsia {
|
||
t.Fatalf("non-ascii regions share group id %s", middleEast)
|
||
}
|
||
if middleEast == "VRRP_LIKEI" || southAsia == "VRRP_LIKEI" {
|
||
t.Fatalf("non-ascii region group ids must not collapse: %s %s", middleEast, southAsia)
|
||
}
|
||
if !strings.HasPrefix(middleEast, "VRRP_LIKEI_REGION_") ||
|
||
!strings.HasPrefix(southAsia, "VRRP_LIKEI_REGION_") {
|
||
t.Fatalf("group ids = %s %s, want hashed region suffix", middleEast, southAsia)
|
||
}
|
||
}
|
||
|
||
func TestDefaultRegionIMGroupNameIsGeneric(t *testing.T) {
|
||
got := defaultRegionIMGroupName("LIKEI", "IR", "Iran")
|
||
if got != "region-im-group-LIKEI-Iran" {
|
||
t.Fatalf("defaultRegionIMGroupName() = %s, want generic region name", got)
|
||
}
|
||
if strings.Contains(got, "red-packet") {
|
||
t.Fatalf("defaultRegionIMGroupName() contains red-packet: %s", got)
|
||
}
|
||
}
|
||
|
||
func TestSendRegionBroadcastResolvesRegionAndEnrichesGiftPayload(t *testing.T) {
|
||
service, db := newRegionIMGroupTestService(t)
|
||
fakeIM := &fakeIMGateway{}
|
||
service.im = fakeIM
|
||
ctx := context.Background()
|
||
now := time.Now()
|
||
if err := db.Create(&model.VoiceRoomRegionIMGroup{
|
||
ID: 3002,
|
||
SysOrigin: "LIKEI",
|
||
RegionCode: "AR",
|
||
RegionName: "Arab",
|
||
GroupID: "@region-ar",
|
||
GroupName: "region-ar",
|
||
Status: imGroupStatusActive,
|
||
CreateTime: now,
|
||
UpdateTime: now,
|
||
}).Error; err != nil {
|
||
t.Fatalf("seed im group: %v", err)
|
||
}
|
||
|
||
resp, err := service.SendRegionBroadcast(ctx, RegionBroadcastRequest{
|
||
SysOrigin: "LIKEI",
|
||
SenderUserID: flexibleInt64(1001),
|
||
Type: "SEND_GIFT",
|
||
Data: map[string]any{
|
||
"roomId": "9001",
|
||
"giftId": "5001",
|
||
"giftQuantity": 2,
|
||
"acceptUserIds": []any{"1002"},
|
||
},
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("SendRegionBroadcast() error = %v", err)
|
||
}
|
||
if resp.RegionCode != "AR" || resp.GroupID != "@region-ar" || resp.Type != "SEND_GIFT" {
|
||
t.Fatalf("SendRegionBroadcast() response = %+v", resp)
|
||
}
|
||
if len(fakeIM.sent) != 1 {
|
||
t.Fatalf("sent messages = %+v, want one region message", fakeIM.sent)
|
||
}
|
||
if fakeIM.sent[0].groupID != "@region-ar" {
|
||
t.Fatalf("sent group = %s, want @region-ar", fakeIM.sent[0].groupID)
|
||
}
|
||
body, ok := fakeIM.sent[0].body.(map[string]any)
|
||
if !ok {
|
||
t.Fatalf("sent body type = %T", fakeIM.sent[0].body)
|
||
}
|
||
if body["type"] != "SEND_GIFT" {
|
||
t.Fatalf("sent type = %v, want SEND_GIFT", body["type"])
|
||
}
|
||
data, ok := body["data"].(map[string]any)
|
||
if !ok {
|
||
t.Fatalf("sent data type = %T", body["data"])
|
||
}
|
||
if data["regionCode"] != "AR" || data["actualAccount"] != "1001" ||
|
||
data["userNickname"] != "sender" || data["acceptNickname"] != "claimer" {
|
||
t.Fatalf("sent data = %+v", data)
|
||
}
|
||
}
|
||
|
||
func TestSendRegionBroadcastRefreshesHighWinMessageWithProfile(t *testing.T) {
|
||
service, db := newRegionIMGroupTestService(t)
|
||
fakeIM := &fakeIMGateway{}
|
||
service.im = fakeIM
|
||
now := time.Now()
|
||
if err := db.Create(&model.VoiceRoomRegionIMGroup{
|
||
ID: 3010,
|
||
SysOrigin: "LIKEI",
|
||
RegionCode: "AR",
|
||
RegionName: "Arab",
|
||
GroupID: "@region-ar",
|
||
GroupName: "region-ar",
|
||
Status: imGroupStatusActive,
|
||
CreateTime: now,
|
||
UpdateTime: now,
|
||
}).Error; err != nil {
|
||
t.Fatalf("seed im group: %v", err)
|
||
}
|
||
|
||
_, err := service.SendRegionBroadcast(context.Background(), RegionBroadcastRequest{
|
||
SysOrigin: "LIKEI",
|
||
Type: "GAME_BAISHUN_WIN",
|
||
Data: map[string]any{
|
||
"userId": "1001",
|
||
"roomId": "9001",
|
||
"multiple": 10,
|
||
"winAmount": 1000,
|
||
"msg": "1001 play game get x 10 win 1000 coins!!!",
|
||
},
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("SendRegionBroadcast() error = %v", err)
|
||
}
|
||
body, ok := fakeIM.sent[0].body.(map[string]any)
|
||
if !ok {
|
||
t.Fatalf("sent body type = %T", fakeIM.sent[0].body)
|
||
}
|
||
data, ok := body["data"].(map[string]any)
|
||
if !ok {
|
||
t.Fatalf("sent data type = %T", body["data"])
|
||
}
|
||
if data["msg"] != "sender play game get x 10 win 1000 coins!!!" {
|
||
t.Fatalf("msg = %v", data["msg"])
|
||
}
|
||
}
|
||
|
||
func TestSendRegionBroadcastPrefersJavaRegionResolver(t *testing.T) {
|
||
service, db := newRegionIMGroupTestService(t)
|
||
service.regionResolver = fakeRegionResolver{
|
||
regions: map[string]string{"LIKEI|SA": "中东区"},
|
||
}
|
||
fakeIM := &fakeIMGateway{}
|
||
service.im = fakeIM
|
||
now := time.Now()
|
||
if err := db.Create(&model.VoiceRoomRegionIMGroup{
|
||
ID: 3003,
|
||
SysOrigin: "LIKEI",
|
||
RegionCode: "中东区",
|
||
RegionName: "Middle East",
|
||
GroupID: "@region-middle-east",
|
||
GroupName: "region-middle-east",
|
||
Status: imGroupStatusActive,
|
||
CreateTime: now,
|
||
UpdateTime: now,
|
||
}).Error; err != nil {
|
||
t.Fatalf("seed im group: %v", err)
|
||
}
|
||
|
||
resp, err := service.SendRegionBroadcast(context.Background(), RegionBroadcastRequest{
|
||
SysOrigin: "LIKEI",
|
||
SenderUserID: flexibleInt64(1001),
|
||
Type: "SEND_GIFT",
|
||
Data: map[string]any{"roomId": "9001"},
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("SendRegionBroadcast() error = %v", err)
|
||
}
|
||
if resp.RegionCode != "中东区" || resp.GroupID != "@region-middle-east" {
|
||
t.Fatalf("SendRegionBroadcast() response = %+v, want Java region group", resp)
|
||
}
|
||
}
|
||
|
||
func newRegionIMGroupTestService(t *testing.T) (*Service, *gorm.DB) {
|
||
t.Helper()
|
||
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
|
||
if err != nil {
|
||
t.Fatalf("open sqlite: %v", err)
|
||
}
|
||
if err := db.AutoMigrate(
|
||
&model.UserBaseInfo{},
|
||
&model.VoiceRoomRegionCountry{},
|
||
&model.VoiceRoomRegionIMGroup{},
|
||
); err != nil {
|
||
t.Fatalf("auto migrate: %v", err)
|
||
}
|
||
now := time.Now()
|
||
if err := db.Create(&[]model.UserBaseInfo{
|
||
{ID: 1001, Account: "1001", UserNickname: "sender", UserAvatar: "sender.png", OriginSys: "LIKEI", CountryCode: "SA", CountryName: "Saudi Arabia", CreateTime: now},
|
||
{ID: 1002, Account: "1002", UserNickname: "claimer", UserAvatar: "claimer.png", OriginSys: "LIKEI", CountryCode: "SA", CountryName: "Saudi Arabia", CreateTime: now},
|
||
}).Error; err != nil {
|
||
t.Fatalf("seed users: %v", err)
|
||
}
|
||
if err := db.Create(&model.VoiceRoomRegionCountry{
|
||
ID: 1,
|
||
SysOrigin: "LIKEI",
|
||
RegionCode: "AR",
|
||
CountryCode: "SA",
|
||
Enabled: true,
|
||
CreateTime: now,
|
||
UpdateTime: now,
|
||
}).Error; err != nil {
|
||
t.Fatalf("seed region: %v", err)
|
||
}
|
||
return NewService(config.Config{}, db), db
|
||
}
|
||
|
||
type fakeIMCreateRecord struct {
|
||
groupID string
|
||
groupName string
|
||
}
|
||
|
||
type fakeIMSendRecord struct {
|
||
groupID string
|
||
body any
|
||
}
|
||
|
||
type fakeIMGateway struct {
|
||
created []fakeIMCreateRecord
|
||
sent []fakeIMSendRecord
|
||
}
|
||
|
||
func (g *fakeIMGateway) CreateAVChatRoom(_ context.Context, groupID string, groupName string) (string, error) {
|
||
g.created = append(g.created, fakeIMCreateRecord{groupID: groupID, groupName: groupName})
|
||
return groupID, nil
|
||
}
|
||
|
||
func (g *fakeIMGateway) SendCustomGroupMessage(_ context.Context, groupID string, body any) error {
|
||
g.sent = append(g.sent, fakeIMSendRecord{groupID: groupID, body: body})
|
||
return nil
|
||
}
|
||
|
||
type fakeRegionResolver struct {
|
||
regions map[string]string
|
||
err error
|
||
}
|
||
|
||
func (g fakeRegionResolver) ResolveRegionCodeByCountryCode(_ context.Context, sysOrigin string, countryCode string) (string, error) {
|
||
if g.err != nil {
|
||
return "", g.err
|
||
}
|
||
key := strings.ToUpper(strings.TrimSpace(sysOrigin)) + "|" + strings.ToUpper(strings.TrimSpace(countryCode))
|
||
return strings.TrimSpace(g.regions[key]), nil
|
||
}
|