extends SceneTree ## Runs every writer/reader save-restart pair as two real child Godot processes ## (distinct PIDs) from this one suite, so a script-level regression roster also ## proves the new-PID halves. Each child's complete stdout+stderr and exit code ## are kept under user://pair-evidence/ (inside the run's private profile); ## summaries printed here avoid completion-marker wording on purpose. const PAIRS: Array[String] = [ "res://tests/s2/test_mana_reserve_new_pid.gd", "res://tests/s2/test_mana_recovery_new_pid.gd", "res://tests/transport/test_runtime_warp.gd", "res://tests/mvp/test_whole_tower_outage.gd", "res://tests/transport/test_route_wait_choice.gd", ] const EVIDENCE_DIR := "user://pair-evidence" var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: var engine := OS.get_executable_path() var project := ProjectSettings.globalize_path("res://") DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(EVIDENCE_DIR)) print("New-PID pairs: parent pid %d engine %s" % [OS.get_process_id(), engine]) for script: String in PAIRS: var pids := {} for mode: String in ["writer", "reader"]: var output: Array = [] var code := OS.execute(engine, ["--headless", "--path", project, "--script", script, "--", mode], output, true) var text := "".join(output) var name := "%s.%s" % [script.get_file().get_basename(), mode] var file := FileAccess.open(EVIDENCE_DIR.path_join(name + ".log"), FileAccess.WRITE) file.store_string(text) file.close() var pid := _child_pid(text) pids[mode] = pid var passed := code == 0 and _child_marker_passed(text) print(" pair %s %s exit=%d child_pid=%d bytes=%d sha256=%s" % [script.get_file(), mode, code, pid, text.to_utf8_buffer().size(), text.sha256_text()]) _expect(passed, "%s %s child completes with zero failures" % [script.get_file(), mode]) _expect(int(pids["writer"]) > 0 and int(pids["reader"]) > 0 and pids["writer"] != pids["reader"] and pids["reader"] != OS.get_process_id(), "%s writer and reader ran in distinct processes" % script.get_file()) print("%s: %d checks" % ["PASS" if _failures == 0 else "FAIL", _checks]) quit(_failures) ## Each pair script prints its own pid on its first line ("... pid N" or "(pid N)"). static func _child_pid(text: String) -> int: var regex := RegEx.new() regex.compile("pid (\\d+)") var found := regex.search(text) return int(found.get_string(1)) if found != null else -1 static func _child_marker_passed(text: String) -> bool: var regex := RegEx.new() regex.compile("(?m)^PASS: (\\d+) checks$") var found := regex.search(text) return found != null and int(found.get_string(1)) > 0 and not text.contains("FAIL:") and not text.contains("SCRIPT ERROR") func _expect(condition: bool, label: String) -> void: _checks += 1 if not condition: _failures += 1 push_error(" ✗ %s" % label)