test_check.py 44 KB

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