Files
TheTree_mock/tests/performance/test_snapshot_ownership.gd
Takeshi b84bade045 Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
2026-10-11 15:58:00 +09:00

66 lines
3.3 KiB
GDScript

extends SceneTree
const Demo := preload("res://scripts/ui/pixel_tower_demo.gd")
var checks := 0
var failures := 0
func _initialize() -> void: call_deferred("run")
func expect(ok: bool, label: String) -> void:
checks += 1
if not ok: failures += 1; push_error(label)
func run() -> void:
var runtime: Variant = root.get_node("SimulationRuntime")
var clock: Variant = root.get_node("GameClock")
var state: Variant = root.get_node("GameState")
# Disposable Demo fixture funds exact Doran signing_cost 300; DEFAULT5000 and paid hire stay unchanged.
clock.reset(1,6,0); state.reset();state.resources[&"gold"] += 300; runtime.initialize(clock,state,424242); clock.set_paused(true)
runtime.configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false})
verify_detached(runtime, "funded disposable initial fixture")
var demo := Demo.new()
expect(await demo.prepare(runtime,clock,self), "populated production fixture prepares")
verify_detached(runtime, "populated game")
var retained: Dictionary = runtime.create_snapshot()
var original := retained.duplicate(true)
clock.advance_minutes(15)
expect(retained == original, "advancing live actors never changes a retained snapshot")
var after: Dictionary = runtime.create_snapshot()
expect(runtime.restore_snapshot(retained), "owned snapshot restores before deterministic replay")
clock.advance_minutes(15)
expect(runtime.create_snapshot() == after, "owned snapshot replays all subsystems identically")
# Keep the general-purpose capture API's protective copy contract.
var extra := {&"caller": {&"rows": [{&"value":1}]}}
var generic: Dictionary = SimulationSnapshot.capture(clock,state,extra)
extra[&"caller"][&"rows"][0][&"value"] = 2
expect(generic[&"systems"][&"caller"][&"rows"][0][&"value"] == 1, "general capture still detaches caller-owned extras")
print("Snapshot ownership: %d checks, %d failures" % [checks,failures]);quit(failures)
func verify_detached(runtime: Variant, stage: String) -> void:
var expected: Dictionary = runtime.create_snapshot().duplicate(true)
for section: Variant in expected[&"systems"][&"runtime"]:
var candidate: Dictionary = runtime.create_snapshot()
poison(candidate[&"systems"][&"runtime"][section])
expect(runtime.create_snapshot() == expected, "%s detached section: %s" % [stage,section])
if failures: return
var candidate: Dictionary = runtime.create_snapshot()
poison(candidate[&"clock"]);poison(candidate[&"game_state"])
expect(runtime.create_snapshot() == expected, "%s clock and resource snapshots remain detached" % stage)
func poison(value: Variant) -> void:
if value is Dictionary:
for child: Variant in value.values(): poison(child)
value.clear()
value[&"ownership_probe"] = true
elif value is Array:
for child: Variant in value: poison(child)
value.clear()
match value.get_typed_builtin():
TYPE_NIL: value.append(null)
TYPE_DICTIONARY: value.append({})
TYPE_ARRAY: value.append([])
TYPE_STRING: value.append("ownership_probe")
TYPE_STRING_NAME: value.append(&"ownership_probe")
TYPE_INT: value.append(99)
TYPE_FLOAT: value.append(99.0)
TYPE_BOOL: value.append(true)
TYPE_VECTOR2I: value.append(Vector2i(99,99))
TYPE_VECTOR3I: value.append(Vector3i(99,99,99))
_: expect(false, "ownership probe covers typed snapshot array %s" % value.get_typed_builtin())