Files
galaxy-game/rtmanager/internal/domain/operation/log_test.go
T
2026-04-28 20:39:18 +02:00

131 lines
3.2 KiB
Go

package operation
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestOpKindIsKnown(t *testing.T) {
for _, kind := range AllOpKinds() {
assert.Truef(t, kind.IsKnown(), "expected %q known", kind)
}
assert.False(t, OpKind("").IsKnown())
assert.False(t, OpKind("rollback").IsKnown())
}
func TestAllOpKindsCoverFrozenSet(t *testing.T) {
assert.ElementsMatch(t,
[]OpKind{
OpKindStart, OpKindStop, OpKindRestart, OpKindPatch,
OpKindCleanupContainer, OpKindReconcileAdopt, OpKindReconcileDispose,
},
AllOpKinds(),
)
}
func TestOpSourceIsKnown(t *testing.T) {
for _, source := range AllOpSources() {
assert.Truef(t, source.IsKnown(), "expected %q known", source)
}
assert.False(t, OpSource("").IsKnown())
assert.False(t, OpSource("manual").IsKnown())
}
func TestAllOpSourcesCoverFrozenSet(t *testing.T) {
assert.ElementsMatch(t,
[]OpSource{
OpSourceLobbyStream, OpSourceGMRest, OpSourceAdminRest,
OpSourceAutoTTL, OpSourceAutoReconcile,
},
AllOpSources(),
)
}
func TestOutcomeIsKnown(t *testing.T) {
for _, outcome := range AllOutcomes() {
assert.Truef(t, outcome.IsKnown(), "expected %q known", outcome)
}
assert.False(t, Outcome("").IsKnown())
assert.False(t, Outcome("partial").IsKnown())
}
func TestAllOutcomesCoverFrozenSet(t *testing.T) {
assert.ElementsMatch(t,
[]Outcome{OutcomeSuccess, OutcomeFailure},
AllOutcomes(),
)
}
func successEntry() OperationEntry {
started := time.Date(2026, 4, 27, 12, 0, 0, 0, time.UTC)
finished := started.Add(time.Second)
return OperationEntry{
GameID: "game-test",
OpKind: OpKindStart,
OpSource: OpSourceLobbyStream,
SourceRef: "1700000000000-0",
ImageRef: "galaxy/game:1.0.0",
ContainerID: "container-1",
Outcome: OutcomeSuccess,
StartedAt: started,
FinishedAt: &finished,
}
}
func TestOperationEntryValidateHappy(t *testing.T) {
require.NoError(t, successEntry().Validate())
}
func TestOperationEntryValidateAcceptsReplayNoOp(t *testing.T) {
entry := successEntry()
entry.ErrorCode = "replay_no_op"
assert.NoError(t, entry.Validate())
}
func TestOperationEntryValidateAcceptsInFlight(t *testing.T) {
entry := successEntry()
entry.FinishedAt = nil
assert.NoError(t, entry.Validate())
}
func TestOperationEntryValidateRejects(t *testing.T) {
tests := []struct {
name string
mutate func(*OperationEntry)
}{
{"empty game id", func(e *OperationEntry) { e.GameID = "" }},
{"unknown op kind", func(e *OperationEntry) { e.OpKind = "exotic" }},
{"unknown op source", func(e *OperationEntry) { e.OpSource = "exotic" }},
{"unknown outcome", func(e *OperationEntry) { e.Outcome = "partial" }},
{"zero started at", func(e *OperationEntry) { e.StartedAt = time.Time{} }},
{"zero finished at", func(e *OperationEntry) {
zero := time.Time{}
e.FinishedAt = &zero
}},
{"finished before started", func(e *OperationEntry) {
before := e.StartedAt.Add(-time.Second)
e.FinishedAt = &before
}},
{"failure without error code", func(e *OperationEntry) {
e.Outcome = OutcomeFailure
e.ErrorCode = ""
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
entry := successEntry()
tt.mutate(&entry)
assert.Error(t, entry.Validate())
})
}
}