"""Реальный smoke: uvicorn + мок OmniRoute, проверка живых HTTP-запросов.""" import json import os import signal import subprocess import sys import time import urllib.request sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from conftest import OmniMock REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) TMP = os.path.join(REPO, ".smoke") os.makedirs(TMP, exist_ok=True) mock = OmniMock() mock.set_completions(usage={"prompt_tokens": 9, "completion_tokens": 4, "total_tokens": 13}) env = dict(os.environ) env.update({ "DB_PATH": os.path.join(TMP, "arena.db"), "OMNIROUTE_URL": mock.url, "OMNIROUTE_API_KEY": "smoke", "ARENA_CACHE_TEXT": "/nonexistent/a.json", "ARENA_CACHE_AGENT": "/nonexistent/b.json", }) proc = subprocess.Popen( [os.path.join(REPO, ".venv/bin/uvicorn"), "main:app", "--host", "127.0.0.1", "--port", "18700"], cwd=os.path.join(REPO, "app"), env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, ) # pip install uvicorn into venv if missing handled outside try: base = "http://127.0.0.1:18700" for _ in range(50): try: urllib.request.urlopen(f"{base}/api/providers", timeout=1) break except Exception: time.sleep(0.2) # 1. UI отдаётся (статика через __file__-путь) ui = urllib.request.urlopen(f"{base}/", timeout=5).read().decode() assert "Arena Dashboard" in ui and "s-tokens-24h" in ui and "loadTokenStats" in ui, "UI не содержит token-элементов" # 2. Ручная проверка с usage chk = json.loads(urllib.request.urlopen(f"{base}/api/check/zai/test-model-a", timeout=10).read()) assert chk["input_tokens"] == 9 and chk["total_tokens"] == 13, chk # 3. Агрегат ts = json.loads(urllib.request.urlopen(f"{base}/api/token_stats", timeout=5).read()) assert ts["window_24h"]["known"] >= 1 and ts["window_24h"]["total_tokens"] >= 13, ts print("SMOKE_OK", json.dumps({ "check_usage": [chk["input_tokens"], chk["output_tokens"], chk["total_tokens"]], "token_stats_24h": ts["window_24h"], "providers": [(p["provider"], p["window_24h"]["total_tokens"]) for p in ts["providers"]], }, ensure_ascii=False)) finally: proc.send_signal(signal.SIGTERM) try: out, _ = proc.communicate(timeout=10) print("--- uvicorn log tail ---") print("\n".join(out.splitlines()[-8:])) except subprocess.TimeoutExpired: proc.kill() mock.close()