extends SceneTree ## Asset-free ownership, lifecycle, dependency and timing regression for WMOs. const REGISTRY_SCRIPT := preload("res://src/render/wmo/wmo_placement_registry.gd") const REGISTRY_PATH := "res://src/render/wmo/wmo_placement_registry.gd" const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd" func _initialize() -> void: var failures: Array[String] = [] _verify_invalid_and_first_reference(failures) _verify_idempotent_and_shared_references(failures) _verify_owner_checked_final_release(failures) _verify_global_reference_and_clear(failures) _verify_detached_sorted_diagnostics(failures) _verify_ownership_boundaries(failures) var elapsed_milliseconds := _verify_bounded_timing(failures) if not failures.is_empty(): for failure in failures: push_error("WMO_PLACEMENT_REGISTRY: %s" % failure) quit(1) return print( "WMO_PLACEMENT_REGISTRY PASS cases=10 iterations=100 elapsed_ms=%.3f" % elapsed_milliseconds ) quit(0) func _verify_invalid_and_first_reference(failures: Array[String]) -> void: var registry: RefCounted = REGISTRY_SCRIPT.new() _expect_false(registry.call("add_reference", "", "tile-a"), "empty placement rejected", failures) _expect_false(registry.call("add_reference", "uid:7", ""), "empty reference rejected", failures) _expect_true(registry.call("add_reference", "uid:7", "tile-a"), "first reference registers", failures) _expect_true(registry.call("contains", "uid:7"), "registered placement contained", failures) _expect_equal(int(registry.call("active_count")), 1, "first active count", failures) func _verify_idempotent_and_shared_references(failures: Array[String]) -> void: var registry: RefCounted = REGISTRY_SCRIPT.new() registry.call("add_reference", "uid:11", "tile-a") _expect_false( registry.call("add_reference", "uid:11", "tile-a"), "same reference idempotent", failures ) _expect_false( registry.call("add_reference", "uid:11", "tile-b"), "shared reference retains placement", failures ) _expect_equal(int(registry.call("active_count")), 1, "shared active count", failures) _expect_false( registry.call("release_reference", "uid:11", "tile-a"), "non-final release retains placement", failures ) _expect_true(registry.call("contains", "uid:11"), "shared placement remains", failures) func _verify_owner_checked_final_release(failures: Array[String]) -> void: var registry: RefCounted = REGISTRY_SCRIPT.new() registry.call("add_reference", "uid:19", "tile-owner") _expect_false( registry.call("release_reference", "uid:19", "tile-other"), "non-owner release ignored", failures ) _expect_false( registry.call("release_reference", "uid:404", "tile-owner"), "unknown placement release ignored", failures ) _expect_true( registry.call("release_reference", "uid:19", "tile-owner"), "final owner release removes placement", failures ) _expect_false(registry.call("contains", "uid:19"), "released placement absent", failures) func _verify_global_reference_and_clear(failures: Array[String]) -> void: var registry: RefCounted = REGISTRY_SCRIPT.new() _expect_true( registry.call("add_reference", "global", "__global__"), "global reference registers", failures ) _expect_true( registry.call("release_reference", "global", "__global__"), "global final release removes", failures ) registry.call("add_reference", "uid:3", "tile-a") registry.call("clear") registry.call("clear") _expect_equal(int(registry.call("active_count")), 0, "clear idempotent", failures) func _verify_detached_sorted_diagnostics(failures: Array[String]) -> void: var registry: RefCounted = REGISTRY_SCRIPT.new() registry.call("add_reference", "uid:20", "tile-b") registry.call("add_reference", "uid:10", "tile-c") registry.call("add_reference", "uid:10", "tile-a") var snapshot: Array = registry.call("diagnostic_snapshot") _expect_equal(snapshot.size(), 2, "diagnostic record count", failures) _expect_string_equal(String(snapshot[0]["placement_key"]), "uid:10", "placement sort", failures) _expect_string_array(snapshot[0]["reference_keys"], ["tile-a", "tile-c"], "reference sort", failures) (snapshot[0]["reference_keys"] as Array).append("mutated") var fresh_snapshot: Array = registry.call("diagnostic_snapshot") _expect_string_array( fresh_snapshot[0]["reference_keys"], ["tile-a", "tile-c"], "diagnostics detached", failures ) func _verify_ownership_boundaries(failures: Array[String]) -> void: var loader_source := _read_text(LOADER_PATH, failures) var registry_source := _read_text(REGISTRY_PATH, failures) _expect_true( loader_source.contains("WMO_PLACEMENT_REGISTRY_SCRIPT.new()"), "loader composes registry", failures ) _expect_true(loader_source.contains("_wmo_placement_registry.add_reference("), "loader delegates add", failures) _expect_true(loader_source.contains("_wmo_placement_registry.release_reference("), "loader delegates release", failures) _expect_true(loader_source.contains("_wmo_placement_registry.clear()"), "loader delegates clear", failures) _expect_true( loader_source.contains("_wmo_instance_nodes_by_unique_key"), "loader retains node map", failures ) _expect_false(loader_source.contains("var _wmo_registry"), "legacy mixed registry removed", failures) for forbidden_token in ["extends Node", "Node3D", "Resource", "RID", "Thread", "Mutex", "Semaphore"]: _expect_false( registry_source.contains(forbidden_token), "registry omits %s ownership" % forbidden_token, failures ) func _verify_bounded_timing(failures: Array[String]) -> float: var registry: RefCounted = REGISTRY_SCRIPT.new() var started_microseconds := Time.get_ticks_usec() for iteration in range(100): for placement_index in range(256): var placement_key := "uid:%d" % placement_index registry.call("add_reference", placement_key, "tile-a") registry.call("add_reference", placement_key, "tile-b") for placement_index in range(256): var placement_key := "uid:%d" % placement_index registry.call("release_reference", placement_key, "tile-a") registry.call("release_reference", placement_key, "tile-b") _expect_equal(int(registry.call("active_count")), 0, "timing cycle %d clears" % iteration, failures) var elapsed_milliseconds := float(Time.get_ticks_usec() - started_microseconds) / 1000.0 _expect_true(elapsed_milliseconds < 1000.0, "100 shared-reference cycles remain bounded", failures) return elapsed_milliseconds 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_string_equal( actual_value: String, expected_value: String, label: String, failures: Array[String] ) -> void: if actual_value != expected_value: failures.append("%s expected %s, got %s" % [label, expected_value, actual_value]) func _expect_string_array( actual_values: Array, expected_values: Array, label: String, failures: Array[String] ) -> void: if actual_values != expected_values: failures.append("%s expected %s, got %s" % [label, expected_values, actual_values]) 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)