feat: gamemaster
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func validRunningRecord() RuntimeRecord {
|
||||
created := time.Date(2026, 4, 27, 12, 0, 0, 0, time.UTC)
|
||||
started := created.Add(time.Minute)
|
||||
updated := started.Add(time.Minute)
|
||||
next := updated.Add(time.Hour)
|
||||
return RuntimeRecord{
|
||||
GameID: "game-1",
|
||||
Status: StatusRunning,
|
||||
EngineEndpoint: "http://galaxy-game-1:8080",
|
||||
CurrentImageRef: "ghcr.io/galaxy/game:v1.2.3",
|
||||
CurrentEngineVersion: "v1.2.3",
|
||||
TurnSchedule: "0 18 * * *",
|
||||
CurrentTurn: 0,
|
||||
NextGenerationAt: &next,
|
||||
CreatedAt: created,
|
||||
UpdatedAt: updated,
|
||||
StartedAt: &started,
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusIsKnown(t *testing.T) {
|
||||
for _, status := range AllStatuses() {
|
||||
assert.True(t, status.IsKnown(), "want known: %q", status)
|
||||
}
|
||||
assert.False(t, Status("exotic").IsKnown())
|
||||
assert.False(t, Status("").IsKnown())
|
||||
}
|
||||
|
||||
func TestStatusIsTerminal(t *testing.T) {
|
||||
assert.True(t, StatusFinished.IsTerminal())
|
||||
for _, status := range AllStatuses() {
|
||||
if status == StatusFinished {
|
||||
continue
|
||||
}
|
||||
assert.False(t, status.IsTerminal(), "%q must not be terminal", status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllStatusesStable(t *testing.T) {
|
||||
first := AllStatuses()
|
||||
second := AllStatuses()
|
||||
assert.Equal(t, first, second)
|
||||
assert.Len(t, first, 7)
|
||||
}
|
||||
|
||||
func TestRuntimeRecordValidateHappy(t *testing.T) {
|
||||
require.NoError(t, validRunningRecord().Validate())
|
||||
}
|
||||
|
||||
func TestRuntimeRecordValidateAcceptsStarting(t *testing.T) {
|
||||
record := validRunningRecord()
|
||||
record.Status = StatusStarting
|
||||
record.StartedAt = nil
|
||||
record.NextGenerationAt = nil
|
||||
|
||||
assert.NoError(t, record.Validate())
|
||||
}
|
||||
|
||||
func TestRuntimeRecordValidateRequiresFinishedAt(t *testing.T) {
|
||||
record := validRunningRecord()
|
||||
record.Status = StatusFinished
|
||||
record.FinishedAt = nil
|
||||
|
||||
assert.Error(t, record.Validate())
|
||||
|
||||
finished := record.UpdatedAt.Add(time.Minute)
|
||||
record.FinishedAt = &finished
|
||||
assert.NoError(t, record.Validate())
|
||||
}
|
||||
|
||||
func TestRuntimeRecordValidateRequiresStoppedAtForStopped(t *testing.T) {
|
||||
record := validRunningRecord()
|
||||
record.Status = StatusStopped
|
||||
assert.Error(t, record.Validate())
|
||||
|
||||
stopped := record.UpdatedAt.Add(time.Minute)
|
||||
record.StoppedAt = &stopped
|
||||
assert.NoError(t, record.Validate())
|
||||
}
|
||||
|
||||
func TestRuntimeRecordValidateRejects(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*RuntimeRecord)
|
||||
}{
|
||||
{"empty game id", func(r *RuntimeRecord) { r.GameID = "" }},
|
||||
{"unknown status", func(r *RuntimeRecord) { r.Status = "exotic" }},
|
||||
{"empty engine endpoint", func(r *RuntimeRecord) { r.EngineEndpoint = "" }},
|
||||
{"empty image ref", func(r *RuntimeRecord) { r.CurrentImageRef = "" }},
|
||||
{"empty engine version", func(r *RuntimeRecord) { r.CurrentEngineVersion = "" }},
|
||||
{"empty turn schedule", func(r *RuntimeRecord) { r.TurnSchedule = "" }},
|
||||
{"negative turn", func(r *RuntimeRecord) { r.CurrentTurn = -1 }},
|
||||
{"zero created at", func(r *RuntimeRecord) { r.CreatedAt = time.Time{} }},
|
||||
{"zero updated at", func(r *RuntimeRecord) { r.UpdatedAt = time.Time{} }},
|
||||
{"updated before created", func(r *RuntimeRecord) {
|
||||
r.UpdatedAt = r.CreatedAt.Add(-time.Minute)
|
||||
}},
|
||||
{"started before created", func(r *RuntimeRecord) {
|
||||
before := r.CreatedAt.Add(-time.Minute)
|
||||
r.StartedAt = &before
|
||||
}},
|
||||
{"running missing started at", func(r *RuntimeRecord) { r.StartedAt = nil }},
|
||||
{"starting with started at", func(r *RuntimeRecord) {
|
||||
r.Status = StatusStarting
|
||||
// keep StartedAt set
|
||||
}},
|
||||
{"zero next generation at", func(r *RuntimeRecord) {
|
||||
zero := time.Time{}
|
||||
r.NextGenerationAt = &zero
|
||||
}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
record := validRunningRecord()
|
||||
tt.mutate(&record)
|
||||
assert.Error(t, record.Validate())
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user