test_version.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. # -*- coding: utf-8 -*-
  2. '''
  3. :codeauthor: Pedro Algarvio (pedro@algarvio.me)
  4. tests.unit.version_test
  5. ~~~~~~~~~~~~~~~~~~~~~~~
  6. Test salt's regex git describe version parsing
  7. '''
  8. # Import python libs
  9. from __future__ import absolute_import
  10. import re
  11. # Import Salt Testing libs
  12. from tests.support.unit import TestCase
  13. from tests.support.mock import MagicMock, patch
  14. # Import Salt libs
  15. from salt.version import SaltStackVersion, versions_report
  16. import salt.version
  17. class VersionTestCase(TestCase):
  18. def test_version_parsing(self):
  19. strip_initial_non_numbers_regex = re.compile(r'(?:[^\d]+)?(?P<vs>.*)')
  20. expect = (
  21. ('v0.12.0-19-g767d4f9', (0, 12, 0, 0, '', 0, 19, 'g767d4f9'), None),
  22. ('v0.12.0-85-g2880105', (0, 12, 0, 0, '', 0, 85, 'g2880105'), None),
  23. ('debian/0.11.1+ds-1-3-ga0afcbd',
  24. (0, 11, 1, 0, '', 0, 3, 'ga0afcbd'), '0.11.1-3-ga0afcbd'),
  25. ('0.12.1', (0, 12, 1, 0, '', 0, 0, None), None),
  26. ('0.12.1', (0, 12, 1, 0, '', 0, 0, None), None),
  27. ('0.17.0rc1', (0, 17, 0, 0, 'rc', 1, 0, None), None),
  28. ('v0.17.0rc1-1-g52ebdfd', (0, 17, 0, 0, 'rc', 1, 1, 'g52ebdfd'), None),
  29. ('v2014.1.4.1', (2014, 1, 4, 1, '', 0, 0, None), None),
  30. ('v2014.1.4.1rc3-n/a-abcdefff', (2014, 1, 4, 1, 'rc', 3, -1, 'abcdefff'), None),
  31. ('v3.4.1.1', (3, 4, 1, 1, '', 0, 0, None), None),
  32. ('v3000', (3000, '', 0, 0, None), '3000'),
  33. ('v3000.0', (3000, '', 0, 0, None), '3000'),
  34. ('v4518.1', (4518, 1, '', 0, 0, None), '4518.1'),
  35. ('v3000rc1', (3000, 'rc', 1, 0, None), '3000rc1'),
  36. ('v3000rc1-n/a-abcdefff', (3000, 'rc', 1, -1, 'abcdefff'), None),
  37. ('3000-n/a-1e7bc8f', (3000, '', 0, -1, '1e7bc8f'), None),
  38. ('3000.1-n/a-1e7bc8f', (3000, 1, '', 0, -1, '1e7bc8f'), None),
  39. )
  40. for vstr, full_info, version in expect:
  41. saltstack_version = SaltStackVersion.parse(vstr)
  42. self.assertEqual(
  43. saltstack_version.full_info, full_info
  44. )
  45. if version is None:
  46. version = strip_initial_non_numbers_regex.search(vstr).group('vs')
  47. self.assertEqual(saltstack_version.string, version)
  48. def test_version_comparison(self):
  49. examples = (
  50. ('debian/0.11.1+ds-1-3-ga0afcbd', '0.11.1+ds-2'),
  51. ('v0.12.0-85-g2880105', 'v0.12.0-19-g767d4f9'),
  52. ('v0.17.0rc1-1-g52ebdfd', '0.17.0rc1'),
  53. ('v0.17.0', 'v0.17.0rc1'),
  54. ('Hydrogen', '0.17.0'),
  55. ('Helium', 'Hydrogen'),
  56. ('v2014.1.4.1-n/a-abcdefff', 'v2014.1.4.1rc3-n/a-abcdefff'),
  57. ('v2014.1.4.1-1-abcdefff', 'v2014.1.4.1-n/a-abcdefff'),
  58. ('v2016.12.0rc1', 'v2016.12.0b1'),
  59. ('v2016.12.0beta1', 'v2016.12.0alpha1'),
  60. ('v2016.12.0alpha1', 'v2016.12.0alpha0'),
  61. ('v3000.1', 'v3000'),
  62. ('v3000rc2', 'v3000rc1'),
  63. ('v3001', 'v3000'),
  64. ('v4023rc1', 'v4022rc1'),
  65. ('v3000', 'v3000rc1'),
  66. ('v3000', 'v2019.2.1'),
  67. ('v3000.1', 'v2019.2.1'),
  68. # we created v3000.0rc1 tag on repo
  69. # but we should not be using this
  70. # version scheme in the future
  71. # but still adding test for it
  72. ('v3000', 'v3000.0rc1'),
  73. ('v3000.1rc1', 'v3000.0rc1'),
  74. ('v3000', 'v2019.2.1rc1'),
  75. ('v3001rc1', 'v2019.2.1rc1'),
  76. )
  77. for higher_version, lower_version in examples:
  78. self.assertTrue(SaltStackVersion.parse(higher_version) > lower_version)
  79. self.assertTrue(SaltStackVersion.parse(lower_version) < higher_version)
  80. assert SaltStackVersion.parse(lower_version) != higher_version
  81. def test_unparsable_version(self):
  82. with self.assertRaises(ValueError):
  83. SaltStackVersion.from_name('Drunk')
  84. with self.assertRaises(ValueError):
  85. SaltStackVersion.parse('Drunk')
  86. def test_sha(self):
  87. '''
  88. test matching sha's
  89. '''
  90. exp_ret = (
  91. ('d6cd1e2bd19e03a81132a23b2025920577f84e37', True),
  92. ('2880105', True),
  93. ('v3000.0.1', False),
  94. ('v0.12.0-85-g2880105', False)
  95. )
  96. for commit, exp in exp_ret:
  97. ret = SaltStackVersion.git_sha_regex.match(commit)
  98. if exp:
  99. assert ret
  100. else:
  101. assert not ret
  102. def test_version_report_lines(self):
  103. '''
  104. Validate padding in versions report is correct
  105. '''
  106. # Get a set of all version report name lenghts including padding
  107. line_lengths = set([
  108. len(line.split(':')[0]) for line in list(versions_report())[4:]
  109. if line != ' ' and line != 'System Versions:'
  110. ])
  111. # Check that they are all the same size (only one element in the set)
  112. assert len(line_lengths) == 1
  113. def test_string_new_version(self):
  114. '''
  115. Validate string property method
  116. using new versioning scheme
  117. '''
  118. maj_ver = '3000'
  119. ver = SaltStackVersion(major=maj_ver)
  120. assert not ver.minor
  121. assert not ver.bugfix
  122. assert maj_ver == ver.string
  123. def test_string_new_version_minor(self):
  124. '''
  125. Validate string property method
  126. using new versioning scheme alongside
  127. minor version
  128. '''
  129. maj_ver = 3000
  130. min_ver = 1
  131. ver = SaltStackVersion(major=maj_ver, minor=min_ver)
  132. assert ver.minor == min_ver
  133. assert not ver.bugfix
  134. assert ver.string == '{0}.{1}'.format(maj_ver, min_ver)
  135. def test_string_new_version_minor_as_string(self):
  136. '''
  137. Validate string property method
  138. using new versioning scheme alongside
  139. minor version
  140. '''
  141. maj_ver = '3000'
  142. min_ver = '1'
  143. ver = SaltStackVersion(major=maj_ver, minor=min_ver)
  144. assert ver.minor == int(min_ver)
  145. assert not ver.bugfix
  146. assert ver.string == '{0}.{1}'.format(maj_ver, min_ver)
  147. # This only seems to happen on a cloned repo without its tags
  148. maj_ver = '3000'
  149. min_ver = ''
  150. ver = SaltStackVersion(major=maj_ver, minor=min_ver)
  151. assert ver.minor is None, '{!r} is not {!r}'.format(ver.minor, min_ver) # pylint: disable=repr-flag-used-in-string
  152. assert not ver.bugfix
  153. assert ver.string == maj_ver
  154. def test_string_old_version(self):
  155. '''
  156. Validate string property method
  157. using old versioning scheme alongside
  158. minor version
  159. '''
  160. maj_ver = '2019'
  161. min_ver = '2'
  162. ver = SaltStackVersion(major=maj_ver, minor=min_ver)
  163. assert ver.bugfix == 0
  164. assert ver.string == '{0}.{1}.0'.format(maj_ver, min_ver)
  165. def test_noc_info(self):
  166. '''
  167. Test noc_info property method
  168. '''
  169. expect = (
  170. ('v2014.1.4.1rc3-n/a-abcdefff', (2014, 1, 4, 1, 'rc', 3, -1)),
  171. ('v3.4.1.1', (3, 4, 1, 1, '', 0, 0)),
  172. ('v3000', (3000, '', 0, 0)),
  173. ('v3000.0', (3000, '', 0, 0)),
  174. ('v4518.1', (4518, 1, '', 0, 0)),
  175. ('v3000rc1', (3000, 'rc', 1, 0)),
  176. ('v3000rc1-n/a-abcdefff', (3000, 'rc', 1, -1)),
  177. )
  178. for vstr, noc_info in expect:
  179. saltstack_version = SaltStackVersion.parse(vstr)
  180. assert saltstack_version.noc_info, noc_info
  181. assert len(saltstack_version.noc_info) == len(noc_info)
  182. def test_full_info(self):
  183. '''
  184. Test full_Info property method
  185. '''
  186. expect = (
  187. ('v2014.1.4.1rc3-n/a-abcdefff', (2014, 1, 4, 1, 'rc', 3, -1, 'abcdefff')),
  188. ('v3.4.1.1', (3, 4, 1, 1, '', 0, 0, None)),
  189. ('v3000', (3000, '', 0, 0, None)),
  190. ('v3000.0', (3000, '', 0, 0, None)),
  191. ('v4518.1', (4518, 1, '', 0, 0, None)),
  192. ('v3000rc1', (3000, 'rc', 1, 0, None)),
  193. ('v3000rc1-n/a-abcdefff', (3000, 'rc', 1, -1, 'abcdefff')),
  194. )
  195. for vstr, full_info in expect:
  196. saltstack_version = SaltStackVersion.parse(vstr)
  197. assert saltstack_version.full_info, full_info
  198. assert len(saltstack_version.full_info) == len(full_info)
  199. def test_full_info_all_versions(self):
  200. '''
  201. Test full_info_all_versions property method
  202. '''
  203. expect = (
  204. ('v2014.1.4.1rc3-n/a-abcdefff', (2014, 1, 4, 1, 'rc', 3, -1, 'abcdefff')),
  205. ('v3.4.1.1', (3, 4, 1, 1, '', 0, 0, None)),
  206. ('v3000', (3000, None, None, 0, '', 0, 0, None)),
  207. ('v3000.0', (3000, 0, None, 0, '', 0, 0, None)),
  208. ('v4518.1', (4518, 1, None, 0, '', 0, 0, None)),
  209. ('v3000rc1', (3000, None, None, 0, 'rc', 2, 0, None)),
  210. ('v3000rc1-n/a-abcdefff', (3000, None, None, 0, 'rc', 1, -1, 'abcdefff')),
  211. )
  212. for vstr, full_info in expect:
  213. saltstack_version = SaltStackVersion.parse(vstr)
  214. assert saltstack_version.full_info_all_versions, full_info
  215. assert len(saltstack_version.full_info_all_versions) == len(full_info)
  216. def test_discover_version(self):
  217. '''
  218. Test call to __discover_version
  219. when using different versions
  220. '''
  221. version = {('3000', None):
  222. {(b'v3000.0rc2-12-g44fe283a77\n', '3000rc2-12-g44fe283a77'),
  223. (b'v3000', '3000'),
  224. (b'1234567', '3000-n/a-1234567'), },
  225. (2019, 2):
  226. {(b'v2019.2.0rc2-12-g44fe283a77\n', '2019.2.0rc2-12-g44fe283a77'),
  227. (b'v2019.2.0', '2019.2.0'),
  228. (b'afc9830198dj', '2019.2.0-n/a-afc9830198dj'), },
  229. }
  230. for maj_min, test_v in version.items():
  231. for tag_ver, exp in version[maj_min]:
  232. salt_ver = SaltStackVersion(major=maj_min[0], minor=maj_min[1], bugfix=None)
  233. attrs = {'communicate.return_value': (tag_ver, b''),
  234. 'returncode.return_value': 0}
  235. proc_ret = MagicMock(**attrs)
  236. proc_mock = patch('subprocess.Popen', return_value=proc_ret)
  237. patch_os = patch('os.path.exists', return_value=True)
  238. with proc_mock, patch_os:
  239. ret = getattr(salt.version, '__discover_version')(salt_ver)
  240. assert ret == exp
  241. def test_info_new_version(self):
  242. '''
  243. test info property method with new versioning scheme
  244. '''
  245. vers = ((3000, None, None),
  246. (3000, 1, None),
  247. (3001, 0, None))
  248. for maj_ver, min_ver, bug_fix in vers:
  249. ver = SaltStackVersion(major=maj_ver, minor=min_ver, bugfix=bug_fix)
  250. if min_ver:
  251. assert ver.info == (maj_ver, min_ver)
  252. else:
  253. assert ver.info == (maj_ver,)
  254. def test_info_old_version(self):
  255. '''
  256. test info property method with old versioning scheme
  257. '''
  258. vers = ((2019, 2, 1),
  259. (2018, 3, 0),
  260. (2017, 7, None))
  261. for maj_ver, min_ver, bug_fix in vers:
  262. ver = SaltStackVersion(major=maj_ver, minor=min_ver, bugfix=bug_fix)
  263. if bug_fix is None:
  264. assert ver.info == (maj_ver, min_ver, 0, 0)
  265. else:
  266. assert ver.info == (maj_ver, min_ver, bug_fix, 0)
  267. def test_bugfix_string(self):
  268. '''
  269. test when bugfix is an empty string
  270. '''
  271. ret = SaltStackVersion(3000, 1, '', 0, 0, None)
  272. assert ret.info == (3000, 1)
  273. assert ret.minor == 1
  274. assert ret.bugfix is None
  275. def test_version_repr(self):
  276. '''
  277. Test SaltStackVersion repr for both date
  278. and new versioning scheme
  279. '''
  280. expect = (
  281. ((3000, 1, None, None, '', 0, 0, None), "<SaltStackVersion name='Neon' major=3000 minor=1>"),
  282. ((3000, 0, None, None, '', 0, 0, None), "<SaltStackVersion name='Neon' major=3000>"),
  283. ((2019, 2, 3, None, '', 0, 0, None), "<SaltStackVersion name='Fluorine' major=2019 minor=2 bugfix=3>"),
  284. ((2019, 2, 3, None, 'rc', 1, 0, None), "<SaltStackVersion name='Fluorine' major=2019 minor=2 bugfix=3 rc=1>")
  285. )
  286. for ver, repr_ret in expect:
  287. assert repr(SaltStackVersion(*ver)) == repr_ret