test_compact.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import logging
  2. from flexmock import flexmock
  3. from borgmatic.borg import compact as module
  4. from ..test_verbosity import insert_logging_mock
  5. def insert_execute_command_mock(
  6. compact_command,
  7. output_log_level,
  8. working_directory=None,
  9. borg_exit_codes=None,
  10. ):
  11. flexmock(module.environment).should_receive('make_environment')
  12. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
  13. working_directory,
  14. )
  15. flexmock(module).should_receive('execute_command').with_args(
  16. compact_command,
  17. output_log_level=output_log_level,
  18. environment=None,
  19. working_directory=working_directory,
  20. borg_local_path=compact_command[0],
  21. borg_exit_codes=borg_exit_codes,
  22. ).once()
  23. COMPACT_COMMAND = ('borg', 'compact')
  24. def test_compact_segments_calls_borg_with_flags():
  25. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  26. insert_execute_command_mock((*COMPACT_COMMAND, 'repo'), logging.INFO)
  27. module.compact_segments(
  28. dry_run=False,
  29. repository_path='repo',
  30. config={},
  31. local_borg_version='1.2.3',
  32. global_arguments=flexmock(),
  33. )
  34. def test_compact_segments_with_log_info_calls_borg_with_info_flag():
  35. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  36. insert_execute_command_mock((*COMPACT_COMMAND, '--info', 'repo'), logging.INFO)
  37. insert_logging_mock(logging.INFO)
  38. module.compact_segments(
  39. repository_path='repo',
  40. config={},
  41. local_borg_version='1.2.3',
  42. global_arguments=flexmock(),
  43. dry_run=False,
  44. )
  45. def test_compact_segments_with_log_debug_calls_borg_with_debug_flag():
  46. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  47. insert_execute_command_mock((*COMPACT_COMMAND, '--debug', '--show-rc', 'repo'), logging.INFO)
  48. insert_logging_mock(logging.DEBUG)
  49. module.compact_segments(
  50. repository_path='repo',
  51. config={},
  52. local_borg_version='1.2.3',
  53. global_arguments=flexmock(),
  54. dry_run=False,
  55. )
  56. def test_compact_segments_with_dry_run_skips_borg_call_when_feature_unavailable():
  57. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  58. flexmock(module.feature).should_receive('available').with_args(
  59. module.feature.Feature.DRY_RUN_COMPACT,
  60. '1.2.3',
  61. ).and_return(False)
  62. flexmock(module.environment).should_receive('make_environment').never()
  63. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').never()
  64. flexmock(module).should_receive('execute_command').never()
  65. flexmock(module.logger).should_receive('info').with_args('Skipping compact (dry run)').once()
  66. module.compact_segments(
  67. repository_path='repo',
  68. config={},
  69. local_borg_version='1.2.3',
  70. global_arguments=flexmock(),
  71. dry_run=True,
  72. )
  73. def test_compact_segments_with_dry_run_executes_borg_call_when_feature_available():
  74. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  75. flexmock(module.feature).should_receive('available').with_args(
  76. module.feature.Feature.DRY_RUN_COMPACT,
  77. '1.4.1',
  78. ).and_return(True)
  79. flexmock(module.environment).should_receive('make_environment').once()
  80. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').once()
  81. flexmock(module).should_receive('execute_command').once()
  82. module.compact_segments(
  83. repository_path='repo',
  84. config={},
  85. local_borg_version='1.4.1',
  86. global_arguments=flexmock(),
  87. dry_run=True,
  88. )
  89. def test_compact_segments_with_local_path_calls_borg_via_local_path():
  90. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  91. insert_execute_command_mock(('borg1', *COMPACT_COMMAND[1:], 'repo'), logging.INFO)
  92. module.compact_segments(
  93. dry_run=False,
  94. repository_path='repo',
  95. config={},
  96. local_borg_version='1.2.3',
  97. global_arguments=flexmock(),
  98. local_path='borg1',
  99. )
  100. def test_compact_segments_with_exit_codes_calls_borg_using_them():
  101. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  102. borg_exit_codes = flexmock()
  103. insert_execute_command_mock(
  104. (*COMPACT_COMMAND, 'repo'),
  105. logging.INFO,
  106. borg_exit_codes=borg_exit_codes,
  107. )
  108. module.compact_segments(
  109. dry_run=False,
  110. repository_path='repo',
  111. config={'borg_exit_codes': borg_exit_codes},
  112. local_borg_version='1.2.3',
  113. global_arguments=flexmock(),
  114. )
  115. def test_compact_segments_with_remote_path_calls_borg_with_remote_path_flags():
  116. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  117. insert_execute_command_mock((*COMPACT_COMMAND, '--remote-path', 'borg1', 'repo'), logging.INFO)
  118. module.compact_segments(
  119. dry_run=False,
  120. repository_path='repo',
  121. config={},
  122. local_borg_version='1.2.3',
  123. global_arguments=flexmock(),
  124. remote_path='borg1',
  125. )
  126. def test_compact_segments_with_progress_calls_borg_with_progress_flag():
  127. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  128. insert_execute_command_mock((*COMPACT_COMMAND, '--progress', 'repo'), logging.INFO)
  129. module.compact_segments(
  130. dry_run=False,
  131. repository_path='repo',
  132. config={'progress': True},
  133. local_borg_version='1.2.3',
  134. global_arguments=flexmock(),
  135. )
  136. def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_flag():
  137. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  138. insert_execute_command_mock((*COMPACT_COMMAND, '--cleanup-commits', 'repo'), logging.INFO)
  139. module.compact_segments(
  140. dry_run=False,
  141. repository_path='repo',
  142. config={},
  143. local_borg_version='1.2.3',
  144. global_arguments=flexmock(),
  145. cleanup_commits=True,
  146. )
  147. def test_compact_segments_with_threshold_calls_borg_with_threshold_flag():
  148. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  149. insert_execute_command_mock((*COMPACT_COMMAND, '--threshold', '20', 'repo'), logging.INFO)
  150. module.compact_segments(
  151. dry_run=False,
  152. repository_path='repo',
  153. config={'compact_threshold': 20},
  154. local_borg_version='1.2.3',
  155. global_arguments=flexmock(),
  156. )
  157. def test_compact_segments_with_umask_calls_borg_with_umask_flags():
  158. config = {'umask': '077'}
  159. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  160. insert_execute_command_mock((*COMPACT_COMMAND, '--umask', '077', 'repo'), logging.INFO)
  161. module.compact_segments(
  162. dry_run=False,
  163. repository_path='repo',
  164. config=config,
  165. local_borg_version='1.2.3',
  166. global_arguments=flexmock(),
  167. )
  168. def test_compact_segments_with_log_json_calls_borg_with_log_json_flags():
  169. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  170. insert_execute_command_mock((*COMPACT_COMMAND, '--log-json', 'repo'), logging.INFO)
  171. module.compact_segments(
  172. dry_run=False,
  173. repository_path='repo',
  174. config={'log_json': True},
  175. local_borg_version='1.2.3',
  176. global_arguments=flexmock(),
  177. )
  178. def test_compact_segments_with_lock_wait_calls_borg_with_lock_wait_flags():
  179. config = {'lock_wait': 5}
  180. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  181. insert_execute_command_mock((*COMPACT_COMMAND, '--lock-wait', '5', 'repo'), logging.INFO)
  182. module.compact_segments(
  183. dry_run=False,
  184. repository_path='repo',
  185. config=config,
  186. local_borg_version='1.2.3',
  187. global_arguments=flexmock(),
  188. )
  189. def test_compact_segments_with_extra_borg_options_calls_borg_with_extra_options():
  190. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  191. insert_execute_command_mock(
  192. (*COMPACT_COMMAND, '--extra', '--options', 'value with space', 'repo'),
  193. logging.INFO,
  194. )
  195. module.compact_segments(
  196. dry_run=False,
  197. repository_path='repo',
  198. config={'extra_borg_options': {'compact': '--extra --options "value with space"'}},
  199. local_borg_version='1.2.3',
  200. global_arguments=flexmock(),
  201. )
  202. def test_compact_segments_calls_borg_with_working_directory():
  203. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  204. insert_execute_command_mock(
  205. (*COMPACT_COMMAND, 'repo'),
  206. logging.INFO,
  207. working_directory='/working/dir',
  208. )
  209. module.compact_segments(
  210. dry_run=False,
  211. repository_path='repo',
  212. config={'working_directory': '/working/dir'},
  213. local_borg_version='1.2.3',
  214. global_arguments=flexmock(),
  215. )