test_archive.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for the archive state
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import os
  7. import shutil
  8. import textwrap
  9. import pytest
  10. import salt.utils.files
  11. import salt.utils.path
  12. import salt.utils.platform
  13. import salt.utils.stringutils
  14. from salt.ext import six
  15. from tests.support.case import ModuleCase
  16. from tests.support.helpers import destructiveTest, slowTest
  17. from tests.support.runtests import RUNTIME_VARS
  18. from tests.support.unit import skipIf
  19. try:
  20. import zipfile # pylint: disable=unused-import
  21. HAS_ZIPFILE = True
  22. except ImportError:
  23. HAS_ZIPFILE = False
  24. @destructiveTest
  25. @pytest.mark.windows_whitelisted
  26. class ArchiveTest(ModuleCase):
  27. """
  28. Validate the archive module
  29. """
  30. @classmethod
  31. def setUpClass(cls):
  32. # Base path used for test artifacts
  33. cls.base_path = os.path.join(RUNTIME_VARS.TMP, "modules", "archive")
  34. @classmethod
  35. def tearDownClass(cls):
  36. cls.base_path = None
  37. def _set_artifact_paths(self, arch_fmt):
  38. """
  39. Define the paths for the source, archive, and destination files
  40. :param str arch_fmt: The archive format used in the test
  41. """
  42. self.src = os.path.join(self.base_path, "{0}_src_dir".format(arch_fmt))
  43. self.src_file = os.path.join(self.src, "file")
  44. self.arch = os.path.join(self.base_path, "archive.{0}".format(arch_fmt))
  45. self.dst = os.path.join(self.base_path, "{0}_dst_dir".format(arch_fmt))
  46. def _set_up(self, arch_fmt, unicode_filename=False):
  47. """
  48. Create source file tree and destination directory
  49. :param str arch_fmt: The archive format used in the test
  50. """
  51. self._set_artifact_paths(arch_fmt)
  52. # Remove the artifacts if any present
  53. if any([os.path.exists(f) for f in (self.src, self.arch, self.dst)]):
  54. self._tear_down()
  55. self._set_artifact_paths(arch_fmt)
  56. # Create source
  57. os.makedirs(self.src)
  58. if unicode_filename:
  59. filename = "file®"
  60. else:
  61. filename = "file"
  62. with salt.utils.files.fopen(os.path.join(self.src, filename), "wb") as theorem:
  63. if six.PY3 and salt.utils.platform.is_windows():
  64. encoding = "utf-8"
  65. else:
  66. encoding = None
  67. theorem.write(
  68. salt.utils.stringutils.to_bytes(
  69. textwrap.dedent(
  70. """\
  71. Compression theorem of computational complexity theory:
  72. Given a Gödel numbering $φ$ of the computable functions and a
  73. Blum complexity measure $Φ$ where a complexity class for a
  74. boundary function $f$ is defined as
  75. $\\mathrm C(f) := \\{φ_i ∈ \\mathbb R^{(1)} | (∀^∞ x) Φ_i(x) ≤ f(x)\\}$.
  76. Then there exists a total computable function $f$ so that for
  77. all $i$
  78. $\\mathrm{Dom}(φ_i) = \\mathrm{Dom}(φ_{f(i)})$
  79. and
  80. $\\mathrm C(φ_i) ⊊ \\mathrm{C}(φ_{f(i)})$.
  81. """
  82. ),
  83. encoding=encoding,
  84. )
  85. )
  86. # Create destination
  87. os.makedirs(self.dst)
  88. def _tear_down(self):
  89. """
  90. Remove source file tree, archive, and destination file tree
  91. """
  92. for f in (self.src, self.arch, self.dst):
  93. if os.path.exists(f):
  94. if os.path.isdir(f):
  95. shutil.rmtree(f, ignore_errors=True)
  96. else:
  97. os.remove(f)
  98. del self.dst
  99. del self.src
  100. del self.arch
  101. del self.src_file
  102. def _assert_artifacts_in_ret(self, ret, file_only=False, unix_sep=False):
  103. """
  104. Assert that the artifact source files are printed in the source command
  105. output
  106. """
  107. def normdir(path):
  108. normdir = os.path.normcase(os.path.abspath(path))
  109. if salt.utils.platform.is_windows():
  110. # Remove the drive portion of path
  111. if len(normdir) >= 2 and normdir[1] == ":":
  112. normdir = normdir.split(":", 1)[1]
  113. normdir = normdir.lstrip(os.path.sep)
  114. # Unzipped paths might have unix line endings
  115. if unix_sep:
  116. normdir = normdir.replace(os.path.sep, "/")
  117. return normdir
  118. # Try to find source directory and file in output lines
  119. dir_in_ret = None
  120. file_in_ret = None
  121. for line in ret:
  122. if normdir(self.src) in os.path.normcase(line) and not normdir(
  123. self.src_file
  124. ) in os.path.normcase(line):
  125. dir_in_ret = True
  126. if normdir(self.src_file) in os.path.normcase(line):
  127. file_in_ret = True
  128. # Assert number of lines, reporting of source directory and file
  129. self.assertTrue(len(ret) >= 1 if file_only else 2)
  130. if not file_only:
  131. self.assertTrue(dir_in_ret)
  132. self.assertTrue(file_in_ret)
  133. @skipIf(not salt.utils.path.which("tar"), "Cannot find tar executable")
  134. @slowTest
  135. def test_tar_pack(self):
  136. """
  137. Validate using the tar function to create archives
  138. """
  139. self._set_up(arch_fmt="tar")
  140. # Test create archive
  141. ret = self.run_function("archive.tar", ["-cvf", self.arch], sources=self.src)
  142. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  143. self._assert_artifacts_in_ret(ret)
  144. self._tear_down()
  145. @skipIf(not salt.utils.path.which("tar"), "Cannot find tar executable")
  146. @slowTest
  147. def test_tar_unpack(self):
  148. """
  149. Validate using the tar function to extract archives
  150. """
  151. self._set_up(arch_fmt="tar")
  152. self.run_function("archive.tar", ["-cvf", self.arch], sources=self.src)
  153. # Test extract archive
  154. ret = self.run_function("archive.tar", ["-xvf", self.arch], dest=self.dst)
  155. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  156. self._assert_artifacts_in_ret(ret)
  157. self._tear_down()
  158. @skipIf(not salt.utils.path.which("tar"), "Cannot find tar executable")
  159. @slowTest
  160. def test_tar_pack_unicode(self):
  161. """
  162. Validate using the tar function to create archives
  163. """
  164. self._set_up(arch_fmt="tar", unicode_filename=True)
  165. # Test create archive
  166. ret = self.run_function("archive.tar", ["-cvf", self.arch], sources=self.src)
  167. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  168. self._assert_artifacts_in_ret(ret)
  169. self._tear_down()
  170. @skipIf(not salt.utils.path.which("tar"), "Cannot find tar executable")
  171. @slowTest
  172. def test_tar_unpack_unicode(self):
  173. """
  174. Validate using the tar function to extract archives
  175. """
  176. self._set_up(arch_fmt="tar", unicode_filename=True)
  177. self.run_function("archive.tar", ["-cvf", self.arch], sources=self.src)
  178. # Test extract archive
  179. ret = self.run_function("archive.tar", ["-xvf", self.arch], dest=self.dst)
  180. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  181. self._assert_artifacts_in_ret(ret)
  182. self._tear_down()
  183. @skipIf(not salt.utils.path.which("tar"), "Cannot find tar executable")
  184. @slowTest
  185. def test_tar_list_unicode(self):
  186. """
  187. Validate using the tar function to extract archives
  188. """
  189. self._set_up(arch_fmt="tar", unicode_filename=True)
  190. self.run_function("archive.tar", ["-cvf", self.arch], sources=self.src)
  191. # Test list archive
  192. ret = self.run_function("archive.list", name=self.arch)
  193. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  194. self._assert_artifacts_in_ret(ret)
  195. self._tear_down()
  196. @skipIf(not salt.utils.path.which("gzip"), "Cannot find gzip executable")
  197. def test_gzip(self):
  198. """
  199. Validate using the gzip function
  200. """
  201. self._set_up(arch_fmt="gz")
  202. # Test create archive
  203. ret = self.run_function("archive.gzip", [self.src_file], options="-v")
  204. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  205. self._assert_artifacts_in_ret(ret, file_only=True)
  206. self._tear_down()
  207. @skipIf(not salt.utils.path.which("gzip"), "Cannot find gzip executable")
  208. @skipIf(not salt.utils.path.which("gunzip"), "Cannot find gunzip executable")
  209. def test_gunzip(self):
  210. """
  211. Validate using the gunzip function
  212. """
  213. self._set_up(arch_fmt="gz")
  214. self.run_function("archive.gzip", [self.src_file], options="-v")
  215. # Test extract archive
  216. ret = self.run_function("archive.gunzip", [self.src_file + ".gz"], options="-v")
  217. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  218. self._assert_artifacts_in_ret(ret, file_only=True)
  219. self._tear_down()
  220. @skipIf(not salt.utils.path.which("zip"), "Cannot find zip executable")
  221. def test_cmd_zip(self):
  222. """
  223. Validate using the cmd_zip function
  224. """
  225. self._set_up(arch_fmt="zip")
  226. # Test create archive
  227. ret = self.run_function("archive.cmd_zip", [self.arch, self.src])
  228. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  229. self._assert_artifacts_in_ret(ret)
  230. self._tear_down()
  231. @skipIf(not salt.utils.path.which("zip"), "Cannot find zip executable")
  232. @skipIf(not salt.utils.path.which("unzip"), "Cannot find unzip executable")
  233. def test_cmd_unzip(self):
  234. """
  235. Validate using the cmd_unzip function
  236. """
  237. self._set_up(arch_fmt="zip")
  238. self.run_function("archive.cmd_zip", [self.arch, self.src])
  239. # Test create archive
  240. ret = self.run_function("archive.cmd_unzip", [self.arch, self.dst])
  241. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  242. self._assert_artifacts_in_ret(ret)
  243. self._tear_down()
  244. @skipIf(not HAS_ZIPFILE, "Cannot find zipfile python module")
  245. @slowTest
  246. def test_zip(self):
  247. """
  248. Validate using the zip function
  249. """
  250. self._set_up(arch_fmt="zip")
  251. # Test create archive
  252. ret = self.run_function("archive.zip", [self.arch, self.src])
  253. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  254. self._assert_artifacts_in_ret(ret)
  255. self._tear_down()
  256. @skipIf(not HAS_ZIPFILE, "Cannot find zipfile python module")
  257. @slowTest
  258. def test_unzip(self):
  259. """
  260. Validate using the unzip function
  261. """
  262. self._set_up(arch_fmt="zip")
  263. self.run_function("archive.zip", [self.arch, self.src])
  264. # Test create archive
  265. ret = self.run_function("archive.unzip", [self.arch, self.dst])
  266. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  267. self._assert_artifacts_in_ret(ret, unix_sep=False)
  268. self._tear_down()
  269. @skipIf(not salt.utils.path.which("rar"), "Cannot find rar executable")
  270. def test_rar(self):
  271. """
  272. Validate using the rar function
  273. """
  274. self._set_up(arch_fmt="rar")
  275. # Test create archive
  276. ret = self.run_function("archive.rar", [self.arch, self.src])
  277. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  278. self._assert_artifacts_in_ret(ret)
  279. self._tear_down()
  280. @skipIf(not salt.utils.path.which("rar"), "Cannot find rar executable")
  281. @skipIf(not salt.utils.path.which("unrar"), "Cannot find unrar executable")
  282. def test_unrar(self):
  283. """
  284. Validate using the unrar function
  285. """
  286. self._set_up(arch_fmt="rar")
  287. self.run_function("archive.rar", [self.arch, self.src])
  288. # Test create archive
  289. ret = self.run_function("archive.unrar", [self.arch, self.dst])
  290. self.assertTrue(isinstance(ret, list), six.text_type(ret))
  291. self._assert_artifacts_in_ret(ret)
  292. self._tear_down()