159 lines
11 KiB
GDScript
159 lines
11 KiB
GDScript
extends SceneTree
|
|
|
|
## A genuine pre-policy Path4 saved every boarded actor in floor density.
|
|
## Rebuild that old representation from five publicly spawned Runtime guests,
|
|
## then verify migration and cross-service rollback with occupied physical cars.
|
|
var _checks := 0
|
|
var _failures := 0
|
|
var _serial := 0
|
|
var _runtime: Variant
|
|
var _clock: Variant
|
|
var _state: Variant
|
|
var _arrivals: Dictionary = {}
|
|
var _original_requests: Dictionary = {}
|
|
var _arrival_errors: Array[String] = []
|
|
const GOAL := Vector3i(0, 1, 0)
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
var global_clock := root.get_node_or_null("GameClock")
|
|
if global_clock != null: global_clock.set_paused(true)
|
|
_runtime = load("res://autoload/simulation_runtime.gd").new()
|
|
_clock = load("res://autoload/game_clock.gd").new()
|
|
_state = load("res://autoload/game_state.gd").new()
|
|
_clock.reset(1, 6, 0)
|
|
_state.reset()
|
|
_expect(_runtime.initialize(_clock, _state, 90583)[&"valid"], "density migration fixture initializes")
|
|
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
|
_clock.set_paused(true)
|
|
for build: Array in [[&"guest_elevator", Vector3i.ZERO], [&"guest_corridor", Vector3i(4, 1, 0)], [&"guest_corridor", Vector3i(4, 2, 0)]]:
|
|
_expect(_command(&"build_facility", {&"definition_id": build[0], &"origin": build[1]}).is_success(), "normal construction pays for migration topology")
|
|
_clock.advance_minutes(10)
|
|
_clock.advance_minutes(280)
|
|
for index: int in range(5):
|
|
var id := StringName("density.guest.%d" % index)
|
|
_expect(_command(&"spawn_guest", {&"guest_id": id, &"guest_type_id": &"traveler", &"gold": 100,
|
|
&"options": {&"current_cell": Vector3i.ZERO, &"state": GuestRuntime.State.MOVING,
|
|
&"state_entered_at": _clock.absolute_minute - 1, &"planned_exit_at": _clock.absolute_minute + 2000,
|
|
&"path_handle": {&"target_cell": GOAL}}}).is_success(), "public Runtime spawn creates actual passenger %d" % index)
|
|
_clock.advance_minutes(2)
|
|
var car: Dictionary = _runtime.elevators.get_report()[&"shafts"][0]
|
|
_expect(car[&"phase"] == &"BOARDING" and car[&"passenger_count"] == 4 and car[&"waiting_count"] == 1, "four real guests board while the fifth waits at the same floor")
|
|
_expect(_runtime.path_service.get_current_density(Vector3i.ZERO) == 1 and _runtime.path_service.get_transit_actor_ids().size() == 4, "new physical floor density excludes four occupied cabin seats")
|
|
var statistics: Dictionary = _runtime.get_elevator_wait_statistics(car[&"shaft_id"])
|
|
_expect(statistics[&"sample_count"] == 4 and statistics[&"mean_wait_minutes"] == 1.0 and statistics[&"p95_wait_minutes"] == 1 and statistics[&"oldest_wait_minutes"] == 1, "live wait read model reports real boarding events and current queue age")
|
|
var current: Dictionary = _runtime.create_snapshot()
|
|
_expect(_runtime.restore_snapshot(current) and _runtime.get_elevator_wait_statistics(car[&"shaft_id"]) == statistics, "wait statistics survive actual Runtime restore without duplicate samples")
|
|
var legacy := _as_v8_path4(current)
|
|
var data: Dictionary = legacy[&"systems"][&"runtime"]
|
|
var old_path: Dictionary = data[&"path"]
|
|
var old_density := 0
|
|
for cell: Dictionary in old_path[&"cell_traffic"]:
|
|
if cell[&"cell"] == Vector3i.ZERO: old_density = cell[&"current_density"]
|
|
_expect(old_density == 5 and not old_path.has(&"transit_actor_ids") and not old_path.has(&"vertical_walk_requires_connector") and not data.has(&"legacy_stairs"), "legacy fixture has genuine Path4 fields and all five old boarding-anchor occupants")
|
|
var forged := legacy.duplicate(true)
|
|
for cell: Dictionary in forged[&"systems"][&"runtime"][&"path"][&"cell_traffic"]:
|
|
if cell[&"cell"] == Vector3i.ZERO: cell[&"current_density"] = 1
|
|
_expect(_rejects(forged), "v8 relabel with new excluded-passenger density is rejected before migration")
|
|
_expect(_runtime.restore_snapshot(legacy), "actual v8 plus Path4 aggregate migrates occupied car and queued passengers")
|
|
_expect(_runtime.get_elevator_wait_statistics(car[&"shaft_id"])[&"sample_count"] == 0 and _runtime.get_elevator_wait_statistics(car[&"shaft_id"])[&"oldest_wait_minutes"] == 1, "legacy load shows no fabricated boarding samples but retains the actual queue age")
|
|
_expect(_runtime.elevators.create_snapshot() == data[&"elevators"], "migration preserves cabin phase, seats, queue IDs, travel clocks and operator power exactly")
|
|
_expect(_runtime.path_service.get_current_density(Vector3i.ZERO) == 1 and _runtime.path_service.get_transit_actor_ids().size() == 4, "migration recomputes floor density without removing any actor or cabin seat")
|
|
_expect(_runtime.path_service.get_vertical_walk_requires_connector() and _runtime.legacy_stairs.create_snapshot()[&"stairs"].size() == 2, "same migration materializes two old corridor stairs and closes implicit vertical walking")
|
|
_expect(_runtime.path_service.find_path(Vector3i(4, 0, 0), Vector3i(4, 2, 0)).size() == 3, "old corridor vertical reachability remains available after policy migration")
|
|
for guest: GuestRuntime in _runtime.guest_service.get_guests():
|
|
_expect(guest.current_cell == Vector3i.ZERO and _runtime.path_service.get_actor_projected_cell(StringName("guest:" + String(guest.guest_id))) == Vector3i.ZERO, "migration preserves actual passenger's logical boarding anchor")
|
|
var canonical: Dictionary = _runtime.create_snapshot()
|
|
_expect(canonical[&"systems"][&"runtime"][&"runtime_schema_version"] == 14 and canonical[&"systems"][&"runtime"][&"path"][&"schema_version"] == 5, "resave emits current Runtime14 and Path5 only")
|
|
_expect(_runtime.restore_snapshot(canonical) and _runtime.create_snapshot() == canonical, "canonical migrated save reloads exactly without applying density or stairs twice")
|
|
forged = canonical.duplicate(true)
|
|
forged[&"systems"][&"runtime"][&"path"][&"transit_actor_ids"].pop_back()
|
|
_expect(_rejects(forged), "current transit list cannot omit a real boarded guest")
|
|
forged = canonical.duplicate(true)
|
|
for cell: Dictionary in forged[&"systems"][&"runtime"][&"path"][&"cell_traffic"]:
|
|
if cell[&"cell"] == Vector3i.ZERO: cell[&"current_density"] = 5
|
|
_expect(_rejects(forged), "current save cannot restore old double-counted cabin density")
|
|
forged = canonical.duplicate(true)
|
|
forged[&"systems"][&"runtime"][&"legacy_stairs"][&"stairs"].pop_back()
|
|
_expect(_rejects(forged), "migrated occupied-car snapshot rejects orphan legacy connector metadata")
|
|
var token: Dictionary = _runtime._capture_event_action_token()
|
|
var first_guest := &"density.guest.0"
|
|
_expect(_runtime.guest_service.begin_leaving(first_guest, _clock.absolute_minute, &"TEST_EVENT_EXIT")[&"ok"] and _runtime.guest_service.despawn_guest(first_guest, _clock.absolute_minute)[&"ok"], "event rollback fixture removes a real boarded actor through normal lifecycle")
|
|
_expect(_runtime._restore_event_action_token(token)[&"ok"] and _runtime.create_snapshot() == canonical, "event action rollback restores guests, seats, Path density, stair ownership and all snapshot participants exactly")
|
|
for trip: Dictionary in _runtime.elevators.get_report()[&"trips"]:
|
|
_original_requests[trip[&"request_id"]] = trip[&"actor_id"]
|
|
_runtime.domain_events.subscribe(&"ELEVATOR_ARRIVED", &"density.migration.arrivals", Callable(self, "_on_arrival"))
|
|
for step: int in range(80):
|
|
_clock.advance_minutes(1)
|
|
for guest: GuestRuntime in _runtime.guest_service.get_guests():
|
|
if guest.current_cell == GOAL:
|
|
_runtime.guest_service.begin_leaving(guest.guest_id, _clock.absolute_minute, &"TEST_DESTINATION_REACHED")
|
|
_runtime.guest_service.despawn_guest(guest.guest_id, _clock.absolute_minute)
|
|
var exactly_once := _arrivals.size() == 5
|
|
for request_id: StringName in _original_requests:
|
|
exactly_once = exactly_once and _arrivals.get(request_id, 0) == 1
|
|
_expect(exactly_once and _arrival_errors.is_empty(), "all five migrated request IDs reach the real destination exactly once")
|
|
_expect(_runtime.guest_service.get_guests().is_empty() and _runtime.elevators.get_report()[&"trips"].is_empty() and _runtime.path_service.get_transit_actor_ids().is_empty(), "completed lifecycle leaves no orphan guest, Path transit actor or elevator trip")
|
|
var final_state: Dictionary = _runtime.create_snapshot()
|
|
_expect(_runtime.restore_snapshot(final_state) and _runtime.create_snapshot() == final_state, "post-arrival migrated world remains strictly canonical")
|
|
_runtime.free()
|
|
_clock.free()
|
|
_state.free()
|
|
print("Transport density migration: %d checks, %d failures" % [_checks, _failures])
|
|
quit(1 if _failures else 0)
|
|
|
|
|
|
func _as_v8_path4(current: Dictionary) -> Dictionary:
|
|
var result := current.duplicate(true)
|
|
var data: Dictionary = result[&"systems"][&"runtime"]
|
|
data[&"runtime_schema_version"] = 8
|
|
data.erase(&"legacy_stairs")
|
|
preload("res://tests/fixtures/pre_upkeep_runtime.gd").strip_empty_upkeep(data)
|
|
var path: Dictionary = data[&"path"]
|
|
path[&"schema_version"] = 4
|
|
path.erase(&"vertical_walk_requires_connector")
|
|
path.erase(&"transit_actor_ids")
|
|
var old_densities: Dictionary = {}
|
|
for actor: Dictionary in path[&"actor_cells"]:
|
|
old_densities[actor[&"cell"]] = int(old_densities.get(actor[&"cell"], 0)) + 1
|
|
for cell: Dictionary in path[&"cell_traffic"]:
|
|
cell[&"current_density"] = int(old_densities.get(cell[&"cell"], 0))
|
|
# V8 had no boarding telemetry event. Stable ID high-water marks remain
|
|
# monotonic; retiring those observer-only events does not renumber history.
|
|
var events: Dictionary = data[&"domain_events"]
|
|
var retired: Array = []
|
|
for event: Dictionary in events["recent_events"]:
|
|
if event["event_type"] == "ELEVATOR_BOARDED": retired.append(event["event_id"])
|
|
events["recent_events"] = events["recent_events"].filter(func(event: Dictionary) -> bool: return event["event_id"] not in retired)
|
|
events["published_ids"] = events["published_ids"].filter(func(id: String) -> bool: return id not in retired)
|
|
return result
|
|
|
|
|
|
func _on_arrival(event: SimulationDomainEvent) -> void:
|
|
var request_id: StringName = event.payload[&"request_id"]
|
|
if not _original_requests.has(request_id):
|
|
_arrival_errors.append("Unrequested duplicate ride: %s" % request_id)
|
|
return
|
|
_arrivals[request_id] = int(_arrivals.get(request_id, 0)) + 1
|
|
if event.payload[&"cell"] != GOAL or event.payload.get(&"emergency", false): _arrival_errors.append("Unexpected migrated destination")
|
|
|
|
|
|
func _command(type: StringName, payload: Dictionary) -> CommandResult:
|
|
_serial += 1
|
|
return _runtime.submit_command(type, payload, &"world", &"", 0, -1, StringName("density.migration.%d" % _serial))
|
|
|
|
|
|
func _rejects(candidate: Dictionary) -> bool:
|
|
var before: Dictionary = _runtime.create_snapshot()
|
|
return not _runtime.restore_snapshot(candidate) and _runtime.create_snapshot() == before
|
|
|
|
|
|
func _expect(ok: bool, label: String) -> void:
|
|
_checks += 1
|
|
if not ok: _failures += 1
|
|
print("%s: %s" % ["PASS" if ok else "FAIL", label])
|