aboutsummaryrefslogtreecommitdiff
path: root/internal/game/harness_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/harness_test.go')
-rw-r--r--internal/game/harness_test.go33
1 files changed, 33 insertions, 0 deletions
diff --git a/internal/game/harness_test.go b/internal/game/harness_test.go
index 3bdce0f..c5377b4 100644
--- a/internal/game/harness_test.go
+++ b/internal/game/harness_test.go
@@ -131,6 +131,39 @@ func newHarness(t *testing.T) *harness {
return h
}
+// newHarnessWithTicks is newHarness with the production master tick
+// subscription registered, so tick-driven systems (disconnect countdown,
+// action advance, casino tick) run exactly as they do in production. Most
+// harness tests drive the systems directly and do not need this.
+func newHarnessWithTicks(t *testing.T) *harness {
+ t.Helper()
+ h := newHarness(t)
+ h.g.SubscribeTicks(1, func() bool {
+ h.g.RunTickSystems()
+ return true
+ })
+ return h
+}
+
+// Regression: the harness must be able to run the real master tick sequence,
+// which is the only way the disconnect countdown (Hub.Remove -> DisconnectTick
+// -> onRemove) is exercised end-to-end.
+func TestHarnessWithTicksCompletesDisconnect(t *testing.T) {
+ h := newHarnessWithTicks(t)
+ h.seedAccount("alice")
+ h.seedCharacter("alice", "alice")
+ sess, _ := h.connect("alice")
+ h.hub.Remove(sess)
+ h.barrier()
+ deadline := time.Now().Add(2 * time.Second)
+ for time.Now().Before(deadline) && len(h.hub.AllSessions()) > 0 {
+ time.Sleep(5 * time.Millisecond)
+ }
+ if got := len(h.hub.AllSessions()); got != 0 {
+ t.Fatalf("session not hard-removed after the countdown: %d", got)
+ }
+}
+
// seedWorld writes the minimal on-disk content a Game needs: three rooms.
func seedWorld(t *testing.T, dir string) {
t.Helper()