af30846091
Validation of a player's order now applies every command against a transient game-state snapshot and records the per-command outcome (cmdApplied, cmdErrorCode) in each command's meta. The order is persisted even when some commands are rejected, and the response is 202 + UserGamesOrder so clients can surface the partial failure without the chain collapsing into "downstream service is unavailable". Pkg/error consts are reshelved onto three explicit ranges with a package doc and helpers (IsInternalCode/IsInputCode/IsGameStateCode): 1xxx internal/server (500/501), 2xxx structural input (400), 3xxx game-state per-command rejection (400 when escaping HTTP, otherwise recorded as cmdErrorCode). Two pre-existing typos fixed mechanically (ErrBeakGroupNumberNotEnough -> ErrBreakGroupNumberNotEnough, ErrRaceExinct -> ErrRaceExtinct) along with all callsites. Engine errorResponse maps *GenericError by shelf rather than mapping everything to 500. The Quit-not-last structural check in Controller.ValidateOrder is preserved and its type assertion fixed (was a value assertion against a pointer-typed command, so the check silently never fired). Backend, gateway and UI are unchanged — they were already correct on the 202 path; only the engine collapsing per-command rejection into 500 was needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package controller_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
e "galaxy/error"
|
|
|
|
"galaxy/game/internal/model/game"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestRaceVote(t *testing.T) {
|
|
c, g := newCache()
|
|
|
|
assert.Equal(t, c.Voted(Race_0_idx), Race_0_idx)
|
|
assert.Equal(t, c.Voted(Race_1_idx), Race_1_idx)
|
|
|
|
assert.NoError(t, g.RaceVote(Race_0.Name, Race_1.Name))
|
|
assert.Equal(t, Race_1_idx, c.Voted(Race_0_idx))
|
|
assert.Equal(t, Race_1_idx, c.Voted(Race_1_idx))
|
|
|
|
assert.ErrorContains(t,
|
|
g.RaceVote(UnknownRace, Race_1.Name),
|
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
|
assert.ErrorContains(t,
|
|
g.RaceVote(Race_0.Name, UnknownRace),
|
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
|
assert.ErrorContains(t,
|
|
g.RaceVote(Race_0.Name, Race_Extinct.Name),
|
|
e.GenericErrorText(e.ErrRaceExtinct))
|
|
assert.ErrorContains(t,
|
|
g.RaceVote(Race_Extinct.Name, Race_1.Name),
|
|
e.GenericErrorText(e.ErrRaceExtinct))
|
|
}
|
|
|
|
func TestRaceRelation(t *testing.T) {
|
|
c, g := newCache()
|
|
|
|
assert.NoError(t, g.RaceRelation(Race_0.Name, Race_1.Name, "war"))
|
|
assert.NoError(t, g.RaceRelation(Race_1.Name, Race_0.Name, "PEACE"))
|
|
|
|
assert.Equal(t, game.RelationWar, c.Relation(Race_0_idx, Race_1_idx))
|
|
assert.Equal(t, game.RelationPeace, c.Relation(Race_1_idx, Race_0_idx))
|
|
|
|
assert.ErrorContains(t,
|
|
g.RaceRelation(Race_0.Name, Race_1.Name, "Wojna"),
|
|
e.GenericErrorText(e.ErrInputUnknownRelation))
|
|
assert.ErrorContains(t,
|
|
g.RaceRelation(Race_0.Name, UnknownRace, "War"),
|
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
|
assert.ErrorContains(t,
|
|
g.RaceRelation(UnknownRace, Race_0.Name, "Peace"),
|
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
|
assert.ErrorContains(t,
|
|
g.RaceRelation(Race_0.Name, Race_Extinct.Name, "War"),
|
|
e.GenericErrorText(e.ErrRaceExtinct))
|
|
assert.ErrorContains(t,
|
|
g.RaceRelation(Race_Extinct.Name, Race_0.Name, "War"),
|
|
e.GenericErrorText(e.ErrRaceExtinct))
|
|
}
|
|
|
|
func TestRaceQuit(t *testing.T) {
|
|
c, g := newCache()
|
|
|
|
assert.ErrorContains(t,
|
|
g.RaceQuit(UnknownRace),
|
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
|
|
|
assert.ErrorContains(t,
|
|
g.RaceQuit(Race_Extinct.Name),
|
|
e.GenericErrorText(e.ErrRaceExtinct))
|
|
|
|
assert.NoError(t, g.RaceQuit(Race_0.Name))
|
|
assert.Equal(t, 3, int(c.Race(Race_0_idx).TTL))
|
|
}
|
|
|
|
func TestRaceID(t *testing.T) {
|
|
c, g := newCache()
|
|
|
|
c.Race(Race_0_idx).TTL = 9
|
|
|
|
_, err := g.RaceID(UnknownRace)
|
|
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputUnknownRace))
|
|
|
|
_, err = g.RaceID(Race_Extinct.Name)
|
|
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrRaceExtinct))
|
|
|
|
id, err := g.RaceID(Race_0.Name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, Race_0_ID, id)
|
|
}
|