55 lines
2.4 KiB
Go
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)
|
|
}
|
|
}
|