test: нагрузочные/стресс-тесты (маркер load): массовый pipeline, apply_ops, конкуренция, HTTP-стресс
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"""Нагрузочный тест: массовый прогон run_pipeline (сотни контрактов × допников).
|
||||
|
||||
Создаёт N контрактов × M допников, прогоняет полный конвейер сверки с Fake LLM
|
||||
(без сети), реально нагружает SQLite: apply_ops + clear_current + reset.
|
||||
|
||||
Проверка: full_replace НЕ дублирует строки в масштабе (у каждого контракта ровно
|
||||
SERVICES строк, а не SERVICES × M_SUPPS).
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from db import contracts, documents, supplements, spec_current
|
||||
from db.connection import query
|
||||
from services import process
|
||||
|
||||
pytestmark = pytest.mark.load
|
||||
|
||||
N_CONTRACTS = int(os.getenv("LOAD_CONTRACTS", "100"))
|
||||
M_SUPPS = int(os.getenv("LOAD_SUPPS", "20"))
|
||||
SERVICES = int(os.getenv("LOAD_SERVICES", "10"))
|
||||
|
||||
|
||||
def _seed():
|
||||
cids = []
|
||||
for ci in range(N_CONTRACTS):
|
||||
c = contracts.insert(f"03700_{ci}")
|
||||
for mi in range(M_SUPPS):
|
||||
d = documents.insert(f"d{ci}_{mi}.docx", "application/octet-stream", "raw", batch_id=f"b{ci}")
|
||||
documents.set_parsed(d["id"], [{"type": "paragraph", "text": f"услуга {mi}"}])
|
||||
supplements.insert(c["id"], d["id"], "initial" if mi == 0 else "additional")
|
||||
cids.append(c["id"])
|
||||
return cids
|
||||
|
||||
|
||||
def _fake_llm():
|
||||
def fake_call(current_spec, doc_text, build_prompt_fn, llm_client=None):
|
||||
ops = [
|
||||
{"action": "ADD", "new_row": {"name": f"услуга {i}", "price": 100 + i, "qty": 1, "sum": 100 + i}}
|
||||
for i in range(SERVICES)
|
||||
]
|
||||
return ({"mode": "full_replace", "ops": ops}, "pid")
|
||||
return fake_call
|
||||
|
||||
|
||||
def test_mass_pipeline(db, monkeypatch):
|
||||
cids = _seed()
|
||||
monkeypatch.setattr("services.llm.call_llm", _fake_llm())
|
||||
|
||||
t0 = time.time()
|
||||
for cid in cids:
|
||||
list(process.run_pipeline(cid, "", lambda cur, txt: ("p", "pid")))
|
||||
elapsed = time.time() - t0
|
||||
|
||||
# Целостность: у каждого контракта ровно SERVICES строк (full_replace без дублей)
|
||||
bad = 0
|
||||
for cid in cids:
|
||||
if len(spec_current.list_by_contract(cid)) != SERVICES:
|
||||
bad += 1
|
||||
assert bad == 0, f"{bad} контрактов с неверным числом строк"
|
||||
|
||||
total_events = query("SELECT count(*) AS c FROM spec_events", ())
|
||||
print(
|
||||
f"\n[load] контрактов={N_CONTRACTS} допников={M_SUPPS} услуг={SERVICES} "
|
||||
f"событий={total_events[0]['c']} время={elapsed:.1f}с"
|
||||
)
|
||||
Reference in New Issue
Block a user