## T-1138 (D-226 T-1124 amendment §4): tests for the client-side ## DistrictWindowLayer LRU cache — keyed on (body_id, center, n), LRU-evict ## only (D-227 determinism means no freshness check is ever needed). class_name TestAtlasWindowCache extends GdUnitTestSuite const AtlasWindowCache := preload("res://ui/implant/apps/atlas/atlas_window_cache.gd") func test_make_key_distinguishes_body_center_and_n() -> void: var k1 := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32) var k2 := AtlasWindowCache.make_key("GJ1d", Vector2i(10, 20), 32) # different body var k3 := AtlasWindowCache.make_key("GJ1c", Vector2i(11, 20), 32) # different center var k4 := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 64) # different n assert_str(k1).is_not_equal(k2) assert_str(k1).is_not_equal(k3) assert_str(k1).is_not_equal(k4) func test_miss_returns_null_and_has_reports_false() -> void: var cache := AtlasWindowCache.new() assert_that(cache.get_window("GJ1c", Vector2i(0, 0), 32)).is_null() assert_bool(cache.has("GJ1c", Vector2i(0, 0), 32)).is_false() func test_put_then_get_round_trips_exact_window() -> void: var cache := AtlasWindowCache.new() var window := {"center": [10, 20], "n": 32, "morphology": PackedByteArray([1, 2, 3])} cache.put("GJ1c", Vector2i(10, 20), 32, window) assert_bool(cache.has("GJ1c", Vector2i(10, 20), 32)).is_true() assert_that(cache.get_window("GJ1c", Vector2i(10, 20), 32)).is_equal(window) ## D-227: a window fetched once is valid FOREVER for that (body, center, n) — ## no expiry, no invalidation path. Repeated get_window() calls across a ## simulated time gap (just repeated calls here — there is no clock in this ## cache at all) must keep returning the same stored value. func test_cached_window_never_expires() -> void: var cache := AtlasWindowCache.new() var window := {"center": [0, 0], "n": 32} cache.put("GJ1c", Vector2i(0, 0), 32, window) for _i in range(50): assert_that(cache.get_window("GJ1c", Vector2i(0, 0), 32)).is_equal(window) ## Different (body_id, center, n) tuples never collide — this is the whole ## point of the composite key (§4: "cacheable client-side keyed on ## (body_id, center, n)"). func test_different_bodies_same_center_do_not_collide() -> void: var cache := AtlasWindowCache.new() var window_a := {"body": "GJ1c"} var window_b := {"body": "GJ1d"} cache.put("GJ1c", Vector2i(10, 20), 32, window_a) cache.put("GJ1d", Vector2i(10, 20), 32, window_b) assert_that(cache.get_window("GJ1c", Vector2i(10, 20), 32)).is_equal(window_a) assert_that(cache.get_window("GJ1d", Vector2i(10, 20), 32)).is_equal(window_b) ## Overwriting the same key replaces the value (e.g. a re-fetch of an ## already-cached window from a server that somehow returns a different ## payload — should never happen under D-227, but the cache itself must not ## silently keep the stale one on an explicit put()). func test_put_overwrites_existing_key() -> void: var cache := AtlasWindowCache.new() cache.put("GJ1c", Vector2i(0, 0), 32, {"v": 1}) cache.put("GJ1c", Vector2i(0, 0), 32, {"v": 2}) assert_int(cache.size()).is_equal(1) assert_that(cache.get_window("GJ1c", Vector2i(0, 0), 32)).is_equal({"v": 2}) # ============================================================================= # LRU eviction # ============================================================================= func test_eviction_drops_least_recently_used_on_overflow() -> void: var cache := AtlasWindowCache.new(2) # max 2 entries cache.put("GJ1c", Vector2i(0, 0), 32, {"id": "a"}) cache.put("GJ1c", Vector2i(1, 0), 32, {"id": "b"}) cache.put("GJ1c", Vector2i(2, 0), 32, {"id": "c"}) # evicts (0,0) — oldest, untouched assert_int(cache.size()).is_equal(2) assert_bool(cache.has("GJ1c", Vector2i(0, 0), 32)).override_failure_message( "oldest entry should have been evicted" ).is_false() assert_bool(cache.has("GJ1c", Vector2i(1, 0), 32)).is_true() assert_bool(cache.has("GJ1c", Vector2i(2, 0), 32)).is_true() ## get_window() touches an entry (moves it to most-recently-used) — reading an ## entry must protect it from the NEXT eviction, otherwise "LRU" degrades to ## FIFO the moment anything reads from the cache (the common case: Esc-then- ## re-enter and pan-back are exactly "read a recently-cached window", §4). func test_get_touches_entry_and_protects_it_from_eviction() -> void: var cache := AtlasWindowCache.new(2) cache.put("GJ1c", Vector2i(0, 0), 32, {"id": "a"}) cache.put("GJ1c", Vector2i(1, 0), 32, {"id": "b"}) cache.get_window("GJ1c", Vector2i(0, 0), 32) # touch (0,0) — now most-recently-used cache.put("GJ1c", Vector2i(2, 0), 32, {"id": "c"}) # should evict (1,0), not (0,0) assert_bool(cache.has("GJ1c", Vector2i(0, 0), 32)).override_failure_message( "touched entry should survive eviction" ).is_true() assert_bool(cache.has("GJ1c", Vector2i(1, 0), 32)).override_failure_message( "untouched entry should be the one evicted" ).is_false() func test_max_entries_clamped_to_at_least_one() -> void: var cache := AtlasWindowCache.new(0) cache.put("GJ1c", Vector2i(0, 0), 32, {"id": "a"}) cache.put("GJ1c", Vector2i(1, 0), 32, {"id": "b"}) assert_int(cache.size()).is_equal(1) func test_clear_empties_the_cache() -> void: var cache := AtlasWindowCache.new() cache.put("GJ1c", Vector2i(0, 0), 32, {"id": "a"}) cache.clear() assert_int(cache.size()).is_equal(0) assert_bool(cache.has("GJ1c", Vector2i(0, 0), 32)).is_false() # ============================================================================= # min_wl_m (T-1150, zoom ladder design doc §3 aliasing risk) # ============================================================================= ## **MANDATORY aliasing regression (client half, T-1150):** two requests ## identical except for `min_wl_m` (the octave cutoff) must not collide — ## different cutoffs are different derived payloads (T-1149/T-1150). func test_make_key_distinguishes_min_wl_m_at_identical_body_center_n() -> void: var k_uncut := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 0) var k_cut := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 512) assert_str(k_uncut).is_not_equal(k_cut) ## Omitting min_wl_m (every pre-T-1150 call site) must produce the SAME key ## as passing the explicit no-cutoff default — byte/string compatibility for ## existing callers, not just "doesn't crash". func test_omitted_min_wl_m_matches_explicit_default() -> void: var k_omitted := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32) var k_explicit := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 0) assert_str(k_omitted).is_equal(k_explicit) # ============================================================================= # granularity_v2 (T-1152/T-1153): the string-tag axis — the ONLY thing that # distinguishes Region from District/Quarter (WindowGranularity has no # integer representation at all — see the server's own doc). This is the # SAME mandatory-aliasing regression class as the min_wl_m tests above, # extended to the new axis. # # T-1159: these tests used to also carry a legacy int `granularity` # positional argument (mirroring the server's now-retired # `window_granularity: u32` wire field) — removed along with the cache's own # legacy key component (see atlas_window_cache.gd's doc). # ============================================================================= ## **MANDATORY aliasing regression (T-1152/T-1153):** a Region-rung key and a ## District-rung key at the IDENTICAL (body_id, center, n, min_wl_m) must be ## DISTINCT cache keys — granularity_v2 is the only axis that can tell them ## apart. func test_make_key_distinguishes_granularity_v2_region_from_district() -> void: var k_district := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 0, "District") var k_region := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 0, "Region") assert_str(k_district).is_not_equal(k_region) ## Omitting granularity_v2 (every pre-T-1152 call site) must produce the SAME ## key as passing the explicit "District" default — byte/string ## compatibility, same contract as the min_wl_m default above. func test_omitted_granularity_v2_matches_explicit_district_default() -> void: var k_omitted := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32) var k_explicit := AtlasWindowCache.make_key("GJ1c", Vector2i(10, 20), 32, 0, "District") assert_str(k_omitted).is_equal(k_explicit) ## End-to-end through put()/get_window(): a Region-rung window and a ## District-rung window at the identical (body, center, n) must both be ## independently retrievable — the exact scenario a full-zoom-out-then-back-in ## at the SAME (center, n) would hit if a player oscillates across the ## District/Region boundary. func test_region_and_district_windows_coexist_at_identical_body_center_n() -> void: var cache := AtlasWindowCache.new() var district_window := {"granularity_v2": "District", "id": "district"} var region_window := {"granularity_v2": "Region", "id": "region"} cache.put("GJ1c", Vector2i(10, 20), 32, district_window, 0, "District") cache.put("GJ1c", Vector2i(10, 20), 32, region_window, 0, "Region") assert_int(cache.size()).is_equal(2) assert_that( cache.get_window("GJ1c", Vector2i(10, 20), 32, 0, "District") ).is_equal(district_window) assert_that( cache.get_window("GJ1c", Vector2i(10, 20), 32, 0, "Region") ).is_equal(region_window)