Files
Artemis-Eapil/tests/unit/test_batch_launchers.py
T

107 lines
3.8 KiB
Python

"""Exercise CMD parsing and Windows PowerShell 5.1 without installing anything."""
import json
import os
from pathlib import Path
import shutil
import subprocess
import pytest
ROOT = Path(__file__).resolve().parents[2]
pytestmark = pytest.mark.skipif(
not shutil.which("cmd.exe") or not shutil.which("powershell.exe"),
reason="Windows CMD and Windows PowerShell required",
)
def copy_launchers(root: Path, newline: bytes) -> None:
root.mkdir()
(root / "scripts").mkdir()
for name in ("start.bat", "start-cn.bat"):
content = (ROOT / name).read_bytes().replace(b"\r\n", b"\n")
# ASCII batch wrappers remain safe even if a zip/editor changes EOLs.
content.decode("ascii")
(root / name).write_bytes(content.replace(b"\n", newline))
@pytest.mark.parametrize("newline", [b"\r\n", b"\n"])
@pytest.mark.parametrize("exit_code", [0, 7])
def test_launch_forwards_options_and_exit_code_without_cmd_garbling(tmp_path, newline, exit_code):
root = tmp_path / "source with spaces"
copy_launchers(root, newline)
(root / "scripts" / "start.ps1").write_text(
"""param([string]$Mirror, [int]$Port, [switch]$NoOpen, [switch]$SkipUpdate, [switch]$SkipMcpSync)
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
Write-Host '镜像地址和下载超时可在 config\\downloads.json 中调整。'
Write-Host ('ARGS=' + (@{mirror=$Mirror;port=$Port;no_open=[bool]$NoOpen;skip_update=[bool]$SkipUpdate;skip_mcp=[bool]$SkipMcpSync;language=$env:ARTEMIS_LAUNCH_LANG} | ConvertTo-Json -Compress))
exit ([int]$env:LAUNCH_TEST_EXIT)
""",
encoding="utf-8-sig",
)
result = subprocess.run(
[
"cmd.exe",
"/d",
"/c",
"start-cn.bat",
"-Port",
"8123",
"-NoOpen",
"-SkipUpdate",
"-SkipMcpSync",
],
cwd=root,
env={**os.environ, "ARTEMIS_NO_PAUSE": "1", "LAUNCH_TEST_EXIT": str(exit_code)},
capture_output=True,
encoding="utf-8",
timeout=15,
)
assert result.returncode == exit_code, result.stdout + result.stderr
assert result.stderr == ""
assert "镜像地址和下载超时可在" in result.stdout
args = json.loads(
next(
line.removeprefix("ARGS=")
for line in result.stdout.splitlines()
if line.startswith("ARGS=")
)
)
assert args == {
"mirror": "China",
"port": 8123,
"no_open": True,
"skip_update": True,
"skip_mcp": True,
"language": "zh-CN",
}
@pytest.mark.parametrize("newline", [b"\r\n", b"\n"])
@pytest.mark.parametrize("help_flag", ["-Help", "--help"])
def test_actual_chinese_help_has_no_encoding_error_or_bootstrap(tmp_path, newline, help_flag):
root = tmp_path / "source with spaces"
copy_launchers(root, newline)
shutil.copyfile(ROOT / "scripts" / "start.ps1", root / "scripts" / "start.ps1")
assert (root / "scripts" / "start.ps1").read_bytes().startswith(b"\xef\xbb\xbf")
result = subprocess.run(
["cmd.exe", "/d", "/c", "start-cn.bat", help_flag],
cwd=root,
capture_output=True,
encoding="utf-8",
timeout=15,
)
assert result.returncode == 0, result.stdout + result.stderr
assert result.stderr == ""
assert "用法:start-cn.bat [选项]" in result.stdout
assert "仅启动网页,跳过 Codex MCP" in result.stdout
assert "国内镜像设置:config\\downloads.json" in result.stdout
assert "�" not in result.stdout
assert not (root / ".venv").exists()
def test_batch_files_are_ascii_and_powershell_text_has_bom():
for name in ("start.bat", "start-cn.bat"):
(ROOT / name).read_bytes().decode("ascii")
assert (ROOT / "scripts" / "start.ps1").read_bytes().startswith(b"\xef\xbb\xbf")