package controller_test import ( "fmt" "testing" "galaxy/model/order" "galaxy/util" "galaxy/game/internal/controller" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestServiceOrderStoredThenAppliedAtTurn is the end-to-end regression for the // order lifecycle against a real Service backed by a temporary storage // directory: an order submitted through ValidateOrder is persisted (FetchOrder // returns it before the turn), applied when the turn is produced (GenerateTurn // advances the turn), and its per-command verdict survives turn production // (FetchOrder still returns it with cmdApplied set). It guards the wiring the // Stage 3 collapse reworked — Service methods threading the concrete repo // through validate → store → produce → read-back. func TestServiceOrderStoredThenAppliedAtTurn(t *testing.T) { root, cleanup := util.CreateWorkDir(t) defer cleanup() svc, err := controller.NewService(root) require.NoError(t, err) races := make([]string, 10) for i := range races { races[i] = fmt.Sprintf("race_%02d", i) } if _, err := svc.GenerateGame(uuid.New(), races); err != nil { t.Fatalf("init game: %v", err) } vote := &order.CommandRaceVote{ CommandMeta: order.CommandMeta{CmdID: uuid.NewString(), CmdType: order.CommandTypeRaceVote}, Acceptor: races[1], } stored, err := svc.ValidateOrder(races[0], vote) require.NoError(t, err) require.Len(t, stored.Commands, 1) // The order is persisted and retrievable for the current turn (0) // before the turn is produced. got, ok, err := svc.FetchOrder(races[0], 0) require.NoError(t, err) require.True(t, ok, "submitted order must be retrievable before the turn") require.Len(t, got.Commands, 1) // Producing the turn applies stored orders and advances the turn. state, err := svc.GenerateTurn() require.NoError(t, err) assert.Equal(t, uint(1), state.Turn, "turn must advance after production") // The turn-0 order still carries its per-command verdict, recorded by // turn production. applied, ok, err := svc.FetchOrder(races[0], 0) require.NoError(t, err) require.True(t, ok) require.Len(t, applied.Commands, 1) v, ok := order.AsCommand[*order.CommandRaceVote](applied.Commands[0]) require.True(t, ok, "stored command must round-trip to its concrete type") require.NotNil(t, v.CmdApplied, "turn production must record cmdApplied") assert.True(t, *v.CmdApplied, "a valid vote must apply at turn production") // Orders are per-turn: the freshly produced turn carries no order yet. _, ok, err = svc.FetchOrder(races[0], 1) require.NoError(t, err) assert.False(t, ok, "the freshly produced turn carries no stored order") }