Files
aetherbound-guild/runtime/tests/p9_9/run_persistence_test.gd
T

113 lines
6.2 KiB
GDScript

extends SceneTree
const RunService = preload("res://p9_9/run_service.gd")
const RunState = preload("res://p9_9/run_state.gd")
const BattleService = preload("res://p9_9/battle_service.gd")
const SaveService = preload("res://p9_9/save_service.gd")
const Fixture = preload("res://tests/p9_9/runtime_fixture.gd")
var failures: Array[String] = []
var save_root := ""
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
save_root = OS.get_environment("ABG_P9_9_RUN_SAVE_ROOT")
if save_root.is_empty():
save_root = "/private/tmp/abg-p99-run-persistence-default"
DirAccess.make_dir_recursive_absolute(save_root)
verify_draft_reload()
verify_interruption_and_market_four()
if failures.is_empty():
print("ABG_P9_9_RUN_PERSISTENCE_OK version=4 draft=stable selected=preserved encounter=checkpoint market4=exact capacity=5 company=4 charter=preserved duplicate_hire=0 duplicate_settlement=0 rollback=true offline_cap=86400 offline_rewards=0 temp_clean=true")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func verify_draft_reload() -> void:
var service = RunService.new(Fixture.claimed_profile("CH-RG01-CATALOG-01"))
service.set_provisional("draft-save-one", "P99-D1", true)
service.set_provisional("draft-save-two", "P99-D3", true)
var saves: Variant = fresh_saves("draft")
expect(saves.save_snapshot(service.state.snapshot(), 1000).ok, "selected draft saves")
expect(not FileAccess.file_exists(saves.save_path + ".tmp"), "atomic draft save leaves no temp")
var loaded: Dictionary = saves.load_snapshot(1012)
expect(loaded.ok and loaded.state_kind == "p99_run" and not loaded.battle_interrupted, "draft loads as a run state")
var restored = RunService.new()
expect(restored.restore_snapshot(loaded.snapshot), "draft snapshot restores")
expect(restored.state.selected_provisional_ids == ["P99-D1", "P99-D3"] and restored.state.draft_offer_ids.size() == 4, "reload preserves selection and all four identities")
expect(restored.confirm_run("draft-save-create").ok and restored.state.coin == 52, "reloaded draft creates the same run")
func verify_interruption_and_market_four() -> void:
var service: Variant = prepared_company()
var saves: Variant = fresh_saves("contract")
expect(service.commit_route("persist-route-r1", "P99-R1-Q0").ok, "Round 1 route commits")
expect(saves.save_snapshot(service.state.snapshot(), 2000).ok, "Encounter checkpoint saves")
var interrupted: Dictionary = saves.load_snapshot(2015)
expect(interrupted.ok and interrupted.battle_interrupted and interrupted.offline_coin == 0 and interrupted.offline_battle_ticks == 0, "Encounter load returns pre-battle Market with no offline progress")
service = RunService.new()
expect(service.restore_snapshot(interrupted.snapshot), "interrupted Market restores")
expect(service.state.phase == RunState.Phase.MARKET and service.state.current_market == 1 and service.state.selected_route.is_empty(), "interruption restores the same decision boundary")
var round_one: Dictionary = play(service, "P99-R1-Q0", "persist-r1-retry")
var round_two: Dictionary = play(service, "P99-R2-Q0", "persist-r2")
var round_three: Dictionary = play(service, "P99-R3-Q0", "persist-r3")
expect(round_one.outcome == "victory" and round_two.outcome == "victory" and round_three.outcome == "victory", "three reloaded Rounds win")
expect(service.state.current_market == 4 and service.state.line_capacity == 5 and service.state.continuation_locked, "Market 4 stopping point is exact")
var market_four: Dictionary = service.state.snapshot()
expect(saves.save_snapshot(market_four, 3000).ok, "Market 4 saves")
var loaded: Dictionary = saves.load_snapshot(2990)
expect(loaded.ok and loaded.clock_rollback and loaded.elapsed_seconds == 0, "clock rollback is inert")
expect(loaded.snapshot == market_four and loaded.snapshot.profile.selected_charter_claim_id == "CH-RG01-THREAT-01", "Market 4 and Charter reload exactly")
var capped: Dictionary = saves.load_snapshot(999999)
expect(capped.ok and capped.elapsed_seconds == SaveService.OFFLINE_CAP_SECONDS and capped.offline_coin == 0 and capped.offline_xp == 0 and capped.offline_renown == 0, "elapsed duration caps with zero offline rewards")
var restored = RunService.new()
expect(restored.restore_snapshot(loaded.snapshot), "Market 4 state restores into service")
var before: Dictionary = restored.state.snapshot()
var duplicate_hire: Dictionary = restored.hire("persist-hire-0", "P99-M1-H1")
expect(duplicate_hire.ok and duplicate_hire.duplicate and restored.state.snapshot() == before, "reloaded hire receipt remains idempotent")
var duplicate_settlement: Dictionary = restored.settle_battle("persist-r3-settle", round_three.snapshot)
expect(duplicate_settlement.ok and duplicate_settlement.duplicate and restored.state.snapshot() == before, "reloaded settlement receipt remains idempotent")
func prepared_company():
var service = RunService.new(Fixture.claimed_profile("CH-RG01-THREAT-01"))
service.set_provisional("persist-select-0", "P99-D1", true)
service.set_provisional("persist-select-1", "P99-D3", true)
expect(service.confirm_run("persist-create").ok, "fixture creates run")
expect(service.hire("persist-hire-0", "P99-M1-H1").ok, "fixture hires first")
expect(service.hire("persist-hire-1", "P99-M1-H2").ok, "fixture hires second")
return service
func play(service, route_id: String, prefix: String) -> Dictionary:
expect(service.commit_route("%s-route" % prefix, route_id).ok, "%s route commits" % prefix)
var battle = BattleService.new(service.state.selected_charter_claim_id)
expect(battle.start_from_market(service.state).ok, "%s battle starts" % prefix)
var guard := 0
while not battle.state.terminal and guard < 1800:
battle.advance_ticks(1)
guard += 1
expect(guard < 1800, "%s battle terminates" % prefix)
var snapshot: Dictionary = battle.state.snapshot()
expect(service.settle_battle("%s-settle" % prefix, snapshot).ok, "%s settles" % prefix)
return {"outcome": battle.state.outcome, "snapshot": snapshot}
func fresh_saves(name: String):
var saves = SaveService.new()
saves.save_path = save_root.path_join("%s.json" % name)
saves.clear()
return saves
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("P9.9 run persistence: %s" % message)