mirror of
https://github.com/valitydev/salt.git
synced 2024-11-06 16:45:27 +00:00
31ca7c6936
This also normalizes some hacks that were in place to import reload from importlib, so that these instances also use the compatibility function.
278 lines
11 KiB
Python
278 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
Tests for salt.utils.path
|
|
'''
|
|
|
|
# Import Python libs
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
import os
|
|
import sys
|
|
import posixpath
|
|
import ntpath
|
|
import platform
|
|
import tempfile
|
|
|
|
# Import Salt Testing libs
|
|
from tests.support.unit import TestCase, skipIf
|
|
from tests.support.mock import patch, NO_MOCK, NO_MOCK_REASON
|
|
|
|
# Import Salt libs
|
|
import salt.utils.compat
|
|
import salt.utils.path
|
|
import salt.utils.platform
|
|
from salt.exceptions import CommandNotFoundError
|
|
|
|
# Import 3rd-party libs
|
|
from salt.ext import six
|
|
|
|
|
|
class PathJoinTestCase(TestCase):
|
|
|
|
PLATFORM_FUNC = platform.system
|
|
BUILTIN_MODULES = sys.builtin_module_names
|
|
|
|
NIX_PATHS = (
|
|
(('/', 'key'), '/key'),
|
|
(('/etc/salt', '/etc/salt/pki'), '/etc/salt/etc/salt/pki'),
|
|
(('/usr/local', '/etc/salt/pki'), '/usr/local/etc/salt/pki')
|
|
|
|
)
|
|
|
|
WIN_PATHS = (
|
|
(('c:', 'temp', 'foo'), 'c:\\temp\\foo'),
|
|
(('c:', r'\temp', r'\foo'), 'c:\\temp\\foo'),
|
|
(('c:\\', r'\temp', r'\foo'), 'c:\\temp\\foo'),
|
|
((r'c:\\', r'\temp', r'\foo'), 'c:\\temp\\foo'),
|
|
(('c:', r'\temp', r'\foo', 'bar'), 'c:\\temp\\foo\\bar'),
|
|
(('c:', r'\temp', r'\foo\bar'), 'c:\\temp\\foo\\bar'),
|
|
)
|
|
|
|
@skipIf(True, 'Skipped until properly mocked')
|
|
def test_nix_paths(self):
|
|
if platform.system().lower() == "windows":
|
|
self.skipTest(
|
|
"Windows platform found. not running *nix salt.utils.path.join tests"
|
|
)
|
|
for idx, (parts, expected) in enumerate(self.NIX_PATHS):
|
|
path = salt.utils.path.join(*parts)
|
|
self.assertEqual(
|
|
'{0}: {1}'.format(idx, path),
|
|
'{0}: {1}'.format(idx, expected)
|
|
)
|
|
|
|
@skipIf(True, 'Skipped until properly mocked')
|
|
def test_windows_paths(self):
|
|
if platform.system().lower() != "windows":
|
|
self.skipTest(
|
|
'Non windows platform found. not running non patched os.path '
|
|
'salt.utils.path.join tests'
|
|
)
|
|
|
|
for idx, (parts, expected) in enumerate(self.WIN_PATHS):
|
|
path = salt.utils.path.join(*parts)
|
|
self.assertEqual(
|
|
'{0}: {1}'.format(idx, path),
|
|
'{0}: {1}'.format(idx, expected)
|
|
)
|
|
|
|
@skipIf(True, 'Skipped until properly mocked')
|
|
def test_windows_paths_patched_path_module(self):
|
|
if platform.system().lower() == "windows":
|
|
self.skipTest(
|
|
'Windows platform found. not running patched os.path '
|
|
'salt.utils.path.join tests'
|
|
)
|
|
|
|
self.__patch_path()
|
|
|
|
for idx, (parts, expected) in enumerate(self.WIN_PATHS):
|
|
path = salt.utils.path.join(*parts)
|
|
self.assertEqual(
|
|
'{0}: {1}'.format(idx, path),
|
|
'{0}: {1}'.format(idx, expected)
|
|
)
|
|
|
|
self.__unpatch_path()
|
|
|
|
@skipIf(salt.utils.platform.is_windows(), '*nix-only test')
|
|
def test_mixed_unicode_and_binary(self):
|
|
'''
|
|
This tests joining paths that contain a mix of components with unicode
|
|
strings and non-unicode strings with the unicode characters as binary.
|
|
|
|
This is no longer something we need to concern ourselves with in
|
|
Python 3, but the test should nonetheless pass on Python 3. Really what
|
|
we're testing here is that we don't get a UnicodeDecodeError when
|
|
running on Python 2.
|
|
'''
|
|
a = u'/foo/bar'
|
|
b = 'Д'
|
|
expected = u'/foo/bar/\u0414'
|
|
actual = salt.utils.path.join(a, b)
|
|
self.assertEqual(actual, expected)
|
|
|
|
def __patch_path(self):
|
|
import imp
|
|
modules = list(self.BUILTIN_MODULES[:])
|
|
modules.pop(modules.index('posix'))
|
|
modules.append('nt')
|
|
|
|
code = """'''Salt unittest loaded NT module'''"""
|
|
module = imp.new_module('nt')
|
|
six.exec_(code, module.__dict__)
|
|
sys.modules['nt'] = module
|
|
|
|
sys.builtin_module_names = modules
|
|
platform.system = lambda: "windows"
|
|
|
|
for module in (ntpath, os, os.path, tempfile):
|
|
salt.utils.compat.reload(module)
|
|
|
|
def __unpatch_path(self):
|
|
del sys.modules['nt']
|
|
sys.builtin_module_names = self.BUILTIN_MODULES[:]
|
|
platform.system = self.PLATFORM_FUNC
|
|
|
|
for module in (posixpath, os, os.path, tempfile, platform):
|
|
salt.utils.compat.reload(module)
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
class PathTestCase(TestCase):
|
|
def test_which_bin(self):
|
|
ret = salt.utils.path.which_bin('str')
|
|
self.assertIs(None, ret)
|
|
|
|
test_exes = ['ls', 'echo']
|
|
with patch('salt.utils.path.which', return_value='/tmp/dummy_path'):
|
|
ret = salt.utils.path.which_bin(test_exes)
|
|
self.assertEqual(ret, '/tmp/dummy_path')
|
|
|
|
ret = salt.utils.path.which_bin([])
|
|
self.assertIs(None, ret)
|
|
|
|
with patch('salt.utils.path.which', return_value=''):
|
|
ret = salt.utils.path.which_bin(test_exes)
|
|
self.assertIs(None, ret)
|
|
|
|
def test_sanitize_win_path(self):
|
|
p = '\\windows\\system'
|
|
self.assertEqual(salt.utils.path.sanitize_win_path('\\windows\\system'), '\\windows\\system')
|
|
self.assertEqual(salt.utils.path.sanitize_win_path('\\bo:g|us\\p?at*h>'), '\\bo_g_us\\p_at_h_')
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
def test_check_or_die(self):
|
|
self.assertRaises(CommandNotFoundError, salt.utils.path.check_or_die, None)
|
|
|
|
with patch('salt.utils.path.which', return_value=False):
|
|
self.assertRaises(CommandNotFoundError, salt.utils.path.check_or_die, 'FAKE COMMAND')
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
def test_join(self):
|
|
with patch('salt.utils.platform.is_windows', return_value=False) as is_windows_mock:
|
|
self.assertFalse(is_windows_mock.return_value)
|
|
expected_path = os.path.join(os.sep + 'a', 'b', 'c', 'd')
|
|
ret = salt.utils.path.join('/a/b/c', 'd')
|
|
self.assertEqual(ret, expected_path)
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
class TestWhich(TestCase):
|
|
'''
|
|
Tests salt.utils.path.which function to ensure that it returns True as
|
|
expected.
|
|
'''
|
|
|
|
# The mock patch below will make sure that ALL calls to the which function
|
|
# returns None
|
|
def test_missing_binary_in_linux(self):
|
|
with patch('salt.utils.path.which', lambda exe: None):
|
|
self.assertTrue(
|
|
salt.utils.path.which('this-binary-does-not-exist') is None
|
|
)
|
|
|
|
# The mock patch below will make sure that ALL calls to the which function
|
|
# return whatever is sent to it
|
|
def test_existing_binary_in_linux(self):
|
|
with patch('salt.utils.path.which', lambda exe: exe):
|
|
self.assertTrue(salt.utils.path.which('this-binary-exists-under-linux'))
|
|
|
|
def test_existing_binary_in_windows(self):
|
|
with patch('os.access') as osaccess:
|
|
# We define the side_effect attribute on the mocked object in order to
|
|
# specify which calls return which values. First call to os.access
|
|
# returns X, the second Y, the third Z, etc...
|
|
osaccess.side_effect = [
|
|
# The first os.access should return False(the abspath one)
|
|
False,
|
|
# The second, iterating through $PATH, should also return False,
|
|
# still checking for Linux
|
|
False,
|
|
# We will now also return False once so we get a .EXE back from
|
|
# the function, see PATHEXT below.
|
|
False,
|
|
# Lastly return True, this is the windows check.
|
|
True
|
|
]
|
|
# Let's patch os.environ to provide a custom PATH variable
|
|
with patch.dict(os.environ, {'PATH': os.sep + 'bin',
|
|
'PATHEXT': '.COM;.EXE;.BAT;.CMD'}):
|
|
# Let's also patch is_windows to return True
|
|
with patch('salt.utils.platform.is_windows', lambda: True):
|
|
with patch('os.path.isfile', lambda x: True):
|
|
self.assertEqual(
|
|
salt.utils.path.which('this-binary-exists-under-windows'),
|
|
os.path.join(os.sep + 'bin', 'this-binary-exists-under-windows.EXE')
|
|
)
|
|
|
|
def test_missing_binary_in_windows(self):
|
|
with patch('os.access') as osaccess:
|
|
osaccess.side_effect = [
|
|
# The first os.access should return False(the abspath one)
|
|
False,
|
|
# The second, iterating through $PATH, should also return False,
|
|
# still checking for Linux
|
|
# which() will add 4 extra paths to the given one, os.access will
|
|
# be called 5 times
|
|
False, False, False, False, False
|
|
]
|
|
# Let's patch os.environ to provide a custom PATH variable
|
|
with patch.dict(os.environ, {'PATH': os.sep + 'bin'}):
|
|
# Let's also patch is_widows to return True
|
|
with patch('salt.utils.platform.is_windows', lambda: True):
|
|
self.assertEqual(
|
|
# Since we're passing the .exe suffix, the last True above
|
|
# will not matter. The result will be None
|
|
salt.utils.path.which('this-binary-is-missing-in-windows.exe'),
|
|
None
|
|
)
|
|
|
|
def test_existing_binary_in_windows_pathext(self):
|
|
with patch('os.access') as osaccess:
|
|
# We define the side_effect attribute on the mocked object in order to
|
|
# specify which calls return which values. First call to os.access
|
|
# returns X, the second Y, the third Z, etc...
|
|
osaccess.side_effect = [
|
|
# The first os.access should return False(the abspath one)
|
|
False,
|
|
# The second, iterating through $PATH, should also return False,
|
|
# still checking for Linux
|
|
False,
|
|
# We will now also return False 3 times so we get a .CMD back from
|
|
# the function, see PATHEXT below.
|
|
# Lastly return True, this is the windows check.
|
|
False, False, False,
|
|
True
|
|
]
|
|
# Let's patch os.environ to provide a custom PATH variable
|
|
with patch.dict(os.environ, {'PATH': os.sep + 'bin',
|
|
'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;'
|
|
'.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY'}):
|
|
# Let's also patch is_windows to return True
|
|
with patch('salt.utils.platform.is_windows', lambda: True):
|
|
with patch('os.path.isfile', lambda x: True):
|
|
self.assertEqual(
|
|
salt.utils.path.which('this-binary-exists-under-windows'),
|
|
os.path.join(os.sep + 'bin', 'this-binary-exists-under-windows.CMD')
|
|
)
|