test_windows_backup_paths_3501.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """A backup from a Windows install restored on Linux finds its files (#3501).
  2. Windows stores paths relative to the data folder with backslashes; Linux reads
  3. them as part of one file name. The restore turns them into slashes.
  4. """
  5. import pytest
  6. from sqlalchemy import select
  7. from backend.app.models.archive import PrintArchive
  8. from backend.app.models.library import LibraryFile
  9. from backend.app.models.print_log import PrintLogEntry
  10. from backend.app.services.backup_paths import convert_windows_paths
  11. def _windows_rows():
  12. archive = PrintArchive(
  13. filename="Brachy.3mf",
  14. file_path="archive\\12\\Brachy.3mf",
  15. file_size=1,
  16. thumbnail_path="archive\\12\\thumbnail.png",
  17. timelapse_path="archive\\12\\timelapse.mp4",
  18. source_3mf_path="archive\\12\\source\\Brachy.3mf",
  19. f3d_path="archive\\12\\design.f3d",
  20. )
  21. library_file = LibraryFile(
  22. filename="Brachy.3mf",
  23. file_path="archive\\library\\files\\abc.3mf",
  24. file_type="3mf",
  25. file_size=1,
  26. thumbnail_path="archive\\library\\thumbnails\\abc.png",
  27. )
  28. log_entry = PrintLogEntry(
  29. status="completed",
  30. thumbnail_path="archive\\12\\thumbnail.png",
  31. timelapse_path="archive\\12\\timelapse.mp4",
  32. )
  33. return archive, library_file, log_entry
  34. async def _convert(db_session, base_dir, **kwargs) -> int:
  35. await db_session.flush()
  36. changed = await convert_windows_paths(await db_session.connection(), base_dir, **kwargs)
  37. db_session.expire_all()
  38. return changed
  39. @pytest.mark.asyncio
  40. async def test_windows_paths_get_slashes(db_session, tmp_path):
  41. db_session.add_all(_windows_rows())
  42. assert await _convert(db_session, tmp_path, windows=False) == 3
  43. archive = (await db_session.execute(select(PrintArchive))).scalar_one()
  44. assert (
  45. archive.file_path,
  46. archive.thumbnail_path,
  47. archive.timelapse_path,
  48. archive.source_3mf_path,
  49. archive.f3d_path,
  50. ) == (
  51. "archive/12/Brachy.3mf",
  52. "archive/12/thumbnail.png",
  53. "archive/12/timelapse.mp4",
  54. "archive/12/source/Brachy.3mf",
  55. "archive/12/design.f3d",
  56. )
  57. library_file = (await db_session.execute(select(LibraryFile))).scalar_one()
  58. assert (library_file.file_path, library_file.thumbnail_path) == (
  59. "archive/library/files/abc.3mf",
  60. "archive/library/thumbnails/abc.png",
  61. )
  62. log_entry = (await db_session.execute(select(PrintLogEntry))).scalar_one()
  63. assert (log_entry.thumbnail_path, log_entry.timelapse_path) == (
  64. "archive/12/thumbnail.png",
  65. "archive/12/timelapse.mp4",
  66. )
  67. @pytest.mark.asyncio
  68. async def test_a_file_whose_name_has_a_backslash_is_kept(db_session, tmp_path):
  69. # On Linux a backslash can be part of a real file name.
  70. (tmp_path / "archive" / "7").mkdir(parents=True)
  71. (tmp_path / "archive" / "7" / "a\\b.3mf").write_bytes(b"x")
  72. db_session.add(PrintArchive(filename="a\\b.3mf", file_path="archive/7/a\\b.3mf", file_size=1))
  73. assert await _convert(db_session, tmp_path, windows=False) == 0
  74. archive = (await db_session.execute(select(PrintArchive))).scalar_one()
  75. assert archive.file_path == "archive/7/a\\b.3mf"
  76. @pytest.mark.asyncio
  77. async def test_nothing_changes_on_windows(db_session, tmp_path):
  78. db_session.add_all(_windows_rows())
  79. assert await _convert(db_session, tmp_path, windows=True) == 0
  80. archive = (await db_session.execute(select(PrintArchive))).scalar_one()
  81. assert archive.file_path == "archive\\12\\Brachy.3mf"
  82. @pytest.mark.asyncio
  83. async def test_linux_paths_and_empty_columns_are_left_alone(db_session, tmp_path):
  84. db_session.add(PrintArchive(filename="x.3mf", file_path="archive/3/x.3mf", file_size=1, thumbnail_path=None))
  85. db_session.add(PrintLogEntry(status="completed"))
  86. assert await _convert(db_session, tmp_path, windows=False) == 0
  87. @pytest.mark.asyncio
  88. async def test_a_second_run_changes_nothing(db_session, tmp_path):
  89. db_session.add_all(_windows_rows())
  90. await _convert(db_session, tmp_path, windows=False)
  91. assert await _convert(db_session, tmp_path, windows=False) == 0