extends SceneTree ## Asset-free M03 regression for pure runtime/editor ADT target planning. const PLANNER_SCRIPT := preload("res://src/render/streaming/streaming_target_planner.gd") const POLICY_SCRIPT := preload("res://src/render/streaming/streaming_target_policy.gd") const COORDINATE_MAPPER_SCRIPT := preload("res://src/domain/coordinates/coordinate_mapper.gd") const ADT_TILE_COORDINATE_SCRIPT := preload("res://src/domain/coordinates/adt_tile_coordinate.gd") const ADT_TILE_LOCAL_POSITION_SCRIPT := preload("res://src/domain/coordinates/adt_tile_local_position.gd") const PLANNER_PATH := "res://src/render/streaming/streaming_target_planner.gd" const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd" const PERFORMANCE_ITERATIONS := 250 const MAXIMUM_AVERAGE_PLAN_MILLISECONDS := 4.0 func _initialize() -> void: var failures: Array[String] = [] var planner = PLANNER_SCRIPT.new() _verify_center_radii_and_isolation(planner, failures) _verify_corner_prefetch_and_catalog_filter(planner, failures) _verify_policy_clamps(planner, failures) _verify_editor_plan(planner, failures) _verify_scene_free_extraction(failures) var elapsed_milliseconds := _measure_planner_iterations(planner, failures) if not failures.is_empty(): for failure in failures: push_error("STREAMING_TARGET_PLANNER: %s" % failure) quit(1) return print("STREAMING_TARGET_PLANNER PASS cases=5 iterations=%d elapsed_ms=%.3f average_ms=%.3f" % [ PERFORMANCE_ITERATIONS, elapsed_milliseconds, elapsed_milliseconds / float(PERFORMANCE_ITERATIONS), ]) quit(0) func _verify_center_radii_and_isolation(planner, failures: Array[String]) -> void: var available_tiles := _tile_catalog(28, 36, 44, 52) var focus_position = _tile_position(32, 48, 0.5, 0.5) var policy = POLICY_SCRIPT.new(0, 1, 0, 1, 1, 0.35) var plan = planner.plan_runtime(available_tiles, focus_position, policy) var wanted_tile_keys: Dictionary = plan.wanted_tile_keys() var retained_tile_keys: Dictionary = plan.retained_tile_keys() _expect_equal(plan.focus_tile.tile_x, 32, "center focus tile X", failures) _expect_equal(plan.focus_tile.tile_y, 48, "center focus tile Y", failures) _expect_equal(wanted_tile_keys.size(), 25, "center wanted 5x5", failures) _expect_equal(retained_tile_keys.size(), 49, "center retained 7x7", failures) _expect_true(wanted_tile_keys.has("30_46"), "wanted includes north-west radius edge", failures) _expect_true(wanted_tile_keys.has("34_50"), "wanted includes south-east radius edge", failures) _expect_true(retained_tile_keys.has("29_45"), "retained includes hysteresis edge", failures) _expect_true(wanted_tile_keys.is_read_only(), "wanted result is immutable", failures) _expect_true(retained_tile_keys.is_read_only(), "retained result is immutable", failures) _expect_equal(available_tiles.size(), 81, "available catalog remains unchanged", failures) func _verify_corner_prefetch_and_catalog_filter(planner, failures: Array[String]) -> void: var available_tiles := { "32_48": "tile-a", "33_48": "tile-b", "32_49": "tile-c", "33_49": "tile-d", "31_48": "outside-prefetch", } var focus_position = _tile_position(32, 48, 0.99, 0.99) var policy = POLICY_SCRIPT.new(0, 0, 0, 0, 0, 0.35) var plan = planner.plan_runtime(available_tiles, focus_position, policy) _expect_set_equal( plan.wanted_tile_keys(), ["32_48", "33_48", "32_49", "33_49"], "corner prefetch cross product", failures ) _expect_set_equal( plan.retained_tile_keys(), ["32_48", "33_48", "32_49", "33_49"], "corner retained cross product", failures ) func _verify_policy_clamps(planner, failures: Array[String]) -> void: var policy = POLICY_SCRIPT.new(16, 2, -5, -3, -4, 0.9) _expect_equal(policy.visible_tile_radius(), 2, "visible radius keeps tile minimum", failures) _expect_equal(policy.load_tile_radius(), 2, "negative prewarm clamps to zero", failures) _expect_equal(policy.retained_tile_radius(), 2, "negative retain clamps to zero", failures) _expect_near(policy.clamped_boundary_prefetch_threshold(), 0.49, "threshold upper clamp", failures) var plan = planner.plan_runtime( _tile_catalog(30, 34, 46, 50), _tile_position(32, 48, 0.5, 0.5), policy ) _expect_equal(plan.wanted_tile_keys().size(), 25, "clamped policy wanted radius", failures) _expect_equal(plan.retained_tile_keys().size(), 25, "clamped policy retained radius", failures) func _verify_editor_plan(planner, failures: Array[String]) -> void: var available_tiles := _tile_catalog(31, 33, 47, 49) var focus_position = _tile_position(32, 48, 0.5, 0.5) var negative_radius_plan = planner.plan_editor(available_tiles, focus_position, -4) _expect_set_equal( negative_radius_plan.wanted_tile_keys(), ["32_48"], "editor negative radius clamps to focus", failures ) _expect_set_equal( negative_radius_plan.retained_tile_keys(), ["32_48"], "editor retained matches wanted", failures ) var radius_one_plan = planner.plan_editor(available_tiles, focus_position, 1) _expect_equal(radius_one_plan.wanted_tile_keys().size(), 9, "editor radius one 3x3", failures) _expect_set_equal( radius_one_plan.retained_tile_keys(), radius_one_plan.wanted_tile_keys().keys(), "editor radius retained matches wanted", failures ) func _verify_scene_free_extraction(failures: Array[String]) -> void: var planner_source := _read_text(PLANNER_PATH, failures) _expect_true(planner_source.contains("extends RefCounted"), "planner is RefCounted", failures) _expect_true(not planner_source.contains("extends Node"), "planner does not inherit Node", failures) _expect_true(not planner_source.contains("Vector3"), "planner keeps typed position boundary", failures) for forbidden_text in ["WorkerThreadPool", "RenderingServer", "ResourceLoader", "_tile_load_queue"]: _expect_true(not planner_source.contains(forbidden_text), "planner omits %s" % forbidden_text, failures) var loader_source := _read_text(LOADER_PATH, failures) _expect_true(loader_source.contains("_streaming_target_planner.plan_runtime"), "loader delegates runtime planning", failures) _expect_true(loader_source.contains("_streaming_target_planner.plan_editor"), "loader delegates editor planning", failures) _expect_true(not loader_source.contains("func _predictive_focus_tiles"), "loader no longer owns prefetch planner", failures) func _measure_planner_iterations(planner, failures: Array[String]) -> float: var available_tiles := _tile_catalog(24, 40, 40, 56) var focus_position = _tile_position(32, 48, 0.99, 0.99) var policy = POLICY_SCRIPT.new(40, 5, 1, 3, 4, 0.42) var started_microseconds := Time.get_ticks_usec() for _iteration in PERFORMANCE_ITERATIONS: planner.plan_runtime(available_tiles, focus_position, policy) var elapsed_milliseconds := float(Time.get_ticks_usec() - started_microseconds) / 1000.0 var average_plan_milliseconds := elapsed_milliseconds / float(PERFORMANCE_ITERATIONS) _expect_true( average_plan_milliseconds <= MAXIMUM_AVERAGE_PLAN_MILLISECONDS, "average plan stays within %.1f ms (actual %.3f)" % [ MAXIMUM_AVERAGE_PLAN_MILLISECONDS, average_plan_milliseconds, ], failures ) return elapsed_milliseconds func _tile_catalog(minimum_tile_x: int, maximum_tile_x: int, minimum_tile_y: int, maximum_tile_y: int) -> Dictionary: var available_tiles: Dictionary = {} for tile_y in range(minimum_tile_y, maximum_tile_y + 1): for tile_x in range(minimum_tile_x, maximum_tile_x + 1): available_tiles["%d_%d" % [tile_x, tile_y]] = "synthetic" return available_tiles func _tile_position(tile_x: int, tile_y: int, east_fraction: float, south_fraction: float) -> GodotWorldPosition: var tile_coordinate = ADT_TILE_COORDINATE_SCRIPT.new(tile_x, tile_y) var tile_local_position = ADT_TILE_LOCAL_POSITION_SCRIPT.new( east_fraction * COORDINATE_MAPPER_SCRIPT.ADT_TILE_SIZE_YARDS, 0.0, south_fraction * COORDINATE_MAPPER_SCRIPT.ADT_TILE_SIZE_YARDS ) return COORDINATE_MAPPER_SCRIPT.adt_tile_local_to_godot(tile_coordinate, tile_local_position) func _read_text(path: String, failures: Array[String]) -> String: var file := FileAccess.open(path, FileAccess.READ) if file == null: failures.append("cannot open %s" % path) return "" return file.get_as_text() func _expect_set_equal(actual_set: Dictionary, expected_keys: Array, label: String, failures: Array[String]) -> void: var actual_keys := actual_set.keys() actual_keys.sort() var sorted_expected_keys := expected_keys.duplicate() sorted_expected_keys.sort() if actual_keys != sorted_expected_keys: failures.append("%s expected %s, got %s" % [label, sorted_expected_keys, actual_keys]) func _expect_equal(actual_value: int, expected_value: int, label: String, failures: Array[String]) -> void: if actual_value != expected_value: failures.append("%s expected %d, got %d" % [label, expected_value, actual_value]) func _expect_near(actual_value: float, expected_value: float, label: String, failures: Array[String]) -> void: if not is_equal_approx(actual_value, expected_value): failures.append("%s expected %.3f, got %.3f" % [label, expected_value, actual_value]) func _expect_true(actual_value: bool, label: String, failures: Array[String]) -> void: if not actual_value: failures.append("%s expected true" % label)