Spaces:
Sleeping
Sleeping
| import asyncio | |
| import hashlib | |
| from io import BytesIO | |
| from pathlib import Path | |
| import pytest | |
| from starlette.datastructures import UploadFile | |
| from app.config import Settings | |
| from app.services.file_validator import FileValidationError, FileValidator | |
| def make_settings(tmp_path: Path, max_upload_mb: int = 20) -> Settings: | |
| return Settings( | |
| app_name="BitCheck Document Verification API", | |
| version="1.0.0", | |
| upload_dir=tmp_path / "uploads", | |
| output_dir=tmp_path / "outputs", | |
| max_upload_mb=max_upload_mb, | |
| max_pdf_pages=5, | |
| deepseek_api_key=None, | |
| deepseek_base_url="https://api.deepseek.com", | |
| deepseek_model="deepseek-chat", | |
| log_level="INFO", | |
| ) | |
| def make_upload(filename: str, data: bytes) -> UploadFile: | |
| return UploadFile(filename=filename, file=BytesIO(data)) | |
| def validate(tmp_path: Path, filename: str, data: bytes): | |
| validator = FileValidator(make_settings(tmp_path)) | |
| return asyncio.run(validator.validate_and_save(make_upload(filename, data))) | |
| def test_supported_extension_passes(tmp_path: Path) -> None: | |
| result = validate(tmp_path, "sample.pdf", b"%PDF-1.7\ncontent") | |
| assert result.valid is True | |
| assert result.extension == ".pdf" | |
| assert Path(result.stored_path).exists() | |
| def test_unsupported_extension_fails(tmp_path: Path) -> None: | |
| validator = FileValidator(make_settings(tmp_path)) | |
| with pytest.raises(FileValidationError) as exc: | |
| asyncio.run(validator.validate_and_save(make_upload("sample.txt", b"hello"))) | |
| assert exc.value.code == "unsupported_file_type" | |
| def test_invalid_file_signature_fails(tmp_path: Path) -> None: | |
| validator = FileValidator(make_settings(tmp_path)) | |
| with pytest.raises(FileValidationError) as exc: | |
| asyncio.run(validator.validate_and_save(make_upload("sample.png", b"not a png"))) | |
| assert exc.value.code == "invalid_document" | |
| def test_hash_generation_works(tmp_path: Path) -> None: | |
| data = b"\xff\xd8jpeg bytes" | |
| result = validate(tmp_path, "sample.jpg", data) | |
| assert result.sha256 == hashlib.sha256(data).hexdigest() | |
| def test_safe_filename_is_used(tmp_path: Path) -> None: | |
| result = validate(tmp_path, "../unsafe.png", b"\x89PNG\r\n\x1a\n") | |
| assert result.original_filename == "unsafe.png" | |
| assert result.stored_filename != "unsafe.png" | |
| assert result.stored_filename.endswith(".png") | |
| assert Path(result.stored_path).parent == (tmp_path / "uploads").resolve() | |