salt/tests/unit/utils/test_path.py
Erik Johnson 3184168365 Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.

A summary of the changes in this PR is as follows:

* Moves the following functions from `salt.utils` to new locations
  (including a deprecation warning if invoked from `salt.utils`):
  `to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
  `dequote`, `is_hex`, `is_bin_str`, `rand_string`,
  `contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
  `which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
  `is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
  `is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
  `is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
  `salt/utils/__init__.py` for better organization, so we can keep the
  deprecated ones separate from the ones yet to be deprecated as we
  continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
  unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
  import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
  accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
  such that it returns a string matching the passed size. Previously
  this function would get `size` bytes from `os.urandom()`,
  base64-encode it, and return the result, which would in most cases not
  be equal to the passed size.
2017-08-08 13:33:43 -05:00

159 lines
5.0 KiB
Python

# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
tests.unit.utils.salt.utils.path.join_test
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''
# Import Python libs
from __future__ import absolute_import
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.path
import salt.utils.platform
# 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):
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):
reload(module)
@skipIf(NO_MOCK, NO_MOCK_REASON)
class WhichTestCase(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)