refactor(M03): extract ADT water load pipeline state

This commit is contained in:
2026-07-17 09:38:24 +04:00
parent 7973945582
commit b7c036f14d
9 changed files with 824 additions and 53 deletions
@@ -0,0 +1,351 @@
extends SceneTree
## Asset-free lifecycle, threading, boundary and timing regression for ADT water loads.
const PIPELINE_SCRIPT := preload(
"res://src/render/liquid/adt_water_load_pipeline_state.gd"
)
const PIPELINE_PATH := "res://src/render/liquid/adt_water_load_pipeline_state.gd"
const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd"
func _initialize() -> void:
var failures: Array[String] = []
_verify_invalid_dedupe_and_fifo(failures)
_verify_active_task_lifecycle(failures)
_verify_result_mailbox_and_payload_identity(failures)
_verify_worker_publication(failures)
_verify_pending_cancellation(failures)
_verify_clear_and_detached_diagnostics(failures)
_verify_ownership_boundaries(failures)
var elapsed_milliseconds := _verify_bounded_timing(failures)
if not failures.is_empty():
for failure in failures:
push_error("ADT_WATER_LOAD_PIPELINE_STATE: %s" % failure)
quit(1)
return
print(
"ADT_WATER_LOAD_PIPELINE_STATE PASS cases=12 iterations=100 elapsed_ms=%.3f"
% elapsed_milliseconds
)
quit(0)
func _verify_invalid_dedupe_and_fifo(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
_expect_false(
pipeline.call("enqueue_request", "", "res://tile.adt"),
"empty tile key rejected",
failures
)
_expect_false(
pipeline.call("enqueue_request", "31:49", ""),
"empty path rejected",
failures
)
_expect_true(
pipeline.call("enqueue_request", "31:49", "res://a.adt"),
"first request accepted",
failures
)
_expect_false(
pipeline.call("enqueue_request", "31:49", "res://duplicate.adt"),
"queued duplicate rejected",
failures
)
pipeline.call("enqueue_request", "32:49", "res://b.adt")
_expect_equal(int(pipeline.call("pending_request_count")), 2, "pending count", failures)
var first_request: Dictionary = pipeline.call("take_next_request")
var second_request: Dictionary = pipeline.call("take_next_request")
_expect_string_equal(String(first_request["key"]), "31:49", "FIFO first key", failures)
_expect_string_equal(String(second_request["key"]), "32:49", "FIFO second key", failures)
_expect_true(
pipeline.call("enqueue_request", "31:49", "res://retry.adt"),
"dequeued key can be requested again",
failures
)
func _verify_active_task_lifecycle(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
_expect_false(
pipeline.call("remember_active_task", "", 7),
"empty active key rejected",
failures
)
_expect_true(
pipeline.call("remember_active_task", "31:49", 101),
"active task accepted",
failures
)
_expect_false(
pipeline.call("remember_active_task", "31:49", 202),
"duplicate active task rejected",
failures
)
_expect_true(
pipeline.call("has_active_task", "31:49"),
"active task observable",
failures
)
_expect_equal(
int(pipeline.call("active_task_id_for", "31:49")),
101,
"opaque task ID retained",
failures
)
_expect_false(
pipeline.call("enqueue_request", "31:49", "res://active.adt"),
"active tile rejects enqueue",
failures
)
_expect_equal(
int(pipeline.call("complete_active_task", "31:49")),
101,
"completion returns task ID",
failures
)
_expect_equal(
int(pipeline.call("complete_active_task", "31:49")),
-1,
"unknown completion rejected",
failures
)
func _verify_result_mailbox_and_payload_identity(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
var water_data := {"chunks": [{"liquid": true}]}
_expect_false(
pipeline.call("publish_result", "", "res://a.adt", water_data),
"empty result key rejected",
failures
)
_expect_true(
pipeline.call("publish_result", "31:49", "res://a.adt", water_data),
"valid result published",
failures
)
_expect_true(pipeline.call("has_result"), "published result observable", failures)
var result: Dictionary = pipeline.call("pop_result")
_expect_string_equal(String(result["key"]), "31:49", "result key", failures)
_expect_string_equal(String(result["path"]), "res://a.adt", "result path", failures)
_expect_true(result["data"] == water_data, "water payload identity retained", failures)
_expect_false(pipeline.call("has_result"), "result pop empties mailbox", failures)
_expect_true(
(pipeline.call("pop_result") as Dictionary).is_empty(),
"empty result pop is safe",
failures
)
func _verify_worker_publication(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
var worker := Thread.new()
var start_error := worker.start(
Callable(pipeline, "publish_result").bind(
"worker",
"res://worker.adt",
{"worker": true}
)
)
_expect_equal(int(start_error), OK, "worker publication starts", failures)
if start_error == OK:
worker.wait_to_finish()
_expect_true(pipeline.call("has_result"), "worker result safely visible", failures)
var result: Dictionary = pipeline.call("pop_result")
_expect_string_equal(String(result.get("key", "")), "worker", "worker result key", failures)
func _verify_pending_cancellation(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
pipeline.call("enqueue_request", "31:49", "res://a.adt")
pipeline.call("enqueue_request", "32:49", "res://b.adt")
pipeline.call("remember_active_task", "31:49-active", 12)
_expect_equal(
int(pipeline.call("cancel_pending_requests", "31:49")),
1,
"tile cancellation removes pending request",
failures
)
_expect_equal(int(pipeline.call("pending_request_count")), 1, "other pending retained", failures)
_expect_true(
pipeline.call("has_active_task", "31:49-active"),
"pending cancellation leaves active work",
failures
)
_expect_equal(
int(pipeline.call("cancel_pending_requests", "unknown")),
0,
"unknown cancellation unchanged",
failures
)
func _verify_clear_and_detached_diagnostics(failures: Array[String]) -> void:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
pipeline.call("enqueue_request", "32:49", "res://b.adt")
pipeline.call("enqueue_request", "31:49", "res://a.adt")
pipeline.call("remember_active_task", "z", 2)
pipeline.call("remember_active_task", "a", 1)
pipeline.call("publish_result", "result", "res://result.adt", {"secret": "payload"})
var snapshot: Dictionary = pipeline.call("diagnostic_snapshot")
_expect_string_array(
snapshot["active_tile_keys"],
["a", "z"],
"active diagnostics sorted",
failures
)
_expect_equal(
(snapshot["pending_requests"] as Array).size(),
2,
"pending diagnostics count",
failures
)
_expect_false(
(snapshot["result_records"][0] as Dictionary).has("data"),
"diagnostics omit water payload",
failures
)
(snapshot["pending_requests"] as Array).clear()
var fresh_snapshot: Dictionary = pipeline.call("diagnostic_snapshot")
_expect_equal(
(fresh_snapshot["pending_requests"] as Array).size(),
2,
"diagnostics detached",
failures
)
pipeline.call("clear")
pipeline.call("clear")
_expect_equal(int(pipeline.call("total_load_count")), 0, "clear load count", failures)
_expect_false(pipeline.call("has_result"), "clear result mailbox", failures)
func _verify_ownership_boundaries(failures: Array[String]) -> void:
var loader_source := _read_text(LOADER_PATH, failures)
var pipeline_source := _read_text(PIPELINE_PATH, failures)
_expect_true(
loader_source.contains("ADT_WATER_LOAD_PIPELINE_STATE_SCRIPT.new()"),
"loader composes pipeline state",
failures
)
for legacy_field in [
"var _water_load_queue:",
"var _water_load_queued:",
"var _water_load_tasks:",
"var _water_result_mutex",
"var _water_result_queue:",
]:
_expect_false(loader_source.contains(legacy_field), "loader removes %s" % legacy_field, failures)
for retained_loader_rule in [
"ClassDB.instantiate(\"ADTLoader\")",
"WorkerThreadPool.add_task(_load_tile_water_task.bind(key, path))",
"RENDER_BUDGET_SCHEDULER_SCRIPT.WATER_FINALIZE",
"_builder.build_tile_water_scene(data, origin)",
"tile_root.add_child(water_root)",
"state[\"water_loaded\"] = true",
]:
_expect_true(loader_source.contains(retained_loader_rule), "loader retains %s" % retained_loader_rule, failures)
for forbidden_token in [
"WorkerThreadPool.",
"ADTLoader",
"RenderBudgetScheduler",
"Node3D",
"Mesh",
"RID",
"_tile_states",
]:
_expect_false(
pipeline_source.contains(forbidden_token),
"pipeline omits %s ownership" % forbidden_token,
failures
)
_expect_equal(
_count_occurrences(loader_source, "_adt_water_load_pipeline_state.clear()"),
2,
"loader retains two clear sites",
failures
)
func _verify_bounded_timing(failures: Array[String]) -> float:
var pipeline: RefCounted = PIPELINE_SCRIPT.new()
var started_microseconds := Time.get_ticks_usec()
for iteration in range(100):
for tile_index in range(256):
var tile_key := "tile:%d" % tile_index
pipeline.call("enqueue_request", tile_key, "res://tile_%d.adt" % tile_index)
while int(pipeline.call("pending_request_count")) > 0:
var request: Dictionary = pipeline.call("take_next_request")
var tile_key := String(request["key"])
pipeline.call("remember_active_task", tile_key, tile_key.hash())
pipeline.call("publish_result", tile_key, String(request["path"]), {})
while pipeline.call("has_result"):
var result: Dictionary = pipeline.call("pop_result")
pipeline.call("complete_active_task", String(result["key"]))
pipeline.call("clear")
_expect_equal(
int(pipeline.call("total_load_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 request/task/result 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 _count_occurrences(text: String, token: String) -> int:
return text.split(token).size() - 1
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)
@@ -0,0 +1 @@
uid://bb3v38yw47utf