Party Hardy

This commit is contained in:
2026-10-17 07:33:08 +02:00
parent d84e4cf3d3
commit 7274cc1840
51 changed files with 2738 additions and 2100 deletions
+4 -3
View File
@@ -156,18 +156,19 @@ def test_rate_limit_block_recorded(monkeypatch):
# limiter re-enabled for itself - the same approach as test_ratelimit.py - and
# asserts the block emits the security.rate_limit.block audit row.
import devplacepy.main as m
import devplacepy.middleware.state as st
from starlette.testclient import TestClient
monkeypatch.setattr(m, "RATE_LIMIT_DISABLED", False)
monkeypatch.setattr(st, "RATE_LIMIT_DISABLED", False)
monkeypatch.setattr(
m,
st,
"get_int_setting",
lambda key, default: {
"rate_limit_per_minute": 1,
"rate_limit_window_seconds": 60,
}.get(key, default),
)
m._rate_limit_store.clear()
st._rate_limit_store.clear()
ip = "203.0.113.77"
client = TestClient(m.app)
codes = [
+4 -3
View File
@@ -1,6 +1,7 @@
# retoor <retoor@molodetz.nl>
import devplacepy.main as m
import devplacepy.middleware.state as st
from starlette.testclient import TestClient
def _patch_limits(monkeypatch, limit, window=60):
def fake_get_int_setting(key, default):
@@ -9,10 +10,10 @@ def _patch_limits(monkeypatch, limit, window=60):
"rate_limit_window_seconds": window,
}.get(key, default)
monkeypatch.setattr(m, "get_int_setting", fake_get_int_setting)
monkeypatch.setattr(st, "get_int_setting", fake_get_int_setting)
# conftest disables the limiter suite-wide; re-enable it for these tests only.
monkeypatch.setattr(m, "RATE_LIMIT_DISABLED", False)
m._rate_limit_store.clear()
monkeypatch.setattr(st, "RATE_LIMIT_DISABLED", False)
st._rate_limit_store.clear()
import requests
from tests.conftest import BASE_URL
def _seed_news_seo():
+6 -5
View File
@@ -3,6 +3,7 @@
import re
import devplacepy.main as m
import devplacepy.middleware.state as st
from starlette.testclient import TestClient
def _patch_limits(monkeypatch, limit, window=60):
def fake_get_int_setting(key, default):
@@ -11,14 +12,14 @@ def _patch_limits(monkeypatch, limit, window=60):
"rate_limit_window_seconds": window,
}.get(key, default)
monkeypatch.setattr(m, "get_int_setting", fake_get_int_setting)
monkeypatch.setattr(st, "get_int_setting", fake_get_int_setting)
# conftest disables the limiter suite-wide; re-enable it for these tests only.
monkeypatch.setattr(m, "RATE_LIMIT_DISABLED", False)
m._rate_limit_store.clear()
monkeypatch.setattr(st, "RATE_LIMIT_DISABLED", False)
st._rate_limit_store.clear()
# _hot_settings caches the limit for HOT_SETTINGS_TTL; force a re-read of the
# patched get_int_setting so a stale value from a prior test cannot leak in.
m._hot_settings_value = None
m._hot_settings_at = 0.0
st._hot_settings_value = None
st._hot_settings_at = 0.0
def test_rate_limit_blocks_excess(monkeypatch):
+2 -2
View File
@@ -27,13 +27,13 @@ def references(path):
return any(needle in body for needle in NEEDLES)
def test_only_main_imports_the_acceptance_package():
def test_only_lifespan_imports_the_acceptance_package():
importers = [
path.relative_to(PACKAGE_ROOT).as_posix()
for path in source_files({".py"})
if references(path)
]
assert importers == ["main.py"]
assert importers == ["lifespan.py"]
def test_no_template_or_static_asset_mentions_the_package():
+54
View File
@@ -0,0 +1,54 @@
# retoor <retoor@molodetz.nl>
import queue
import threading
from tests.conftest import run_async
from devplacepy.services.background import BackgroundQueue
def _fill(direct_queue, count, executed):
for _ in range(count):
direct_queue.put_nowait((executed.append, ("x",), {}))
def test_stop_without_start_returns_cleanly():
direct = BackgroundQueue()
run_async(direct.stop())
assert direct.stats()["running"] is False
def test_stop_full_queue_does_not_block():
direct = BackgroundQueue(maxsize=4)
dead = threading.Thread(target=lambda: None)
dead.start()
dead.join()
direct._thread = dead
executed = []
_fill(direct._queue, 4, executed)
run_async(direct.stop())
assert executed == ["x"] * 4
def test_stop_bounds_shutdown_drain_and_counts_dropped():
from devplacepy.services.background import SHUTDOWN_DRAIN_MAX
direct = BackgroundQueue(maxsize=5000)
executed = []
_fill(direct._queue, SHUTDOWN_DRAIN_MAX + 200, executed)
run_async(direct.stop())
stats = direct.stats()
assert len(executed) == SHUTDOWN_DRAIN_MAX
assert stats["dropped"] == 200
def test_start_stop_roundtrip_executes_submitted_task():
direct = BackgroundQueue()
run_async(direct.start())
try:
executed = []
direct.submit(executed.append, "x")
finally:
run_async(direct.stop())
assert executed == ["x"]
assert direct.stats()["running"] is False
+36
View File
@@ -793,3 +793,39 @@ def test_tunnel_target_is_empty_without_a_route_to_the_port():
instance = {"ports_json": "[]", "container_gateway": "172.17.0.1"}
assert api.tunnel_target(instance, 3000) == (None, None)
assert api.tunnel_target({"container_ip": "172.17.0.9"}, 0) == (None, None)
def test_allocate_host_port_returns_lowest_free(monkeypatch):
monkeypatch.setattr(api, "_host_port_free", lambda port: True)
assert api.allocate_host_port(set()) == api.HOST_PORT_MIN
assert api.allocate_host_port({20001, 20002}) == 20003
def test_allocate_host_port_skips_bound_ports(monkeypatch):
monkeypatch.setattr(api, "_host_port_free", lambda port: port != 20001)
assert api.allocate_host_port(set()) == 20002
def test_allocate_host_port_probe_budget_exhausted(monkeypatch):
from devplacepy.services.containers.api import ContainerError
calls = []
monkeypatch.setattr(
api, "_host_port_free", lambda port: calls.append(port) or False
)
with pytest.raises(ContainerError, match="probing"):
api.allocate_host_port(set())
assert len(calls) == api.MAX_PORT_PROBES
def test_parse_ports_accepts_mapping_cap():
value = "\n".join(str(8000 + i) for i in range(api.MAX_PORTS_PER_INSTANCE))
assert len(api.parse_ports(value)) == api.MAX_PORTS_PER_INSTANCE
def test_parse_ports_rejects_too_many_mappings():
from devplacepy.services.containers.api import ContainerError
value = "\n".join(str(8000 + i) for i in range(api.MAX_PORTS_PER_INSTANCE + 1))
with pytest.raises(ContainerError, match="at most"):
api.parse_ports(value)
@@ -0,0 +1 @@
# retoor <retoor@molodetz.nl>
@@ -0,0 +1,41 @@
# retoor <retoor@molodetz.nl>
from dataclasses import replace
from devplacepy.services.devii.config import load_settings
from devplacepy.services.devii.fetch.controller import MIN_FETCH_CHARS, FetchController
def _controller(ceiling):
return FetchController(replace(load_settings(), fetch_max_chars=ceiling))
def test_optional_cap_defaults_to_ceiling():
controller = _controller(2000)
assert controller._optional_cap(None, "a" * 5000) == "a" * 2000
def test_optional_cap_clamps_large_request_to_ceiling():
controller = _controller(2000)
assert controller._optional_cap(10**9, "b" * 5000) == "b" * 2000
def test_optional_cap_honors_smaller_request():
controller = _controller(2000)
assert controller._optional_cap(1500, "c" * 5000) == "c" * 1500
def test_optional_cap_floors_tiny_request():
controller = _controller(2000)
assert controller._optional_cap(10, "d" * 5000) == "d" * MIN_FETCH_CHARS
def test_optional_cap_invalid_request_falls_back_to_ceiling():
controller = _controller(2000)
assert controller._optional_cap("many", "e" * 5000) == "e" * 2000
def test_optional_cap_leaves_short_content_alone():
controller = _controller(2000)
assert controller._optional_cap(None, "short") == "short"
assert controller._optional_cap(1500, "short") == "short"