212 lines
7.0 KiB
Go
212 lines
7.0 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
roomv1 "hyapp.local/api/proto/room/v1"
|
|
walletv1 "hyapp.local/api/proto/wallet/v1"
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/services/room-service/internal/integration"
|
|
roomservice "hyapp/services/room-service/internal/room/service"
|
|
"hyapp/services/room-service/internal/router"
|
|
"hyapp/services/room-service/internal/testutil/mysqltest"
|
|
)
|
|
|
|
type recordingRoomGiftLeaderboard struct {
|
|
increments []roomservice.RoomGiftLeaderboardIncrement
|
|
}
|
|
|
|
func (s *recordingRoomGiftLeaderboard) IncrementRoomGift(_ context.Context, input roomservice.RoomGiftLeaderboardIncrement) error {
|
|
s.increments = append(s.increments, input)
|
|
return nil
|
|
}
|
|
|
|
func (s *recordingRoomGiftLeaderboard) ListRoomGiftLeaderboard(context.Context, roomservice.RoomGiftLeaderboardQuery) (roomservice.RoomGiftLeaderboardPage, error) {
|
|
return roomservice.RoomGiftLeaderboardPage{}, nil
|
|
}
|
|
|
|
func TestSendGiftWritesRoomGiftLeaderboardWithHeatValue(t *testing.T) {
|
|
ctx := context.Background()
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{
|
|
BillingReceiptId: "receipt-gift-leaderboard",
|
|
CoinSpent: 100,
|
|
ChargeAmount: 100,
|
|
GiftPointAdded: 100,
|
|
HeatValue: 10,
|
|
GiftTypeCode: "lucky",
|
|
}}}
|
|
leaderboard := &recordingRoomGiftLeaderboard{}
|
|
now := &fixedRoomRocketClock{now: time.Date(2026, 6, 5, 12, 0, 0, 0, time.UTC)}
|
|
svc := roomservice.New(roomservice.Config{
|
|
NodeID: "node-gift-leaderboard-test",
|
|
LeaseTTL: 10 * time.Second,
|
|
RankLimit: 20,
|
|
SnapshotEveryN: 1,
|
|
Clock: now,
|
|
RoomGiftLeaderboard: leaderboard,
|
|
}, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
|
|
|
|
roomID := "room-gift-leaderboard"
|
|
senderID := int64(18001)
|
|
targetID := int64(18002)
|
|
createRocketRoom(t, ctx, svc, roomID, senderID, 9001)
|
|
joinRocketRoom(t, ctx, svc, roomID, targetID)
|
|
|
|
if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{
|
|
Meta: &roomv1.RequestMeta{
|
|
RequestId: "req-gift-leaderboard",
|
|
CommandId: "cmd-gift-leaderboard",
|
|
ActorUserId: senderID,
|
|
RoomId: roomID,
|
|
AppCode: appcode.Default,
|
|
SentAtMs: now.Now().UnixMilli(),
|
|
},
|
|
TargetType: "user",
|
|
TargetUserId: targetID,
|
|
GiftId: "gift-leaderboard",
|
|
GiftCount: 1,
|
|
}); err != nil {
|
|
t.Fatalf("send gift failed: %v", err)
|
|
}
|
|
|
|
if len(leaderboard.increments) != 1 {
|
|
t.Fatalf("expected one leaderboard increment, got %+v", leaderboard.increments)
|
|
}
|
|
if leaderboard.increments[0].CoinSpent != 10 {
|
|
t.Fatalf("leaderboard must use heat value after global ratio, got %+v", leaderboard.increments[0])
|
|
}
|
|
}
|
|
|
|
func TestAdminRoomContributionUsesCurrentUTCWeek(t *testing.T) {
|
|
ctx := context.Background()
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{
|
|
{
|
|
BillingReceiptId: "receipt-week-one",
|
|
CoinSpent: 100,
|
|
ChargeAmount: 100,
|
|
HeatValue: 10,
|
|
GiftTypeCode: "normal",
|
|
},
|
|
{
|
|
BillingReceiptId: "receipt-week-two",
|
|
CoinSpent: 70,
|
|
ChargeAmount: 70,
|
|
HeatValue: 7,
|
|
GiftTypeCode: "normal",
|
|
},
|
|
}}
|
|
now := &fixedRoomRocketClock{now: time.Date(2026, 6, 5, 12, 0, 0, 0, time.UTC)}
|
|
svc := roomservice.New(roomservice.Config{
|
|
NodeID: "node-admin-weekly-contribution-test",
|
|
LeaseTTL: 10 * time.Second,
|
|
RankLimit: 20,
|
|
SnapshotEveryN: 1,
|
|
Clock: now,
|
|
}, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
|
|
|
|
roomID := "room-admin-weekly-contribution"
|
|
senderID := int64(18101)
|
|
targetID := int64(18102)
|
|
createRocketRoom(t, ctx, svc, roomID, senderID, 9001)
|
|
joinRocketRoom(t, ctx, svc, roomID, targetID)
|
|
sendGiftForWeeklyContribution(t, ctx, svc, roomID, senderID, targetID, "cmd-week-one")
|
|
|
|
firstWeek, err := svc.AdminListRooms(ctx, &roomv1.AdminListRoomsRequest{
|
|
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
|
|
Page: 1,
|
|
PageSize: 20,
|
|
SortBy: "room_contribution",
|
|
SortDirection: "desc",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("list first week rooms failed: %v", err)
|
|
}
|
|
if got := adminRoomHeatByID(firstWeek.GetRooms(), roomID); got != 10 {
|
|
t.Fatalf("first week contribution mismatch: got %d want 10", got)
|
|
}
|
|
|
|
now.now = time.Date(2026, 6, 8, 0, 0, 0, 0, time.UTC)
|
|
cutoverBuffer, err := svc.AdminListRooms(ctx, &roomv1.AdminListRoomsRequest{
|
|
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
|
|
Page: 1,
|
|
PageSize: 20,
|
|
SortBy: "room_contribution",
|
|
SortDirection: "desc",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("list cutover buffer rooms failed: %v", err)
|
|
}
|
|
if got := adminRoomHeatByID(cutoverBuffer.GetRooms(), roomID); got != 10 {
|
|
t.Fatalf("monday 00:00 UTC must keep previous contribution until UTC+1 cutover: got %d want 10", got)
|
|
}
|
|
|
|
now.now = time.Date(2026, 6, 8, 1, 0, 0, 0, time.UTC)
|
|
nextWeekBeforeGift, err := svc.AdminListRooms(ctx, &roomv1.AdminListRoomsRequest{
|
|
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
|
|
Page: 1,
|
|
PageSize: 20,
|
|
SortBy: "room_contribution",
|
|
SortDirection: "desc",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("list next contribution week rooms failed: %v", err)
|
|
}
|
|
if got := adminRoomHeatByID(nextWeekBeforeGift.GetRooms(), roomID); got != 0 {
|
|
t.Fatalf("next UTC+1 week must clear contribution before new gifts: got %d want 0", got)
|
|
}
|
|
|
|
resp := sendGiftForWeeklyContribution(t, ctx, svc, roomID, senderID, targetID, "cmd-week-two")
|
|
if resp.GetRoomHeat() != 17 {
|
|
t.Fatalf("room heat must remain cumulative Room Cell state: got %d want 17", resp.GetRoomHeat())
|
|
}
|
|
nextWeekAfterGift, err := svc.AdminListRooms(ctx, &roomv1.AdminListRoomsRequest{
|
|
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
|
|
Page: 1,
|
|
PageSize: 20,
|
|
SortBy: "room_contribution",
|
|
SortDirection: "desc",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("list next week rooms after gift failed: %v", err)
|
|
}
|
|
if got := adminRoomHeatByID(nextWeekAfterGift.GetRooms(), roomID); got != 7 {
|
|
t.Fatalf("next UTC+1 week contribution must restart from new gifts: got %d want 7", got)
|
|
}
|
|
}
|
|
|
|
func sendGiftForWeeklyContribution(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, senderID int64, targetID int64, commandID string) *roomv1.SendGiftResponse {
|
|
t.Helper()
|
|
|
|
resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{
|
|
Meta: &roomv1.RequestMeta{
|
|
RequestId: "req-" + commandID,
|
|
CommandId: commandID,
|
|
ActorUserId: senderID,
|
|
RoomId: roomID,
|
|
AppCode: appcode.Default,
|
|
SentAtMs: time.Now().UTC().UnixMilli(),
|
|
},
|
|
TargetType: "user",
|
|
TargetUserId: targetID,
|
|
GiftId: "gift-weekly-contribution",
|
|
GiftCount: 1,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("send gift %s failed: %v", commandID, err)
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func adminRoomHeatByID(items []*roomv1.AdminRoomListItem, roomID string) int64 {
|
|
for _, item := range items {
|
|
if item.GetRoomId() == roomID {
|
|
return item.GetHeat()
|
|
}
|
|
}
|
|
return -1
|
|
}
|