extends SceneTree ## P05-02 F6, writer phase. Plays the day script, writes ordinary save files at ## mid-day, just before the day 2 00:00 close and just after it, and hands the ## exact save packages to the reader suite (test_p05_funds_restart_2_read.gd), ## which runs as a separate engine process. The handoff is the declared generated ## report res://artifacts/p05-02/restart-handoff.json ## (tools/regression/suite-policy.json fixed_generated_report_routes). const Fixture := preload("res://tests/helpers/p05_funds_restart_fixture.gd") var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: print("P05-02: restart writer") var fixtures := Fixture.new(_expect) var straight := fixtures.new_fixture() fixtures.play(straight, 0, Fixture.LAST_MINUTE, Callable()) var straight_runtime: Variant = straight[&"runtime"] _expect(straight_runtime.economy_service.get_balance(Fixture.FRONT) == 35 and straight_runtime.economy_service.get_balance(Fixture.BACK) == 695, "uninterrupted day script ends with front 35 and hidden 695") _expect(fixtures.category_count(straight_runtime, [FinancePolicy.TOP_UP_CATEGORY]) == 1, "uninterrupted day script tops up once (day 2)") var saving := fixtures.new_fixture() var saved_paths: Dictionary = {} fixtures.play(saving, 0, Fixture.LAST_MINUTE, func(minute: int) -> void: if minute in Fixture.SAVE_MINUTES: var path := Fixture.WRITER_SAVE % minute _expect(bool(saving[&"runtime"].save_to_path(path).get(&"ok", false)), "save file at minute %d" % minute) saved_paths[minute] = path) _expect(fixtures.economy_bytes(saving[&"runtime"]) == fixtures.economy_bytes(straight_runtime), "writing the save files leaves the ledger as without saving") var saves: Array = [] for minute: int in Fixture.SAVE_MINUTES: var directory := ProjectSettings.globalize_path(str(saved_paths.get(minute, Fixture.WRITER_SAVE % minute))) _expect(DirAccess.dir_exists_absolute(directory) and DirAccess.get_directories_at(directory).is_empty(), "save package at minute %d holds only files" % minute) var files := {} for name: String in DirAccess.get_files_at(directory): var bytes := FileAccess.get_file_as_bytes(directory.path_join(name)) files[name] = {"sha256": Fixture.sha256(bytes), "bytes": bytes.size(), "base64": Marshalls.raw_to_base64(bytes)} _expect(files.has("manifest.json") and files.has("world.bin"), "save package at minute %d has its manifest and world" % minute) saves.append({"minute": minute, "files": files}) var handoff := { "schema": Fixture.HANDOFF_SCHEMA, "writer_pid": OS.get_process_id(), "writer_source_sha256": FileAccess.get_sha256(Fixture.WRITER_SOURCE), "seed": Fixture.SEED, "last_minute": Fixture.LAST_MINUTE, "straight_economy_sha256": Fixture.sha256(fixtures.economy_bytes(straight_runtime)), "straight_days_base64": Marshalls.raw_to_base64(var_to_bytes(fixtures.days_value(straight_runtime))), "saves": saves, } DirAccess.make_dir_recursive_absolute(Fixture.HANDOFF_PATH.get_base_dir()) var file := FileAccess.open(Fixture.HANDOFF_PATH, FileAccess.WRITE) _expect(file != null, "handoff file opens for writing") if file != null: file.store_string(JSON.stringify(handoff, "\t") + "\n") file.close() print("P05_RESTART_WRITER pid=%d handoff_sha256=%s" % [OS.get_process_id(), FileAccess.get_sha256(Fixture.HANDOFF_PATH)]) fixtures.free_fixture(straight) fixtures.free_fixture(saving) await process_frame if _failures == 0: print("PASS: %d checks" % _checks) else: push_error("FAIL: %d of %d checks failed" % [_failures, _checks]) quit(_failures) func _expect(condition: bool, message: String) -> void: _checks += 1 if not condition: _failures += 1 push_error(message)