test_virtualenv_mod.py 14 KB

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