107 lines
3.8 KiB
Python
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")
|