extends SceneTree var checks := 0 var failures := 0 func _initialize() -> void: call_deferred("_run") func expect(ok: bool, message: String) -> void: checks += 1 if not ok: failures += 1 push_error(message) 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") var definition: FacilityDefinition = runtime.definition_registry.get_facility(&"guest_corridor") var old_rate := definition.maintenance_gold definition.maintenance_gold = 1440 expect(runtime.submit_command(&"build_facility", {&"definition_id": &"guest_corridor", &"origin": Vector3i(4, 1, 0)}).is_success(), "build completed asset") runtime.operations_coordinator._legacy_calendar_last_day = 1 clock.advance_minutes(1079) var legacy: Dictionary = runtime.create_snapshot() var data: Dictionary = legacy[&"systems"][&"runtime"] data[&"runtime_schema_version"] = 9 preload("res://tests/fixtures/pre_upkeep_runtime.gd").strip_empty_upkeep(data) data[&"operations"][&"coordinator"][&"schema_version"] = 3 data[&"operations"][&"coordinator"].erase(&"legacy_calendar_last_day") data[&"operations"][&"coordinator"].erase(&"legacy_history_last_day") data[&"operations"][&"coordinator"].erase(&"legacy_principal_profit_last_day") expect(runtime.restore_snapshot(legacy), "constructed v9/v3 calendar fixture migrates before midnight") var ledger_before: Dictionary = runtime.economy_service.create_snapshot() runtime.set_operations_test_boundary_hook(&"MIDNIGHT_UPKEEP", func(_payload: Dictionary, phase: StringName, _token: Variant) -> Dictionary: return {&"ok": phase != runtime.OPERATIONS_TEST_AFTER_FIRST_MUTATION_PHASE}) clock.advance_minutes(1) expect(runtime.get_operations_report()[&"runtime_failure_latched"] and clock.absolute_minute == 1440, "midnight failure pauses before legacy financial close") expect(runtime.economy_service.create_snapshot() == ledger_before and runtime.upkeep_settlement.get_settled_period_count() == 0, "midnight rollback restores cash ledger and receipt atomically") var failed: Dictionary = runtime.create_snapshot() expect(runtime.restore_snapshot(failed), "failed midnight checkpoint restores") runtime.set_operations_test_boundary_hook(&"MIDNIGHT_UPKEEP", Callable()) expect(runtime.acknowledge_operations_pause()[&"ok"], "same midnight retries through existing acknowledgement") expect(runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 1 and runtime.upkeep_settlement.get_settled_period_count() == 1, "only post-migration minute settles at midnight") expect(runtime.operations_coordinator.get_day_summaries().is_empty(), "legacy payroll and financial day are not rewritten") var midnight: Dictionary = runtime.create_snapshot() expect(runtime.restore_snapshot(midnight) and runtime.create_snapshot() == midnight, "midnight interim payment roundtrips exactly") clock.advance_minutes(360) var summary: Dictionary = runtime.operations_coordinator.get_day_summary(1) expect(not summary.is_empty() and summary[&"closed_at"] == 1800, "legacy financial close remains at 06:00") if not summary.is_empty(): expect(summary[&"category_totals"][&"maintenance"] == 1 and runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 1, "06:00 reports midnight expense without a second charge") expect(runtime.restore_snapshot(runtime.create_snapshot()), "06:00 history and earlier midnight receipt reconcile on load") # A later failure must retain the already committed midnight payment exactly once. expect(runtime.restore_snapshot(legacy), "restore before later-boundary failure") runtime.set_operations_test_boundary_hook(&"ARRIVAL_PLAN", func(_payload: Dictionary, phase: StringName, _token: Variant) -> Dictionary: return {&"ok": phase != runtime.OPERATIONS_TEST_PREPARE_PHASE}) clock.advance_minutes(1) expect(runtime.get_operations_report()[&"runtime_failure_latched"] and runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 1, "later failure preserves committed midnight payment") var after_payment_failure: Dictionary = runtime.create_snapshot() expect(runtime.restore_snapshot(after_payment_failure), "save distinguishes committed payment from pending later boundary") runtime.set_operations_test_boundary_hook(&"ARRIVAL_PLAN", Callable()) expect(runtime.acknowledge_operations_pause()[&"ok"] and runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 1 and runtime.upkeep_settlement.get_settled_period_count() == 1, "retry never duplicates earlier midnight payment") # New interim debt blocks spending immediately, without rewriting old summaries. expect(runtime.restore_snapshot(legacy), "restore legacy insufficient-cash branch") var cash: int = runtime.economy_service.get_balance(&"PLAYER_CASH") expect(runtime.economy_service.transfer(&"PLAYER_CASH", &"CONSTRUCTION_EXPENSE", cash, 1439, &"CONSTRUCTION").is_success(), "deplete cash") clock.advance_minutes(1) expect(runtime.get_operations_report()[&"arrears_total"] == 1 and runtime.operations_coordinator.get_arrears_total() == 0, "live debt is visible while closed financial history stays unchanged") clock.set_paused(true) var blocked: CommandResult = runtime.submit_command(&"build_facility", {&"definition_id": &"guest_corridor", &"origin": Vector3i(5, 1, 0)}) expect(not blocked.is_success() and blocked.details.get(&"reason") == &"UNPAID_EXPENSES", "interim upkeep debt blocks new investment at midnight") expect(runtime.restore_snapshot(runtime.create_snapshot()), "interim debt saves and restores without a synthetic daily summary") definition.maintenance_gold = old_rate runtime.free() clock.free() state.free() print("%s: %d checks" % ["PASS" if failures == 0 else "FAIL", checks]) quit(failures)