237 lines
9.2 KiB
Go
237 lines
9.2 KiB
Go
package service_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
activityv1 "hyapp.local/api/proto/activity/v1"
|
|
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 luckyGiftTestClient struct {
|
|
checks []*activityv1.CheckLuckyGiftRequest
|
|
draws []*activityv1.ExecuteLuckyGiftDrawRequest
|
|
drawResults []*activityv1.LuckyGiftDrawResult
|
|
}
|
|
|
|
func (c *luckyGiftTestClient) CheckLuckyGift(_ context.Context, req *activityv1.CheckLuckyGiftRequest) (*activityv1.CheckLuckyGiftResponse, error) {
|
|
c.checks = append(c.checks, req)
|
|
return &activityv1.CheckLuckyGiftResponse{
|
|
Enabled: true,
|
|
Reason: "enabled",
|
|
GiftId: req.GetGiftId(),
|
|
PoolId: req.GetPoolId(),
|
|
RuleVersion: 12,
|
|
ExperiencePool: "novice",
|
|
}, nil
|
|
}
|
|
|
|
func (c *luckyGiftTestClient) ExecuteLuckyGiftDraw(_ context.Context, req *activityv1.ExecuteLuckyGiftDrawRequest) (*activityv1.ExecuteLuckyGiftDrawResponse, error) {
|
|
c.draws = append(c.draws, req)
|
|
meta := req.GetLuckyGift()
|
|
if len(c.drawResults) > 0 {
|
|
index := len(c.draws) - 1
|
|
if index >= len(c.drawResults) {
|
|
index = len(c.drawResults) - 1
|
|
}
|
|
result := proto.Clone(c.drawResults[index]).(*activityv1.LuckyGiftDrawResult)
|
|
if result.CommandId == "" {
|
|
result.CommandId = meta.GetCommandId()
|
|
}
|
|
if result.PoolId == "" {
|
|
result.PoolId = meta.GetPoolId()
|
|
}
|
|
if result.GiftId == "" {
|
|
result.GiftId = meta.GetGiftId()
|
|
}
|
|
return &activityv1.ExecuteLuckyGiftDrawResponse{Result: result}, nil
|
|
}
|
|
return &activityv1.ExecuteLuckyGiftDrawResponse{Result: &activityv1.LuckyGiftDrawResult{
|
|
DrawId: "lucky_draw_test",
|
|
CommandId: meta.GetCommandId(),
|
|
PoolId: meta.GetPoolId(),
|
|
GiftId: meta.GetGiftId(),
|
|
RuleVersion: 12,
|
|
ExperiencePool: "novice",
|
|
SelectedTierId: "novice_2x",
|
|
MultiplierPpm: 2_000_000,
|
|
BaseRewardCoins: 200,
|
|
EffectiveRewardCoins: 200,
|
|
RewardStatus: "granted",
|
|
WalletTransactionId: "wallet_tx_lucky",
|
|
CoinBalanceAfter: 8800,
|
|
CreatedAtMs: 1_779_258_000_000,
|
|
}}, nil
|
|
}
|
|
|
|
func TestSendGiftReturnsLuckyGiftDrawResult(t *testing.T) {
|
|
ctx := context.Background()
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{
|
|
BillingReceiptId: "receipt-lucky",
|
|
CoinSpent: 100,
|
|
GiftPointAdded: 100,
|
|
HeatValue: 100,
|
|
GiftTypeCode: "super_lucky",
|
|
}}}
|
|
luckyGift := &luckyGiftTestClient{drawResults: []*activityv1.LuckyGiftDrawResult{
|
|
{
|
|
DrawId: "lucky_draw_target_202",
|
|
SelectedTierId: "novice_2x",
|
|
MultiplierPpm: 2_000_000,
|
|
BaseRewardCoins: 200,
|
|
EffectiveRewardCoins: 200,
|
|
RewardStatus: "granted",
|
|
WalletTransactionId: "wallet_tx_lucky_202",
|
|
CoinBalanceAfter: 8800,
|
|
CreatedAtMs: 1_779_258_000_000,
|
|
},
|
|
{
|
|
DrawId: "lucky_draw_target_303",
|
|
SelectedTierId: "normal_3x",
|
|
MultiplierPpm: 3_000_000,
|
|
BaseRewardCoins: 300,
|
|
EffectiveRewardCoins: 300,
|
|
RewardStatus: "granted",
|
|
WalletTransactionId: "wallet_tx_lucky_303",
|
|
CoinBalanceAfter: 9100,
|
|
CreatedAtMs: 1_779_258_000_001,
|
|
StageFeedback: true,
|
|
HighMultiplier: true,
|
|
},
|
|
}}
|
|
svc := roomservice.New(roomservice.Config{
|
|
NodeID: "node-lucky-test",
|
|
LeaseTTL: 10 * time.Second,
|
|
RankLimit: 20,
|
|
SnapshotEveryN: 1,
|
|
}, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher(), luckyGift)
|
|
|
|
roomID := "room-lucky-gift"
|
|
ownerID := int64(101)
|
|
viewerID := int64(202)
|
|
createRocketRoom(t, ctx, svc, roomID, ownerID, 9001)
|
|
joinRocketRoom(t, ctx, svc, roomID, viewerID)
|
|
|
|
resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{
|
|
Meta: &roomv1.RequestMeta{
|
|
RequestId: "req-lucky",
|
|
CommandId: "cmd-lucky",
|
|
ActorUserId: ownerID,
|
|
RoomId: roomID,
|
|
SessionId: "device-session-1",
|
|
AppCode: appcode.Default,
|
|
SentAtMs: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC).UnixMilli(),
|
|
},
|
|
TargetType: "user",
|
|
TargetUserId: viewerID,
|
|
GiftId: "rose",
|
|
GiftCount: 1,
|
|
PoolId: "super_lucky",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("send lucky gift failed: %v", err)
|
|
}
|
|
if resp.GetLuckyGift().GetDrawId() != "lucky_draw_test" || resp.GetLuckyGift().GetMultiplierPpm() != 2_000_000 || resp.GetLuckyGift().GetEffectiveRewardCoins() != 200 || resp.GetLuckyGift().GetRewardStatus() != "granted" || resp.GetLuckyGift().GetWalletTransactionId() != "wallet_tx_lucky" || resp.GetLuckyGift().GetCoinBalanceAfter() != 8800 {
|
|
t.Fatalf("lucky gift result mismatch: %+v", resp.GetLuckyGift())
|
|
}
|
|
if len(resp.GetLuckyGifts()) != 1 || resp.GetLuckyGifts()[0].GetTargetUserId() != viewerID {
|
|
t.Fatalf("single-target lucky_gifts response mismatch: %+v", resp.GetLuckyGifts())
|
|
}
|
|
if len(luckyGift.checks) != 1 || luckyGift.checks[0].GetPoolId() != "super_lucky" || luckyGift.checks[0].GetGiftId() != "rose" {
|
|
t.Fatalf("lucky check request mismatch: %+v", luckyGift.checks)
|
|
}
|
|
if len(luckyGift.draws) != 1 {
|
|
t.Fatalf("expected one lucky draw, got %d", len(luckyGift.draws))
|
|
}
|
|
drawMeta := luckyGift.draws[0].GetLuckyGift()
|
|
if drawMeta.GetCommandId() != "cmd-lucky" ||
|
|
drawMeta.GetCoinSpent() != 100 ||
|
|
drawMeta.GetDeviceId() != "device-session-1" ||
|
|
drawMeta.GetAnchorId() != "101" ||
|
|
drawMeta.GetVisibleRegionId() != 9001 {
|
|
t.Fatalf("lucky draw meta mismatch: %+v", drawMeta)
|
|
}
|
|
}
|
|
|
|
func TestSendGiftReturnsLuckyGiftDrawResultsForMultipleTargets(t *testing.T) {
|
|
ctx := context.Background()
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{
|
|
{BillingReceiptId: "receipt-lucky-202", CoinSpent: 100, ChargeAmount: 100, GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "super_lucky"},
|
|
{BillingReceiptId: "receipt-lucky-303", CoinSpent: 200, ChargeAmount: 200, GiftPointAdded: 200, HeatValue: 200, GiftTypeCode: "super_lucky"},
|
|
}}
|
|
luckyGift := &luckyGiftTestClient{}
|
|
svc := roomservice.New(roomservice.Config{
|
|
NodeID: "node-lucky-multi-test",
|
|
LeaseTTL: 10 * time.Second,
|
|
RankLimit: 20,
|
|
SnapshotEveryN: 1,
|
|
}, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher(), luckyGift)
|
|
|
|
roomID := "room-lucky-gift-multi"
|
|
ownerID := int64(101)
|
|
firstTargetID := int64(202)
|
|
secondTargetID := int64(303)
|
|
createRocketRoom(t, ctx, svc, roomID, ownerID, 9001)
|
|
joinRocketRoom(t, ctx, svc, roomID, firstTargetID)
|
|
joinRocketRoom(t, ctx, svc, roomID, secondTargetID)
|
|
|
|
resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{
|
|
Meta: &roomv1.RequestMeta{
|
|
RequestId: "req-lucky-multi",
|
|
CommandId: "cmd-lucky-multi",
|
|
ActorUserId: ownerID,
|
|
RoomId: roomID,
|
|
SessionId: "device-session-multi",
|
|
AppCode: appcode.Default,
|
|
SentAtMs: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC).UnixMilli(),
|
|
},
|
|
TargetType: "user",
|
|
TargetUserIds: []int64{firstTargetID, secondTargetID},
|
|
GiftId: "rose",
|
|
GiftCount: 1,
|
|
PoolId: "super_lucky",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("send multi-target lucky gift failed: %v", err)
|
|
}
|
|
if len(luckyGift.checks) != 1 || luckyGift.checks[0].GetPoolId() != "super_lucky" {
|
|
t.Fatalf("multi-target lucky gift should check pool once: %+v", luckyGift.checks)
|
|
}
|
|
if len(luckyGift.draws) != 2 {
|
|
t.Fatalf("multi-target lucky gift should draw once per target, got %d", len(luckyGift.draws))
|
|
}
|
|
firstDraw := luckyGift.draws[0].GetLuckyGift()
|
|
secondDraw := luckyGift.draws[1].GetLuckyGift()
|
|
if firstDraw.GetCommandId() != "cmd-lucky-multi:target:202" || firstDraw.GetTargetUserId() != firstTargetID || firstDraw.GetCoinSpent() != 100 {
|
|
t.Fatalf("first target lucky draw mismatch: %+v", firstDraw)
|
|
}
|
|
if secondDraw.GetCommandId() != "cmd-lucky-multi:target:303" || secondDraw.GetTargetUserId() != secondTargetID || secondDraw.GetCoinSpent() != 200 {
|
|
t.Fatalf("second target lucky draw mismatch: %+v", secondDraw)
|
|
}
|
|
if resp.GetLuckyGift().GetCommandId() != "cmd-lucky-multi" ||
|
|
resp.GetLuckyGift().GetTargetUserId() != 0 ||
|
|
resp.GetLuckyGift().GetSelectedTierId() != "batch" ||
|
|
resp.GetLuckyGift().GetMultiplierPpm() != 5_000_000 ||
|
|
resp.GetLuckyGift().GetEffectiveRewardCoins() != 500 ||
|
|
resp.GetLuckyGift().GetWalletTransactionId() != "" ||
|
|
resp.GetLuckyGift().GetCoinBalanceAfter() != 9100 ||
|
|
!resp.GetLuckyGift().GetStageFeedback() ||
|
|
!resp.GetLuckyGift().GetHighMultiplier() ||
|
|
len(resp.GetLuckyGifts()) != 2 {
|
|
t.Fatalf("multi-target lucky response must include aggregate and list results: %+v", resp)
|
|
}
|
|
if resp.GetLuckyGifts()[0].GetCommandId() != "cmd-lucky-multi:target:202" || resp.GetLuckyGifts()[0].GetMultiplierPpm() != 2_000_000 || resp.GetLuckyGifts()[1].GetCommandId() != "cmd-lucky-multi:target:303" || resp.GetLuckyGifts()[1].GetMultiplierPpm() != 3_000_000 || resp.GetLuckyGifts()[1].GetTargetUserId() != secondTargetID {
|
|
t.Fatalf("multi-target lucky_gifts response mismatch: %+v", resp.GetLuckyGifts())
|
|
}
|
|
}
|