hyapp-server/services/activity-service/internal/app/vip_rebate_notice_test.go

91 lines
3.8 KiB
Go

package app
import (
"context"
"testing"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/walletmq"
messageservice "hyapp/services/activity-service/internal/service/message"
"hyapp/services/activity-service/internal/testutil/mysqltest"
)
func TestVIPRebateAvailableEventFromWalletMessage(t *testing.T) {
body := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{
"rebate_id":"viprebate_fami_2027-01-15_42",
"user_id":42,
"task_day":"2027-01-15",
"vip_level":9,
"vip_name":"VIP9",
"coin_amount":100000,
"available_at_ms":1800000000000,
"expires_at_ms":1800086400000,
"config_version":7,
"created_at_ms":1800000000100
}`)
event, ok, err := vipRebateAvailableEventFromWalletMessage(body)
if err != nil || !ok {
t.Fatalf("parse VIP rebate event failed: ok=%v event=%+v err=%v", ok, event, err)
}
if event.AppCode != "fami" || event.EventID != "wev-vip-rebate" || event.RebateID != "viprebate_fami_2027-01-15_42" || event.UserID != 42 || event.TaskDay != "2027-01-15" || event.VIPLevel != 9 || event.CoinAmount != 100000 || event.ExpiresAtMS != 1800086400000 || event.ConfigVersion != 7 {
t.Fatalf("VIP rebate event mismatch: %+v", event)
}
}
func TestVIPRebateWalletEventSkipsOtherFactsAndRejectsCorruptTarget(t *testing.T) {
other := vipRebateWalletMessage(t, "WalletRechargeRecorded", 42, `{}`)
if event, ok, err := vipRebateAvailableEventFromWalletMessage(other); err != nil || ok || event.EventID != "" {
t.Fatalf("non-target event should be acknowledged: ok=%v event=%+v err=%v", ok, event, err)
}
corrupt := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{"rebate_id":"r1","user_id":99}`)
if _, ok, err := vipRebateAvailableEventFromWalletMessage(corrupt); err == nil || ok {
t.Fatalf("corrupt target event must fail for MQ retry: ok=%v err=%v", ok, err)
}
}
func TestVIPRebateWalletEventCreatesOneIdempotentSystemNotice(t *testing.T) {
ctx := appcode.WithContext(context.Background(), "fami")
repository := mysqltest.NewRepository(t)
service := messageservice.New(messageservice.Config{NodeID: "activity-test"}, repository)
service.SetClock(func() time.Time { return time.UnixMilli(1800000000200) })
event := vipRebateAvailableEvent{
AppCode: "fami", EventID: "wev-vip-rebate", RebateID: "viprebate_fami_2027-01-15_42",
UserID: 42, TaskDay: "2027-01-15", VIPLevel: 9, VIPName: "VIP9", CoinAmount: 100000,
AvailableAtMS: 1800000000000, ExpiresAtMS: 1800086400000, ConfigVersion: 7, CreatedAtMS: 1800000000100,
}
if err := createVIPRebateSystemNotice(ctx, service, event); err != nil {
t.Fatalf("create system notice failed: %v", err)
}
if err := createVIPRebateSystemNotice(ctx, service, event); err != nil {
t.Fatalf("duplicate system notice should be idempotent: %v", err)
}
items, _, err := service.ListInboxMessages(ctx, 42, "system", 20, "")
if err != nil || len(items) != 1 {
t.Fatalf("system inbox mismatch: items=%+v err=%v", items, err)
}
item := items[0]
if item.Title != "VIP金币返现" || item.ActionType != "vip_coin_rebate_claim" || item.AggregateID != event.RebateID || item.ExpireAtMS != event.ExpiresAtMS || item.ActionParam == "" {
t.Fatalf("VIP rebate notice mismatch: %+v", item)
}
}
func vipRebateWalletMessage(t *testing.T, eventType string, userID int64, payload string) []byte {
t.Helper()
body, err := walletmq.EncodeWalletOutboxMessage(walletmq.WalletOutboxMessage{
AppCode: "fami",
EventID: "wev-vip-rebate",
EventType: eventType,
TransactionID: "viprebate_fami_2027-01-15_42",
CommandID: "vip-rebate-generate:fami:2027-01-15:42",
UserID: userID,
AssetType: "COIN",
PayloadJSON: payload,
OccurredAtMS: 1800000000100,
})
if err != nil {
t.Fatalf("encode wallet outbox message: %v", err)
}
return body
}