# tests/test_synthesizer.py import json import pytest from pathlib import Path from voice_gen.synthesizer import synthesize, _build_cmd from voice_gen.errors import MmxError def test_build_cmd_minimum(): cmd = _build_cmd( text_file=Path("input.txt"), voice_id=123, out_path=Path("out.mp3"), format="mp3", ) assert cmd[:5] == ["mmx", "speech", "synthesize", "--non-interactive", "--quiet"] assert "--text-file" in cmd and "input.txt" in cmd assert "--text" not in cmd assert "--voice" in cmd and "123" in cmd assert "--out" in cmd and "out.mp3" in cmd assert "--format" in cmd and "mp3" in cmd def test_synthesize_invokes_mmx_and_returns_path(tmp_path): captured = {} def fake_run(cmd, **kwargs): captured["cmd"] = cmd captured["kwargs"] = kwargs out = Path(cmd[cmd.index("--out") + 1]) out.parent.mkdir(parents=True, exist_ok=True) out.write_bytes(b"fake-audio") return type("R", (), {"returncode": 0, "stderr": ""})() out = synthesize( text="hello", voice_id=999, out_path=tmp_path / "x.mp3", format="mp3", run=fake_run, ) assert out == tmp_path / "x.mp3" assert out.exists() assert captured["cmd"][2] == "synthesize" assert "--voice" in captured["cmd"] assert captured["cmd"][captured["cmd"].index("--voice") + 1] == "999" def test_synthesize_passes_long_utf8_text_via_temporary_file(tmp_path): text = ("这是一段用于验证 Windows 长命令行安全性的中文口播稿。\n" * 500)[:9000] captured = {} def fake_run(cmd, **kwargs): captured["cmd"] = cmd assert "--text" not in cmd text_path = Path(cmd[cmd.index("--text-file") + 1]) captured["text_path"] = text_path captured["text"] = text_path.read_text(encoding="utf-8") out = Path(cmd[cmd.index("--out") + 1]) out.write_bytes(b"fake-audio") return type("R", (), {"returncode": 0, "stderr": ""})() out = synthesize( text=text, voice_id="test-voice", out_path=tmp_path / "long.mp3", run=fake_run, ) assert out.exists() assert captured["text"] == text assert not captured["text_path"].exists() def test_synthesize_raises_mmxerror_on_nonzero(tmp_path): def fake_run(cmd, **kwargs): return type("R", (), {"returncode": 3, "stderr": "auth failed"})() with pytest.raises(MmxError) as exc: synthesize( text="x", voice_id=1, out_path=tmp_path / "x.mp3", format="mp3", run=fake_run, ) assert exc.value.exit_code == 3 assert "auth failed" in str(exc.value)