mirror of
https://github.com/simonw/datasette.git
synced 2026-10-19 15:56:58 +02:00
75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
"""
|
|
A fast, fixed-seed subset of the connection torture harness
|
|
(tests/connection_torture.py). Each scenario runs in its own process, so a
|
|
segfault or a hang fails one test instead of killing the test run.
|
|
|
|
Several event loops (threads) drive one Datasette with extreme settings
|
|
(smallest pool, 1ms idle timeout, 10ms schema polling) through reads,
|
|
writes of every kind, DDL, isolated functions, analyze_sql, cancellation,
|
|
add/remove_database, external schema changes, files
|
|
replaced and deleted, Database.close() and Datasette.close() mid-flight,
|
|
and non-threaded mode. See the harness docstring for what is checked.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
HARNESS = os.path.join(os.path.dirname(__file__), "connection_torture.py")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"scenario,seed",
|
|
[
|
|
("mixed", 101),
|
|
("lifecycle", 102),
|
|
("close", 103),
|
|
("cancel", 104),
|
|
("pool", 105),
|
|
("nothreads", 106),
|
|
("writes", 107),
|
|
],
|
|
)
|
|
def test_connection_torture(scenario, seed):
|
|
try:
|
|
proc = subprocess.run(
|
|
[
|
|
sys.executable,
|
|
HARNESS,
|
|
scenario,
|
|
"--seed",
|
|
str(seed),
|
|
"--duration",
|
|
"1.5",
|
|
],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=150,
|
|
check=False,
|
|
)
|
|
except subprocess.TimeoutExpired as e: # pragma: no cover
|
|
pytest.fail(f"{scenario} hung:\n{(e.stderr or '')[-4000:]}")
|
|
if proc.returncode < 0: # pragma: no cover
|
|
pytest.fail(
|
|
f"{scenario} crashed with {signal.Signals(-proc.returncode).name}:\n"
|
|
f"{proc.stderr[-4000:]}"
|
|
)
|
|
lines = proc.stdout.strip().splitlines()
|
|
if not lines:
|
|
pytest.fail(
|
|
f"{scenario} exited {proc.returncode} without a summary:\n"
|
|
f"{proc.stderr[-4000:]}"
|
|
)
|
|
summary = json.loads(lines[-1])
|
|
problems = "\n".join(
|
|
f"[{p['kind']}] {p['message'][:600]}" for p in summary["problems"]
|
|
)
|
|
assert proc.returncode == 0, f"{scenario} seed {seed}:\n{problems}"
|
|
assert summary["ok"]
|
|
# It did something (the slow-query scenarios do a few dozen operations
|
|
# in 1.5s on a busy machine, the others hundreds)
|
|
assert sum(summary["counts"].values()) > 10
|