Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
extends SceneTree
|
||||
var checks:=0
|
||||
var failures:=0
|
||||
func expect(ok: bool,label:String)->void:
|
||||
checks+=1
|
||||
if not ok:failures+=1;push_error(label)
|
||||
class Fixture extends RefCounted:
|
||||
var facility_service:=FacilityService.new()
|
||||
var path_service:=PathService.new()
|
||||
func _initialize()->void:call_deferred("run")
|
||||
func run()->void:
|
||||
var fixture:=Fixture.new()
|
||||
var bridge=preload("res://scripts/environment/facility_cleaning_bridge.gd").new()
|
||||
bridge.configure(fixture)
|
||||
fixture.facility_service.create_instance({&"instance_id":&"target",&"definition_id":&"reception",&"origin":Vector3i(3,0,0),&"occupied_cells":[Vector3i(3,0,0),Vector3i(4,0,0)]})
|
||||
var worker:=StaffRuntime.new();worker.current_cell=Vector3i(6,0,0)
|
||||
var task:=StaffTask.new().configure(&"clean",&"facility_clean",50,0,{&"target_entity_id":&"target",&"target_cell":Vector3i(2,0,0),&"estimated_minutes":8})
|
||||
var cells: Array[Vector3i]=[Vector3i(2,0,0),Vector3i(4,0,0),Vector3i(5,0,0),Vector3i(6,0,0)]
|
||||
fixture.path_service.rebuild_graph(cells)
|
||||
expect(bridge.prepare_route(task,worker) and task.target_cell==Vector3i(5,0,0),"isolated first access is replaced by reachable closest access")
|
||||
var destination:=task.target_cell
|
||||
expect(bridge.prepare_route(task,worker) and task.target_cell==destination,"reachable destination remains stable")
|
||||
cells=[Vector3i(2,0,0),Vector3i(4,0,0),Vector3i(6,0,0)]
|
||||
fixture.path_service.rebuild_graph(cells)
|
||||
expect(destination in bridge.access_cells(fixture.facility_service.get_instance(&"target"),fixture.path_service,false) and destination not in bridge.access_cells(fixture.facility_service.get_instance(&"target"),fixture.path_service),"blocked saved destination remains geometrically valid while not walkable")
|
||||
expect(not bridge.prepare_route(task,worker) and worker.current_cell==Vector3i(6,0,0) and task.target_cell==destination,"total isolation neither moves worker nor invents destination")
|
||||
cells=[Vector3i(2,0,0),Vector3i(3,0,0),Vector3i(4,0,0),Vector3i(5,0,0),Vector3i(6,0,0)]
|
||||
fixture.path_service.rebuild_graph(cells)
|
||||
expect(bridge.prepare_route(task,worker),"route resumes after reconnection")
|
||||
fixture.facility_service.unregister_instance(&"target")
|
||||
expect(not bridge.prepare_route(task,worker),"removed facility has no work destination")
|
||||
print("Cleaning access: %d checks, %d failures"%[checks,failures]);quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://rvfm06u8dee3
|
||||
@@ -0,0 +1,89 @@
|
||||
extends SceneTree
|
||||
const Cleanliness = preload("res://scripts/environment/facility_cleanliness_service.gd")
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
func expect(ok: bool, label: String) -> void:
|
||||
checks += 1
|
||||
if not ok: failures += 1; push_error(label)
|
||||
func _initialize() -> void: call_deferred("run")
|
||||
func run() -> void:
|
||||
var room: FacilityDefinition = load("res://data/facilities/expansion/cleaning_room.tres")
|
||||
expect(room.is_valid() and room.footprint == Vector2i(2,1) and room.layer == FacilityDefinition.ViewLayer.BACK, "original cleaning room dimensions and layer")
|
||||
expect(room.construction_cost == {&"gold":350,&"materials":4} and room.build_minutes == 60 and room.maintenance_gold == 2, "approved trial construction and upkeep")
|
||||
expect(room.staff_min == 1 and room.staff_max == 2 and room.required_roles == [&"cleaner"], "approved cleaner staffing")
|
||||
expect(room.customer_capacity == 0 and room.base_price == 0, "cleaning room has no customer use or fee")
|
||||
var policy: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://data/environment/cleaning_policy.json"))
|
||||
expect(policy["initial_cleanliness"] == 100 and policy["maximum_cleanliness"] == 100 and policy["clean_at_or_below"] == 75 and policy["work_minutes"] == 8 and policy["recovery_per_completed_task"] == 25, "approved trial cleaning policy")
|
||||
var rules = preload("res://scripts/environment/facility_cleaning_policy.gd").new()
|
||||
expect(rules.load_file(), "approved JSON policy loads through strict validator")
|
||||
var approved: Dictionary = rules.create_snapshot()
|
||||
var corrupt_policies: Array = []
|
||||
for change: Dictionary in [{"schema_version":2}, {"initial_cleanliness":101}, {"maximum_cleanliness":0}, {"clean_at_or_below":100}, {"work_minutes":0}, {"work_minutes":8.5}, {"recovery_per_completed_task":0}, {"work_minutes":true}, {"work_minutes":INF}]:
|
||||
var invalid_policy: Dictionary = approved.duplicate(true)
|
||||
invalid_policy.merge(change, true)
|
||||
corrupt_policies.append(invalid_policy)
|
||||
var missing_policy: Dictionary = approved.duplicate(true)
|
||||
missing_policy.erase("work_minutes")
|
||||
corrupt_policies.append(missing_policy)
|
||||
for invalid_policy: Dictionary in corrupt_policies:
|
||||
expect(not rules.configure(invalid_policy) and rules.create_snapshot() == approved, "invalid policy rejects without replacing approved values")
|
||||
var detached_policy: Dictionary = rules.create_snapshot()
|
||||
detached_policy["work_minutes"] = 99
|
||||
expect(rules.create_snapshot()["work_minutes"] == 8, "policy read cannot change work duration")
|
||||
var ordered = Cleanliness.new()
|
||||
var names: Array[String] = []
|
||||
for index in range(31, -1, -1):
|
||||
var name := "clean_order_%03d" % ((index * 17) % 32)
|
||||
names.append(name)
|
||||
ordered.register_facility(StringName(name), 75, 100)
|
||||
names.sort()
|
||||
var dirty := ordered.get_dirty_facility_ids(75)
|
||||
var rows: Array = ordered.create_snapshot()["facilities"]
|
||||
var text_order_matches := true
|
||||
for index in names.size():
|
||||
text_order_matches = text_order_matches and String(dirty[index]) == names[index] and rows[index]["id"] == names[index]
|
||||
expect(text_order_matches, "generated IDs use lexical order for saves and cleaning dispatch")
|
||||
var reordered: Dictionary = ordered.create_snapshot()
|
||||
reordered["facilities"].reverse()
|
||||
expect(ordered.restore_snapshot(reordered) and ordered.create_snapshot()["facilities"] == rows, "legacy row order restores to canonical lexical order")
|
||||
var service = Cleanliness.new()
|
||||
expect(service.register_facility(&"b", 100, 100) and service.register_facility(&"a", 50, 100), "explicit initial and maximum values")
|
||||
expect(not service.register_facility(&"b", 100,100), "duplicate facility rejected")
|
||||
expect(not service.register_facility(&"bad", -1,100), "invalid initial value rejected")
|
||||
expect(service.record_use(&"b", &"visit",25), "completed visit soils facility")
|
||||
expect(service.get_facility(&"b")["current"]==75, "soil amount applied")
|
||||
expect(service.get_dirty_facility_ids(75)==[&"a",&"b"], "threshold inclusive with stable ordering")
|
||||
expect(service.get_dirty_facility_ids(74)==[&"a"], "threshold excludes cleaner facility")
|
||||
var saved: Dictionary=service.create_snapshot()
|
||||
expect(service.record_use(&"b", &"visit",25) and service.create_snapshot()==saved, "replayed completion does not double soil")
|
||||
expect(not service.record_use(&"b", &"visit",26) and service.create_snapshot()==saved, "conflicting completion is atomic")
|
||||
expect(not service.record_use(&"missing", &"unknown",1), "unknown facility cannot receive effect")
|
||||
expect(not service.record_cleaning(&"b",&"negative",-1), "negative recovery rejected")
|
||||
expect(service.record_cleaning(&"b",&"work",9223372036854775807) and service.get_facility(&"b")["current"]==100, "recovery clamps without overflow")
|
||||
expect(service.record_use(&"b",&"dirty",9223372036854775807) and service.get_facility(&"b")["current"]==0, "soil clamps without overflow")
|
||||
expect(service.record_cleaning(&"b",&"work",9223372036854775807) and service.get_facility(&"b")["current"]==0, "old cleaning completion does not clean later dirt again")
|
||||
var restored=Cleanliness.new()
|
||||
expect(restored.restore_snapshot(service.create_snapshot()), "history and state restore")
|
||||
expect(restored.create_snapshot()==service.create_snapshot(), "exact roundtrip")
|
||||
expect(restored.record_cleaning(&"b",&"next",25) and service.record_cleaning(&"b",&"next",25) and restored.create_snapshot()==service.create_snapshot(), "restored continuation matches")
|
||||
var detached: Dictionary=restored.get_facility(&"b");detached["current"]=99
|
||||
expect(restored.get_facility(&"b")["current"]==25, "read result detached")
|
||||
var intact: Dictionary=restored.create_snapshot()
|
||||
var bad_cases: Array=[]
|
||||
var bad: Dictionary=intact.duplicate(true);bad["schema_version"]=2;bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["facilities"][0]["current"]=33;bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["facilities"].append(bad["facilities"][0].duplicate(true));bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["receipts"].append(bad["receipts"][0].duplicate(true));bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["receipts"][0]["facility_id"]="missing";bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["receipts"][0]["amount"]=1.5;bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["receipts"][0]["kind"]="unknown";bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["facilities"]=false;bad_cases.append(bad)
|
||||
bad=intact.duplicate(true);bad["unexpected"]=1;bad_cases.append(bad)
|
||||
for candidate: Dictionary in bad_cases:
|
||||
expect(not restored.restore_snapshot(candidate) and restored.create_snapshot()==intact, "malformed or inconsistent save preserves live state")
|
||||
var mutated: Dictionary=restored.create_snapshot();mutated["receipts"].clear();mutated["facilities"].clear()
|
||||
expect(restored.create_snapshot()==intact, "saved arrays do not alias live state")
|
||||
expect(restored.unregister_facility(&"b") and restored.get_facility(&"b").is_empty(), "demolition removes facility state")
|
||||
var after_remove=Cleanliness.new()
|
||||
expect(after_remove.restore_snapshot(restored.create_snapshot()), "demolition retains no dangling completion receipts")
|
||||
print("Facility cleanliness: %d checks, %d failures" % [checks,failures]);quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://b0g1ir0itwtlx
|
||||
@@ -0,0 +1,74 @@
|
||||
extends SceneTree
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
func expect(ok: bool, label: String) -> void:
|
||||
checks += 1
|
||||
if not ok: failures += 1; push_error(label)
|
||||
func _initialize() -> void: call_deferred("run")
|
||||
func run() -> void:
|
||||
var runtime: Variant = load("res://autoload/simulation_runtime.gd").new()
|
||||
var clock: Variant = load("res://autoload/game_clock.gd").new()
|
||||
var state: Variant = load("res://autoload/game_state.gd").new()
|
||||
clock.reset(1,6,0); state.reset()
|
||||
expect(runtime.initialize(clock,state,42630)[&"valid"], "initialize with validated approved policy")
|
||||
clock.set_paused(true)
|
||||
expect(runtime.submit_command(&"build_facility", {&"definition_id":&"reception",&"origin":Vector3i(-6,0,0)}).is_success(), "normal paid construction begins")
|
||||
expect(runtime.facility_cleanliness.create_snapshot()["facilities"].is_empty(), "unfinished building has no cleanliness record")
|
||||
clock.advance_minutes(120)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instances()[0]
|
||||
var id := facility.instance_id
|
||||
expect(runtime.facility_cleanliness.get_facility(id)["current"] == 100, "construction completion starts clean")
|
||||
expect(runtime.submit_command(&"set_facility_conditions",{&"facility_id":id,&"conditions":{&"active_staff_ids":[&"reception_fixture"]}}).is_success(), "controlled staffing for transaction test")
|
||||
expect(runtime.submit_command(&"register_guest_wallet",{&"guest_id":&"payer",&"gold":100}).is_success(), "payer wallet created")
|
||||
expect(runtime.submit_command(&"create_service_request",{&"request_id":&"visit1",&"facility_id":id,&"guest_ids":[&"payer"],&"service_type":&"check_in"}).is_success(), "normal service request")
|
||||
clock.advance_one_minute()
|
||||
var active: Array = runtime.facility_service.get_active_services(id)
|
||||
expect(active.size()==1, "service actually starts")
|
||||
if active.is_empty(): runtime.free(); clock.free(); state.free(); quit(failures); return
|
||||
var service_id: StringName = active[0].service_id
|
||||
expect(runtime.facility_cleanliness.get_facility(id)["current"]==100, "starting a visit does not apply completion dirt")
|
||||
var midpoint: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.restore_snapshot(midpoint), "in-progress service with cleanliness restores")
|
||||
clock.advance_minutes(21)
|
||||
expect(runtime.facility_service.get_service(service_id).state==ServiceInstance.State.COMPLETED and runtime.facility_cleanliness.get_facility(id)["current"]==99, "completed reception visit applies defined dirt once")
|
||||
var complete: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.restore_snapshot(complete) and runtime.create_snapshot()==complete, "completed dirt and visit roundtrip exactly")
|
||||
clock.advance_one_minute()
|
||||
expect(runtime.facility_cleanliness.get_facility(id)["current"]==99, "saved completion does not repeat dirt")
|
||||
expect(runtime.restore_snapshot(midpoint), "rewind visit")
|
||||
clock.advance_minutes(21)
|
||||
expect(runtime.create_snapshot()==complete, "save continuation reproduces full Runtime exactly")
|
||||
var intact: Dictionary=runtime.create_snapshot()
|
||||
var bad: Dictionary=intact.duplicate(true)
|
||||
bad[&"systems"][&"runtime"].erase(&"facility_cleanliness")
|
||||
expect(not runtime.restore_snapshot(bad) and runtime.create_snapshot()==intact, "v12 missing cleanliness rejects atomically")
|
||||
bad=intact.duplicate(true)
|
||||
bad[&"systems"][&"runtime"][&"facility_cleanliness"]["receipts"][0]["source_id"]="invented"
|
||||
expect(not runtime.restore_snapshot(bad) and runtime.create_snapshot()==intact, "receipt without completed visit rejects atomically")
|
||||
bad=intact.duplicate(true)
|
||||
bad[&"systems"][&"runtime"][&"facility_cleanliness"]["facilities"]=[]
|
||||
bad[&"systems"][&"runtime"][&"facility_cleanliness"]["receipts"]=[]
|
||||
expect(not runtime.restore_snapshot(bad) and runtime.create_snapshot()==intact, "missing live facility cleanliness rejects")
|
||||
var legacy: Dictionary=intact.duplicate(true)
|
||||
legacy[&"systems"][&"runtime"][&"runtime_schema_version"]=11
|
||||
legacy[&"systems"][&"runtime"].erase(&"facility_cleanliness")
|
||||
expect(runtime.restore_snapshot(legacy) and runtime.facility_cleanliness.get_facility(id)["current"]==100, "v11 initializes cleanliness without guessing past dirt")
|
||||
expect(runtime.create_snapshot()[&"systems"][&"runtime"][&"weather"]==intact[&"systems"][&"runtime"][&"weather"], "v11 weather survives migration unchanged")
|
||||
expect(runtime.restore_snapshot(intact), "restore current dirt before rollback checks")
|
||||
var rollback: Dictionary=runtime.call("_capture_infrastructure_demolition_state")
|
||||
runtime.facility_cleanliness.unregister_facility(id)
|
||||
expect(runtime.call("_restore_infrastructure_demolition_state",rollback) and runtime.create_snapshot()==intact, "infrastructure rollback includes cleanliness")
|
||||
# Force the final dirt boundary to fail after payment/output staging; no partial settlement.
|
||||
expect(runtime.restore_snapshot(midpoint), "rewind for failed cleanliness commit")
|
||||
runtime.facility_cleanliness.unregister_facility(id)
|
||||
clock.advance_minutes(21)
|
||||
expect(runtime.facility_service.get_service(service_id).state!=ServiceInstance.State.COMPLETED, "missing dirt participant prevents partial service completion")
|
||||
expect(runtime.economy_service.get_balance(&"GUEST_WALLET:payer")==100, "failed cleanliness transaction leaves wallet unchanged")
|
||||
runtime.facility_cleanliness.register_facility(id,100,100)
|
||||
clock.advance_one_minute()
|
||||
expect(runtime.facility_service.get_service(service_id).state==ServiceInstance.State.COMPLETED and runtime.facility_cleanliness.get_facility(id)["current"]==99, "failed boundary retries once after recovery")
|
||||
expect(runtime.submit_command(&"demolish_facility",{&"instance_id":id}).is_success(), "normal demolition command")
|
||||
expect(runtime.facility_cleanliness.get_facility(id).is_empty() and runtime.facility_cleanliness.create_snapshot()["receipts"].is_empty(), "demolition removes state and dangling receipts")
|
||||
expect(runtime.restore_snapshot(runtime.create_snapshot()), "post-demolition Runtime remains restorable")
|
||||
runtime.free();clock.free();state.free()
|
||||
print("Runtime cleanliness: %d checks, %d failures" % [checks,failures]);quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://didx6256rlc4d
|
||||
@@ -0,0 +1,51 @@
|
||||
extends SceneTree
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
func expect(ok: bool, message: String) -> void:
|
||||
checks += 1
|
||||
if not ok: failures += 1; push_error(message)
|
||||
func _initialize() -> void: call_deferred("run")
|
||||
func run() -> void:
|
||||
var runtime: Variant = load("res://autoload/simulation_runtime.gd").new()
|
||||
var clock: Variant = load("res://autoload/game_clock.gd").new()
|
||||
var state: Variant = load("res://autoload/game_state.gd").new()
|
||||
clock.reset(1,6,0); state.reset()
|
||||
expect(runtime.initialize(clock,state,424242)[&"valid"], "initialize Runtime")
|
||||
clock.set_paused(true)
|
||||
expect(runtime.enable_production_operations()[&"ok"], "enable production arrivals")
|
||||
var original: Dictionary = runtime.create_snapshot()
|
||||
var legacy := original.duplicate(true)
|
||||
legacy[&"systems"][&"runtime"][&"runtime_schema_version"] = 10
|
||||
legacy[&"systems"][&"runtime"].erase(&"weather")
|
||||
legacy[&"systems"][&"runtime"].erase(&"facility_cleanliness")
|
||||
expect(runtime.restore_snapshot(legacy) and runtime.weather.get_kind() == &"clear" and runtime.weather.get_minute() == 360, "v10 migrates to neutral weather at saved minute")
|
||||
expect(runtime.create_snapshot() == original, "old neutral save migration preserves other state")
|
||||
var malformed := original.duplicate(true)
|
||||
malformed[&"systems"][&"runtime"][&"weather"][&"minute"] = 361
|
||||
expect(not runtime.restore_snapshot(malformed) and runtime.create_snapshot() == original, "future weather clock rejects atomically")
|
||||
malformed = original.duplicate(true)
|
||||
malformed[&"systems"][&"runtime"].erase(&"weather")
|
||||
expect(not runtime.restore_snapshot(malformed), "new schema cannot silently lose weather")
|
||||
expect(runtime.weather.schedule(&"storm",390)[&"ok"] and runtime.weather.schedule(&"clear",420)[&"ok"], "schedule weather boundaries")
|
||||
clock.advance_minutes(29)
|
||||
var before: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.weather.get_kind() == &"clear", "storm does not apply before boundary")
|
||||
var spawned := {&"count":0}
|
||||
runtime.guest_service.guest_spawned.connect(func(_guest: GuestRuntime) -> void: spawned[&"count"] += 1)
|
||||
clock.advance_minutes(1)
|
||||
expect(runtime.weather.get_kind() == &"storm" and spawned[&"count"] == 0, "storm starts before same-minute production admission")
|
||||
var boundary: Dictionary = runtime.call("_operations_arrival_boundary", {}, OperationsCoordinator.PHASE_CAPTURE, null)
|
||||
expect(boundary[&"capacity_remaining"] == 0, "storm exposes zero admission capacity")
|
||||
var stopped: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.restore_snapshot(stopped) and runtime.create_snapshot() == stopped, "storm and recovery schedule round trip exactly")
|
||||
clock.advance_minutes(30)
|
||||
expect(runtime.weather.get_kind() == &"clear", "scheduled recovery resumes weather at boundary")
|
||||
boundary = runtime.call("_operations_arrival_boundary", {}, OperationsCoordinator.PHASE_CAPTURE, null)
|
||||
expect(boundary[&"capacity_remaining"] > 0, "recovery restores admission capacity")
|
||||
var recovered: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.restore_snapshot(before), "rewind before storm")
|
||||
clock.advance_minutes(31)
|
||||
expect(runtime.create_snapshot() == recovered, "full Runtime weather and arrivals replay identically")
|
||||
expect(not runtime.get_operations_report()[&"runtime_failure_latched"], "weather does not quarantine operations")
|
||||
runtime.free(); clock.free(); state.free()
|
||||
print("Runtime weather: %d checks, %d failures" % [checks, failures]); quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c524n3edolklf
|
||||
@@ -0,0 +1,39 @@
|
||||
extends SceneTree
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
func expect(ok: bool, message: String) -> void:
|
||||
checks += 1
|
||||
if not ok: failures += 1; push_error(message)
|
||||
func _initialize() -> void: call_deferred("run")
|
||||
func run() -> void:
|
||||
var runtime: Variant = load("res://autoload/simulation_runtime.gd").new()
|
||||
var clock: Variant = load("res://autoload/game_clock.gd").new()
|
||||
var state: Variant = load("res://autoload/game_state.gd").new()
|
||||
clock.reset(1,6,0); state.reset()
|
||||
expect(runtime.initialize(clock,state,424242)[&"valid"], "initialize")
|
||||
clock.set_paused(true)
|
||||
expect(runtime.enable_production_operations()[&"ok"], "enable arrivals")
|
||||
expect(runtime.weather.schedule(&"storm",390)[&"ok"] and runtime.weather.schedule(&"clear",420)[&"ok"], "schedule storm and recovery")
|
||||
clock.advance_minutes(29)
|
||||
runtime.set_operations_test_boundary_hook(&"ARRIVAL_PLAN", func(_payload: Dictionary, _phase: StringName, _token: Variant) -> Dictionary: return {&"ok": false})
|
||||
clock.advance_minutes(1)
|
||||
expect(clock.absolute_minute == 390 and runtime.get_operations_report()[&"runtime_failure_latched"], "arrival failure pauses at weather boundary")
|
||||
expect(runtime.weather.get_kind() == &"storm" and runtime.weather.get_minute() == 390, "weather commits before failed arrival")
|
||||
var weather_before: Dictionary = runtime.weather.create_snapshot()
|
||||
var path := "user://tests/weather_recovery_%d" % OS.get_process_id()
|
||||
expect(runtime.save_to_path(path)[&"ok"], "write interrupted weather to actual save package")
|
||||
expect(runtime.load_from_path(path)[&"ok"] and runtime.weather.create_snapshot() == weather_before, "disk load preserves storm and pending recovery")
|
||||
expect(runtime.get_operations_report()[&"deferred_runtime_minute"] == 390, "disk load preserves failed boundary for retry")
|
||||
runtime.set_operations_test_boundary_hook(&"ARRIVAL_PLAN", Callable())
|
||||
var arrivals := {&"count":0}
|
||||
runtime.guest_service.guest_spawned.connect(func(_guest: GuestRuntime) -> void: arrivals[&"count"] += 1)
|
||||
expect(runtime.acknowledge_operations_pause()[&"ok"], "retry failed storm boundary")
|
||||
expect(arrivals[&"count"] == 0 and runtime.weather.create_snapshot() == weather_before, "retry neither admits storm guests nor duplicates weather transition")
|
||||
var completed: Dictionary = runtime.create_snapshot()
|
||||
expect(runtime.restore_snapshot(completed) and runtime.create_snapshot() == completed, "completed retry restores exactly")
|
||||
clock.advance_minutes(30)
|
||||
expect(runtime.weather.get_kind() == &"clear" and runtime.weather.create_snapshot()[&"pending"].is_empty(), "disk-restored recovery occurs once at scheduled minute")
|
||||
expect(not runtime.get_operations_report()[&"runtime_failure_latched"], "recovery resumes ordinary operations")
|
||||
expect(SaveService.delete_save(path), "delete isolated test save")
|
||||
runtime.free(); clock.free(); state.free()
|
||||
print("Weather recovery: %d checks, %d failures" % [checks, failures]); quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://dgtxyr8gxg6nj
|
||||
@@ -0,0 +1,43 @@
|
||||
extends SceneTree
|
||||
const Weather = preload("res://scripts/environment/weather_timeline.gd")
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
func expect(ok: bool, message: String) -> void:
|
||||
checks += 1
|
||||
if not ok: failures += 1; push_error(message)
|
||||
func _initialize() -> void:
|
||||
var weather = Weather.new()
|
||||
expect(not weather.permits_new_arrivals(), "uninitialized weather never grants admission")
|
||||
expect(not weather.initialize(&"unknown", 360) and not weather.initialize(&"clear", 1.5), "invalid initial data rejected")
|
||||
expect(weather.initialize(&"clear", 360), "caller explicitly chooses initial weather and time")
|
||||
expect(not weather.initialize(&"storm", 400), "initialize cannot reset a live simulation")
|
||||
expect(weather.schedule(&"clear", 390)[&"ok"] and weather.schedule(&"storm", 380)[&"ok"] and weather.schedule(&"rain", 370)[&"ok"], "out of order scheduling retains chronological execution")
|
||||
expect(weather.schedule(&"storm", 380)[&"replayed"] and not weather.schedule(&"rain", 380)[&"ok"], "same boundary retry is idempotent and conflict rejected")
|
||||
expect(not weather.schedule(&"storm", 360)[&"ok"], "past and current weather cannot be retroactively changed")
|
||||
var checkpoint: Dictionary = weather.create_snapshot()
|
||||
expect(weather.advance_to(379)[&"changes"] == [{&"from": &"clear", &"to": &"rain", &"minute": 370}], "rain changes at its scheduled time")
|
||||
expect(weather.permits_new_arrivals(), "rain is not treated as a storm admission ban")
|
||||
expect(weather.advance_to(380)[&"changes"].size() == 1 and not weather.permits_new_arrivals(), "storm blocks admission at exact boundary")
|
||||
var storm: Dictionary = weather.create_snapshot()
|
||||
var replay: Dictionary = weather.advance_to(380)
|
||||
expect(replay[&"replayed"] and replay[&"changes"].is_empty() and weather.create_snapshot() == storm, "same minute cannot duplicate a transition")
|
||||
expect(not weather.advance_to(379)[&"ok"] and weather.create_snapshot() == storm, "time reversal cannot change state")
|
||||
expect(weather.advance_to(390)[&"ok"] and weather.permits_new_arrivals(), "clear restores admission")
|
||||
var finished: Dictionary = weather.create_snapshot()
|
||||
expect(weather.restore_snapshot(checkpoint), "restore earlier weather and pending schedule")
|
||||
expect(weather.advance_to(390)[&"changes"].size() == 3 and weather.create_snapshot() == finished, "jump and minute-step replay produce identical weather state")
|
||||
var encoded: Dictionary = bytes_to_var(var_to_bytes(storm))
|
||||
expect(weather.restore_snapshot(encoded) and weather.get_kind() == &"storm", "production Variant codec preserves integer weather time and IDs")
|
||||
var baseline: Dictionary = weather.create_snapshot()
|
||||
for field: String in ["version", "minute", "kind", "since", "pending"]:
|
||||
var bad := baseline.duplicate(true); bad.erase(field)
|
||||
expect(not weather.restore_snapshot(bad) and weather.create_snapshot() == baseline, "missing field rejects atomically: " + field)
|
||||
for change: Dictionary in [{"version": 2}, {"minute": 380.0}, {"kind": "snow"}, {"since": 381}, {"pending": [{"kind":"clear","minute":380}]}, {"pending": [{"kind":"clear","minute":400},{"kind":"rain","minute":390}]}, {"extra":true}]:
|
||||
var bad := baseline.duplicate(true)
|
||||
bad.merge(change, true)
|
||||
expect(not weather.restore_snapshot(bad) and weather.create_snapshot() == baseline, "malformed or contradictory state rejects atomically")
|
||||
var detached: Dictionary = weather.create_snapshot(); detached[&"pending"].clear()
|
||||
expect(not weather.create_snapshot()[&"pending"].is_empty(), "caller cannot mutate pending weather through snapshot alias")
|
||||
expect(weather.schedule(&"mana_fog", 400)[&"ok"] and weather.advance_to(400)[&"ok"] and weather.get_kind() == &"mana_fog", "mana fog is persisted without invented efficiency multipliers")
|
||||
print("Weather timeline: %d checks, %d failures" % [checks, failures])
|
||||
quit(failures)
|
||||
@@ -0,0 +1 @@
|
||||
uid://cmqkqajl1u1d
|
||||
Reference in New Issue
Block a user