113 lines
6.2 KiB
GDScript
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)
|