aboutsummaryrefslogtreecommitdiff
path: root/internal/player/roomset_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/player/roomset_test.go')
-rw-r--r--internal/player/roomset_test.go58
1 files changed, 58 insertions, 0 deletions
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")
+ }
+}