From 0e60567a7a0addb9421769ee7be7853bfa8788cb Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sat, 19 Sep 2026 03:15:59 -0400 Subject: refactor: simplifcation, change how rooms are stored in player yaml, remove legacy code --- internal/player/roomset_test.go | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'internal/player/roomset_test.go') diff --git a/internal/player/roomset_test.go b/internal/player/roomset_test.go index 2b6b9cb..38bd993 100644 --- a/internal/player/roomset_test.go +++ b/internal/player/roomset_test.go @@ -1,6 +1,8 @@ package player import ( + "encoding/base64" + "encoding/binary" "strings" "testing" @@ -85,3 +87,59 @@ func TestRoomSetMarshalEmpty(t *testing.T) { t.Errorf("MarshalYAML empty = %q, want empty string", s) } } + +// Sparse, high room IDs are the reason RoomSet is not a dense bitset: the +// encoding must stay proportional to the visited count, not the largest ID. +func TestRoomSetSparseEncodingIsCompact(t *testing.T) { + var rs RoomSet + for _, id := range []int{1001, 1002, 1003, 2001, 2006, 99999301} { + rs.Add(id) + } + data, err := yaml.Marshal(PlayerStats{RoomsVisited: rs}) + if err != nil { + t.Fatalf("marshal: %v", err) + } + if len(data) > 200 { + t.Fatalf("encoding is not compact for sparse IDs: %d bytes\n%s", len(data), data) + } + + var loaded PlayerStats + if err := yaml.Unmarshal(data, &loaded); err != nil { + t.Fatalf("unmarshal: %v", err) + } + for _, id := range []int{1001, 1002, 1003, 2001, 2006, 99999301} { + if !loaded.RoomsVisited.Has(id) { + t.Errorf("round trip lost room %d", id) + } + } + if loaded.RoomsVisited.Has(5000) { + t.Error("round trip invented room 5000") + } +} + +// The prototype has no legacy formats: anything without the v1 prefix is a +// hard error rather than a silently-decoded old bitset. +func TestRoomSetRejectsUnknownEncoding(t *testing.T) { + var wrap struct { + Visited RoomSet `yaml:"rooms_visited"` + } + if err := yaml.Unmarshal([]byte("rooms_visited: AQIDBA==\n"), &wrap); err == nil { + t.Fatal("expected error for unprefixed encoding") + } + if err := yaml.Unmarshal([]byte("rooms_visited: [7, 42, 900]\n"), &wrap); err == nil { + t.Fatal("expected error for YAML sequence encoding") + } +} + +func TestRoomSetRejectsOutOfRangeDelta(t *testing.T) { + // A valid uvarint delta above roomSetMaxID must fail rather than wrap or + // synthesize an absurd room ID. + buf := binary.AppendUvarint(nil, uint64(roomSetMaxID)+1) + encoded := roomSetV1Prefix + base64.StdEncoding.EncodeToString(buf) + var wrap struct { + Visited RoomSet `yaml:"rooms_visited"` + } + if err := yaml.Unmarshal([]byte("rooms_visited: "+encoded+"\n"), &wrap); err == nil { + t.Fatal("expected error for out-of-range delta") + } +} -- cgit v1.2.3