| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- """A virtual printer's upload stored in the File Manager (library_store)."""
- from pathlib import Path
- import pytest
- from sqlalchemy import func, select
- from backend.app.models.library import LibraryFile, LibraryFolder
- from backend.app.models.virtual_printer import VirtualPrinter
- from backend.app.services.virtual_printer.library_store import store_upload, upload_folder, upload_settings
- pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
- @pytest.fixture(autouse=True)
- def _library_in_tmp(tmp_path, monkeypatch):
- """The File Manager writes below archive_dir: keep it out of the real one."""
- from backend.app.core.config import settings
- monkeypatch.setattr(settings, "archive_dir", tmp_path / "archive")
- def _upload(tmp_path: Path, name: str = "Plate_1.gcode.3mf", content: bytes = b"plate one") -> Path:
- path = tmp_path / "uploads" / name
- path.parent.mkdir(exist_ok=True)
- path.write_bytes(content)
- return path
- async def _files(db) -> int:
- return (await db.execute(select(func.count(LibraryFile.id)))).scalar()
- async def test_stored_with_its_name_and_copied_from_disk(db_session, tmp_path):
- source = _upload(tmp_path)
- library_file, reused = await store_upload(db_session, source_path=source, filename=source.name, folder_id=None)
- assert reused is False
- assert library_file.filename == "Plate_1.gcode.3mf"
- assert library_file.source_type == "virtual_printer"
- assert library_file.file_size == len(b"plate one")
- from backend.app.api.routes.library import get_library_files_dir
- assert (get_library_files_dir() / Path(library_file.file_path).name).read_bytes() == b"plate one"
- assert source.exists(), "the caller removes its temp file, not the store"
- async def test_the_same_file_sent_again_is_the_file_already_there(db_session, tmp_path):
- first, _ = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- again, reused = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- assert reused is True
- assert again.id == first.id
- assert await _files(db_session) == 1
- @pytest.mark.parametrize(
- ("name", "content"),
- [("Plate_1.gcode.3mf", b"changed plate"), ("Other.gcode.3mf", b"plate one")],
- ids=["other-content", "other-name"],
- )
- async def test_other_content_or_another_name_is_a_new_file(db_session, tmp_path, name, content):
- await store_upload(db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None)
- _, reused = await store_upload(
- db_session, source_path=_upload(tmp_path, name, content), filename=name, folder_id=None
- )
- assert reused is False
- assert await _files(db_session) == 2
- async def test_a_file_put_there_by_hand_is_never_taken_over(db_session, tmp_path):
- first, _ = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- first.source_type = None # as an upload through the File Manager would be
- await db_session.commit()
- again, reused = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- assert reused is False
- assert again.id != first.id
- async def test_the_configured_folder_is_used(db_session):
- folder = LibraryFolder(name="Class 7b", shared=True)
- db_session.add(folder)
- await db_session.flush()
- assert (await upload_folder(db_session, folder.id)).id == folder.id
- @pytest.mark.parametrize("case", ["none", "deleted", "external"])
- async def test_otherwise_the_shared_virtual_printer_folder(db_session, tmp_path, case):
- folder_id = None
- if case == "deleted":
- folder_id = 4242
- elif case == "external":
- mount = LibraryFolder(name="NAS", is_external=True, external_path=str(tmp_path), shared=True)
- db_session.add(mount)
- await db_session.flush()
- folder_id = mount.id
- folder = await upload_folder(db_session, folder_id)
- assert folder.name == "Virtual Printer"
- assert folder.parent_id is None
- assert folder.is_external is False
- assert folder.shared is True
- # One shared folder, not one per upload.
- assert (await upload_folder(db_session, None)).id == folder.id
- async def test_upload_settings_are_read_from_the_virtual_printer(db_session):
- folder = LibraryFolder(name="Queue", shared=True)
- db_session.add(folder)
- await db_session.flush()
- vp = VirtualPrinter(name="Q", mode="queue", library_folder_id=folder.id, queue_remove_after_print=True)
- db_session.add(vp)
- await db_session.flush()
- assert await upload_settings(db_session, vp.id) == (folder.id, True)
- assert await upload_settings(db_session, 9999) == (None, False)
- async def test_a_users_private_folder_of_that_name_is_not_the_shared_one(db_session):
- # With auth on, a user may make a private top-level "Virtual Printer"
- # folder; uploads of every VP without a folder must not vanish into it.
- from backend.app.models.user import User
- alice = User(username="alice", password_hash="x", role="user")
- db_session.add(alice)
- await db_session.flush()
- private = LibraryFolder(name="Virtual Printer", created_by_id=alice.id, shared=False)
- db_session.add(private)
- await db_session.flush()
- folder = await upload_folder(db_session, None)
- assert folder.id != private.id
- assert folder.shared is True
- assert folder.created_by_id is None
- async def test_a_file_a_queue_job_removes_once_it_prints_is_not_shared(db_session, tmp_path):
- from backend.app.models.print_queue import PrintQueueItem
- # The queue VP with "Remove from File Manager once it prints" gets a file
- # of its own, even with the same file already in the folder ...
- kept, _ = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- own, reused = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None, reuse=False
- )
- assert reused is False
- assert own.id != kept.id
- db_session.add(PrintQueueItem(library_file_id=own.id, status="pending", cleanup_library_after_dispatch=True))
- await db_session.commit()
- # ... and a later upload of it never takes that one, which its print removes.
- again, reused = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- assert reused is True
- assert again.id == kept.id
- await db_session.delete(kept)
- await db_session.commit()
- fresh, reused = await store_upload(
- db_session, source_path=_upload(tmp_path), filename="Plate_1.gcode.3mf", folder_id=None
- )
- assert reused is False
- assert fresh.id not in (kept.id, own.id)
|