243 lines
7.4 KiB
Go
243 lines
7.4 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 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
|
|
}
|