mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
routes/email_routes.py (7,194 lines), routes/email_helpers.py (2,025) and routes/email_pollers.py (1,764) were the largest flat email area left in routes/. They now live in routes/email/, following the pattern fifteen route areas already use: the canonical module under the package, a shim at the old path that replaces itself in sys.modules with the canonical object. The shim matters more here than the move. Dozens of email tests monkeypatch module attributes, and several pop the module from sys.modules and re-import it. Without identity between routes.email_routes and routes.email.email_routes those patches would apply to a different object than the app uses. Intra-package imports keep the flat path, matching routes/document/ and routes/gallery/: the shim resolves them and the diff stays a move. Eight path references in five test modules read these files as source rather than importing them, so they now read the canonical location. That is the same adjustment every previous conversion made, and it is why the note/document shims mention source-introspection tests explicitly. No behaviour change. Verified with the full suite and under several explicit collection orders, since a byte-identical routes move has broken tests under one ordering before.
62 lines
1.9 KiB
Python
62 lines
1.9 KiB
Python
import io
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from fastapi import HTTPException, UploadFile
|
|
|
|
from src.upload_limits import format_byte_limit, read_upload_limited
|
|
|
|
REPO = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def _upload(name: str, data: bytes) -> UploadFile:
|
|
return UploadFile(filename=name, file=io.BytesIO(data))
|
|
|
|
|
|
def _source(path: str) -> str:
|
|
return (REPO / path).read_text(encoding="utf-8")
|
|
|
|
|
|
async def test_read_upload_limited_accepts_exact_limit():
|
|
assert await read_upload_limited(_upload("ok.bin", b"abcd"), 4, "Test upload") == b"abcd"
|
|
|
|
|
|
async def test_read_upload_limited_rejects_oversized_upload():
|
|
with pytest.raises(HTTPException) as exc:
|
|
await read_upload_limited(_upload("too-big.bin", b"abcde"), 4, "Test upload")
|
|
|
|
assert exc.value.status_code == 413
|
|
assert exc.value.detail == "Test upload exceeds 4 bytes limit"
|
|
|
|
|
|
def test_upload_limit_formatting_is_human_readable():
|
|
assert format_byte_limit(25 * 1024 * 1024) == "25 MB"
|
|
assert format_byte_limit(512 * 1024) == "512 KB"
|
|
assert format_byte_limit(7) == "7 bytes"
|
|
|
|
|
|
def test_direct_upload_routes_use_bounded_reads():
|
|
expectations = {
|
|
"routes/stt_routes.py": [
|
|
"read_upload_limited(file, STT_MAX_AUDIO_BYTES",
|
|
],
|
|
"routes/gallery/gallery_routes.py": [
|
|
"read_upload_limited(file, GALLERY_UPLOAD_MAX_BYTES",
|
|
"read_upload_limited(file, GALLERY_TRANSFORM_UPLOAD_MAX_BYTES",
|
|
],
|
|
"routes/memory/memory_routes.py": [
|
|
"read_upload_limited(file, MEMORY_IMPORT_MAX_BYTES",
|
|
],
|
|
"routes/calendar_routes.py": [
|
|
"read_upload_limited(file, ICS_MAX_BYTES",
|
|
],
|
|
"routes/email/email_routes.py": [
|
|
"read_upload_limited(file, EMAIL_COMPOSE_UPLOAD_MAX_BYTES",
|
|
],
|
|
}
|
|
|
|
for path, needles in expectations.items():
|
|
text = _source(path)
|
|
for needle in needles:
|
|
assert needle in text
|