154 lines
4.9 KiB
Python
Executable File
154 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Temporarily switch selected legacy client packs to .m2p and run the Wine login smoke test."
|
|
)
|
|
parser.add_argument(
|
|
"--runtime-root",
|
|
type=Path,
|
|
required=True,
|
|
help="Client runtime root containing pack/ and config/.",
|
|
)
|
|
parser.add_argument(
|
|
"--client-repo",
|
|
type=Path,
|
|
required=True,
|
|
help="Path to m2dev-client-src checkout.",
|
|
)
|
|
parser.add_argument(
|
|
"--master-key",
|
|
type=Path,
|
|
required=True,
|
|
help="Path to m2pack runtime master key file.",
|
|
)
|
|
parser.add_argument(
|
|
"--key-id",
|
|
type=str,
|
|
default="1",
|
|
help="Runtime key_id to inject into the client.",
|
|
)
|
|
parser.add_argument(
|
|
"--timeout",
|
|
type=int,
|
|
default=20,
|
|
help="Wine run timeout in seconds.",
|
|
)
|
|
parser.add_argument(
|
|
"--pack",
|
|
dest="packs",
|
|
action="append",
|
|
required=True,
|
|
help="Pack basename to test as .m2p. Repeat for multiple packs.",
|
|
)
|
|
parser.add_argument(
|
|
"--json",
|
|
action="store_true",
|
|
help="Emit machine-readable JSON result.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def activate_pack(pack_dir: Path, pack_name: str, moved: list[tuple[Path, Path]]) -> None:
|
|
offsingle = pack_dir / f"{pack_name}.m2p.offsingle"
|
|
m2p = pack_dir / f"{pack_name}.m2p"
|
|
legacy = pack_dir / f"{pack_name}.pck"
|
|
legacy_backup = pack_dir / f"{pack_name}.pck.testbak"
|
|
|
|
if offsingle.exists():
|
|
offsingle.rename(m2p)
|
|
moved.append((m2p, offsingle))
|
|
|
|
if legacy.exists():
|
|
legacy.rename(legacy_backup)
|
|
moved.append((legacy_backup, legacy))
|
|
|
|
|
|
def restore_moves(moved: list[tuple[Path, Path]]) -> None:
|
|
for src, dst in reversed(moved):
|
|
if src.exists():
|
|
src.rename(dst)
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
|
|
runtime_root = args.runtime_root.resolve()
|
|
client_repo = args.client_repo.resolve()
|
|
pack_dir = runtime_root / "pack"
|
|
run_script = client_repo / "scripts" / "run-wine-headless.sh"
|
|
build_bin = client_repo / "build-mingw64-lld" / "bin"
|
|
log_dir = build_bin / "log"
|
|
|
|
if not pack_dir.is_dir():
|
|
raise SystemExit(f"runtime pack dir not found: {pack_dir}")
|
|
if not run_script.is_file():
|
|
raise SystemExit(f"wine runner not found: {run_script}")
|
|
if not (build_bin / "Metin2_RelWithDebInfo.exe").is_file():
|
|
raise SystemExit(f"client binary not found: {build_bin / 'Metin2_RelWithDebInfo.exe'}")
|
|
|
|
moved: list[tuple[Path, Path]] = []
|
|
try:
|
|
for pack_name in args.packs:
|
|
activate_pack(pack_dir, pack_name, moved)
|
|
|
|
log_dir.mkdir(parents=True, exist_ok=True)
|
|
for file_path in log_dir.glob("*.txt"):
|
|
file_path.unlink(missing_ok=True)
|
|
for file_path in [build_bin / "syserr.txt", build_bin / "ErrorLog.txt"]:
|
|
file_path.unlink(missing_ok=True)
|
|
|
|
env = os.environ.copy()
|
|
env["M2PACK_MASTER_KEY_HEX"] = args.master_key.read_text(encoding="utf-8").strip()
|
|
env["M2PACK_KEY_ID"] = args.key_id
|
|
env["M2_TIMEOUT"] = str(args.timeout)
|
|
env.setdefault("WINEDEBUG", "-all")
|
|
|
|
completed = subprocess.run(
|
|
[str(run_script), str(build_bin)],
|
|
cwd=client_repo,
|
|
env=env,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
|
|
prototype_trace = (log_dir / "prototype_trace.txt").read_text(encoding="utf-8", errors="ignore") if (log_dir / "prototype_trace.txt").exists() else ""
|
|
system_trace = (log_dir / "system_py_trace.txt").read_text(encoding="utf-8", errors="ignore") if (log_dir / "system_py_trace.txt").exists() else ""
|
|
syserr = (build_bin / "syserr.txt").read_text(encoding="utf-8", errors="ignore") if (build_bin / "syserr.txt").exists() else ""
|
|
|
|
result = {
|
|
"ok": "SetLoginPhase ok" in prototype_trace,
|
|
"returncode": completed.returncode,
|
|
"packs": args.packs,
|
|
"prototype_tail": prototype_trace.strip().splitlines()[-10:],
|
|
"system_tail": system_trace.strip().splitlines()[-10:],
|
|
"syserr_tail": syserr.strip().splitlines()[-10:],
|
|
}
|
|
|
|
if args.json:
|
|
print(json.dumps(result, indent=2))
|
|
else:
|
|
print(f"packs={','.join(args.packs)} ok={result['ok']} returncode={completed.returncode}")
|
|
if result["prototype_tail"]:
|
|
print("prototype tail:")
|
|
for line in result["prototype_tail"]:
|
|
print(f" {line}")
|
|
|
|
return 0 if result["ok"] else 1
|
|
finally:
|
|
restore_moves(moved)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|