import asyncio import pytest from fastapi import HTTPException from modules.upload_validation import MAX_UPLOAD_BYTES, read_pdf_upload_bytes, read_upload_bytes class FakeUpload: def __init__(self, data: bytes, content_type: str, filename: str = "file.bin"): self._data = data self._pos = 0 self.content_type = content_type self.filename = filename async def read(self, size: int = -1) -> bytes: if self._pos >= len(self._data): return b"" if size is None or size < 0: size = len(self._data) - self._pos chunk = self._data[self._pos : self._pos + size] self._pos += len(chunk) return chunk def run(coro): return asyncio.run(coro) def test_valid_pdf_upload_passes_and_returns_mime(): data, mime = run(read_upload_bytes(FakeUpload(b"%PDF-1.7\n", "application/pdf"))) assert data.startswith(b"%PDF-") assert mime == "application/pdf" def test_disallowed_mime_rejected_with_415(): with pytest.raises(HTTPException) as exc: run(read_upload_bytes(FakeUpload(b"print(1)", "application/x-python"))) assert exc.value.status_code == 415 assert "Unsupported upload type" in exc.value.detail def test_oversize_upload_rejected_with_413(): with pytest.raises(HTTPException) as exc: run(read_upload_bytes(FakeUpload(b"x" * (MAX_UPLOAD_BYTES + 1), "text/plain"))) assert exc.value.status_code == 413 assert "exceeds max size" in exc.value.detail def test_pdf_helper_rejects_spoofed_pdf_mime(): with pytest.raises(HTTPException) as exc: run(read_pdf_upload_bytes(FakeUpload(b"not a pdf", "application/pdf"))) assert exc.value.status_code == 415 assert "not a valid PDF" in exc.value.detail