Files
the-nexus/tests/test_ws_load_test.py

122 lines
4.0 KiB
Python

"""Tests for WebSocket load testing infrastructure (issue #1505)."""
from __future__ import annotations
import importlib.util
import json
import sys
from pathlib import Path
from unittest.mock import patch
PROJECT_ROOT = Path(__file__).parent.parent
_spec = importlib.util.spec_from_file_location(
"ws_load_test_test",
PROJECT_ROOT / "bin" / "ws_load_test.py",
)
_mod = importlib.util.module_from_spec(_spec)
sys.modules["ws_load_test_test"] = _mod
_spec.loader.exec_module(_mod)
main = _mod.main
measure_memory = _mod.measure_memory
run_load_test = _mod.run_load_test
write_report = _mod.write_report
class TestMemoryStats:
@patch("ws_load_test_test.tracemalloc.get_traced_memory", return_value=(1024, 4096))
@patch("ws_load_test_test.resource.getrusage")
def test_measure_memory_reports_tracemalloc_and_rss_bytes(self, mock_getrusage, _mock_tracemalloc):
mock_getrusage.return_value = type("Usage", (), {"ru_maxrss": 512})()
with patch.object(_mod.sys, "platform", "linux"):
stats = measure_memory()
assert stats["tracemalloc_current_bytes"] == 1024
assert stats["tracemalloc_peak_bytes"] == 4096
assert stats["rss_bytes"] == 512 * 1024
class TestRunLoadTest:
def test_run_load_test_reports_concurrency_and_messages(self):
events = []
class FakeConnection:
def __init__(self, url):
self.url = url
async def __aenter__(self):
events.append(("enter", self.url))
return self
async def __aexit__(self, exc_type, exc, tb):
events.append(("exit", self.url))
async def send(self, payload):
events.append(("send", payload))
async def exercise():
return await run_load_test(
url="ws://nexus.local:8765",
concurrency=3,
rounds=2,
hold_seconds=0,
payload={"type": "probe"},
connector=lambda url: FakeConnection(url),
)
report = _mod.asyncio.run(exercise())
assert report["url"] == "ws://nexus.local:8765"
assert report["concurrency"] == 3
assert report["rounds"] == 2
assert report["attempted_connections"] == 6
assert report["successful_connections"] == 6
assert report["failed_connections"] == 0
assert report["messages_sent"] == 6
assert report["success_rate"] == 1.0
assert "memory_before" in report
assert "memory_after" in report
assert len([e for e in events if e[0] == "send"]) == 6
class TestReportOutput:
def test_write_report_serializes_json(self, tmp_path):
out = tmp_path / "ws-load-report.json"
payload = {"successful_connections": 4, "failed_connections": 0}
write_report(out, payload)
assert json.loads(out.read_text()) == payload
def test_main_writes_output_file(self, tmp_path):
out = tmp_path / "report.json"
fake_report = {
"url": "ws://127.0.0.1:8765",
"concurrency": 4,
"rounds": 2,
"attempted_connections": 8,
"successful_connections": 8,
"failed_connections": 0,
"messages_sent": 0,
"success_rate": 1.0,
"memory_before": {"rss_bytes": 1, "tracemalloc_current_bytes": 2, "tracemalloc_peak_bytes": 3},
"memory_after": {"rss_bytes": 4, "tracemalloc_current_bytes": 5, "tracemalloc_peak_bytes": 6},
}
async def fake_run_load_test(**_kwargs):
return fake_report
with patch.object(_mod, "run_load_test", fake_run_load_test):
rc = main([
"--url",
"ws://127.0.0.1:8765",
"--concurrency",
"4",
"--rounds",
"2",
"--output",
str(out),
])
assert rc == 0
assert json.loads(out.read_text()) == fake_report