2026-07-12 00:47:20 +08:00

55 lines
2.4 KiB
Go

package mysql
import (
"context"
"testing"
"hyapp/internal/testutil/mysqlschema"
"hyapp/pkg/appcode"
roomservice "hyapp/services/room-service/internal/room/service"
)
func TestEnsureGiftOperationDoesNotReactivateBeforeServicePayloadCheck(t *testing.T) {
schema := mysqlschema.New(t, mysqlschema.Config{
EnvVar: "ROOM_SERVICE_MYSQL_TEST_DSN",
InitDBPath: mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_room_service.sql"),
DatabasePrefix: "hyapp_room_gift_reactivate",
})
ctx := appcode.WithContext(context.Background(), appcode.Default)
repository, err := Open(ctx, schema.DSN, 4, 4)
if err != nil {
t.Fatalf("open repository: %v", err)
}
defer repository.Close()
stored := roomservice.GiftOperation{
AppCode: appcode.Default, RoomID: "room-reactivate", CommandID: "cmd-reactivate", ActorUserID: 101,
CommandPayload: []byte("stored-command"), RequestPayload: []byte("stored-request"),
Status: roomservice.GiftOperationStatusCompensated, LastError: "insufficient balance",
CreatedAtMS: 1_000, UpdatedAtMS: 1_000,
}
if _, created, err := repository.EnsureGiftOperation(ctx, stored); err != nil || !created {
t.Fatalf("insert compensated operation: created=%v err=%v", created, err)
}
conflicting := stored
conflicting.CommandPayload = []byte("different-command")
conflicting.RequestPayload = []byte("different-request")
conflicting.UpdatedAtMS = 2_000
got, created, err := repository.EnsureGiftOperation(ctx, conflicting)
if err != nil || created {
t.Fatalf("read duplicate operation: created=%v err=%v", created, err)
}
if got.Status != roomservice.GiftOperationStatusCompensated || string(got.CommandPayload) != "stored-command" {
t.Fatalf("Ensure mutated an unverified historical operation: %+v", got)
}
got, reactivated, err := repository.ReactivateCompensatedGiftOperation(ctx, stored.RoomID, stored.CommandID, 3_000)
if err != nil || !reactivated || got.Status != roomservice.GiftOperationStatusPending {
t.Fatalf("payload-checked CAS did not reactivate: reactivated=%v operation=%+v err=%v", reactivated, got, err)
}
got, reactivated, err = repository.ReactivateCompensatedGiftOperation(ctx, stored.RoomID, stored.CommandID, 4_000)
if err != nil || reactivated || got.Status != roomservice.GiftOperationStatusPending {
t.Fatalf("reactivation must be idempotent after status advances: reactivated=%v operation=%+v err=%v", reactivated, got, err)
}
}