Files
open-wc/src/tools/verify_m2_mesh_resource_extractor.gd
T
sindoring 7b0e1eac5f refactor(M03): extract M2 mesh resource traversal
Work-Package: M03-RND-M2-MESH-RESOURCE-EXTRACTOR-001
Agent: sindo-main-codex
Tests: 36 headless renderer/coordinate contracts pass; checkpoint dry-run 7/7; documentation and coordination gates pass
Fidelity: preserves first-Mesh preorder and temporary PackedScene cleanup; no visual parity claim
2026-07-17 13:02:40 +04:00

186 lines
6.6 KiB
GDScript

extends SceneTree
## Synthetic direct-Resource/PackedScene/subtree/order/lifetime/boundary/timing
## regression for first-Mesh extraction.
const EXTRACTOR_SCRIPT := preload("res://src/render/m2/m2_mesh_resource_extractor.gd")
const EXTRACTOR_PATH := "res://src/render/m2/m2_mesh_resource_extractor.gd"
const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd"
func _initialize() -> void:
var failures: Array[String] = []
_verify_direct_and_invalid_resources(failures)
_verify_depth_first_subtree_order(failures)
_verify_packed_scene_mesh_and_temporary_lifetime(failures)
_verify_ownership_boundaries(failures)
var elapsed_milliseconds := _verify_bounded_timing(failures)
if not failures.is_empty():
for failure in failures:
push_error("M2_MESH_RESOURCE_EXTRACTOR: %s" % failure)
quit(1)
return
print(
"M2_MESH_RESOURCE_EXTRACTOR PASS cases=10 iterations=10000 elapsed_ms=%.3f"
% elapsed_milliseconds
)
quit(0)
func _verify_direct_and_invalid_resources(failures: Array[String]) -> void:
var extractor: RefCounted = EXTRACTOR_SCRIPT.new()
var direct_mesh := ArrayMesh.new()
_expect_same(
extractor.call("extract_first_mesh", direct_mesh),
direct_mesh,
"direct Mesh reference retained",
failures
)
_expect_same(extractor.call("extract_first_mesh", Resource.new()), null, "unsupported Resource returns null", failures)
_expect_same(extractor.call("extract_first_mesh", null), null, "null Resource returns null", failures)
_expect_same(extractor.call("find_first_mesh_in_subtree", null), null, "null subtree returns null", failures)
func _verify_depth_first_subtree_order(failures: Array[String]) -> void:
var extractor: RefCounted = EXTRACTOR_SCRIPT.new()
var root := Node3D.new()
var first_branch := Node3D.new()
var second_branch := Node3D.new()
var first_mesh_instance := MeshInstance3D.new()
var second_mesh_instance := MeshInstance3D.new()
var first_mesh := ArrayMesh.new()
var second_mesh := ArrayMesh.new()
first_mesh_instance.mesh = first_mesh
second_mesh_instance.mesh = second_mesh
root.add_child(first_branch)
root.add_child(second_branch)
first_branch.add_child(first_mesh_instance)
second_branch.add_child(second_mesh_instance)
_expect_same(
extractor.call("find_first_mesh_in_subtree", root),
first_mesh,
"depth-first child order retained",
failures
)
_expect_same(first_mesh_instance.get_parent(), first_branch, "subtree ownership unchanged", failures)
first_mesh_instance.mesh = null
_expect_same(
extractor.call("find_first_mesh_in_subtree", root),
second_mesh,
"null MeshInstance Mesh skipped by parent traversal",
failures
)
root.free()
func _verify_packed_scene_mesh_and_temporary_lifetime(failures: Array[String]) -> void:
var extractor: RefCounted = EXTRACTOR_SCRIPT.new()
var source_root := Node3D.new()
var mesh_instance := MeshInstance3D.new()
var packed_mesh := ArrayMesh.new()
mesh_instance.mesh = packed_mesh
source_root.add_child(mesh_instance)
mesh_instance.owner = source_root
var packed_scene := PackedScene.new()
_expect_equal(packed_scene.pack(source_root), OK, "synthetic PackedScene packs", failures)
source_root.free()
var node_count_before := int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT))
var extracted_mesh: Mesh = extractor.call("extract_first_mesh", packed_scene)
var node_count_after := int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT))
_expect_same(extracted_mesh, packed_mesh, "PackedScene first Mesh retained", failures)
_expect_equal(node_count_after, node_count_before, "temporary PackedScene root freed", failures)
func _verify_ownership_boundaries(failures: Array[String]) -> void:
var extractor_source := FileAccess.get_file_as_string(EXTRACTOR_PATH)
var loader_source := FileAccess.get_file_as_string(LOADER_PATH)
_expect_true(
loader_source.contains("M2_MESH_RESOURCE_EXTRACTOR_SCRIPT.new()"),
"loader composes Mesh resource extractor",
failures
)
_expect_false(
loader_source.contains("func _extract_first_mesh_from_m2_resource("),
"legacy Resource extractor removed",
failures
)
_expect_false(
loader_source.contains("func _find_first_mesh_recursive("),
"legacy subtree extractor removed",
failures
)
_expect_equal(
loader_source.count("_m2_mesh_resource_extractor.extract_first_mesh("),
1,
"threaded Resource finalization delegates",
failures
)
_expect_equal(
loader_source.count("_m2_mesh_resource_extractor.find_first_mesh_in_subtree("),
2,
"rebuild and synchronous fallback delegate",
failures
)
for retained_loader_rule in [
"ResourceLoader.load_threaded_get(path)",
"_prepare_m2_mesh_for_runtime(normalized_rel, mesh)",
"_m2_mesh_resource_cache_state.store_mesh(",
"M2_BUILDER_SCRIPT.build(data, extracted_dir)",
"_m2_missing_cache[normalized_rel]",
]:
_expect_true(loader_source.contains(retained_loader_rule), "loader retains %s" % retained_loader_rule, failures)
for forbidden_dependency in [
"ResourceLoader.",
"FileAccess.",
"WorkerThreadPool.",
"M2Builder",
"_m2_mesh_resource_cache_state",
"_m2_missing_cache",
"MultiMesh",
]:
_expect_false(
extractor_source.contains(forbidden_dependency),
"extractor omits %s ownership" % forbidden_dependency,
failures
)
_expect_true(extractor_source.contains("temporary_root.free()"), "temporary root free remains explicit", failures)
func _verify_bounded_timing(failures: Array[String]) -> float:
var extractor: RefCounted = EXTRACTOR_SCRIPT.new()
var root := Node3D.new()
var branch := root
for _depth_index in range(8):
var child_branch := Node3D.new()
branch.add_child(child_branch)
branch = child_branch
var mesh_instance := MeshInstance3D.new()
mesh_instance.mesh = ArrayMesh.new()
branch.add_child(mesh_instance)
var started_microseconds := Time.get_ticks_usec()
for _iteration in range(10000):
extractor.call("find_first_mesh_in_subtree", root)
var elapsed_milliseconds := float(Time.get_ticks_usec() - started_microseconds) / 1000.0
root.free()
_expect_true(elapsed_milliseconds < 1000.0, "10000 subtree lookups under 1 second", failures)
return elapsed_milliseconds
func _expect_true(condition: bool, label: String, failures: Array[String]) -> void:
if not condition:
failures.append(label)
func _expect_false(condition: bool, label: String, failures: Array[String]) -> void:
_expect_true(not condition, label, failures)
func _expect_equal(actual: int, expected: int, label: String, failures: Array[String]) -> void:
if actual != expected:
failures.append("%s expected=%d actual=%d" % [label, expected, actual])
func _expect_same(actual: Variant, expected: Variant, label: String, failures: Array[String]) -> void:
if not is_same(actual, expected):
failures.append(label)