aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/room_rename_state_test.go
blob: 8c5be93fdf13e01cd2431b95be27bba552a629fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package admin

// Room-rename runtime-state regressions: renaming a room must move its live
// contents (ground items, seeded spawn markers, object state) to the new ID
// — never clear them — and undo must bring them back.

import (
	"testing"
)

// TestRoomRenameMovesRuntimeState: renaming a room with ground items moves
// them to the new room ID. The old implementation cleared the state before
// the migration callback could rekey it, destroying the room's contents.
func TestRoomRenameMovesRuntimeState(t *testing.T) {
	s := newTestAdminServer(t, map[int]string{
		1: "id: 1\nname: Room\nexits:\n  east:\n    room: 2\n",
		2: "id: 2\nname: Neighbor\nexits:\n  west:\n    room: 1\n",
	})
	s.world.AddGroundItem(1, "chips", 50)
	s.world.AddGroundItem(1, "chips", 10) // second entry: rekey must move the whole list
	s.rewriteRoomIDs = func(idMap map[int]int) { s.world.RekeyRooms(idMap) }
	s.undoStack.SetMigrateRoomIDs(s.rewriteRoomIDs)

	if rec := renameRoom(t, s, 1, 3); rec.Code != 200 {
		t.Fatalf("rename failed: %d %s", rec.Code, rec.Body.String())
	}
	if got := s.world.GroundItems(3)["chips"]; got != 60 {
		t.Fatalf("ground items after rename = %d, want 60 in room 3", got)
	}
	if got := s.world.GroundItems(1)["chips"]; got != 0 {
		t.Fatalf("ground items left behind in the old room: %d", got)
	}

	// Undo restores the files AND the runtime state through the inverse map.
	if s.undoStack.Undo() == nil {
		t.Fatal("undo failed")
	}
	if got := s.world.GroundItems(1)["chips"]; got != 60 {
		t.Fatalf("ground items after undo = %d, want 60 back in room 1", got)
	}
}

// TestRoomRenameUndoDoesNotClearSurvivingRoomState: undoing a rename must
// not clear runtime state of rooms whose files still exist afterwards
// (only undo-of-create / redo-of-delete drops state).
func TestRoomRenameUndoDoesNotClearSurvivingRoomState(t *testing.T) {
	s := newTestAdminServer(t, map[int]string{
		1: "id: 1\nname: Room\n",
		2: "id: 2\nname: Unrelated\n",
	})
	s.world.AddGroundItem(2, "chips", 5)
	s.rewriteRoomIDs = func(idMap map[int]int) { s.world.RekeyRooms(idMap) }
	s.undoStack.SetMigrateRoomIDs(s.rewriteRoomIDs)

	if rec := renameRoom(t, s, 1, 3); rec.Code != 200 {
		t.Fatalf("rename failed: %d %s", rec.Code, rec.Body.String())
	}
	// The unrelated room's state must survive the rename and its undo.
	if got := s.world.GroundItems(2)["chips"]; got != 5 {
		t.Fatalf("unrelated room state lost during rename: %d", got)
	}
	if s.undoStack.Undo() == nil {
		t.Fatal("undo failed")
	}
	if got := s.world.GroundItems(2)["chips"]; got != 5 {
		t.Fatalf("unrelated room state lost during undo: %d", got)
	}
}