124 lines
4.0 KiB
Go
124 lines
4.0 KiB
Go
package luckygiftmq
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
luckygifteventsv1 "hyapp.local/api/proto/events/luckygift/v1"
|
|
)
|
|
|
|
func TestLuckyGiftOutboxMessageRoundTrip(t *testing.T) {
|
|
envelope := validLuckyGiftEnvelope(t)
|
|
body, err := EncodeLuckyGiftOutboxMessage(envelope)
|
|
if err != nil {
|
|
t.Fatalf("EncodeLuckyGiftOutboxMessage failed: %v", err)
|
|
}
|
|
|
|
decoded, message, err := DecodeLuckyGiftOutboxMessage(body)
|
|
if err != nil {
|
|
t.Fatalf("DecodeLuckyGiftOutboxMessage failed: %v", err)
|
|
}
|
|
if !proto.Equal(decoded, envelope) {
|
|
t.Fatalf("decoded envelope mismatch: got=%v want=%v", decoded, envelope)
|
|
}
|
|
if message.MessageType != MessageTypeLuckyGiftOutboxEvent || message.EventType != EventTypeLuckyGiftDrawn || message.DrawID != "draw-1" {
|
|
t.Fatalf("decoded wrapper metadata mismatch: %+v", message)
|
|
}
|
|
}
|
|
|
|
func TestLuckyGiftOutboxMessageRejectsWrapperEnvelopeDrift(t *testing.T) {
|
|
envelope := validLuckyGiftEnvelope(t)
|
|
body, err := EncodeLuckyGiftOutboxMessage(envelope)
|
|
if err != nil {
|
|
t.Fatalf("EncodeLuckyGiftOutboxMessage failed: %v", err)
|
|
}
|
|
var message LuckyGiftOutboxMessage
|
|
if err := json.Unmarshal(body, &message); err != nil {
|
|
t.Fatalf("decode wrapper: %v", err)
|
|
}
|
|
message.DrawID = "draw-other"
|
|
tampered, err := json.Marshal(message)
|
|
if err != nil {
|
|
t.Fatalf("encode tampered wrapper: %v", err)
|
|
}
|
|
if _, _, err := DecodeLuckyGiftOutboxMessage(tampered); err == nil {
|
|
t.Fatal("wrapper/envelope drift must be rejected")
|
|
}
|
|
}
|
|
|
|
func TestLuckyGiftOutboxMessageRejectsUnsettledFact(t *testing.T) {
|
|
envelope := validLuckyGiftEnvelope(t)
|
|
var drawn luckygifteventsv1.LuckyGiftDrawn
|
|
if err := proto.Unmarshal(envelope.GetBody(), &drawn); err != nil {
|
|
t.Fatalf("decode lucky body: %v", err)
|
|
}
|
|
drawn.RewardStatus = "pending"
|
|
body, err := proto.Marshal(&drawn)
|
|
if err != nil {
|
|
t.Fatalf("encode pending lucky body: %v", err)
|
|
}
|
|
envelope.Body = body
|
|
if _, err := EncodeLuckyGiftOutboxMessage(envelope); err == nil {
|
|
t.Fatal("pending reward must not be published as LuckyGiftDrawn")
|
|
}
|
|
}
|
|
|
|
func TestLuckyGiftEventTypeTagAndDisplayBoundary(t *testing.T) {
|
|
tag, err := EventTypeTag(EventTypeLuckyGiftDrawn)
|
|
if err != nil || tag != TagLuckyGiftDrawn {
|
|
t.Fatalf("EventTypeTag result: tag=%q err=%v", tag, err)
|
|
}
|
|
if _, err := EventTypeTag("LuckyGiftUnknown"); err == nil {
|
|
t.Fatal("unsupported lucky gift event type must be rejected")
|
|
}
|
|
if LuckyGiftDisplayMinMultiplierPPM != 10_000_000 {
|
|
t.Fatalf("display threshold=%d, want exact 10x ppm", LuckyGiftDisplayMinMultiplierPPM)
|
|
}
|
|
}
|
|
|
|
func validLuckyGiftEnvelope(t *testing.T) *luckygifteventsv1.EventEnvelope {
|
|
t.Helper()
|
|
const drawCreatedAtMS int64 = 1_783_940_398_274
|
|
drawn := &luckygifteventsv1.LuckyGiftDrawn{
|
|
DrawId: "draw-1",
|
|
CommandId: "command-1",
|
|
RoomId: "room-1",
|
|
PoolId: "default",
|
|
GiftId: "43",
|
|
GiftCount: 1,
|
|
SenderUserId: 123456,
|
|
TargetUserId: 654321,
|
|
SenderName: "Lucky User",
|
|
SenderAvatar: "https://cdn.example/avatar.png",
|
|
SenderDisplayUserId: "123456",
|
|
SenderPrettyDisplayUserId: "888888",
|
|
VisibleRegionId: 1,
|
|
CountryId: 86,
|
|
CoinSpent: 100,
|
|
RuleVersion: 7,
|
|
ExperiencePool: "normal",
|
|
SelectedTierId: "normal_50x",
|
|
MultiplierPpm: 50_000_000,
|
|
BaseRewardCoins: 5_000,
|
|
EffectiveRewardCoins: 5_000,
|
|
HighMultiplier: true,
|
|
RewardStatus: "granted",
|
|
WalletTransactionId: "wallet-tx-1",
|
|
DrawCreatedAtMs: drawCreatedAtMS,
|
|
RewardGrantedAtMs: drawCreatedAtMS + 20,
|
|
}
|
|
body, err := proto.Marshal(drawn)
|
|
if err != nil {
|
|
t.Fatalf("marshal lucky body: %v", err)
|
|
}
|
|
return &luckygifteventsv1.EventEnvelope{
|
|
EventId: "lucky_gift_drawn:draw-1",
|
|
EventType: EventTypeLuckyGiftDrawn,
|
|
AppCode: "lalu",
|
|
DrawId: "draw-1",
|
|
OccurredAtMs: drawCreatedAtMS,
|
|
Body: body,
|
|
}
|
|
}
|