Files
fquiz/api/tests/test_atp_engine_task.py
T

111 lines
4.3 KiB
Python
Raw Normal View History

from __future__ import annotations
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session, sessionmaker
from app.core import database as core_database
from app.core.config import get_settings
from app.core.database import Base
from app.models.atp_model import AtpModel, AtpModelVersion, AtpSimulationRun
from app.schemas.atp_model import AtpSimulationRunRequest
from app.services import atp_model_service
def _build_sessionmaker():
engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(
bind=engine,
tables=[
AtpModel.__table__,
AtpModelVersion.__table__,
AtpSimulationRun.__table__,
],
)
return sessionmaker(bind=engine, autocommit=False, autoflush=False, expire_on_commit=False)
def test_run_model_version_dry_run_records_worker_command(monkeypatch, tmp_path) -> None:
testing_session = _build_sessionmaker()
monkeypatch.setattr(core_database, "SessionLocal", testing_session)
monkeypatch.setattr(atp_model_service, "_publish_change", lambda *args, **kwargs: None)
monkeypatch.setattr(atp_model_service, "_resolve_storage_root", lambda: tmp_path / "storage")
monkeypatch.setattr(atp_model_service, "_resolve_engine_workdir", lambda: tmp_path / "runs")
monkeypatch.setattr(
atp_model_service,
"_resolve_wine_engine_executable",
lambda: ("/usr/bin/wine", "/tmp/tpbig.exe", None),
)
session: Session = testing_session()
try:
model = AtpModel(
code="ATP-DRY-001",
name="Dry Run ATP",
source_type="atp",
status="enabled",
latest_version_no=1,
active_version_no=1,
)
session.add(model)
session.flush()
version = AtpModelVersion(
model_id=model.id,
version_no=1,
status="released",
entry_file="case.atp",
atp_text="BEGIN ATP CASE",
content_hash="dry-hash-v1",
)
session.add(version)
session.commit()
result = atp_model_service.run_model_version(
session,
model_id=model.id,
payload=AtpSimulationRunRequest(version_id=version.id, dry_run=True),
actor_user_id="tester",
)
assert result.status == "success"
assert result.engine_command is not None
assert result.engine_command.startswith("/usr/bin/wine /tmp/tpbig.exe ")
assert result.engine_command.endswith("/case.atp")
assert result.working_dir is not None
assert result.stdout_text is not None
saved = session.execute(select(AtpSimulationRun).where(AtpSimulationRun.id == result.id)).scalar_one()
assert saved.status == "success"
assert saved.exit_code == 0
assert saved.error_message is None
assert "dry_run" in (saved.stdout_text or "")
finally:
session.close()
def test_get_engine_status_includes_legacy_asset_checks(monkeypatch, tmp_path) -> None:
allowed_root = tmp_path / "wine-root"
template_root = allowed_root / "ATP" / "templates"
template_root.mkdir(parents=True)
(template_root / "EGM").mkdir()
(allowed_root / "ATP").mkdir(exist_ok=True)
(allowed_root / "ATP" / "tpbig.exe").write_text("binary", encoding="utf-8")
(allowed_root / "ATP" / "rjtzl.exe").write_text("binary", encoding="utf-8")
settings = get_settings()
monkeypatch.setattr(settings, "wine_allowed_root", str(allowed_root))
monkeypatch.setattr(settings, "atp_legacy_root", str(allowed_root / "ATP"))
monkeypatch.setattr(settings, "atp_template_root", str(template_root))
monkeypatch.setattr(settings, "atp_run_root", str(allowed_root / "runs"))
monkeypatch.setattr(settings, "atp_tpbig_executable", "ATP/tpbig.exe")
monkeypatch.setattr(settings, "atp_rjtzl_executable", "ATP/rjtzl.exe")
monkeypatch.setattr(atp_model_service, "_resolve_wine_engine_executable", lambda: ("/usr/bin/wine", "/tmp/tpbig.exe", None))
result = atp_model_service.get_engine_status()
assert "legacy_root" in result.checks
assert result.checks["legacy_root"]["available"] is True
assert result.checks["tpbig_executable"]["available"] is True
assert result.checks["rjtzl_executable"]["available"] is True
assert result.checks["egm_subdir"]["available"] is True