test_shared.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. from collections import OrderedDict
  2. import os
  3. from flexmock import flexmock
  4. from atticmatic.backends import shared as module
  5. from atticmatic.tests.builtins import builtins_mock
  6. from atticmatic.verbosity import VERBOSITY_SOME, VERBOSITY_LOTS
  7. def test_initialize_with_passphrase_should_set_environment():
  8. orig_environ = os.environ
  9. try:
  10. os.environ = {}
  11. module.initialize({'encryption_passphrase': 'pass'}, command='attic')
  12. assert os.environ.get('ATTIC_PASSPHRASE') == 'pass'
  13. finally:
  14. os.environ = orig_environ
  15. def test_initialize_without_passphrase_should_not_set_environment():
  16. orig_environ = os.environ
  17. try:
  18. os.environ = {}
  19. module.initialize({}, command='attic')
  20. assert os.environ.get('ATTIC_PASSPHRASE') == None
  21. finally:
  22. os.environ = orig_environ
  23. def insert_subprocess_mock(check_call_command, **kwargs):
  24. subprocess = flexmock()
  25. subprocess.should_receive('check_call').with_args(check_call_command, **kwargs).once()
  26. flexmock(module).subprocess = subprocess
  27. def insert_subprocess_never():
  28. subprocess = flexmock()
  29. subprocess.should_receive('check_call').never()
  30. flexmock(module).subprocess = subprocess
  31. def insert_platform_mock():
  32. flexmock(module.platform).should_receive('node').and_return('host')
  33. def insert_datetime_mock():
  34. flexmock(module).datetime = flexmock().should_receive('now').and_return(
  35. flexmock().should_receive('isoformat').and_return('now').mock
  36. ).mock
  37. CREATE_COMMAND_WITHOUT_EXCLUDES = ('attic', 'create', 'repo::host-now', 'foo', 'bar')
  38. CREATE_COMMAND = CREATE_COMMAND_WITHOUT_EXCLUDES + ('--exclude-from', 'excludes')
  39. def test_create_archive_should_call_attic_with_parameters():
  40. insert_subprocess_mock(CREATE_COMMAND)
  41. insert_platform_mock()
  42. insert_datetime_mock()
  43. module.create_archive(
  44. excludes_filename='excludes',
  45. verbosity=None,
  46. storage_config={},
  47. source_directories='foo bar',
  48. repository='repo',
  49. command='attic',
  50. )
  51. def test_create_archive_with_two_spaces_in_source_directories():
  52. insert_subprocess_mock(CREATE_COMMAND)
  53. insert_platform_mock()
  54. insert_datetime_mock()
  55. module.create_archive(
  56. excludes_filename='excludes',
  57. verbosity=None,
  58. storage_config={},
  59. source_directories='foo bar',
  60. repository='repo',
  61. command='attic',
  62. )
  63. def test_create_archive_with_none_excludes_filename_should_call_attic_without_excludes():
  64. insert_subprocess_mock(CREATE_COMMAND_WITHOUT_EXCLUDES)
  65. insert_platform_mock()
  66. insert_datetime_mock()
  67. module.create_archive(
  68. excludes_filename=None,
  69. verbosity=None,
  70. storage_config={},
  71. source_directories='foo bar',
  72. repository='repo',
  73. command='attic',
  74. )
  75. def test_create_archive_with_verbosity_some_should_call_attic_with_stats_parameter():
  76. insert_subprocess_mock(CREATE_COMMAND + ('--stats',))
  77. insert_platform_mock()
  78. insert_datetime_mock()
  79. module.create_archive(
  80. excludes_filename='excludes',
  81. verbosity=VERBOSITY_SOME,
  82. storage_config={},
  83. source_directories='foo bar',
  84. repository='repo',
  85. command='attic',
  86. )
  87. def test_create_archive_with_verbosity_lots_should_call_attic_with_verbose_parameter():
  88. insert_subprocess_mock(CREATE_COMMAND + ('--verbose', '--stats'))
  89. insert_platform_mock()
  90. insert_datetime_mock()
  91. module.create_archive(
  92. excludes_filename='excludes',
  93. verbosity=VERBOSITY_LOTS,
  94. storage_config={},
  95. source_directories='foo bar',
  96. repository='repo',
  97. command='attic',
  98. )
  99. def test_create_archive_with_compression_should_call_attic_with_compression_parameters():
  100. insert_subprocess_mock(CREATE_COMMAND + ('--compression', 'rle'))
  101. insert_platform_mock()
  102. insert_datetime_mock()
  103. module.create_archive(
  104. excludes_filename='excludes',
  105. verbosity=None,
  106. storage_config={'compression': 'rle'},
  107. source_directories='foo bar',
  108. repository='repo',
  109. command='attic',
  110. )
  111. def test_create_archive_with_one_file_system_should_call_attic_with_one_file_system_parameters():
  112. insert_subprocess_mock(CREATE_COMMAND + ('--one-file-system',))
  113. insert_platform_mock()
  114. insert_datetime_mock()
  115. module.create_archive(
  116. excludes_filename='excludes',
  117. verbosity=None,
  118. storage_config={},
  119. source_directories='foo bar',
  120. repository='repo',
  121. command='attic',
  122. one_file_system=True,
  123. )
  124. def test_create_archive_with_umask_should_call_attic_with_umask_parameters():
  125. insert_subprocess_mock(CREATE_COMMAND + ('--umask', '740'))
  126. insert_platform_mock()
  127. insert_datetime_mock()
  128. module.create_archive(
  129. excludes_filename='excludes',
  130. verbosity=None,
  131. storage_config={'umask': 740},
  132. source_directories='foo bar',
  133. repository='repo',
  134. command='attic',
  135. )
  136. def test_create_archive_with_source_directories_glob_expands():
  137. insert_subprocess_mock(('attic', 'create', 'repo::host-now', 'foo', 'food'))
  138. insert_platform_mock()
  139. insert_datetime_mock()
  140. flexmock(module).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
  141. module.create_archive(
  142. excludes_filename=None,
  143. verbosity=None,
  144. storage_config={},
  145. source_directories='foo*',
  146. repository='repo',
  147. command='attic',
  148. )
  149. def test_create_archive_with_non_matching_source_directories_glob_passes_through():
  150. insert_subprocess_mock(('attic', 'create', 'repo::host-now', 'foo*'))
  151. insert_platform_mock()
  152. insert_datetime_mock()
  153. flexmock(module).should_receive('glob').with_args('foo*').and_return([])
  154. module.create_archive(
  155. excludes_filename=None,
  156. verbosity=None,
  157. storage_config={},
  158. source_directories='foo*',
  159. repository='repo',
  160. command='attic',
  161. )
  162. def test_create_archive_with_glob_should_call_attic_with_expanded_directories():
  163. insert_subprocess_mock(('attic', 'create', 'repo::host-now', 'foo', 'food'))
  164. insert_platform_mock()
  165. insert_datetime_mock()
  166. flexmock(module).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
  167. module.create_archive(
  168. excludes_filename=None,
  169. verbosity=None,
  170. storage_config={},
  171. source_directories='foo*',
  172. repository='repo',
  173. command='attic',
  174. )
  175. BASE_PRUNE_FLAGS = (
  176. ('--keep-daily', '1'),
  177. ('--keep-weekly', '2'),
  178. ('--keep-monthly', '3'),
  179. )
  180. def test_make_prune_flags_should_return_flags_from_config():
  181. retention_config = OrderedDict(
  182. (
  183. ('keep_daily', 1),
  184. ('keep_weekly', 2),
  185. ('keep_monthly', 3),
  186. )
  187. )
  188. result = module._make_prune_flags(retention_config)
  189. assert tuple(result) == BASE_PRUNE_FLAGS
  190. PRUNE_COMMAND = (
  191. 'attic', 'prune', 'repo', '--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3',
  192. )
  193. def test_prune_archives_should_call_attic_with_parameters():
  194. retention_config = flexmock()
  195. flexmock(module).should_receive('_make_prune_flags').with_args(retention_config).and_return(
  196. BASE_PRUNE_FLAGS,
  197. )
  198. insert_subprocess_mock(PRUNE_COMMAND)
  199. module.prune_archives(
  200. verbosity=None,
  201. repository='repo',
  202. retention_config=retention_config,
  203. command='attic',
  204. )
  205. def test_prune_archives_with_verbosity_some_should_call_attic_with_stats_parameter():
  206. retention_config = flexmock()
  207. flexmock(module).should_receive('_make_prune_flags').with_args(retention_config).and_return(
  208. BASE_PRUNE_FLAGS,
  209. )
  210. insert_subprocess_mock(PRUNE_COMMAND + ('--stats',))
  211. module.prune_archives(
  212. repository='repo',
  213. verbosity=VERBOSITY_SOME,
  214. retention_config=retention_config,
  215. command='attic',
  216. )
  217. def test_prune_archives_with_verbosity_lots_should_call_attic_with_verbose_parameter():
  218. retention_config = flexmock()
  219. flexmock(module).should_receive('_make_prune_flags').with_args(retention_config).and_return(
  220. BASE_PRUNE_FLAGS,
  221. )
  222. insert_subprocess_mock(PRUNE_COMMAND + ('--verbose', '--stats',))
  223. module.prune_archives(
  224. repository='repo',
  225. verbosity=VERBOSITY_LOTS,
  226. retention_config=retention_config,
  227. command='attic',
  228. )
  229. def test_parse_checks_returns_them_as_tuple():
  230. checks = module._parse_checks({'checks': 'foo disabled bar'})
  231. assert checks == ('foo', 'bar')
  232. def test_parse_checks_with_missing_value_returns_defaults():
  233. checks = module._parse_checks({})
  234. assert checks == module.DEFAULT_CHECKS
  235. def test_parse_checks_with_blank_value_returns_defaults():
  236. checks = module._parse_checks({'checks': ''})
  237. assert checks == module.DEFAULT_CHECKS
  238. def test_parse_checks_with_disabled_returns_no_checks():
  239. checks = module._parse_checks({'checks': 'disabled'})
  240. assert checks == ()
  241. def test_make_check_flags_with_checks_returns_flags():
  242. flags = module._make_check_flags(('foo', 'bar'))
  243. assert flags == ('--foo-only', '--bar-only')
  244. def test_make_check_flags_with_default_checks_returns_no_flags():
  245. flags = module._make_check_flags(module.DEFAULT_CHECKS)
  246. assert flags == ()
  247. def test_make_check_flags_with_checks_and_last_returns_flags_including_last():
  248. flags = module._make_check_flags(('foo', 'bar'), check_last=3)
  249. assert flags == ('--foo-only', '--bar-only', '--last', 3)
  250. def test_make_check_flags_with_last_returns_last_flag():
  251. flags = module._make_check_flags(module.DEFAULT_CHECKS, check_last=3)
  252. assert flags == ('--last', 3)
  253. def test_check_archives_should_call_attic_with_parameters():
  254. checks = flexmock()
  255. check_last = flexmock()
  256. consistency_config = flexmock().should_receive('get').and_return(check_last).mock
  257. flexmock(module).should_receive('_parse_checks').and_return(checks)
  258. flexmock(module).should_receive('_make_check_flags').with_args(checks, check_last).and_return(())
  259. stdout = flexmock()
  260. insert_subprocess_mock(
  261. ('attic', 'check', 'repo'),
  262. stdout=stdout,
  263. )
  264. insert_platform_mock()
  265. insert_datetime_mock()
  266. builtins_mock().should_receive('open').and_return(stdout)
  267. flexmock(module.os).should_receive('devnull')
  268. module.check_archives(
  269. verbosity=None,
  270. repository='repo',
  271. consistency_config=consistency_config,
  272. command='attic',
  273. )
  274. def test_check_archives_with_verbosity_some_should_call_attic_with_verbose_parameter():
  275. consistency_config = flexmock().should_receive('get').and_return(None).mock
  276. flexmock(module).should_receive('_parse_checks').and_return(flexmock())
  277. flexmock(module).should_receive('_make_check_flags').and_return(())
  278. insert_subprocess_mock(
  279. ('attic', 'check', 'repo', '--verbose'),
  280. stdout=None,
  281. )
  282. insert_platform_mock()
  283. insert_datetime_mock()
  284. module.check_archives(
  285. verbosity=VERBOSITY_SOME,
  286. repository='repo',
  287. consistency_config=consistency_config,
  288. command='attic',
  289. )
  290. def test_check_archives_with_verbosity_lots_should_call_attic_with_verbose_parameter():
  291. consistency_config = flexmock().should_receive('get').and_return(None).mock
  292. flexmock(module).should_receive('_parse_checks').and_return(flexmock())
  293. flexmock(module).should_receive('_make_check_flags').and_return(())
  294. insert_subprocess_mock(
  295. ('attic', 'check', 'repo', '--verbose'),
  296. stdout=None,
  297. )
  298. insert_platform_mock()
  299. insert_datetime_mock()
  300. module.check_archives(
  301. verbosity=VERBOSITY_LOTS,
  302. repository='repo',
  303. consistency_config=consistency_config,
  304. command='attic',
  305. )
  306. def test_check_archives_without_any_checks_should_bail():
  307. consistency_config = flexmock().should_receive('get').and_return(None).mock
  308. flexmock(module).should_receive('_parse_checks').and_return(())
  309. insert_subprocess_never()
  310. module.check_archives(
  311. verbosity=None,
  312. repository='repo',
  313. consistency_config=consistency_config,
  314. command='attic',
  315. )