"""Tests für upload_folder() — Kopie per shutil.copyfile statt read_bytes().""" from __future__ import annotations from pathlib import Path from unittest.mock import patch from pdf_ocr_hotfolder.config import FolderUpload from pdf_ocr_hotfolder.uploaders import upload_folder def test_upload_folder_copies_file(tmp_path: Path) -> None: src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4 inhalt\n") target = tmp_path / "ziel" assert upload_folder(src, FolderUpload(enabled=True, target=str(target)), tmp_path / "out") is True assert (target / "OCR_scan.pdf").read_bytes() == b"%PDF-1.4 inhalt\n" # Quelle bleibt liegen (Kopie, kein Move) assert src.exists() def test_upload_folder_uses_copyfile_not_read_bytes(tmp_path: Path) -> None: """Große PDFs dürfen nicht komplett in den Speicher gelesen werden.""" src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4\n") target = tmp_path / "ziel" with patch("pdf_ocr_hotfolder.uploaders.shutil.copyfile") as copyfile: upload_folder(src, FolderUpload(enabled=True, target=str(target)), tmp_path / "out") copyfile.assert_called_once() def test_upload_folder_skips_self_target(tmp_path: Path) -> None: """Ist das Ziel = outgoing, wird nicht auf sich selbst kopiert.""" out = tmp_path / "out" out.mkdir() src = out / "OCR_scan.pdf" src.write_bytes(b"%PDF-1.4\n") with patch("pdf_ocr_hotfolder.uploaders.shutil.copyfile") as copyfile: assert upload_folder(src, FolderUpload(enabled=True, target=""), out) is True copyfile.assert_not_called() assert src.read_bytes() == b"%PDF-1.4\n" def test_upload_folder_disabled_returns_true(tmp_path: Path) -> None: src = tmp_path / "OCR_scan.pdf" src.write_bytes(b"%PDF-1.4\n") assert upload_folder(src, FolderUpload(enabled=False), tmp_path) is True def test_upload_folder_reports_failure(tmp_path: Path) -> None: """OSError beim Kopieren → False (wird vom Service als Fehler gezählt).""" src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4\n") with patch("pdf_ocr_hotfolder.uploaders.shutil.copyfile", side_effect=OSError("disk full")): assert upload_folder(src, FolderUpload(enabled=True, target=str(tmp_path / "ziel")), tmp_path / "out") is False # ---------------- Punkt 3: kein stilles Überschreiben im Ziel ---------------- def test_upload_folder_does_not_overwrite_existing(tmp_path: Path) -> None: """Gleichnamige Datei im abweichenden target wurde bisher still ersetzt.""" src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4 neu\n") target = tmp_path / "ziel" target.mkdir() (target / "OCR_scan.pdf").write_bytes(b"%PDF-1.4 alt\n") assert upload_folder(src, FolderUpload(enabled=True, target=str(target)), tmp_path / "out") is True assert (target / "OCR_scan.pdf").read_bytes() == b"%PDF-1.4 alt\n" neu = list(target.glob("OCR_scan_*.pdf")) assert len(neu) == 1 assert neu[0].read_bytes() == b"%PDF-1.4 neu\n" def test_upload_folder_logs_warning_on_collision(tmp_path: Path, caplog) -> None: import logging src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4 neu\n") target = tmp_path / "ziel" target.mkdir() (target / "OCR_scan.pdf").write_bytes(b"%PDF-1.4 alt\n") with caplog.at_level(logging.WARNING, logger="pdf_ocr_hotfolder.uploaders"): upload_folder(src, FolderUpload(enabled=True, target=str(target)), tmp_path / "out") assert "OCR_scan.pdf" in caplog.text assert "überschrieben" in caplog.text def test_upload_folder_without_collision_logs_nothing(tmp_path: Path, caplog) -> None: import logging src = tmp_path / "out" / "OCR_scan.pdf" src.parent.mkdir() src.write_bytes(b"%PDF-1.4\n") with caplog.at_level(logging.WARNING, logger="pdf_ocr_hotfolder.uploaders"): upload_folder(src, FolderUpload(enabled=True, target=str(tmp_path / "ziel")), tmp_path / "out") assert "überschrieben" not in caplog.text assert (tmp_path / "ziel" / "OCR_scan.pdf").exists() def test_upload_folder_self_target_is_not_renamed(tmp_path: Path) -> None: """Default (leeres target -> outgoing/): der resolve()-Kurzschluss greift. Ohne ihn würde die Datei hier gegen sich selbst kollidieren und eine Zeitstempel-Kopie neben sich selbst erzeugen. """ out = tmp_path / "out" out.mkdir() src = out / "OCR_scan.pdf" src.write_bytes(b"%PDF-1.4\n") assert upload_folder(src, FolderUpload(enabled=True, target=""), out) is True assert list(out.iterdir()) == [src]