Локальный FastAPI-сервис поверх GigaAM v3 и sherpa-onnx: приём аудио, очередь задач, разделение по говорящим, постобработка терминов. Доставка на Windows - ZIP со встроенным Python, без установки чего-либо. Обновление кода при запуске тянется из релизов Gitea: меняется только папка app, десятки килобайт вместо всего пакета. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
78 lines
3.4 KiB
Python
78 lines
3.4 KiB
Python
"""Тесты сборки Windows-пакета.
|
||
|
||
Регрессия на реальный баг: .bat, записанный с переводами строк LF, cmd.exe
|
||
читает криво и теряет первый символ строки - `set TALKSCORE_ASR_HOME`
|
||
превращался в `ALKSCORE_ASR_HOME is not recognized`.
|
||
"""
|
||
import importlib.util
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def build_mod():
|
||
spec = importlib.util.spec_from_file_location(
|
||
"make_windows_zip", ROOT / "build" / "make_windows_zip.py")
|
||
mod = importlib.util.module_from_spec(spec)
|
||
sys.modules["make_windows_zip"] = mod
|
||
spec.loader.exec_module(mod)
|
||
return mod
|
||
|
||
|
||
class TestBatFiles:
|
||
def test_written_with_crlf(self, build_mod, tmp_path):
|
||
target = tmp_path / "t.bat"
|
||
build_mod.write_bat(target, "@echo off\nset \"X=1\"\n")
|
||
raw = target.read_bytes()
|
||
assert b"\r\n" in raw
|
||
assert b"\n" not in raw.replace(b"\r\n", b"")
|
||
|
||
def test_bat_templates_are_ascii_only(self, build_mod):
|
||
"""Кириллица в .bat ломается: кодировка консоли заранее неизвестна."""
|
||
for name, text in (("start", build_mod.START_BAT),
|
||
("download", build_mod.DOWNLOAD_BAT)):
|
||
text.encode("ascii") # бросит UnicodeEncodeError, если появится кириллица
|
||
|
||
def test_start_bat_sets_home_variable(self, build_mod):
|
||
assert 'set "TALKSCORE_ASR_HOME=%~dp0"' in build_mod.START_BAT
|
||
|
||
def test_bat_switches_console_to_utf8(self, build_mod):
|
||
"""Python печатает в UTF-8, консоль должна быть переведена в неё же."""
|
||
for text in (build_mod.START_BAT, build_mod.DOWNLOAD_BAT):
|
||
assert "chcp 65001" in text
|
||
|
||
def test_quoted_paths_survive_spaces(self, build_mod):
|
||
"""Путь установки может содержать пробелы."""
|
||
for text in (build_mod.START_BAT, build_mod.DOWNLOAD_BAT):
|
||
assert '"%~dp0python\\python.exe"' in text
|
||
|
||
def test_written_file_has_no_bom(self, build_mod, tmp_path):
|
||
target = tmp_path / "t.bat"
|
||
build_mod.write_bat(target, "@echo off\n")
|
||
assert not target.read_bytes().startswith(b"\xef\xbb\xbf")
|
||
|
||
|
||
class TestDownloadScript:
|
||
def test_uses_requests_not_urllib(self):
|
||
"""У встраиваемого Python нет сертификатов, urllib падает на HTTPS."""
|
||
src = (ROOT / "build" / "download_models.py").read_text(encoding="utf-8")
|
||
assert "import requests" in src
|
||
assert "urllib.request.urlopen" not in src
|
||
|
||
def test_downloads_to_temp_then_renames(self):
|
||
"""Прерванная закачка не должна оставлять битый файл как готовый."""
|
||
src = (ROOT / "build" / "download_models.py").read_text(encoding="utf-8")
|
||
assert ".part" in src and "replace(dst)" in src
|
||
|
||
|
||
class TestUpdateInStartup:
|
||
def test_start_bat_runs_updater_before_service(self, build_mod):
|
||
"""Обновление должно применяться до запуска, иначе смысла в нём нет."""
|
||
text = build_mod.START_BAT
|
||
assert "-m app.updater" in text
|
||
assert text.index("-m app.updater") < text.index("-m app.main")
|