Files
open-wc/src/tools/verify_m2_build_resource_snapshot.gd
T

231 lines
6.9 KiB
GDScript

extends SceneTree
## Asset-free M2 resource observation identity, adoption, lifetime, boundary and
## bounded-timing regression.
const SNAPSHOT_SCRIPT := preload(
"res://src/render/m2/m2_build_resource_snapshot.gd"
)
const SNAPSHOT_PATH := "res://src/render/m2/m2_build_resource_snapshot.gd"
const DISPATCH_PATH := "res://src/render/m2/m2_build_dispatch_planner.gd"
const STATIC_OBSERVER_PATH := "res://src/render/m2/m2_static_build_resource_observer.gd"
const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd"
func _initialize() -> void:
var failures: Array[String] = []
_verify_initial_observation(failures)
_verify_static_adoption_and_replacement(failures)
_verify_detached_diagnostics(failures)
_verify_engine_lifetime(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("M2_BUILD_RESOURCE_SNAPSHOT: %s" % failure)
quit(1)
return
print(
"M2_BUILD_RESOURCE_SNAPSHOT PASS cases=12 iterations=20000 elapsed_ms=%.3f"
% elapsed_milliseconds
)
quit(0)
func _verify_initial_observation(failures: Array[String]) -> void:
var prototype := Node3D.new()
var snapshot: RefCounted = SNAPSHOT_SCRIPT.new(
"world/example.m2",
prototype,
true
)
_expect_string(
String(snapshot.call("normalized_relative_path")),
"world/example.m2",
"normalized path retained",
failures
)
_expect_same(
snapshot.call("animated_prototype"),
prototype,
"animated prototype identity retained",
failures
)
_expect_true(
bool(snapshot.call("has_animated_prototype")),
"animated availability",
failures
)
_expect_true(
bool(snapshot.call("animation_request_pending")),
"animation pending retained",
failures
)
_expect_false(bool(snapshot.call("has_static_mesh")), "static defaults empty", failures)
_expect_false(
bool(snapshot.call("static_model_missing")),
"missing defaults false",
failures
)
prototype.free()
func _verify_static_adoption_and_replacement(failures: Array[String]) -> void:
var snapshot: RefCounted = SNAPSHOT_SCRIPT.new("world/static.m2", null, false)
var first_mesh := ArrayMesh.new()
var second_mesh := ArrayMesh.new()
snapshot.call("adopt_static_observation", first_mesh, true)
_expect_same(snapshot.call("static_mesh"), first_mesh, "first Mesh identity", failures)
_expect_true(bool(snapshot.call("has_static_mesh")), "static available", failures)
_expect_true(
bool(snapshot.call("static_model_missing")),
"contradictory missing flag retained",
failures
)
snapshot.call("adopt_static_observation", second_mesh, false)
_expect_same(
snapshot.call("static_mesh"),
second_mesh,
"replacement Mesh identity",
failures
)
_expect_false(
bool(snapshot.call("static_model_missing")),
"replacement missing flag",
failures
)
snapshot.call("adopt_static_observation", null, true)
_expect_false(bool(snapshot.call("has_static_mesh")), "Mesh may clear", failures)
_expect_true(bool(snapshot.call("static_model_missing")), "terminal missing adopted", failures)
func _verify_detached_diagnostics(failures: Array[String]) -> void:
var prototype := Node3D.new()
var mesh := ArrayMesh.new()
var snapshot: RefCounted = SNAPSHOT_SCRIPT.new("world/diag.m2", prototype, false)
snapshot.call("adopt_static_observation", mesh, true)
var diagnostics: Dictionary = snapshot.call("diagnostic_snapshot")
_expect_true(
diagnostics == {
"normalized_relative_path": "world/diag.m2",
"has_animated_prototype": true,
"animation_request_pending": false,
"has_static_mesh": true,
"static_model_missing": true,
},
"diagnostic scalar contract",
failures
)
_expect_false(diagnostics.values().has(prototype), "diagnostics omit prototype", failures)
_expect_false(diagnostics.values().has(mesh), "diagnostics omit Mesh", failures)
diagnostics["has_static_mesh"] = false
var fresh: Dictionary = snapshot.call("diagnostic_snapshot")
_expect_true(bool(fresh["has_static_mesh"]), "diagnostics detached", failures)
prototype.free()
func _verify_engine_lifetime(failures: Array[String]) -> void:
var prototype := Node3D.new()
var snapshot: RefCounted = SNAPSHOT_SCRIPT.new("world/lifetime.m2", prototype, false)
snapshot = null
_expect_true(is_instance_valid(prototype), "snapshot release keeps Node valid", failures)
prototype.free()
func _verify_loader_and_dependency_boundaries(failures: Array[String]) -> void:
var loader_source := FileAccess.get_file_as_string(LOADER_PATH)
var dispatch_source := FileAccess.get_file_as_string(DISPATCH_PATH)
var static_observer_source := FileAccess.get_file_as_string(STATIC_OBSERVER_PATH)
var snapshot_source := FileAccess.get_file_as_string(SNAPSHOT_PATH)
for delegated_token in [
"M2_BUILD_RESOURCE_SNAPSHOT_SCRIPT.new(",
"resource_snapshot.call(\"animated_prototype\")",
"resource_snapshot.call(\"static_mesh\")",
]:
_expect_true(
loader_source.contains(delegated_token),
"loader uses %s" % delegated_token,
failures
)
_expect_true(
static_observer_source.contains("\"adopt_static_observation\""),
"static observer adopts snapshot",
failures
)
_expect_true(
dispatch_source.contains("resource_snapshot.call(\"animation_request_pending\")")
and dispatch_source.contains("resource_snapshot.call(\"has_static_mesh\")"),
"dispatch planner consumes typed snapshot",
failures
)
for forbidden_token in [
"queue_free",
"free(",
"ResourceLoader",
"RenderingServer",
"FileAccess",
"WorkerThreadPool",
"Thread",
"Mutex",
]:
_expect_false(
snapshot_source.contains(forbidden_token),
"snapshot omits %s ownership" % forbidden_token,
failures
)
func _verify_bounded_timing(failures: Array[String]) -> float:
var mesh := ArrayMesh.new()
var started_microseconds := Time.get_ticks_usec()
for iteration in range(20000):
var snapshot: RefCounted = SNAPSHOT_SCRIPT.new(
"world/%d.m2" % (iteration % 64),
null,
iteration % 5 == 0
)
snapshot.call(
"adopt_static_observation",
mesh if iteration % 3 == 0 else null,
iteration % 7 == 0
)
snapshot.call("diagnostic_snapshot")
var elapsed_milliseconds := (
float(Time.get_ticks_usec() - started_microseconds) / 1000.0
)
_expect_true(
elapsed_milliseconds < 1000.0,
"20,000 snapshot cycles remain bounded",
failures
)
return elapsed_milliseconds
func _expect_string(
actual: String,
expected: String,
label: String,
failures: Array[String]
) -> void:
if actual != expected:
failures.append("%s expected=%s actual=%s" % [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)
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)