test_archive_file_path_guard.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. """Tests for archive file_path guard against empty paths and directories (#475).
  2. When a 3mf download fails (e.g. BambuStudio-initiated prints), the fallback
  3. archive is created with file_path="". Previously, `settings.base_dir / ""`
  4. resolved to the base directory itself, which passed `exists()` but caused
  5. `[Errno 21] Is a directory` when opened as a ZipFile.
  6. The fix replaces `.exists()` with `.is_file()` across all archive endpoints,
  7. and adds an `archive.file_path` truthiness check for photo capture.
  8. """
  9. from pathlib import Path
  10. import pytest
  11. class TestIsFileGuard:
  12. """Verify that is_file() correctly rejects directories and empty paths."""
  13. def test_empty_path_resolves_to_parent(self, tmp_path: Path):
  14. """Path('') / '' resolves to the parent directory (which exists but is not a file)."""
  15. base_dir = tmp_path / "data"
  16. base_dir.mkdir()
  17. file_path = base_dir / ""
  18. # exists() returns True (the directory exists) — this was the old broken check
  19. assert file_path.exists()
  20. # is_file() returns False (it's a directory, not a file)
  21. assert not file_path.is_file()
  22. def test_real_file_passes_is_file(self, tmp_path: Path):
  23. """A real 3mf file passes is_file()."""
  24. fake_3mf = tmp_path / "archive" / "test.3mf"
  25. fake_3mf.parent.mkdir(parents=True)
  26. fake_3mf.write_bytes(b"PK\x03\x04") # ZIP magic bytes
  27. assert fake_3mf.is_file()
  28. def test_nonexistent_file_fails_is_file(self, tmp_path: Path):
  29. """A nonexistent path fails is_file()."""
  30. missing = tmp_path / "archive" / "missing.3mf"
  31. assert not missing.is_file()
  32. def test_directory_fails_is_file(self, tmp_path: Path):
  33. """A directory path fails is_file()."""
  34. dir_path = tmp_path / "archive"
  35. dir_path.mkdir()
  36. assert not dir_path.is_file()
  37. class TestFallbackArchiveFilePath:
  38. """Verify that a fallback archive (file_path='') is handled safely."""
  39. def test_base_dir_slash_empty_string_is_base_dir(self, tmp_path: Path):
  40. """Joining base_dir with empty string produces base_dir (a directory)."""
  41. base_dir = tmp_path / "data"
  42. base_dir.mkdir()
  43. # Simulate: file_path = settings.base_dir / archive.file_path
  44. # where archive.file_path = ""
  45. file_path = base_dir / ""
  46. # The resolved path IS the directory itself
  47. assert file_path.resolve() == base_dir.resolve()
  48. # exists() says True (this caused the old bug)
  49. assert file_path.exists()
  50. # is_file() says False (this is the fix)
  51. assert not file_path.is_file()
  52. def test_archive_file_path_empty_string_is_falsy(self):
  53. """Empty string file_path is falsy (used for photo capture guard)."""
  54. file_path = ""
  55. assert not file_path
  56. def test_archive_file_path_real_is_truthy(self):
  57. """Real file_path is truthy."""
  58. file_path = "archive/2026/02/test.3mf"
  59. assert file_path
  60. class TestPhotoPathDerivation:
  61. """Verify that photo directory derivation is safe with empty file_path."""
  62. def test_empty_file_path_parent_is_dot(self):
  63. """Path('').parent is '.' — would resolve to base_dir instead of archive dir."""
  64. parent = Path("").parent
  65. assert str(parent) == "."
  66. def test_real_file_path_parent_is_archive_dir(self):
  67. """Real file_path parent gives the correct archive directory."""
  68. parent = Path("archive/2026/02/test.3mf").parent
  69. assert str(parent) == "archive/2026/02"