diff options
Diffstat (limited to 'internal/game/correct_vanished_account_reset_test.go')
| -rw-r--r-- | internal/game/correct_vanished_account_reset_test.go | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/internal/game/correct_vanished_account_reset_test.go b/internal/game/correct_vanished_account_reset_test.go new file mode 100644 index 0000000..d40f602 --- /dev/null +++ b/internal/game/correct_vanished_account_reset_test.go @@ -0,0 +1,75 @@ +package game + +// Regression: a session whose account file has vanished (purged, or deleted +// through the admin raw file editor) must be reset to the account-name prompt +// with no pending registration state left behind. Clearing Account alone left +// PendingPass set, so an already-buffered confirm-password line could still +// reach a handler that dereferences the account; applyNewAccount now also +// refuses to dereference a nil account. + +import ( + "strings" + "testing" + + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/player" +) + +func TestPublishAccountUpdateVanishedAccountResetsSession(t *testing.T) { + h := newHarness(t) + + conn := newChanConn() + sess := &net.Session{Conn: conn, Account: &player.Account{Name: "bob"}} + sess.SetState(net.StateNewAccount) + sess.PendingPass = "pw" + h.hub.Add(sess) + + h.g.RunOnOwner(func() { h.g.publishAccountUpdate("bob", "bob") }) + + if got := sess.State(); got != net.StateAccountName { + t.Errorf("state = %v, want StateAccountName", got) + } + if sess.Account != nil { + t.Errorf("account not cleared: %+v", sess.Account) + } + if sess.PendingPass != "" { + t.Errorf("PendingPass = %q, want it cleared with the account", sess.PendingPass) + } + out := string(conn.Bytes()) + if !strings.Contains(out, "Your account no longer exists.") { + t.Errorf("missing vanished-account notice; output = %q", out) + } + if !strings.Contains(out, "Account name: ") { + t.Errorf("missing account-name prompt; output = %q", out) + } +} + +func TestApplyNewAccountResetsWhenAccountVanished(t *testing.T) { + h := newHarness(t) + + conn := newChanConn() + sess := &net.Session{Conn: conn} + sess.SetState(net.StateNewAccount) + sess.PendingPass = "pw" + + // Direct call: the menu handlers run on the owner goroutine, so the test + // goroutine stands in for it and an unguarded dereference fails loudly. + h.g.applyNewAccount(sess, "hash", nil) + + if got := sess.State(); got != net.StateAccountName { + t.Errorf("state = %v, want StateAccountName", got) + } + if sess.Account != nil { + t.Errorf("account not cleared: %+v", sess.Account) + } + if sess.PendingPass != "" { + t.Errorf("PendingPass = %q, want it cleared", sess.PendingPass) + } + out := string(conn.Bytes()) + if !strings.Contains(out, "Account name: ") { + t.Errorf("missing account-name prompt; output = %q", out) + } + if _, err := h.g.AccountStore.LoadAccount("bob"); err == nil { + t.Error("an account was created for a session with no account bound") + } +} |
