test_win_path.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Rahul Handay <rahulha@saltstack.com>
  4. """
  5. # Import Python Libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import os
  8. # Import Salt Libs
  9. import salt.modules.win_path as win_path
  10. import salt.utils.stringutils
  11. # Import Salt Testing Libs
  12. from tests.support.mixins import LoaderModuleMockMixin
  13. from tests.support.mock import MagicMock, patch
  14. from tests.support.unit import TestCase
  15. class WinPathTestCase(TestCase, LoaderModuleMockMixin):
  16. """
  17. Test cases for salt.modules.win_path
  18. """
  19. def setup_loader_modules(self):
  20. return {win_path: {}}
  21. def __init__(self, *args, **kwargs):
  22. super(WinPathTestCase, self).__init__(*args, **kwargs)
  23. self.pathsep = str(";") # future lint: disable=blacklisted-function
  24. def assert_call_matches(self, mock_obj, new_path):
  25. mock_obj.assert_called_once_with(
  26. win_path.HIVE,
  27. win_path.KEY,
  28. win_path.VNAME,
  29. self.pathsep.join(new_path),
  30. win_path.VTYPE,
  31. )
  32. def assert_path_matches(self, env, new_path):
  33. self.assertEqual(
  34. env["PATH"], salt.utils.stringutils.to_str(self.pathsep.join(new_path))
  35. )
  36. def test_get_path(self):
  37. """
  38. Test to Returns the system path
  39. """
  40. mock = MagicMock(return_value={"vdata": "C:\\Salt"})
  41. with patch.dict(win_path.__utils__, {"reg.read_value": mock}):
  42. self.assertListEqual(win_path.get_path(), ["C:\\Salt"])
  43. def test_exists(self):
  44. """
  45. Test to check if the directory is configured
  46. """
  47. get_mock = MagicMock(return_value=["C:\\Foo", "C:\\Bar"])
  48. with patch.object(win_path, "get_path", get_mock):
  49. # Ensure case insensitivity respected
  50. self.assertTrue(win_path.exists("C:\\FOO"))
  51. self.assertTrue(win_path.exists("c:\\foo"))
  52. self.assertFalse(win_path.exists("c:\\mystuff"))
  53. def test_add(self):
  54. """
  55. Test to add the directory to the SYSTEM path
  56. """
  57. orig_path = ("C:\\Foo", "C:\\Bar")
  58. def _env(path):
  59. return {
  60. str(
  61. "PATH"
  62. ): salt.utils.stringutils.to_str( # future lint: disable=blacklisted-function
  63. self.pathsep.join(path)
  64. )
  65. }
  66. def _run(name, index=None, retval=True, path=None):
  67. if path is None:
  68. path = orig_path
  69. env = _env(path)
  70. mock_get = MagicMock(return_value=list(path))
  71. mock_set = MagicMock(return_value=retval)
  72. with patch.object(win_path, "PATHSEP", self.pathsep), patch.object(
  73. win_path, "get_path", mock_get
  74. ), patch.object(os, "environ", env), patch.dict(
  75. win_path.__utils__, {"reg.set_value": mock_set}
  76. ), patch.object(
  77. win_path, "rehash", MagicMock(return_value=True)
  78. ):
  79. return win_path.add(name, index), env, mock_set
  80. # Test a successful reg update
  81. ret, env, mock_set = _run("c:\\salt", retval=True)
  82. new_path = ("C:\\Foo", "C:\\Bar", "c:\\salt")
  83. self.assertTrue(ret)
  84. self.assert_call_matches(mock_set, new_path)
  85. self.assert_path_matches(env, new_path)
  86. # Test an unsuccessful reg update
  87. ret, env, mock_set = _run("c:\\salt", retval=False)
  88. new_path = ("C:\\Foo", "C:\\Bar", "c:\\salt")
  89. self.assertFalse(ret)
  90. self.assert_call_matches(mock_set, new_path)
  91. # The local path should still have been modified even
  92. # though reg.set_value failed.
  93. self.assert_path_matches(env, new_path)
  94. # Test adding with a custom index
  95. ret, env, mock_set = _run("c:\\salt", index=1, retval=True)
  96. new_path = ("C:\\Foo", "c:\\salt", "C:\\Bar")
  97. self.assertTrue(ret)
  98. self.assert_call_matches(mock_set, new_path)
  99. self.assert_path_matches(env, new_path)
  100. # Test adding with a custom index of 0
  101. ret, env, mock_set = _run("c:\\salt", index=0, retval=True)
  102. new_path = ("c:\\salt", "C:\\Foo", "C:\\Bar")
  103. self.assertTrue(ret)
  104. self.assert_call_matches(mock_set, new_path)
  105. self.assert_path_matches(env, new_path)
  106. # Test adding path with a case-insensitive match already present, and
  107. # no index provided. The path should remain unchanged and we should not
  108. # update the registry.
  109. ret, env, mock_set = _run("c:\\foo", retval=True)
  110. self.assertTrue(ret)
  111. mock_set.assert_not_called()
  112. self.assert_path_matches(env, orig_path)
  113. # Test adding path with a case-insensitive match already present, and a
  114. # negative index provided which does not match the current index. The
  115. # match should be removed, and the path should be added to the end of
  116. # the list.
  117. ret, env, mock_set = _run("c:\\foo", index=-1, retval=True)
  118. new_path = ("C:\\Bar", "c:\\foo")
  119. self.assertTrue(ret)
  120. self.assert_call_matches(mock_set, new_path)
  121. self.assert_path_matches(env, new_path)
  122. # Test adding path with a case-insensitive match already present, and a
  123. # negative index provided which matches the current index. No changes
  124. # should be made.
  125. ret, env, mock_set = _run("c:\\foo", index=-2, retval=True)
  126. self.assertTrue(ret)
  127. mock_set.assert_not_called()
  128. self.assert_path_matches(env, orig_path)
  129. # Test adding path with a case-insensitive match already present, and a
  130. # negative index provided which is larger than the size of the list. No
  131. # changes should be made, since in these cases we assume an index of 0,
  132. # and the case-insensitive match is also at index 0.
  133. ret, env, mock_set = _run("c:\\foo", index=-5, retval=True)
  134. self.assertTrue(ret)
  135. mock_set.assert_not_called()
  136. self.assert_path_matches(env, orig_path)
  137. # Test adding path with a case-insensitive match already present, and a
  138. # negative index provided which is larger than the size of the list.
  139. # The match should be removed from its current location and inserted at
  140. # the beginning, since when a negative index is larger than the list,
  141. # we put it at the beginning of the list.
  142. ret, env, mock_set = _run("c:\\bar", index=-5, retval=True)
  143. new_path = ("c:\\bar", "C:\\Foo")
  144. self.assertTrue(ret)
  145. self.assert_call_matches(mock_set, new_path)
  146. self.assert_path_matches(env, new_path)
  147. # Test adding path with a case-insensitive match already present, and a
  148. # negative index provided which matches the current index. The path
  149. # should remain unchanged and we should not update the registry.
  150. ret, env, mock_set = _run("c:\\bar", index=-1, retval=True)
  151. self.assertTrue(ret)
  152. mock_set.assert_not_called()
  153. self.assert_path_matches(env, orig_path)
  154. # Test adding path with a case-insensitive match already present, and
  155. # an index provided which does not match the current index, and is also
  156. # larger than the size of the PATH list. The match should be removed,
  157. # and the path should be added to the end of the list.
  158. ret, env, mock_set = _run("c:\\foo", index=5, retval=True)
  159. new_path = ("C:\\Bar", "c:\\foo")
  160. self.assertTrue(ret)
  161. self.assert_call_matches(mock_set, new_path)
  162. self.assert_path_matches(env, new_path)
  163. def test_remove(self):
  164. """
  165. Test win_path.remove
  166. """
  167. orig_path = ("C:\\Foo", "C:\\Bar", "C:\\Baz")
  168. def _env(path):
  169. return {
  170. str(
  171. "PATH"
  172. ): salt.utils.stringutils.to_str( # future lint: disable=blacklisted-function
  173. self.pathsep.join(path)
  174. )
  175. }
  176. def _run(name="c:\\salt", index=None, retval=True, path=None):
  177. if path is None:
  178. path = orig_path
  179. env = _env(path)
  180. mock_get = MagicMock(return_value=list(path))
  181. mock_set = MagicMock(return_value=retval)
  182. with patch.object(win_path, "PATHSEP", self.pathsep), patch.object(
  183. win_path, "get_path", mock_get
  184. ), patch.object(os, "environ", env), patch.dict(
  185. win_path.__utils__, {"reg.set_value": mock_set}
  186. ), patch.object(
  187. win_path, "rehash", MagicMock(return_value=True)
  188. ):
  189. return win_path.remove(name), env, mock_set
  190. # Test a successful reg update
  191. ret, env, mock_set = _run("C:\\Bar", retval=True)
  192. new_path = ("C:\\Foo", "C:\\Baz")
  193. self.assertTrue(ret)
  194. self.assert_call_matches(mock_set, new_path)
  195. self.assert_path_matches(env, new_path)
  196. # Test a successful reg update with a case-insensitive match
  197. ret, env, mock_set = _run("c:\\bar", retval=True)
  198. new_path = ("C:\\Foo", "C:\\Baz")
  199. self.assertTrue(ret)
  200. self.assert_call_matches(mock_set, new_path)
  201. self.assert_path_matches(env, new_path)
  202. # Test a successful reg update with multiple case-insensitive matches.
  203. # All matches should be removed.
  204. old_path = orig_path + ("C:\\BAR",)
  205. ret, env, mock_set = _run("c:\\bar", retval=True)
  206. new_path = ("C:\\Foo", "C:\\Baz")
  207. self.assertTrue(ret)
  208. self.assert_call_matches(mock_set, new_path)
  209. self.assert_path_matches(env, new_path)
  210. # Test an unsuccessful reg update
  211. ret, env, mock_set = _run("c:\\bar", retval=False)
  212. new_path = ("C:\\Foo", "C:\\Baz")
  213. self.assertFalse(ret)
  214. self.assert_call_matches(mock_set, new_path)
  215. # The local path should still have been modified even
  216. # though reg.set_value failed.
  217. self.assert_path_matches(env, new_path)
  218. # Test when no match found
  219. ret, env, mock_set = _run("C:\\NotThere", retval=True)
  220. self.assertTrue(ret)
  221. mock_set.assert_not_called()
  222. self.assert_path_matches(env, orig_path)