## T-1182 tests: step_canvas_request.gd — request lifecycle (cache hit/miss, ## staleness gate, the extent ECHO rule). Live mode is required for ## SimBridge.request_step_canvas() to actually send (test_mode short-circuits ## it), so these tests exercise on_response()/request_now() against a ## directly-constructed StepCanvasRequest node without a live bridge ## connection — request_now() on a cache MISS calls into SimBridge, which is ## a silent no-op in test_mode (SimBridge.test_mode defaults true outside ## SR_LIVE=1), so no live server is needed for these assertions. class_name TestStepCanvasRequest extends GdUnitTestSuite const StepCanvasRequestScript := preload("res://ui/implant/apps/atlas/step_canvas/step_canvas_request.gd") func test_cache_hit_emits_canvas_ready_synchronously_with_no_pending_state() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) var canvas := {"width": 64, "height": 64} req.get_cache().put("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64), canvas) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.request_now("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64)) assert_int(received.size()).is_equal(1) assert_that(received[0]).is_equal(canvas) assert_bool(req.is_pending()).is_false() func test_cache_miss_sets_pending_true() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "Chunk", Vector2i(0, 0), Vector2i(64, 64)) assert_bool(req.is_pending()).is_true() func test_on_response_ignores_a_response_for_a_different_body() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64)) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.on_response( { "body_id": "SomeOtherBody", "rung": "District", "center": Vector2i(0, 0), "min_wl_m": 0, "status": "Ready", "canvas": {"width": 1}, } ) assert_int(received.size()).is_equal(0) func test_on_response_ignores_a_response_for_a_different_rung() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64)) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.on_response( { "body_id": "GJ1c", "rung": "Chunk", # a different rung answering — must be ignored "center": Vector2i(0, 0), "min_wl_m": 0, "status": "Ready", "canvas": {"width": 1}, } ) assert_int(received.size()).is_equal(0) func test_on_response_ignores_a_stale_center_for_a_fixed_rung() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64)) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.on_response( { "body_id": "GJ1c", "rung": "District", "center": Vector2i(999, 999), # answers a since-panned-away-from center "min_wl_m": 0, "status": "Ready", "canvas": {"width": 1}, } ) assert_int(received.size()).is_equal(0) ## Global ignores center/extent server-side — a Global response's staleness ## check must NOT compare center at all (an echoed (0,0) sentinel must not ## be rejected as "stale" against whatever was requested). func test_on_response_global_rung_ignores_center_in_staleness_check() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "Global", Vector2i.ZERO, Vector2i.ZERO) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.on_response( { "body_id": "GJ1c", "rung": "Global", "center": Vector2i.ZERO, "extent": Vector2i.ZERO, "min_wl_m": 0, "status": "Ready", "canvas": {"width": 19_139, "height": 9_569}, } ) assert_int(received.size()).is_equal(1) ## The extent ECHO rule (T-1181 wire addendum, mandatory): held extent comes ## from the RESPONSE's own echoed extent, never the requested one — a ## server-side clamp can shrink the actual canvas below what was asked for. func test_on_response_holds_the_echoed_extent_not_the_requested_one() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "Chunk", Vector2i(0, 0), Vector2i(9_999, 9_999)) req.on_response( { "body_id": "GJ1c", "rung": "Chunk", "center": Vector2i(0, 0), "extent": Vector2i(3_840, 2_160), # server-clamped echo, smaller than requested "min_wl_m": 0, "status": "Ready", "canvas": {"width": 3_840, "height": 2_160}, } ) assert_that(req.get_held_extent()).is_equal(Vector2i(3_840, 2_160)) ## Global's held extent comes from the canvas's own width/height (the wire ## extent echo is a fixed (0,0) sentinel for that rung — nothing to read). func test_on_response_global_held_extent_derives_from_canvas_dimensions() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "Global", Vector2i.ZERO, Vector2i.ZERO) req.on_response( { "body_id": "GJ1c", "rung": "Global", "center": Vector2i.ZERO, "extent": Vector2i.ZERO, "min_wl_m": 0, "status": "Ready", "canvas": {"width": 19_139, "height": 9_569}, } ) assert_that(req.get_held_extent()).is_equal(Vector2i(19_139, 9_569)) func test_on_response_ready_with_null_canvas_retries_rather_than_adopting() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "District", Vector2i(0, 0), Vector2i(64, 64)) var received: Array = [] req.canvas_ready.connect(func(c: Dictionary) -> void: received.append(c)) req.on_response( { "body_id": "GJ1c", "rung": "District", "center": Vector2i(0, 0), "min_wl_m": 0, "status": "Ready", "canvas": null, } ) assert_int(received.size()).is_equal(0) assert_bool(req.is_pending()).is_true() func test_on_response_not_found_gives_up_immediately() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "Chunk", Vector2i(0, 0), Vector2i(64, 64)) req.on_response({"body_id": "GJ1c", "rung": "Chunk", "status": "NotFound"}) assert_bool(req.is_pending()).is_false() func test_on_response_stores_a_fresh_ready_canvas_in_the_cache() -> void: var req = auto_free(StepCanvasRequestScript.new()) add_child(req) req.request_now("GJ1c", "District", Vector2i(5, 5), Vector2i(64, 64)) req.on_response( { "body_id": "GJ1c", "rung": "District", "center": Vector2i(5, 5), "extent": Vector2i(64, 64), "min_wl_m": 0, "status": "Ready", "canvas": {"width": 64, "height": 64}, } ) assert_bool(req.get_cache().has("GJ1c", "District", Vector2i(5, 5), Vector2i(64, 64))).is_true()