extends SceneTree ## Asset-free ordering, cursor, dependency and timing regression for WMO builds. const PLANNER_SCRIPT := preload("res://src/render/wmo/wmo_render_build_step_planner.gd") const PLANNER_PATH := "res://src/render/wmo/wmo_render_build_step_planner.gd" const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd" func _initialize() -> void: var failures: Array[String] = [] _verify_mesh_steps_precede_multimeshes(failures) _verify_multimesh_cursor_and_completion(failures) _verify_empty_and_raw_integer_behavior(failures) _verify_fresh_results(failures) _verify_loader_and_dependency_boundaries(failures) var elapsed_milliseconds := _verify_bounded_timing(failures) if not failures.is_empty(): for failure in failures: push_error("WMO_RENDER_BUILD_STEP_PLANNER: %s" % failure) quit(1) return print( "WMO_RENDER_BUILD_STEP_PLANNER PASS cases=9 iterations=20000 elapsed_ms=%.3f" % elapsed_milliseconds ) quit(0) func _verify_mesh_steps_precede_multimeshes(failures: Array[String]) -> void: var planner: RefCounted = PLANNER_SCRIPT.new() var first: Dictionary = planner.call("plan_step", 2, 0, 3, 0) _expect_operation(first, PLANNER_SCRIPT.OPERATION_MESH, 0, 1, 0, "first mesh", failures) var second: Dictionary = planner.call("plan_step", 2, 1, 3, 0) _expect_operation(second, PLANNER_SCRIPT.OPERATION_MESH, 1, 2, 0, "second mesh", failures) var after_meshes: Dictionary = planner.call("plan_step", 2, 2, 3, 0) _expect_operation( after_meshes, PLANNER_SCRIPT.OPERATION_MULTIMESH, 0, 2, 1, "multimesh follows meshes", failures ) func _verify_multimesh_cursor_and_completion(failures: Array[String]) -> void: var planner: RefCounted = PLANNER_SCRIPT.new() var last_multimesh: Dictionary = planner.call("plan_step", 1, 1, 2, 1) _expect_operation( last_multimesh, PLANNER_SCRIPT.OPERATION_MULTIMESH, 1, 1, 2, "last multimesh", failures ) var complete: Dictionary = planner.call("plan_step", 1, 1, 2, 2) _expect_operation( complete, PLANNER_SCRIPT.OPERATION_COMPLETE, -1, 1, 2, "both ranges complete", failures ) func _verify_empty_and_raw_integer_behavior(failures: Array[String]) -> void: var planner: RefCounted = PLANNER_SCRIPT.new() var empty: Dictionary = planner.call("plan_step", 0, 0, 0, 0) _expect_operation(empty, PLANNER_SCRIPT.OPERATION_COMPLETE, -1, 0, 0, "empty", failures) var negative_mesh_cursor: Dictionary = planner.call("plan_step", 1, -1, 0, 0) _expect_operation( negative_mesh_cursor, PLANNER_SCRIPT.OPERATION_MESH, -1, 0, 0, "negative mesh cursor is not clamped", failures ) var negative_counts: Dictionary = planner.call("plan_step", -1, 0, -1, 0) _expect_operation( negative_counts, PLANNER_SCRIPT.OPERATION_COMPLETE, -1, 0, 0, "negative counts preserve comparisons", failures ) func _verify_fresh_results(failures: Array[String]) -> void: var planner: RefCounted = PLANNER_SCRIPT.new() var first: Dictionary = planner.call("plan_step", 1, 0, 0, 0) first["next_mesh_index"] = 99 var second: Dictionary = planner.call("plan_step", 1, 0, 0, 0) _expect_equal(int(second["next_mesh_index"]), 1, "result is fresh", failures) func _verify_loader_and_dependency_boundaries(failures: Array[String]) -> void: var loader_source := _read_text(LOADER_PATH, failures) var planner_source := _read_text(PLANNER_PATH, failures) _expect_true( loader_source.contains("WMO_RENDER_BUILD_STEP_PLANNER_SCRIPT.new()"), "loader composes planner", failures ) _expect_true( loader_source.contains("_wmo_render_build_step_planner.plan_step("), "loader delegates step decision", failures ) _expect_true( loader_source.contains("MeshInstance3D.new()") and loader_source.contains("MultiMeshInstance3D.new()"), "loader retains node materialization", failures ) _expect_false( loader_source.contains("if mesh_index < meshes.size():"), "loader omits mesh cursor decision", failures ) for forbidden_token in [ "extends Node", "Node3D", "Resource", "Mesh", "RID", "Thread", "Mutex", "FileAccess" ]: _expect_false( planner_source.contains(forbidden_token), "planner omits %s dependency" % forbidden_token, failures ) func _verify_bounded_timing(failures: Array[String]) -> float: var planner: RefCounted = PLANNER_SCRIPT.new() var started_microseconds := Time.get_ticks_usec() var checksum := 0 for iteration in range(20000): var step: Dictionary = planner.call( "plan_step", 48, iteration % 49, 24, iteration % 25 ) checksum += int(step["selected_index"]) var elapsed_milliseconds := float(Time.get_ticks_usec() - started_microseconds) / 1000.0 _expect_true(checksum > 0, "timing checksum", failures) _expect_true(elapsed_milliseconds < 1000.0, "20,000 plans remain bounded", failures) return elapsed_milliseconds func _expect_operation( actual_step: Dictionary, expected_operation: StringName, expected_selected_index: int, expected_next_mesh_index: int, expected_next_multimesh_index: int, label: String, failures: Array[String] ) -> void: if actual_step["operation"] != expected_operation: failures.append( "%s operation expected %s, got %s" % [label, expected_operation, actual_step["operation"]] ) _expect_equal( int(actual_step["selected_index"]), expected_selected_index, "%s selected" % label, failures ) _expect_equal( int(actual_step["next_mesh_index"]), expected_next_mesh_index, "%s next mesh" % label, failures ) _expect_equal( int(actual_step["next_multimesh_index"]), expected_next_multimesh_index, "%s next multimesh" % label, failures ) 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_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_true(actual_value: bool, label: String, failures: Array[String]) -> void: if not actual_value: failures.append("%s expected true" % label) func _expect_false(actual_value: bool, label: String, failures: Array[String]) -> void: if actual_value: failures.append("%s expected false" % label)