4.1 KiB
Testing
Linux headless
m2pack-secure can be validated headless on a Linux VPS without GUI support.
This covers the archive toolchain and release artifacts, not the full Windows client runtime.
Run:
cmake -S . -B build
cmake --build build -j
python3 scripts/headless_e2e.py
Or through npm:
npm run headless:e2e
The headless E2E test covers:
keygenbuildlistverifydiffexport-client-configexport-runtime-keyinjsonexport-runtime-keyinblobextract- byte-for-byte comparison of extracted files
What it does not cover
- Windows SDK compilation of the client
- Direct3D startup
- shared-memory launcher bootstrap on Windows
- in-game runtime behavior of the client loader
Full client runtime
To test the actual client runtime you still need one of these:
- a Windows build machine
- a Windows VM
- or a Linux host with
wineplus the required runtime dependencies
The Linux VPS path is now validated as well.
Confirmed runtime path on this host:
- Linux-hosted Windows build of
m2dev-client-src - headless execution through
xvfb-run + wine - runtime key delivery through:
M2PACK_MASTER_KEY_HEXM2PACK_KEY_ID
Confirmed .m2p smoke tests:
root.m2ponly, withroot.pckremovedroot.m2p+patch1.m2p, with both legacy.pckfiles removedroot.m2p+patch1.m2p+season3_eu.m2p, with all three legacy.pckfiles removedroot.m2p+patch1.m2p+patch2.m2p+season3_eu.m2p, with all four legacy.pckfiles removedroot.m2p+patch1.m2p+patch2.m2p+season3_eu.m2p+metin2_patch_snow.m2p+metin2_patch_snow_dungeon.m2p+metin2_patch_etc_costume1.m2p+metin2_patch_pet1.m2p, with all eight matching legacy.pckfiles removedroot.m2p+patch1.m2p+patch2.m2p+season3_eu.m2p+metin2_patch_snow.m2p+metin2_patch_snow_dungeon.m2p+metin2_patch_etc_costume1.m2p+metin2_patch_pet1.m2p+metin2_patch_pet2.m2p+metin2_patch_ramadan_costume.m2p+metin2_patch_flame.m2p+metin2_patch_flame_dungeon.m2p, with all twelve matching legacy.pckfiles removed- the same twelve-pack startup set plus:
locale.m2puiscript.m2puiloading.m2pETC.m2pwith all sixteen matching legacy.pckfiles removed
- the same sixteen-pack startup and UI bootstrap set plus:
item.m2peffect.m2picon.m2pproperty.m2pwith all twenty matching legacy.pckfiles removed
In every confirmed case the client reached the login bootstrap path under Wine and completed:
PackInitialize- Python bootstrap through
prototype.py app.Create(...)app.SetCamera(...)MainStream.SetLoginPhase()
This is now enough to treat the .m2p path as validated for the current core
startup, UI bootstrap, and shared login-adjacent content pack set used by the
client runtime.
At this point the login-phase smoke test stops being a strong validator for additional packs such as world, NPC, monster, and late-load gameplay content. Those should be validated with map loads or in-game scenario coverage rather than startup-only checks.
Current non-fatal runtime issues on the VPS:
- missing
Tahomafont mapping in the client runtime - headless ALSA / audio decoder warnings
Those do not currently block .m2p loading or the login-phase smoke test.
Example runtime command:
M2PACK_MASTER_KEY_HEX="$(cat /home/mt2.jakubkadlec.dev/.secrets/m2pack-secure/2026-04-14/master.key)" \
M2PACK_KEY_ID=1 \
M2_TIMEOUT=20 \
WINEDEBUG=-all \
/home/mt2.jakubkadlec.dev/metin/repos/m2dev-client-src/scripts/run-wine-headless.sh \
/home/mt2.jakubkadlec.dev/metin/repos/m2dev-client-src/build-mingw64-lld/bin
Automated smoke runner for selected packs:
python3 scripts/runtime_smoke_wine.py \
--runtime-root /tmp/m2dev-client-runtime-http \
--client-repo /home/mt2.jakubkadlec.dev/metin/repos/m2dev-client-src \
--master-key /home/mt2.jakubkadlec.dev/.secrets/m2pack-secure/2026-04-14/master.key \
--key-id 1 \
--pack root \
--pack patch1 \
--pack patch2 \
--pack season3_eu \
--pack locale \
--pack uiscript \
--pack uiloading \
--pack ETC \
--json