test_check.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. import logging
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic.borg import check as module
  5. from ..test_verbosity import insert_logging_mock
  6. def insert_execute_command_mock(
  7. command, output_file=None, working_directory=None, borg_exit_codes=None
  8. ):
  9. flexmock(module.environment).should_receive('make_environment')
  10. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
  11. working_directory,
  12. )
  13. flexmock(module).should_receive('execute_command').with_args(
  14. command,
  15. output_file=output_file,
  16. environment=None,
  17. working_directory=working_directory,
  18. borg_local_path=command[0],
  19. borg_exit_codes=borg_exit_codes,
  20. ).once()
  21. def insert_execute_command_never():
  22. flexmock(module).should_receive('execute_command').never()
  23. def test_make_archive_filter_flags_with_default_checks_and_prefix_returns_default_flags():
  24. flexmock(module.feature).should_receive('available').and_return(True)
  25. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  26. flags = module.make_archive_filter_flags(
  27. '1.2.3',
  28. {'prefix': 'foo'},
  29. ('repository', 'archives'),
  30. check_arguments=flexmock(match_archives=None),
  31. )
  32. assert flags == ('--match-archives', 'sh:foo*')
  33. def test_make_archive_filter_flags_with_all_checks_and_prefix_returns_default_flags():
  34. flexmock(module.feature).should_receive('available').and_return(True)
  35. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  36. flags = module.make_archive_filter_flags(
  37. '1.2.3',
  38. {'prefix': 'foo'},
  39. ('repository', 'archives', 'extract'),
  40. check_arguments=flexmock(match_archives=None),
  41. )
  42. assert flags == ('--match-archives', 'sh:foo*')
  43. def test_make_archive_filter_flags_with_all_checks_and_prefix_without_borg_features_returns_glob_archives_flags():
  44. flexmock(module.feature).should_receive('available').and_return(False)
  45. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  46. flags = module.make_archive_filter_flags(
  47. '1.2.3',
  48. {'prefix': 'foo'},
  49. ('repository', 'archives', 'extract'),
  50. check_arguments=flexmock(match_archives=None),
  51. )
  52. assert flags == ('--glob-archives', 'foo*')
  53. def test_make_archive_filter_flags_with_archives_check_and_last_includes_last_flag():
  54. flexmock(module.feature).should_receive('available').and_return(True)
  55. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  56. flags = module.make_archive_filter_flags(
  57. '1.2.3',
  58. {'check_last': 3},
  59. ('archives',),
  60. check_arguments=flexmock(match_archives=None),
  61. )
  62. assert flags == ('--last', '3')
  63. def test_make_archive_filter_flags_with_data_check_and_last_includes_last_flag():
  64. flexmock(module.feature).should_receive('available').and_return(True)
  65. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  66. flags = module.make_archive_filter_flags(
  67. '1.2.3',
  68. {'check_last': 3},
  69. ('data',),
  70. check_arguments=flexmock(match_archives=None),
  71. )
  72. assert flags == ('--last', '3')
  73. def test_make_archive_filter_flags_with_repository_check_and_last_omits_last_flag():
  74. flexmock(module.feature).should_receive('available').and_return(True)
  75. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  76. flags = module.make_archive_filter_flags(
  77. '1.2.3',
  78. {'check_last': 3},
  79. ('repository',),
  80. check_arguments=flexmock(match_archives=None),
  81. )
  82. assert flags == ()
  83. def test_make_archive_filter_flags_with_default_checks_and_last_includes_last_flag():
  84. flexmock(module.feature).should_receive('available').and_return(True)
  85. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  86. flags = module.make_archive_filter_flags(
  87. '1.2.3',
  88. {'check_last': 3},
  89. ('repository', 'archives'),
  90. check_arguments=flexmock(match_archives=None),
  91. )
  92. assert flags == ('--last', '3')
  93. def test_make_archive_filter_flags_with_archives_check_and_prefix_includes_match_archives_flag():
  94. flexmock(module.feature).should_receive('available').and_return(True)
  95. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  96. flags = module.make_archive_filter_flags(
  97. '1.2.3',
  98. {'prefix': 'foo-'},
  99. ('archives',),
  100. check_arguments=flexmock(match_archives=None),
  101. )
  102. assert flags == ('--match-archives', 'sh:foo-*')
  103. def test_make_archive_filter_flags_with_data_check_and_prefix_includes_match_archives_flag():
  104. flexmock(module.feature).should_receive('available').and_return(True)
  105. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  106. flags = module.make_archive_filter_flags(
  107. '1.2.3',
  108. {'prefix': 'foo-'},
  109. ('data',),
  110. check_arguments=flexmock(match_archives=None),
  111. )
  112. assert flags == ('--match-archives', 'sh:foo-*')
  113. def test_make_archive_filter_flags_prefers_check_arguments_match_archives_to_config_match_archives():
  114. flexmock(module.feature).should_receive('available').and_return(True)
  115. flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
  116. 'baz-*', None, '1.2.3'
  117. ).and_return(('--match-archives', 'sh:baz-*'))
  118. flags = module.make_archive_filter_flags(
  119. '1.2.3',
  120. {'match_archives': 'bar-{now}', 'prefix': ''}, # noqa: FS003
  121. ('archives',),
  122. check_arguments=flexmock(match_archives='baz-*'),
  123. )
  124. assert flags == ('--match-archives', 'sh:baz-*')
  125. def test_make_archive_filter_flags_with_archives_check_and_empty_prefix_uses_archive_name_format_instead():
  126. flexmock(module.feature).should_receive('available').and_return(True)
  127. flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
  128. None, 'bar-{now}', '1.2.3' # noqa: FS003
  129. ).and_return(('--match-archives', 'sh:bar-*'))
  130. flags = module.make_archive_filter_flags(
  131. '1.2.3',
  132. {'archive_name_format': 'bar-{now}', 'prefix': ''}, # noqa: FS003
  133. ('archives',),
  134. check_arguments=flexmock(match_archives=None),
  135. )
  136. assert flags == ('--match-archives', 'sh:bar-*')
  137. def test_make_archive_filter_flags_with_archives_check_and_none_prefix_omits_match_archives_flag():
  138. flexmock(module.feature).should_receive('available').and_return(True)
  139. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  140. flags = module.make_archive_filter_flags(
  141. '1.2.3',
  142. {},
  143. ('archives',),
  144. check_arguments=flexmock(match_archives=None),
  145. )
  146. assert flags == ()
  147. def test_make_archive_filter_flags_with_repository_check_and_prefix_omits_match_archives_flag():
  148. flexmock(module.feature).should_receive('available').and_return(True)
  149. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  150. flags = module.make_archive_filter_flags(
  151. '1.2.3',
  152. {'prefix': 'foo-'},
  153. ('repository',),
  154. check_arguments=flexmock(match_archives=None),
  155. )
  156. assert flags == ()
  157. def test_make_archive_filter_flags_with_default_checks_and_prefix_includes_match_archives_flag():
  158. flexmock(module.feature).should_receive('available').and_return(True)
  159. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  160. flags = module.make_archive_filter_flags(
  161. '1.2.3',
  162. {'prefix': 'foo-'},
  163. ('repository', 'archives'),
  164. check_arguments=flexmock(match_archives=None),
  165. )
  166. assert flags == ('--match-archives', 'sh:foo-*')
  167. def test_make_check_name_flags_with_repository_check_returns_flag():
  168. flags = module.make_check_name_flags({'repository'}, ())
  169. assert flags == ('--repository-only',)
  170. def test_make_check_name_flags_with_archives_check_returns_flag():
  171. flags = module.make_check_name_flags({'archives'}, ())
  172. assert flags == ('--archives-only',)
  173. def test_make_check_name_flags_with_archives_check_and_archive_filter_flags_includes_those_flags():
  174. flags = module.make_check_name_flags({'archives'}, ('--match-archives', 'sh:foo-*'))
  175. assert flags == ('--archives-only', '--match-archives', 'sh:foo-*')
  176. def test_make_check_name_flags_without_archives_check_and_with_archive_filter_flags_includes_those_flags():
  177. flags = module.make_check_name_flags({'repository'}, ('--match-archives', 'sh:foo-*'))
  178. assert flags == ('--repository-only',)
  179. def test_make_check_name_flags_with_archives_and_data_check_returns_verify_data_flag():
  180. flexmock(module.feature).should_receive('available').and_return(True)
  181. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  182. flags = module.make_check_name_flags({'archives', 'data'}, ())
  183. assert flags == (
  184. '--archives-only',
  185. '--verify-data',
  186. )
  187. def test_make_check_name_flags_with_repository_and_data_check_returns_verify_data_flag():
  188. flexmock(module.feature).should_receive('available').and_return(True)
  189. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  190. flags = module.make_check_name_flags({'archives', 'data', 'repository'}, ())
  191. assert flags == ('--verify-data',)
  192. def test_make_check_name_flags_with_extract_omits_extract_flag():
  193. flexmock(module.feature).should_receive('available').and_return(True)
  194. flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
  195. flags = module.make_check_name_flags({'extract'}, ())
  196. assert flags == ()
  197. def test_get_repository_id_with_valid_json_does_not_raise():
  198. config = {}
  199. flexmock(module.repo_info).should_receive('display_repository_info').and_return(
  200. '{"repository": {"id": "repo"}}'
  201. )
  202. assert module.get_repository_id(
  203. repository_path='repo',
  204. config=config,
  205. local_borg_version='1.2.3',
  206. global_arguments=flexmock(log_json=False),
  207. local_path='borg',
  208. remote_path=None,
  209. )
  210. def test_get_repository_id_with_json_error_raises():
  211. config = {}
  212. flexmock(module.repo_info).should_receive('display_repository_info').and_return(
  213. '{"unexpected": {"id": "repo"}}'
  214. )
  215. with pytest.raises(ValueError):
  216. module.get_repository_id(
  217. repository_path='repo',
  218. config=config,
  219. local_borg_version='1.2.3',
  220. global_arguments=flexmock(log_json=False),
  221. local_path='borg',
  222. remote_path=None,
  223. )
  224. def test_get_repository_id_with_missing_json_keys_raises():
  225. config = {}
  226. flexmock(module.repo_info).should_receive('display_repository_info').and_return('{invalid JSON')
  227. with pytest.raises(ValueError):
  228. module.get_repository_id(
  229. repository_path='repo',
  230. config=config,
  231. local_borg_version='1.2.3',
  232. global_arguments=flexmock(log_json=False),
  233. local_path='borg',
  234. remote_path=None,
  235. )
  236. def test_check_archives_favors_progress_flag_over_config():
  237. config = {'progress': False}
  238. flexmock(module).should_receive('make_check_name_flags').with_args(
  239. {'repository'}, ()
  240. ).and_return(())
  241. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  242. flexmock(module.environment).should_receive('make_environment')
  243. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  244. flexmock(module).should_receive('execute_command').with_args(
  245. ('borg', 'check', '--progress', 'repo'),
  246. output_file=module.DO_NOT_CAPTURE,
  247. environment=None,
  248. working_directory=None,
  249. borg_local_path='borg',
  250. borg_exit_codes=None,
  251. ).once()
  252. module.check_archives(
  253. repository_path='repo',
  254. config=config,
  255. local_borg_version='1.2.3',
  256. check_arguments=flexmock(
  257. progress=True,
  258. repair=None,
  259. only_checks=None,
  260. force=None,
  261. match_archives=None,
  262. max_duration=None,
  263. ),
  264. global_arguments=flexmock(log_json=False),
  265. checks={'repository'},
  266. archive_filter_flags=(),
  267. )
  268. def test_check_archives_defaults_to_progress_config():
  269. config = {'progress': True}
  270. flexmock(module).should_receive('make_check_name_flags').with_args(
  271. {'repository'}, ()
  272. ).and_return(())
  273. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  274. flexmock(module.environment).should_receive('make_environment')
  275. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  276. flexmock(module).should_receive('execute_command').with_args(
  277. ('borg', 'check', '--progress', 'repo'),
  278. output_file=module.DO_NOT_CAPTURE,
  279. environment=None,
  280. working_directory=None,
  281. borg_local_path='borg',
  282. borg_exit_codes=None,
  283. ).once()
  284. module.check_archives(
  285. repository_path='repo',
  286. config=config,
  287. local_borg_version='1.2.3',
  288. check_arguments=flexmock(
  289. progress=None,
  290. repair=None,
  291. only_checks=None,
  292. force=None,
  293. match_archives=None,
  294. max_duration=None,
  295. ),
  296. global_arguments=flexmock(log_json=False),
  297. checks={'repository'},
  298. archive_filter_flags=(),
  299. )
  300. def test_check_archives_with_repair_passes_through_to_borg():
  301. config = {}
  302. flexmock(module).should_receive('make_check_name_flags').with_args(
  303. {'repository'}, ()
  304. ).and_return(())
  305. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  306. flexmock(module.environment).should_receive('make_environment')
  307. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  308. flexmock(module).should_receive('execute_command').with_args(
  309. ('borg', 'check', '--repair', 'repo'),
  310. output_file=module.DO_NOT_CAPTURE,
  311. environment=None,
  312. working_directory=None,
  313. borg_local_path='borg',
  314. borg_exit_codes=None,
  315. ).once()
  316. module.check_archives(
  317. repository_path='repo',
  318. config=config,
  319. local_borg_version='1.2.3',
  320. check_arguments=flexmock(
  321. progress=None,
  322. repair=True,
  323. only_checks=None,
  324. force=None,
  325. match_archives=None,
  326. max_duration=None,
  327. ),
  328. global_arguments=flexmock(log_json=False),
  329. checks={'repository'},
  330. archive_filter_flags=(),
  331. )
  332. def test_check_archives_with_max_duration_flag_passes_through_to_borg():
  333. config = {}
  334. flexmock(module).should_receive('make_check_name_flags').with_args(
  335. {'repository'}, ()
  336. ).and_return(())
  337. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  338. flexmock(module.environment).should_receive('make_environment')
  339. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  340. flexmock(module).should_receive('execute_command').with_args(
  341. ('borg', 'check', '--max-duration', '33', 'repo'),
  342. output_file=None,
  343. environment=None,
  344. working_directory=None,
  345. borg_local_path='borg',
  346. borg_exit_codes=None,
  347. ).once()
  348. module.check_archives(
  349. repository_path='repo',
  350. config=config,
  351. local_borg_version='1.2.3',
  352. check_arguments=flexmock(
  353. progress=None,
  354. repair=None,
  355. only_checks=None,
  356. force=None,
  357. match_archives=None,
  358. max_duration=33,
  359. ),
  360. global_arguments=flexmock(log_json=False),
  361. checks={'repository'},
  362. archive_filter_flags=(),
  363. )
  364. def test_check_archives_with_max_duration_option_passes_through_to_borg():
  365. config = {'checks': [{'name': 'repository', 'max_duration': 33}]}
  366. flexmock(module).should_receive('make_check_name_flags').with_args(
  367. {'repository'}, ()
  368. ).and_return(())
  369. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  370. flexmock(module.environment).should_receive('make_environment')
  371. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  372. flexmock(module).should_receive('execute_command').with_args(
  373. ('borg', 'check', '--max-duration', '33', 'repo'),
  374. output_file=None,
  375. environment=None,
  376. working_directory=None,
  377. borg_local_path='borg',
  378. borg_exit_codes=None,
  379. ).once()
  380. module.check_archives(
  381. repository_path='repo',
  382. config=config,
  383. local_borg_version='1.2.3',
  384. check_arguments=flexmock(
  385. progress=None,
  386. repair=None,
  387. only_checks=None,
  388. force=None,
  389. match_archives=None,
  390. max_duration=None,
  391. ),
  392. global_arguments=flexmock(log_json=False),
  393. checks={'repository'},
  394. archive_filter_flags=(),
  395. )
  396. def test_check_archives_with_max_duration_option_and_archives_check_runs_repository_check_separately():
  397. config = {'checks': [{'name': 'repository', 'max_duration': 33}, {'name': 'archives'}]}
  398. flexmock(module).should_receive('make_check_name_flags').with_args({'archives'}, ()).and_return(
  399. ('--archives-only',)
  400. )
  401. flexmock(module).should_receive('make_check_name_flags').with_args(
  402. {'repository'}, ()
  403. ).and_return(('--repository-only',))
  404. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  405. insert_execute_command_mock(('borg', 'check', '--archives-only', 'repo'))
  406. insert_execute_command_mock(
  407. ('borg', 'check', '--max-duration', '33', '--repository-only', 'repo')
  408. )
  409. module.check_archives(
  410. repository_path='repo',
  411. config=config,
  412. local_borg_version='1.2.3',
  413. check_arguments=flexmock(
  414. progress=None,
  415. repair=None,
  416. only_checks=None,
  417. force=None,
  418. match_archives=None,
  419. max_duration=None,
  420. ),
  421. global_arguments=flexmock(log_json=False),
  422. checks={'repository', 'archives'},
  423. archive_filter_flags=(),
  424. )
  425. def test_check_archives_with_max_duration_flag_and_archives_check_runs_repository_check_separately():
  426. config = {'checks': [{'name': 'repository'}, {'name': 'archives'}]}
  427. flexmock(module).should_receive('make_check_name_flags').with_args({'archives'}, ()).and_return(
  428. ('--archives-only',)
  429. )
  430. flexmock(module).should_receive('make_check_name_flags').with_args(
  431. {'repository'}, ()
  432. ).and_return(('--repository-only',))
  433. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  434. insert_execute_command_mock(('borg', 'check', '--archives-only', 'repo'))
  435. insert_execute_command_mock(
  436. ('borg', 'check', '--max-duration', '33', '--repository-only', 'repo')
  437. )
  438. module.check_archives(
  439. repository_path='repo',
  440. config=config,
  441. local_borg_version='1.2.3',
  442. check_arguments=flexmock(
  443. progress=None,
  444. repair=None,
  445. only_checks=None,
  446. force=None,
  447. match_archives=None,
  448. max_duration=33,
  449. ),
  450. global_arguments=flexmock(log_json=False),
  451. checks={'repository', 'archives'},
  452. archive_filter_flags=(),
  453. )
  454. def test_check_archives_with_max_duration_option_and_data_check_runs_repository_check_separately():
  455. config = {'checks': [{'name': 'repository', 'max_duration': 33}, {'name': 'data'}]}
  456. flexmock(module).should_receive('make_check_name_flags').with_args(
  457. {'data', 'archives'}, ()
  458. ).and_return(('--archives-only', '--verify-data'))
  459. flexmock(module).should_receive('make_check_name_flags').with_args(
  460. {'repository'}, ()
  461. ).and_return(('--repository-only',))
  462. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  463. insert_execute_command_mock(('borg', 'check', '--archives-only', '--verify-data', 'repo'))
  464. insert_execute_command_mock(
  465. ('borg', 'check', '--max-duration', '33', '--repository-only', 'repo')
  466. )
  467. module.check_archives(
  468. repository_path='repo',
  469. config=config,
  470. local_borg_version='1.2.3',
  471. check_arguments=flexmock(
  472. progress=None,
  473. repair=None,
  474. only_checks=None,
  475. force=None,
  476. match_archives=None,
  477. max_duration=None,
  478. ),
  479. global_arguments=flexmock(log_json=False),
  480. checks={'repository', 'data'},
  481. archive_filter_flags=(),
  482. )
  483. def test_check_archives_with_max_duration_flag_and_data_check_runs_repository_check_separately():
  484. config = {'checks': [{'name': 'repository'}, {'name': 'data'}]}
  485. flexmock(module).should_receive('make_check_name_flags').with_args(
  486. {'data', 'archives'}, ()
  487. ).and_return(('--archives-only', '--verify-data'))
  488. flexmock(module).should_receive('make_check_name_flags').with_args(
  489. {'repository'}, ()
  490. ).and_return(('--repository-only',))
  491. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  492. insert_execute_command_mock(('borg', 'check', '--archives-only', '--verify-data', 'repo'))
  493. insert_execute_command_mock(
  494. ('borg', 'check', '--max-duration', '33', '--repository-only', 'repo')
  495. )
  496. module.check_archives(
  497. repository_path='repo',
  498. config=config,
  499. local_borg_version='1.2.3',
  500. check_arguments=flexmock(
  501. progress=None,
  502. repair=None,
  503. only_checks=None,
  504. force=None,
  505. match_archives=None,
  506. max_duration=33,
  507. ),
  508. global_arguments=flexmock(log_json=False),
  509. checks={'repository', 'data'},
  510. archive_filter_flags=(),
  511. )
  512. def test_check_archives_with_max_duration_flag_overrides_max_duration_option():
  513. config = {'checks': [{'name': 'repository', 'max_duration': 33}]}
  514. flexmock(module).should_receive('make_check_name_flags').with_args(
  515. {'repository'}, ()
  516. ).and_return(())
  517. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  518. flexmock(module.environment).should_receive('make_environment')
  519. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  520. flexmock(module).should_receive('execute_command').with_args(
  521. ('borg', 'check', '--max-duration', '44', 'repo'),
  522. output_file=None,
  523. environment=None,
  524. working_directory=None,
  525. borg_local_path='borg',
  526. borg_exit_codes=None,
  527. ).once()
  528. module.check_archives(
  529. repository_path='repo',
  530. config=config,
  531. local_borg_version='1.2.3',
  532. check_arguments=flexmock(
  533. progress=None,
  534. repair=None,
  535. only_checks=None,
  536. force=None,
  537. match_archives=None,
  538. max_duration=44,
  539. ),
  540. global_arguments=flexmock(log_json=False),
  541. checks={'repository'},
  542. archive_filter_flags=(),
  543. )
  544. @pytest.mark.parametrize(
  545. 'checks',
  546. (
  547. ('repository',),
  548. ('archives',),
  549. ('repository', 'archives'),
  550. ('repository', 'archives', 'other'),
  551. ),
  552. )
  553. def test_check_archives_calls_borg_with_parameters(checks):
  554. config = {}
  555. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  556. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  557. insert_execute_command_mock(('borg', 'check', 'repo'))
  558. module.check_archives(
  559. repository_path='repo',
  560. config=config,
  561. local_borg_version='1.2.3',
  562. check_arguments=flexmock(
  563. progress=None,
  564. repair=None,
  565. only_checks=None,
  566. force=None,
  567. match_archives=None,
  568. max_duration=None,
  569. ),
  570. global_arguments=flexmock(log_json=False),
  571. checks=checks,
  572. archive_filter_flags=(),
  573. )
  574. def test_check_archives_with_data_check_implies_archives_check_calls_borg_with_parameters():
  575. config = {}
  576. flexmock(module).should_receive('make_check_name_flags').with_args(
  577. {'data', 'archives'}, ()
  578. ).and_return(())
  579. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  580. insert_execute_command_mock(('borg', 'check', 'repo'))
  581. module.check_archives(
  582. repository_path='repo',
  583. config=config,
  584. local_borg_version='1.2.3',
  585. check_arguments=flexmock(
  586. progress=None,
  587. repair=None,
  588. only_checks=None,
  589. force=None,
  590. match_archives=None,
  591. max_duration=None,
  592. ),
  593. global_arguments=flexmock(log_json=False),
  594. checks={'data'},
  595. archive_filter_flags=(),
  596. )
  597. def test_check_archives_with_log_info_passes_through_to_borg():
  598. config = {}
  599. flexmock(module).should_receive('make_check_name_flags').with_args(
  600. {'repository'}, ()
  601. ).and_return(())
  602. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  603. insert_logging_mock(logging.INFO)
  604. insert_execute_command_mock(('borg', 'check', '--info', 'repo'))
  605. module.check_archives(
  606. repository_path='repo',
  607. config=config,
  608. local_borg_version='1.2.3',
  609. check_arguments=flexmock(
  610. progress=None,
  611. repair=None,
  612. only_checks=None,
  613. force=None,
  614. match_archives=None,
  615. max_duration=None,
  616. ),
  617. global_arguments=flexmock(log_json=False),
  618. checks={'repository'},
  619. archive_filter_flags=(),
  620. )
  621. def test_check_archives_with_log_debug_passes_through_to_borg():
  622. config = {}
  623. flexmock(module).should_receive('make_check_name_flags').with_args(
  624. {'repository'}, ()
  625. ).and_return(())
  626. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  627. insert_logging_mock(logging.DEBUG)
  628. insert_execute_command_mock(('borg', 'check', '--debug', '--show-rc', 'repo'))
  629. module.check_archives(
  630. repository_path='repo',
  631. config=config,
  632. local_borg_version='1.2.3',
  633. check_arguments=flexmock(
  634. progress=None,
  635. repair=None,
  636. only_checks=None,
  637. force=None,
  638. match_archives=None,
  639. max_duration=None,
  640. ),
  641. global_arguments=flexmock(log_json=False),
  642. checks={'repository'},
  643. archive_filter_flags=(),
  644. )
  645. def test_check_archives_with_local_path_calls_borg_via_local_path():
  646. checks = {'repository'}
  647. config = {}
  648. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  649. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  650. insert_execute_command_mock(('borg1', 'check', 'repo'))
  651. module.check_archives(
  652. repository_path='repo',
  653. config=config,
  654. local_borg_version='1.2.3',
  655. check_arguments=flexmock(
  656. progress=None,
  657. repair=None,
  658. only_checks=None,
  659. force=None,
  660. match_archives=None,
  661. max_duration=None,
  662. ),
  663. global_arguments=flexmock(log_json=False),
  664. checks=checks,
  665. archive_filter_flags=(),
  666. local_path='borg1',
  667. )
  668. def test_check_archives_with_exit_codes_calls_borg_using_them():
  669. checks = {'repository'}
  670. borg_exit_codes = flexmock()
  671. config = {'borg_exit_codes': borg_exit_codes}
  672. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  673. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  674. insert_execute_command_mock(('borg', 'check', 'repo'), borg_exit_codes=borg_exit_codes)
  675. module.check_archives(
  676. repository_path='repo',
  677. config=config,
  678. local_borg_version='1.2.3',
  679. check_arguments=flexmock(
  680. progress=None,
  681. repair=None,
  682. only_checks=None,
  683. force=None,
  684. match_archives=None,
  685. max_duration=None,
  686. ),
  687. global_arguments=flexmock(log_json=False),
  688. checks=checks,
  689. archive_filter_flags=(),
  690. )
  691. def test_check_archives_with_remote_path_passes_through_to_borg():
  692. checks = {'repository'}
  693. config = {}
  694. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  695. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  696. insert_execute_command_mock(('borg', 'check', '--remote-path', 'borg1', 'repo'))
  697. module.check_archives(
  698. repository_path='repo',
  699. config=config,
  700. local_borg_version='1.2.3',
  701. check_arguments=flexmock(
  702. progress=None,
  703. repair=None,
  704. only_checks=None,
  705. force=None,
  706. match_archives=None,
  707. max_duration=None,
  708. ),
  709. global_arguments=flexmock(log_json=False),
  710. checks=checks,
  711. archive_filter_flags=(),
  712. remote_path='borg1',
  713. )
  714. def test_check_archives_with_umask_passes_through_to_borg():
  715. checks = {'repository'}
  716. config = {'umask': '077'}
  717. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  718. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  719. insert_execute_command_mock(('borg', 'check', '--umask', '077', 'repo'))
  720. module.check_archives(
  721. repository_path='repo',
  722. config=config,
  723. local_borg_version='1.2.3',
  724. check_arguments=flexmock(
  725. progress=None,
  726. repair=None,
  727. only_checks=None,
  728. force=None,
  729. match_archives=None,
  730. max_duration=None,
  731. ),
  732. global_arguments=flexmock(log_json=False),
  733. checks=checks,
  734. archive_filter_flags=(),
  735. )
  736. def test_check_archives_with_log_json_passes_through_to_borg():
  737. checks = {'repository'}
  738. config = {}
  739. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  740. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  741. insert_execute_command_mock(('borg', 'check', '--log-json', 'repo'))
  742. module.check_archives(
  743. repository_path='repo',
  744. config=config,
  745. local_borg_version='1.2.3',
  746. check_arguments=flexmock(
  747. progress=None,
  748. repair=None,
  749. only_checks=None,
  750. force=None,
  751. match_archives=None,
  752. max_duration=None,
  753. ),
  754. global_arguments=flexmock(log_json=True),
  755. checks=checks,
  756. archive_filter_flags=(),
  757. )
  758. def test_check_archives_with_lock_wait_passes_through_to_borg():
  759. checks = {'repository'}
  760. config = {'lock_wait': 5}
  761. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  762. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  763. insert_execute_command_mock(('borg', 'check', '--lock-wait', '5', 'repo'))
  764. module.check_archives(
  765. repository_path='repo',
  766. config=config,
  767. local_borg_version='1.2.3',
  768. check_arguments=flexmock(
  769. progress=None,
  770. repair=None,
  771. only_checks=None,
  772. force=None,
  773. match_archives=None,
  774. max_duration=None,
  775. ),
  776. global_arguments=flexmock(log_json=False),
  777. checks=checks,
  778. archive_filter_flags=(),
  779. )
  780. def test_check_archives_with_retention_prefix():
  781. checks = {'repository'}
  782. prefix = 'foo-'
  783. config = {'prefix': prefix}
  784. flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
  785. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  786. insert_execute_command_mock(('borg', 'check', 'repo'))
  787. module.check_archives(
  788. repository_path='repo',
  789. config=config,
  790. local_borg_version='1.2.3',
  791. check_arguments=flexmock(
  792. progress=None,
  793. repair=None,
  794. only_checks=None,
  795. force=None,
  796. match_archives=None,
  797. max_duration=None,
  798. ),
  799. global_arguments=flexmock(log_json=False),
  800. checks=checks,
  801. archive_filter_flags=(),
  802. )
  803. def test_check_archives_with_extra_borg_options_passes_through_to_borg():
  804. config = {'extra_borg_options': {'check': '--extra --options'}}
  805. flexmock(module).should_receive('make_check_name_flags').with_args(
  806. {'repository'}, ()
  807. ).and_return(())
  808. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  809. insert_execute_command_mock(('borg', 'check', '--extra', '--options', 'repo'))
  810. module.check_archives(
  811. repository_path='repo',
  812. config=config,
  813. local_borg_version='1.2.3',
  814. check_arguments=flexmock(
  815. progress=None,
  816. repair=None,
  817. only_checks=None,
  818. force=None,
  819. match_archives=None,
  820. max_duration=None,
  821. ),
  822. global_arguments=flexmock(log_json=False),
  823. checks={'repository'},
  824. archive_filter_flags=(),
  825. )
  826. def test_check_archives_with_match_archives_passes_through_to_borg():
  827. config = {'checks': [{'name': 'archives'}]}
  828. flexmock(module).should_receive('make_check_name_flags').with_args(
  829. {'archives'}, object
  830. ).and_return(('--match-archives', 'foo-*'))
  831. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  832. flexmock(module.environment).should_receive('make_environment')
  833. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  834. flexmock(module).should_receive('execute_command').with_args(
  835. ('borg', 'check', '--match-archives', 'foo-*', 'repo'),
  836. output_file=None,
  837. environment=None,
  838. working_directory=None,
  839. borg_local_path='borg',
  840. borg_exit_codes=None,
  841. ).once()
  842. module.check_archives(
  843. repository_path='repo',
  844. config=config,
  845. local_borg_version='1.2.3',
  846. check_arguments=flexmock(
  847. progress=None,
  848. repair=None,
  849. only_checks=None,
  850. force=None,
  851. match_archives='foo-*',
  852. max_duration=None,
  853. ),
  854. global_arguments=flexmock(log_json=False),
  855. checks={'archives'},
  856. archive_filter_flags=('--match-archives', 'foo-*'),
  857. )
  858. def test_check_archives_calls_borg_with_working_directory():
  859. config = {'working_directory': '/working/dir'}
  860. flexmock(module).should_receive('make_check_name_flags').with_args(
  861. {'repository'}, ()
  862. ).and_return(())
  863. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  864. flexmock(module.environment).should_receive('make_environment')
  865. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  866. insert_execute_command_mock(('borg', 'check', 'repo'), working_directory='/working/dir')
  867. module.check_archives(
  868. repository_path='repo',
  869. config=config,
  870. local_borg_version='1.2.3',
  871. check_arguments=flexmock(
  872. progress=False,
  873. repair=None,
  874. only_checks=None,
  875. force=None,
  876. match_archives=None,
  877. max_duration=None,
  878. ),
  879. global_arguments=flexmock(log_json=False),
  880. checks={'repository'},
  881. archive_filter_flags=(),
  882. )