1
0

test_virtualenv_mod.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Pedro Algarvio (pedro@algarvio.me)
  4. tests.unit.modules.virtualenv_test
  5. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6. """
  7. # Import python libraries
  8. from __future__ import absolute_import, print_function, unicode_literals
  9. import sys
  10. # Import salt libs
  11. import salt.modules.virtualenv_mod as virtualenv_mod
  12. from salt.exceptions import CommandExecutionError
  13. from tests.support.helpers import ForceImportErrorOn, TstSuiteLoggingHandler
  14. # Import Salt Testing libs
  15. from tests.support.mixins import LoaderModuleMockMixin
  16. from tests.support.mock import MagicMock, patch
  17. from tests.support.unit import TestCase
  18. class VirtualenvTestCase(TestCase, LoaderModuleMockMixin):
  19. def setup_loader_modules(self):
  20. base_virtualenv_mock = MagicMock()
  21. base_virtualenv_mock.__version__ = "1.9.1"
  22. patcher = patch("salt.utils.path.which", lambda exe: exe)
  23. patcher.start()
  24. self.addCleanup(patcher.stop)
  25. return {
  26. virtualenv_mod: {
  27. "__opts__": {"venv_bin": "virtualenv"},
  28. "_install_script": MagicMock(
  29. return_value={
  30. "retcode": 0,
  31. "stdout": "Installed script!",
  32. "stderr": "",
  33. }
  34. ),
  35. "sys.modules": {"virtualenv": base_virtualenv_mock},
  36. }
  37. }
  38. def test_issue_6029_deprecated_distribute(self):
  39. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  40. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  41. virtualenv_mod.create(
  42. "/tmp/foo", system_site_packages=True, distribute=True
  43. )
  44. mock.assert_called_once_with(
  45. ["virtualenv", "--distribute", "--system-site-packages", "/tmp/foo"],
  46. runas=None,
  47. python_shell=False,
  48. )
  49. with TstSuiteLoggingHandler() as handler:
  50. # Let's fake a higher virtualenv version
  51. virtualenv_mock = MagicMock()
  52. virtualenv_mock.__version__ = "1.10rc1"
  53. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  54. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  55. with patch.dict("sys.modules", {"virtualenv": virtualenv_mock}):
  56. virtualenv_mod.create(
  57. "/tmp/foo", system_site_packages=True, distribute=True
  58. )
  59. mock.assert_called_once_with(
  60. ["virtualenv", "--system-site-packages", "/tmp/foo"],
  61. runas=None,
  62. python_shell=False,
  63. )
  64. # Are we logging the deprecation information?
  65. self.assertIn(
  66. "INFO:The virtualenv '--distribute' option has been "
  67. "deprecated in virtualenv(>=1.10), as such, the "
  68. "'distribute' option to `virtualenv.create()` has "
  69. "also been deprecated and it's not necessary anymore.",
  70. handler.messages,
  71. )
  72. def test_issue_6030_deprecated_never_download(self):
  73. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  74. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  75. virtualenv_mod.create("/tmp/foo", never_download=True)
  76. mock.assert_called_once_with(
  77. ["virtualenv", "--never-download", "/tmp/foo"],
  78. runas=None,
  79. python_shell=False,
  80. )
  81. with TstSuiteLoggingHandler() as handler:
  82. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  83. # Let's fake a higher virtualenv version
  84. virtualenv_mock = MagicMock()
  85. virtualenv_mock.__version__ = "1.10rc1"
  86. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  87. with patch.dict("sys.modules", {"virtualenv": virtualenv_mock}):
  88. virtualenv_mod.create("/tmp/foo", never_download=True)
  89. mock.assert_called_once_with(
  90. ["virtualenv", "/tmp/foo"], runas=None, python_shell=False
  91. )
  92. # Are we logging the deprecation information?
  93. self.assertIn(
  94. "INFO:--never-download was deprecated in 1.10.0, "
  95. "but reimplemented in 14.0.0. If this feature is needed, "
  96. "please install a supported virtualenv version.",
  97. handler.messages,
  98. )
  99. def test_issue_6031_multiple_extra_search_dirs(self):
  100. extra_search_dirs = ["/tmp/bar-1", "/tmp/bar-2", "/tmp/bar-3"]
  101. # Passing extra_search_dirs as a list
  102. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  103. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  104. virtualenv_mod.create("/tmp/foo", extra_search_dir=extra_search_dirs)
  105. mock.assert_called_once_with(
  106. [
  107. "virtualenv",
  108. "--extra-search-dir=/tmp/bar-1",
  109. "--extra-search-dir=/tmp/bar-2",
  110. "--extra-search-dir=/tmp/bar-3",
  111. "/tmp/foo",
  112. ],
  113. runas=None,
  114. python_shell=False,
  115. )
  116. # Passing extra_search_dirs as comma separated list
  117. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  118. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  119. virtualenv_mod.create(
  120. "/tmp/foo", extra_search_dir=",".join(extra_search_dirs)
  121. )
  122. mock.assert_called_once_with(
  123. [
  124. "virtualenv",
  125. "--extra-search-dir=/tmp/bar-1",
  126. "--extra-search-dir=/tmp/bar-2",
  127. "--extra-search-dir=/tmp/bar-3",
  128. "/tmp/foo",
  129. ],
  130. runas=None,
  131. python_shell=False,
  132. )
  133. def test_unapplicable_options(self):
  134. # ----- Virtualenv using pyvenv options ----------------------------->
  135. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  136. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  137. self.assertRaises(
  138. CommandExecutionError,
  139. virtualenv_mod.create,
  140. "/tmp/foo",
  141. venv_bin="virtualenv",
  142. upgrade=True,
  143. )
  144. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  145. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  146. self.assertRaises(
  147. CommandExecutionError,
  148. virtualenv_mod.create,
  149. "/tmp/foo",
  150. venv_bin="virtualenv",
  151. symlinks=True,
  152. )
  153. # <---- Virtualenv using pyvenv options ------------------------------
  154. # ----- pyvenv using virtualenv options ----------------------------->
  155. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  156. with patch.dict(
  157. virtualenv_mod.__salt__,
  158. {"cmd.run_all": mock, "cmd.which_bin": lambda _: "pyvenv"},
  159. ):
  160. self.assertRaises(
  161. CommandExecutionError,
  162. virtualenv_mod.create,
  163. "/tmp/foo",
  164. venv_bin="pyvenv",
  165. python="python2.7",
  166. )
  167. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  168. self.assertRaises(
  169. CommandExecutionError,
  170. virtualenv_mod.create,
  171. "/tmp/foo",
  172. venv_bin="pyvenv",
  173. prompt="PY Prompt",
  174. )
  175. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  176. self.assertRaises(
  177. CommandExecutionError,
  178. virtualenv_mod.create,
  179. "/tmp/foo",
  180. venv_bin="pyvenv",
  181. never_download=True,
  182. )
  183. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  184. self.assertRaises(
  185. CommandExecutionError,
  186. virtualenv_mod.create,
  187. "/tmp/foo",
  188. venv_bin="pyvenv",
  189. extra_search_dir="/tmp/bar",
  190. )
  191. # <---- pyvenv using virtualenv options ------------------------------
  192. def test_get_virtualenv_version_from_shell(self):
  193. with ForceImportErrorOn("virtualenv"):
  194. # ----- virtualenv binary not available ------------------------->
  195. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  196. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  197. self.assertRaises(
  198. CommandExecutionError, virtualenv_mod.create, "/tmp/foo",
  199. )
  200. # <---- virtualenv binary not available --------------------------
  201. # ----- virtualenv binary present but > 0 exit code ------------->
  202. mock = MagicMock(
  203. side_effect=[
  204. {"retcode": 1, "stdout": "", "stderr": "This is an error"},
  205. {"retcode": 0, "stdout": ""},
  206. ]
  207. )
  208. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  209. self.assertRaises(
  210. CommandExecutionError,
  211. virtualenv_mod.create,
  212. "/tmp/foo",
  213. venv_bin="virtualenv",
  214. )
  215. # <---- virtualenv binary present but > 0 exit code --------------
  216. # ----- virtualenv binary returns 1.9.1 as its version --------->
  217. mock = MagicMock(
  218. side_effect=[
  219. {"retcode": 0, "stdout": "1.9.1"},
  220. {"retcode": 0, "stdout": ""},
  221. ]
  222. )
  223. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  224. virtualenv_mod.create("/tmp/foo", never_download=True)
  225. mock.assert_called_with(
  226. ["virtualenv", "--never-download", "/tmp/foo"],
  227. runas=None,
  228. python_shell=False,
  229. )
  230. # <---- virtualenv binary returns 1.9.1 as its version ----------
  231. # ----- virtualenv binary returns 1.10rc1 as its version ------->
  232. mock = MagicMock(
  233. side_effect=[
  234. {"retcode": 0, "stdout": "1.10rc1"},
  235. {"retcode": 0, "stdout": ""},
  236. ]
  237. )
  238. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  239. virtualenv_mod.create("/tmp/foo", never_download=True)
  240. mock.assert_called_with(
  241. ["virtualenv", "/tmp/foo"], runas=None, python_shell=False
  242. )
  243. # <---- virtualenv binary returns 1.10rc1 as its version --------
  244. def test_python_argument(self):
  245. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  246. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  247. virtualenv_mod.create(
  248. "/tmp/foo", python=sys.executable,
  249. )
  250. mock.assert_called_once_with(
  251. ["virtualenv", "--python={0}".format(sys.executable), "/tmp/foo"],
  252. runas=None,
  253. python_shell=False,
  254. )
  255. def test_prompt_argument(self):
  256. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  257. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  258. virtualenv_mod.create("/tmp/foo", prompt="PY Prompt")
  259. mock.assert_called_once_with(
  260. ["virtualenv", "--prompt='PY Prompt'", "/tmp/foo"],
  261. runas=None,
  262. python_shell=False,
  263. )
  264. # Now with some quotes on the mix
  265. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  266. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  267. virtualenv_mod.create("/tmp/foo", prompt="'PY' Prompt")
  268. mock.assert_called_once_with(
  269. ["virtualenv", "--prompt=''PY' Prompt'", "/tmp/foo"],
  270. runas=None,
  271. python_shell=False,
  272. )
  273. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  274. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  275. virtualenv_mod.create("/tmp/foo", prompt='"PY" Prompt')
  276. mock.assert_called_once_with(
  277. ["virtualenv", "--prompt='\"PY\" Prompt'", "/tmp/foo"],
  278. runas=None,
  279. python_shell=False,
  280. )
  281. def test_clear_argument(self):
  282. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  283. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  284. virtualenv_mod.create("/tmp/foo", clear=True)
  285. mock.assert_called_once_with(
  286. ["virtualenv", "--clear", "/tmp/foo"], runas=None, python_shell=False
  287. )
  288. def test_upgrade_argument(self):
  289. # We test for pyvenv only because with virtualenv this is un
  290. # unsupported option.
  291. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  292. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  293. virtualenv_mod.create("/tmp/foo", venv_bin="pyvenv", upgrade=True)
  294. mock.assert_called_once_with(
  295. ["pyvenv", "--upgrade", "/tmp/foo"], runas=None, python_shell=False
  296. )
  297. def test_symlinks_argument(self):
  298. # We test for pyvenv only because with virtualenv this is un
  299. # unsupported option.
  300. mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
  301. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock}):
  302. virtualenv_mod.create("/tmp/foo", venv_bin="pyvenv", symlinks=True)
  303. mock.assert_called_once_with(
  304. ["pyvenv", "--symlinks", "/tmp/foo"], runas=None, python_shell=False
  305. )
  306. def test_virtualenv_ver(self):
  307. """
  308. test virtualenv_ver when there is no ImportError
  309. """
  310. ret = virtualenv_mod.virtualenv_ver(venv_bin="pyvenv")
  311. assert ret == (1, 9, 1)
  312. def test_virtualenv_ver_importerror(self):
  313. """
  314. test virtualenv_ver when there is an ImportError
  315. """
  316. with ForceImportErrorOn("virtualenv"):
  317. mock_ver = MagicMock(return_value={"retcode": 0, "stdout": "1.9.1"})
  318. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock_ver}):
  319. ret = virtualenv_mod.virtualenv_ver(venv_bin="pyenv")
  320. assert ret == (1, 9, 1)
  321. def test_virtualenv_ver_importerror_cmd_error(self):
  322. """
  323. test virtualenv_ver when there is an ImportError
  324. and virtualenv --version does not return anything
  325. """
  326. with ForceImportErrorOn("virtualenv"):
  327. mock_ver = MagicMock(return_value={"retcode": 0, "stdout": ""})
  328. with patch.dict(virtualenv_mod.__salt__, {"cmd.run_all": mock_ver}):
  329. with self.assertRaises(CommandExecutionError):
  330. virtualenv_mod.virtualenv_ver(venv_bin="pyenv")