test_cleanup.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import collections
  2. import logging
  3. import os
  4. import pathlib
  5. import unittest.mock
  6. import _pytest.logging # pylint: disable=import-private-name; typing
  7. import free_disk
  8. # pylint: disable=protected-access
  9. _DiskUsage = collections.namedtuple("_DiskUsage", ("free",))
  10. def _folder_content_size_bytes(path: pathlib.Path) -> int:
  11. return sum(p.stat().st_size for p in path.rglob("*") if p.is_file())
  12. def test__main_remove_some(
  13. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  14. ) -> None:
  15. tmp_path.joinpath("a").write_bytes(b"a" * 4)
  16. tmp_path.joinpath("b").write_bytes(b"b" * 3)
  17. tmp_path.joinpath("c").write_bytes(b"c" * 5)
  18. tmp_path.joinpath("d").write_bytes(b"d" * 2)
  19. tmp_path.joinpath("e").write_bytes(b"d" * 7)
  20. with unittest.mock.patch(
  21. "shutil.disk_usage",
  22. lambda p: _DiskUsage(free=42 - _folder_content_size_bytes(tmp_path)),
  23. ), unittest.mock.patch(
  24. "sys.argv", ["", "--free-bytes", "30B", str(tmp_path)]
  25. ), caplog.at_level(
  26. logging.DEBUG
  27. ):
  28. free_disk._main()
  29. assert {p.name for p in tmp_path.rglob("*")} == {"e", "d"}
  30. assert caplog.record_tuples[:-1] == [
  31. ("root", logging.DEBUG, m)
  32. for m in [
  33. "Required free bytes: 30",
  34. "_DiskUsage(free=21)",
  35. f"Removed file {tmp_path.joinpath('a')}",
  36. f"Removed file {tmp_path.joinpath('b')}",
  37. f"Removed file {tmp_path.joinpath('c')}",
  38. ]
  39. ]
  40. assert caplog.records[-1].levelno == logging.INFO
  41. assert caplog.records[-1].message.startswith(
  42. "Removed 3 file(s) with modification date <= 20"
  43. )
  44. def test__main_remove_from_subfolder(
  45. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  46. ) -> None:
  47. tmp_path.joinpath("a").mkdir()
  48. tmp_path.joinpath("a", "aa").write_bytes(b"a" * 4)
  49. tmp_path.joinpath("b").write_bytes(b"b" * 3)
  50. tmp_path.joinpath("c").write_bytes(b"c" * 5)
  51. with unittest.mock.patch(
  52. "shutil.disk_usage",
  53. lambda p: _DiskUsage(free=42 - _folder_content_size_bytes(tmp_path)),
  54. ), unittest.mock.patch(
  55. "sys.argv", ["", "--free-bytes", "35B", str(tmp_path)]
  56. ), caplog.at_level(
  57. logging.DEBUG
  58. ):
  59. free_disk._main()
  60. assert {p.name for p in tmp_path.rglob("*")} == {"a", "c"}
  61. assert caplog.record_tuples[:-1] == [
  62. ("root", logging.DEBUG, m)
  63. for m in [
  64. "Required free bytes: 35",
  65. "_DiskUsage(free=30)",
  66. f"Removed file {tmp_path.joinpath('a', 'aa')}",
  67. f"Removed file {tmp_path.joinpath('b')}",
  68. ]
  69. ]
  70. assert caplog.records[-1].levelno == logging.INFO
  71. assert caplog.records[-1].message.startswith(
  72. "Removed 2 file(s) with modification date <= 20"
  73. )
  74. def test__main_sufficient_space(
  75. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  76. ) -> None:
  77. tmp_path.joinpath("a").write_bytes(b"a" * 4)
  78. tmp_path.joinpath("b").write_bytes(b"b" * 3)
  79. tmp_path.joinpath("c").write_bytes(b"c" * 5)
  80. with unittest.mock.patch(
  81. "shutil.disk_usage",
  82. lambda p: _DiskUsage(free=42 - _folder_content_size_bytes(tmp_path)),
  83. ), unittest.mock.patch(
  84. "sys.argv", ["", "--free-bytes", "30B", str(tmp_path)]
  85. ), caplog.at_level(
  86. logging.DEBUG
  87. ):
  88. free_disk._main()
  89. assert {p.name for p in tmp_path.rglob("*")} == {"a", "b", "c"}
  90. assert caplog.record_tuples == [
  91. ("root", logging.DEBUG, "Required free bytes: 30"),
  92. ("root", logging.DEBUG, "_DiskUsage(free=30)"),
  93. ("root", logging.DEBUG, "Requirement already fulfilled"),
  94. ]
  95. def test__main_no_files(
  96. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  97. ) -> None:
  98. with unittest.mock.patch(
  99. "shutil.disk_usage", return_value=_DiskUsage(free=21)
  100. ), unittest.mock.patch(
  101. "sys.argv", ["", "--free-bytes", "30B", str(tmp_path)]
  102. ), caplog.at_level(
  103. logging.DEBUG
  104. ):
  105. free_disk._main()
  106. assert caplog.record_tuples == [
  107. ("root", logging.DEBUG, "Required free bytes: 30"),
  108. ("root", logging.DEBUG, "_DiskUsage(free=21)"),
  109. ("root", logging.WARNING, "No files to remove"),
  110. ]
  111. def test__main_path_regex_absolute(
  112. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  113. ) -> None:
  114. tmp_path.joinpath("a").mkdir()
  115. tmp_path.joinpath("a", "aa").write_bytes(b"aa")
  116. tmp_path.joinpath("a", "a~").write_bytes(b"a~")
  117. tmp_path.joinpath("b").write_bytes(b"b")
  118. tmp_path.joinpath("c").write_bytes(b"c")
  119. tmp_path.joinpath("d").write_bytes(b"d")
  120. with unittest.mock.patch(
  121. "shutil.disk_usage",
  122. lambda p: _DiskUsage(free=42 - _folder_content_size_bytes(tmp_path)),
  123. ), unittest.mock.patch(
  124. "sys.argv",
  125. [
  126. "",
  127. "--free-bytes",
  128. "42B",
  129. str(tmp_path),
  130. "--delete-path-regex",
  131. r"a/a|^b|c$|^.*/d$",
  132. ],
  133. ), caplog.at_level(
  134. logging.INFO
  135. ):
  136. free_disk._main()
  137. assert {p.name for p in tmp_path.rglob("*")} == {"a", "b"}
  138. assert caplog.records[-1].message.startswith(
  139. "Removed 4 file(s) with modification date <= 20"
  140. )
  141. def test__main_path_regex_relative(
  142. caplog: _pytest.logging.LogCaptureFixture, tmp_path: pathlib.Path
  143. ) -> None:
  144. tmp_path.joinpath("a").mkdir()
  145. tmp_path.joinpath("a", "aa").write_bytes(b"aa")
  146. tmp_path.joinpath("a", "aaa").write_bytes(b"aaa")
  147. tmp_path.joinpath("a", "A").write_bytes(b"A")
  148. tmp_path.joinpath("b").write_bytes(b"b")
  149. tmp_path.joinpath("b2").write_bytes(b"b2")
  150. tmp_path.joinpath("c").write_bytes(b"c")
  151. with unittest.mock.patch(
  152. "shutil.disk_usage",
  153. lambda p: _DiskUsage(free=42 - _folder_content_size_bytes(tmp_path)),
  154. ), unittest.mock.patch(
  155. "sys.argv",
  156. ["", "--free-bytes", "123B", ".", "--delete-path-regex", r"/aa|^b|\d$|^\./c$"],
  157. ), caplog.at_level(
  158. logging.INFO
  159. ):
  160. old_working_dir = os.getcwd()
  161. try:
  162. os.chdir(tmp_path)
  163. free_disk._main()
  164. finally:
  165. os.chdir(old_working_dir)
  166. assert {p.name for p in tmp_path.rglob("*")} == {"a", "A", "b"}
  167. assert caplog.records[-1].message.startswith(
  168. "Removed 4 file(s) with modification date <= 20"
  169. )