feat: troppa roba davvero

This commit is contained in:
gabdevele
2026-05-07 09:21:45 +02:00 Unverified
parent d977a953cc
commit 53dcdafdb1
73 changed files with 4772 additions and 960 deletions
+39 -5
View File
@@ -1,8 +1,9 @@
import asyncio
from models.proxy import ProxyDocument
from models.service import ServiceEndpointDocument
from services.mitmproxy.health import check_proxy
from app.models.health import HealthSnapshot
from app.models.proxy import ProxyDocument
from app.models.service import ServiceEndpointDocument
from app.services.mitmproxy.health import check_proxy
def test_check_proxy_reports_upstream_and_proxy_healthy():
@@ -26,11 +27,44 @@ def test_check_proxy_reports_upstream_and_proxy_healthy():
await upstream.wait_closed()
await proxy.wait_closed()
assert health["overall"] == "healthy"
assert [check["target"] for check in health["checks"]] == [
assert isinstance(health, HealthSnapshot)
assert health.overall == "healthy"
assert [check.target for check in health.checks] == [
"upstream",
"proxy",
]
assert all(check.duration_ms is None for check in health.checks)
asyncio.run(run())
def test_check_proxy_reports_benchmark_latency_when_enabled():
async def run():
upstream = await asyncio.start_server(http_handler, "127.0.0.1", 0)
proxy = await asyncio.start_server(http_handler, "127.0.0.1", 0)
try:
upstream_port = upstream.sockets[0].getsockname()[1]
proxy_port = proxy.sockets[0].getsockname()[1]
document = ProxyDocument(
proxy_port=proxy_port,
name="health",
code="",
healthcheck={"benchmark_enabled": True},
service=ServiceEndpointDocument(port=upstream_port),
)
health = await check_proxy(document)
finally:
upstream.close()
proxy.close()
await upstream.wait_closed()
await proxy.wait_closed()
assert isinstance(health, HealthSnapshot)
assert all(
check.duration_ms is not None and check.duration_ms >= 0
for check in health.checks
)
asyncio.run(run())
@@ -0,0 +1,218 @@
import asyncio
from datetime import UTC, datetime
import pytest
from app.models.health import HealthSnapshot
from app.models.proxy import ProxyDocument
from app.models.service import ServiceEndpointDocument
from app.services.mitmproxy.health_monitor import HealthMonitor
def make_proxy(**updates):
data = {
"proxy_port": 8080,
"name": "svc",
"code": "",
"status": "running",
"service": ServiceEndpointDocument(port=9000),
}
data.update(updates)
return ProxyDocument(**data)
def make_snapshot(proxy_port: int, *, overall: str = "healthy") -> HealthSnapshot:
return HealthSnapshot(
proxy_port=proxy_port,
timestamp=datetime.now(UTC),
enabled=True,
overall=overall,
checks=[],
)
def test_run_cycle_records_and_publishes_running_healthchecks(monkeypatch):
monitor = HealthMonitor()
proxy = make_proxy()
captured: dict[str, object] = {}
snapshot = make_snapshot(8080)
async def fake_list_proxies():
return [proxy]
async def fake_check_proxy(document):
captured["checked"] = document.proxy_port
return snapshot
async def fake_record_health_sample(document):
captured["recorded"] = document
return document
async def fake_publish(proxy_port, document):
captured["published"] = (proxy_port, document)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.list_proxies",
fake_list_proxies,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.check_proxy",
fake_check_proxy,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.record_health_sample",
fake_record_health_sample,
)
monkeypatch.setattr(monitor, "publish", fake_publish)
asyncio.run(monitor.run_cycle())
assert captured["checked"] == 8080
assert captured["recorded"] == snapshot
assert captured["published"] == (8080, snapshot)
def test_run_cycle_skips_stopped_or_disabled_proxies(monkeypatch):
monitor = HealthMonitor()
running_disabled = make_proxy(healthcheck={"enabled": False})
stopped = make_proxy(proxy_port=8081, status="stopped")
called = False
async def fake_list_proxies():
return [running_disabled, stopped]
async def fake_check_proxy(_document):
nonlocal called
called = True
return make_snapshot(8080)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.list_proxies",
fake_list_proxies,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.check_proxy",
fake_check_proxy,
)
asyncio.run(monitor.run_cycle())
assert called is False
def test_run_cycle_checks_proxies_in_parallel(monkeypatch):
monitor = HealthMonitor()
proxies = [
make_proxy(proxy_port=8080),
make_proxy(proxy_port=8081),
make_proxy(proxy_port=8082),
]
started: list[int] = []
release = asyncio.Event()
async def fake_list_proxies():
return proxies
async def fake_check_proxy(document):
started.append(document.proxy_port)
if len(started) == len(proxies):
release.set()
await release.wait()
return make_snapshot(document.proxy_port)
async def fake_record_health_sample(document):
return document
async def fake_publish(_proxy_port, _document):
return None
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.list_proxies",
fake_list_proxies,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.check_proxy",
fake_check_proxy,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.record_health_sample",
fake_record_health_sample,
)
monkeypatch.setattr(monitor, "publish", fake_publish)
asyncio.run(asyncio.wait_for(monitor.run_cycle(), timeout=1))
assert started == [8080, 8081, 8082]
def test_run_cycle_continues_when_one_proxy_check_fails(monkeypatch):
monitor = HealthMonitor()
proxies = [
make_proxy(proxy_port=8080),
make_proxy(proxy_port=8081),
]
captured: list[int] = []
async def fake_list_proxies():
return proxies
async def fake_check_proxy(document):
if document.proxy_port == 8080:
raise RuntimeError("boom")
return make_snapshot(document.proxy_port)
async def fake_record_health_sample(document):
captured.append(document.proxy_port)
return document
async def fake_publish(proxy_port, _document):
captured.append(proxy_port + 10_000)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.list_proxies",
fake_list_proxies,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.check_proxy",
fake_check_proxy,
)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.record_health_sample",
fake_record_health_sample,
)
monkeypatch.setattr(monitor, "publish", fake_publish)
asyncio.run(monitor.run_cycle())
assert captured == [8081, 18081]
def test_run_retries_after_cycle_failure(monkeypatch):
monitor = HealthMonitor()
calls = {"run_cycle": 0}
sleep_calls: list[float] = []
async def fake_run_cycle():
calls["run_cycle"] += 1
if calls["run_cycle"] == 1:
raise RuntimeError("temporary failure")
raise asyncio.CancelledError
async def fake_sleep(seconds):
sleep_calls.append(seconds)
return None
monkeypatch.setattr(monitor, "run_cycle", fake_run_cycle)
monkeypatch.setattr(
"app.services.mitmproxy.health_monitor.asyncio.sleep",
fake_sleep,
)
try:
asyncio.run(monitor.run())
except asyncio.CancelledError:
pass
assert calls["run_cycle"] == 2
assert len(sleep_calls) == 1
assert sleep_calls[0] == pytest.approx(1.0, abs=0.01)
@@ -1,9 +1,11 @@
import asyncio
from pathlib import Path
from models.proxy import ProxyDocument
from models.service import ServiceEndpointDocument
from services.mitmproxy.manager import MitmdumpManager
import pytest
from app.models.proxy import ProxyDocument
from app.models.service import ServiceEndpointDocument
from app.services.mitmproxy.manager import MitmdumpError, MitmdumpManager
def make_proxy(**updates):
@@ -65,6 +67,20 @@ def test_regular_mode_uses_proxy_port_as_listen_port():
assert command[-2:] == ["--listen-port", "8080"]
def test_start_rejects_reserved_backend_port():
manager = MitmdumpManager()
proxy = make_proxy(proxy_port=3671)
async def run():
await manager.start(proxy)
with pytest.raises(
MitmdumpError,
match="Proxy port 3671 is reserved for the backend API",
):
asyncio.run(run())
def test_running_document_without_pid_is_treated_as_stopped():
manager = MitmdumpManager()
proxy = make_proxy(status="running", pid=None)
@@ -167,3 +183,99 @@ def test_reconcile_restores_upstream_when_process_is_gone():
"service.upstream_port": None,
"last_error": None,
}
def test_cleanup_runtime_artifacts_removes_generated_files(tmp_path: Path):
manager = MitmdumpManager(work_dir=str(tmp_path / "theplug"))
proxy = make_proxy(
script_path=str(manager.script_path_for(make_proxy())),
config_path=str(manager.config_path_for(make_proxy())),
log_path=str(manager.log_path_for(make_proxy())),
)
script_path = Path(proxy.script_path)
config_path = Path(proxy.config_path)
log_path = Path(proxy.log_path)
script_path.parent.mkdir(parents=True, exist_ok=True)
config_path.parent.mkdir(parents=True, exist_ok=True)
log_path.parent.mkdir(parents=True, exist_ok=True)
script_path.write_text("print('hello')", encoding="utf-8")
config_path.write_text("block_global: false\n", encoding="utf-8")
log_path.write_text("old log\n", encoding="utf-8")
manager.cleanup_runtime_artifacts(proxy)
assert script_path.exists() is False
assert log_path.exists() is False
assert config_path.exists() is False
assert manager.conf_dir_for(proxy).exists() is False
def test_prepare_upstream_retries_until_port_remap_succeeds(monkeypatch):
manager = MitmdumpManager()
proxy = make_proxy(
mode="reverse",
service=ServiceEndpointDocument(
port=9000,
name="echo",
folder="/tmp/playground",
),
)
attempted_ports: list[int] = []
candidate_ports = iter([54001, 54002, 54003])
async def fake_change_port(
_service_name,
_folder,
_port_from,
port_to,
**_kwargs,
):
attempted_ports.append(port_to)
return port_to == 54003
monkeypatch.setattr(
"app.services.mitmproxy.manager.get_random_port",
lambda: next(candidate_ports),
)
monkeypatch.setattr(
"app.services.mitmproxy.manager.change_port",
fake_change_port,
)
upstream_port = asyncio.run(manager.prepare_upstream(proxy))
assert upstream_port == 54003
assert attempted_ports == [54001, 54002, 54003]
def test_prepare_upstream_fails_after_retry_budget(monkeypatch):
manager = MitmdumpManager()
manager.upstream_port_attempts = 3
proxy = make_proxy(
mode="reverse",
service=ServiceEndpointDocument(
port=9000,
name="echo",
folder="/tmp/playground",
),
)
candidate_ports = iter([54001, 54002, 54003])
async def fake_change_port(*_args, **_kwargs):
return False
monkeypatch.setattr(
"app.services.mitmproxy.manager.get_random_port",
lambda: next(candidate_ports),
)
monkeypatch.setattr(
"app.services.mitmproxy.manager.change_port",
fake_change_port,
)
with pytest.raises(
MitmdumpError,
match="Unable to move Docker service port after retries",
):
asyncio.run(manager.prepare_upstream(proxy))
@@ -1,5 +1,6 @@
import pytest
from services.mitmproxy.options import (
from app.services.mitmproxy.options import (
MitmOption,
parse_options,
public_options,
+1 -1
View File
@@ -1,4 +1,4 @@
from services.editor import python_lsp
from app.services.editor import python_lsp
def test_encode_message():
+3 -3
View File
@@ -1,8 +1,8 @@
import asyncio
from models.proxy import ProxyDocument
from models.service import ServiceEndpointDocument
from services.mitmproxy import recovery as recovery_module
from app.models.proxy import ProxyDocument
from app.models.service import ServiceEndpointDocument
from app.services.mitmproxy import recovery as recovery_module
def make_proxy(**updates):
+13
View File
@@ -0,0 +1,13 @@
from app.services.mitmproxy.templates import BUILTIN_TEMPLATES
def test_builtin_templates_use_four_space_indentation():
for template in BUILTIN_TEMPLATES:
for line in template.code.splitlines():
assert "\t" not in line, f"{template.id} contains a tab: {line!r}"
if not line.strip():
continue
indent = len(line) - len(line.lstrip(" "))
assert indent % 4 == 0, (
f"{template.id} has non-4-space indentation: {line!r}"
)