From 1efbdc1f22d7ca6c61406f5771d8a7fcb6fbc7aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
 <psuarezhernandez@suse.com>
Date: Tue, 6 Sep 2016 11:21:05 +0100
Subject: [PATCH 72/73] Unit test fixes for 2015.8.7

* Fixing skipped boto tests to prevent errors if boto3 does not exists.
* Skip utils_test if timelib is not installed (#32699)
  date_cast() throws a RuntimeError, not an ImportError
* Fix tests that assert CommandExecutionError (#32485)
  Trying to assert that an exception was raised using
  helper_open.write.assertRaises() is bogus--there is no such method. Use
  standard unittest.assertRaises() instead.
* Fix missing first data in stream when subscribing stream using a function 'read_async'.
* Make sure spm tests are picked up by runtests.
  Lists in py2 don't have the clear method
* Rename dockerio.py unit tests to dockerio_test.py
  These tests have never run automatically because of an incorrect file name.
  Added a skipIf on these tests as they are currently non-functioning and the
  module they're testing has been deprecated.
* Fixed LoadAuthTestCase
  Fixed use of assert_has_calls in tests.
  The method logic was changed in mock-1.1.0.
  This mades the use of the method compatible with both <1.1.0 and >=1.1.0
* Fixed tests
  Fixed more lint
* Fix tests that assert CommandExecutionError (#32485)
  Trying to assert that an exception was raised using
  helper_open.write.assertRaises() is bogus--there is no such method. Use
  standard unittest.assertRaises() instead.
* Remove test for file dir behavior
  Refs #34809
* modules.darwin_sysctl: __virtual__ return err msg.
  Updated message in darwin_sysctl module when return False if OS is not OSX.
* rename darwin_sysctl.py to mac_sysctl.py
* Fixed _interfaces_ifconfig output for SunOS test
* Prevent tests failure if /etc/fstab does not exists
* Prevent tests failures if boto does not exists
* SPM: packaging doesn't work in Python 2.6. Fixed.
---
 salt/modules/boto_elb.py                     |   2 +-
 salt/modules/darwin_sysctl.py                | 190 --------------------------
 salt/modules/linux_sysctl.py                 |   6 +-
 salt/modules/mac_sysctl.py                   | 193 ++++++++++++++++++++++++++
 salt/spm/__init__.py                         |   5 +-
 tests/unit/auth_test.py                      |   4 +-
 tests/unit/modules/boto_secgroup_test.py     |   1 +
 tests/unit/modules/boto_vpc_test.py          |  14 +-
 tests/unit/modules/cron_test.py              |   2 +-
 tests/unit/modules/darwin_sysctl_test.py     | 108 ---------------
 tests/unit/modules/linux_sysctl_test.py      |  19 ++-
 tests/unit/modules/mac_sysctl_test.py        | 108 +++++++++++++++
 tests/unit/modules/mount_test.py             |  21 ++-
 tests/unit/modules/mysql_test.py             |   6 +-
 tests/unit/modules/puppet_test.py            |  15 +-
 tests/unit/netapi/rest_tornado/test_utils.py |  27 +++-
 tests/unit/spm.py                            | 177 ------------------------
 tests/unit/spm_test.py                       | 177 ++++++++++++++++++++++++
 tests/unit/states/dockerio.py                | 112 ---------------
 tests/unit/states/dockerio_test.py           | 113 +++++++++++++++
 tests/unit/states/file_test.py               |  22 +--
 tests/unit/utils/network.py                  | 196 +++++++++++++++++++++++++++
 tests/unit/utils/utils_test.py               |  11 +-
 23 files changed, 868 insertions(+), 661 deletions(-)
 delete mode 100644 salt/modules/darwin_sysctl.py
 create mode 100644 salt/modules/mac_sysctl.py
 delete mode 100644 tests/unit/modules/darwin_sysctl_test.py
 create mode 100644 tests/unit/modules/mac_sysctl_test.py
 delete mode 100644 tests/unit/spm.py
 create mode 100644 tests/unit/spm_test.py
 delete mode 100644 tests/unit/states/dockerio.py
 create mode 100644 tests/unit/states/dockerio_test.py
 create mode 100644 tests/unit/utils/network.py

diff --git a/salt/modules/boto_elb.py b/salt/modules/boto_elb.py
index e34d5b4..8336b78 100644
--- a/salt/modules/boto_elb.py
+++ b/salt/modules/boto_elb.py
@@ -57,6 +57,7 @@ log = logging.getLogger(__name__)
 # Import third party libs
 try:
     import boto
+    import boto.ec2  # pylint: enable=unused-import
     # connection settings were added in 2.33.0
     required_boto_version = '2.33.0'
     if (_LooseVersion(boto.__version__) <
@@ -64,7 +65,6 @@ try:
         msg = 'boto_elb requires boto {0}.'.format(required_boto_version)
         logging.debug(msg)
         raise ImportError()
-    import boto.ec2
     from boto.ec2.elb import HealthCheck
     from boto.ec2.elb.attributes import AccessLogAttribute
     from boto.ec2.elb.attributes import ConnectionDrainingAttribute
diff --git a/salt/modules/darwin_sysctl.py b/salt/modules/darwin_sysctl.py
deleted file mode 100644
index dce868a..0000000
--- a/salt/modules/darwin_sysctl.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Module for viewing and modifying sysctl parameters
-'''
-from __future__ import absolute_import
-
-# Import python libs
-import os
-
-# Import salt libs
-import salt.utils
-from salt.exceptions import CommandExecutionError
-
-# Define the module's virtual name
-__virtualname__ = 'sysctl'
-
-
-def __virtual__():
-    '''
-    Only run on Darwin (OS X) systems
-    '''
-    return __virtualname__ if __grains__['os'] == 'MacOS' else False
-
-
-def show(config_file=False):
-    '''
-    Return a list of sysctl parameters for this minion
-
-    CLI Example:
-
-    .. code-block:: bash
-
-        salt '*' sysctl.show
-    '''
-    roots = (
-        'audit',
-        'debug',
-        'hw',
-        'hw',
-        'kern',
-        'machdep',
-        'net',
-        'net',
-        'security',
-        'user',
-        'vfs',
-        'vm',
-    )
-    cmd = 'sysctl -a'
-    ret = {}
-    out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
-    comps = ['']
-    for line in out.splitlines():
-        # This might need to be converted to a regex, and more, as sysctl output
-        # can for some reason contain entries such as:
-        #
-        # user.tzname_max = 255
-        # kern.clockrate: hz = 100, tick = 10000, profhz = 100, stathz = 100
-        # kern.clockrate: {hz = 100, tick = 10000, tickadj = 2, profhz = 100,
-        #                 stathz = 100}
-        #
-        # Yes. That's two `kern.clockrate`.
-        #
-        if any([line.startswith('{0}.'.format(root)) for root in roots]):
-            comps = line.split(': ' if ': ' in line else ' = ', 1)
-            if len(comps) == 2:
-                ret[comps[0]] = comps[1]
-            else:
-                ret[comps[0]] = ''
-        elif comps[0]:
-            ret[comps[0]] += '{0}\n'.format(line)
-        else:
-            continue
-    return ret
-
-
-def get(name):
-    '''
-    Return a single sysctl parameter for this minion
-
-    name
-        The name of the sysctl value to display.
-
-    CLI Example:
-
-    .. code-block:: bash
-
-        salt '*' sysctl.get hw.physmem
-    '''
-    cmd = 'sysctl -n {0}'.format(name)
-    out = __salt__['cmd.run'](cmd, python_shell=False)
-    return out
-
-
-def assign(name, value):
-    '''
-    Assign a single sysctl parameter for this minion
-
-    name
-        The name of the sysctl value to edit.
-
-    value
-        The sysctl value to apply.
-
-    CLI Example:
-
-    .. code-block:: bash
-
-        salt '*' sysctl.assign net.inet.icmp.icmplim 50
-    '''
-    ret = {}
-    cmd = 'sysctl -w {0}="{1}"'.format(name, value)
-    data = __salt__['cmd.run_all'](cmd, python_shell=False)
-
-    if data['retcode'] != 0:
-        raise CommandExecutionError('sysctl failed: {0}'.format(
-            data['stderr']))
-    new_name, new_value = data['stdout'].split(':', 1)
-    ret[new_name] = new_value.split(' -> ')[-1]
-    return ret
-
-
-def persist(name, value, config='/etc/sysctl.conf', apply_change=False):
-    '''
-    Assign and persist a simple sysctl parameter for this minion
-
-    name
-        The name of the sysctl value to edit.
-
-    value
-        The sysctl value to apply.
-
-    config
-        The location of the sysctl configuration file.
-
-    apply_change
-        Default is False; Default behavior only creates or edits
-        the sysctl.conf file. If apply is set to True, the changes are
-        applied to the system.
-
-    CLI Example:
-
-    .. code-block:: bash
-
-        salt '*' sysctl.persist net.inet.icmp.icmplim 50
-        salt '*' sysctl.persist coretemp_load NO config=/etc/sysctl.conf
-    '''
-    nlines = []
-    edited = False
-    value = str(value)
-
-    # If the sysctl.conf is not present, add it
-    if not os.path.isfile(config):
-        try:
-            with salt.utils.fopen(config, 'w+') as _fh:
-                _fh.write('#\n# Kernel sysctl configuration\n#\n')
-        except (IOError, OSError):
-            msg = 'Could not write to file: {0}'
-            raise CommandExecutionError(msg.format(config))
-
-    with salt.utils.fopen(config, 'r') as ifile:
-        for line in ifile:
-            if not line.startswith('{0}='.format(name)):
-                nlines.append(line)
-                continue
-            else:
-                key, rest = line.split('=', 1)
-                if rest.startswith('"'):
-                    _, rest_v, rest = rest.split('"', 2)
-                elif rest.startswith('\''):
-                    _, rest_v, rest = rest.split('\'', 2)
-                else:
-                    rest_v = rest.split()[0]
-                    rest = rest[len(rest_v):]
-                if rest_v == value:
-                    return 'Already set'
-                new_line = '{0}={1}'.format(name, value)
-                nlines.append(new_line)
-                nlines.append('\n')
-                edited = True
-    if not edited:
-        nlines.append('{0}={1}'.format(name, value))
-        nlines.append('\n')
-    with salt.utils.fopen(config, 'w+') as ofile:
-        ofile.writelines(nlines)
-    # If apply_change=True, apply edits to system
-    if apply_change is True:
-        assign(name, value)
-        return 'Updated and applied'
-    return 'Updated'
diff --git a/salt/modules/linux_sysctl.py b/salt/modules/linux_sysctl.py
index b1ba481..2335058 100644
--- a/salt/modules/linux_sysctl.py
+++ b/salt/modules/linux_sysctl.py
@@ -41,7 +41,11 @@ def _check_systemd_salt_config():
         sysctl_dir = os.path.split(conf)[0]
         if not os.path.exists(sysctl_dir):
             os.makedirs(sysctl_dir)
-        salt.utils.fopen(conf, 'w').close()
+        try:
+            salt.utils.fopen(conf, 'w').close()
+        except (IOError, OSError):
+            msg = 'Could not create file: {0}'
+            raise CommandExecutionError(msg.format(conf))
     return conf
 
 
diff --git a/salt/modules/mac_sysctl.py b/salt/modules/mac_sysctl.py
new file mode 100644
index 0000000..fe91666
--- /dev/null
+++ b/salt/modules/mac_sysctl.py
@@ -0,0 +1,193 @@
+# -*- coding: utf-8 -*-
+'''
+Module for viewing and modifying sysctl parameters
+'''
+from __future__ import absolute_import
+
+# Import python libs
+import os
+
+# Import salt libs
+import salt.utils
+from salt.exceptions import CommandExecutionError
+
+# Define the module's virtual name
+__virtualname__ = 'sysctl'
+
+
+def __virtual__():
+    '''
+    Only run on Darwin (OS X) systems
+    '''
+    if __grains__['os'] == 'MacOS':
+        return __virtualname__
+    return (False, 'The darwin_sysctl execution module cannot be loaded: '
+            'only available on MacOS systems.')
+
+
+def show(config_file=False):
+    '''
+    Return a list of sysctl parameters for this minion
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' sysctl.show
+    '''
+    roots = (
+        'audit',
+        'debug',
+        'hw',
+        'hw',
+        'kern',
+        'machdep',
+        'net',
+        'net',
+        'security',
+        'user',
+        'vfs',
+        'vm',
+    )
+    cmd = 'sysctl -a'
+    ret = {}
+    out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
+    comps = ['']
+    for line in out.splitlines():
+        # This might need to be converted to a regex, and more, as sysctl output
+        # can for some reason contain entries such as:
+        #
+        # user.tzname_max = 255
+        # kern.clockrate: hz = 100, tick = 10000, profhz = 100, stathz = 100
+        # kern.clockrate: {hz = 100, tick = 10000, tickadj = 2, profhz = 100,
+        #                 stathz = 100}
+        #
+        # Yes. That's two `kern.clockrate`.
+        #
+        if any([line.startswith('{0}.'.format(root)) for root in roots]):
+            comps = line.split(': ' if ': ' in line else ' = ', 1)
+            if len(comps) == 2:
+                ret[comps[0]] = comps[1]
+            else:
+                ret[comps[0]] = ''
+        elif comps[0]:
+            ret[comps[0]] += '{0}\n'.format(line)
+        else:
+            continue
+    return ret
+
+
+def get(name):
+    '''
+    Return a single sysctl parameter for this minion
+
+    name
+        The name of the sysctl value to display.
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' sysctl.get hw.physmem
+    '''
+    cmd = 'sysctl -n {0}'.format(name)
+    out = __salt__['cmd.run'](cmd, python_shell=False)
+    return out
+
+
+def assign(name, value):
+    '''
+    Assign a single sysctl parameter for this minion
+
+    name
+        The name of the sysctl value to edit.
+
+    value
+        The sysctl value to apply.
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' sysctl.assign net.inet.icmp.icmplim 50
+    '''
+    ret = {}
+    cmd = 'sysctl -w {0}="{1}"'.format(name, value)
+    data = __salt__['cmd.run_all'](cmd, python_shell=False)
+
+    if data['retcode'] != 0:
+        raise CommandExecutionError('sysctl failed: {0}'.format(
+            data['stderr']))
+    new_name, new_value = data['stdout'].split(':', 1)
+    ret[new_name] = new_value.split(' -> ')[-1]
+    return ret
+
+
+def persist(name, value, config='/etc/sysctl.conf', apply_change=False):
+    '''
+    Assign and persist a simple sysctl parameter for this minion
+
+    name
+        The name of the sysctl value to edit.
+
+    value
+        The sysctl value to apply.
+
+    config
+        The location of the sysctl configuration file.
+
+    apply_change
+        Default is False; Default behavior only creates or edits
+        the sysctl.conf file. If apply is set to True, the changes are
+        applied to the system.
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' sysctl.persist net.inet.icmp.icmplim 50
+        salt '*' sysctl.persist coretemp_load NO config=/etc/sysctl.conf
+    '''
+    nlines = []
+    edited = False
+    value = str(value)
+
+    # If the sysctl.conf is not present, add it
+    if not os.path.isfile(config):
+        try:
+            with salt.utils.fopen(config, 'w+') as _fh:
+                _fh.write('#\n# Kernel sysctl configuration\n#\n')
+        except (IOError, OSError):
+            msg = 'Could not write to file: {0}'
+            raise CommandExecutionError(msg.format(config))
+
+    with salt.utils.fopen(config, 'r') as ifile:
+        for line in ifile:
+            if not line.startswith('{0}='.format(name)):
+                nlines.append(line)
+                continue
+            else:
+                key, rest = line.split('=', 1)
+                if rest.startswith('"'):
+                    _, rest_v, rest = rest.split('"', 2)
+                elif rest.startswith('\''):
+                    _, rest_v, rest = rest.split('\'', 2)
+                else:
+                    rest_v = rest.split()[0]
+                    rest = rest[len(rest_v):]
+                if rest_v == value:
+                    return 'Already set'
+                new_line = '{0}={1}'.format(name, value)
+                nlines.append(new_line)
+                nlines.append('\n')
+                edited = True
+    if not edited:
+        nlines.append('{0}={1}'.format(name, value))
+        nlines.append('\n')
+    with salt.utils.fopen(config, 'w+') as ofile:
+        ofile.writelines(nlines)
+    # If apply_change=True, apply edits to system
+    if apply_change is True:
+        assign(name, value)
+        return 'Updated and applied'
+    return 'Updated'
diff --git a/salt/spm/__init__.py b/salt/spm/__init__.py
index 721c277..0028e87 100644
--- a/salt/spm/__init__.py
+++ b/salt/spm/__init__.py
@@ -620,12 +620,11 @@ class SPMClient(object):
 
         formula_tar = tarfile.open(out_path, 'w:bz2')
 
-        # Add FORMULA first, to speed up create_repo on large packages
-        formula_tar.add(formula_path, formula_conf['name'], filter=self._exclude)
-
         try:
+            formula_tar.add(formula_path, formula_conf['name'], filter=self._exclude)
             formula_tar.add(self.abspath, formula_conf['name'], filter=self._exclude)
         except TypeError:
+            formula_tar.add(formula_path, formula_conf['name'], exclude=self._exclude)
             formula_tar.add(self.abspath, formula_conf['name'], exclude=self._exclude)
         formula_tar.close()
 
diff --git a/tests/unit/auth_test.py b/tests/unit/auth_test.py
index b6bddb2..d68cb25 100644
--- a/tests/unit/auth_test.py
+++ b/tests/unit/auth_test.py
@@ -48,7 +48,7 @@ class LoadAuthTestCase(TestCase):
                 'eauth': 'pam'
             }, expected_extra_kws=auth.AUTH_INTERNAL_KEYWORDS)
             ret = self.lauth.load_name(valid_eauth_load)
-            format_call_mock.assert_has_calls(expected_ret)
+            format_call_mock.assert_has_calls((expected_ret,), any_order=True)
 
     def test_get_groups(self):
         valid_eauth_load = {'username': 'test_user',
@@ -63,7 +63,7 @@ class LoadAuthTestCase(TestCase):
                 'eauth': 'pam'
                 }, expected_extra_kws=auth.AUTH_INTERNAL_KEYWORDS)
             self.lauth.get_groups(valid_eauth_load)
-            format_call_mock.assert_has_calls(expected_ret)
+            format_call_mock.assert_has_calls((expected_ret,), any_order=True)
 
 
 @patch('zmq.Context', MagicMock())
diff --git a/tests/unit/modules/boto_secgroup_test.py b/tests/unit/modules/boto_secgroup_test.py
index 9792c38..6c4cbed 100644
--- a/tests/unit/modules/boto_secgroup_test.py
+++ b/tests/unit/modules/boto_secgroup_test.py
@@ -23,6 +23,7 @@ import salt.loader
 from salt.ext.six.moves import range  # pylint: disable=redefined-builtin
 try:
     import boto
+    import boto.ec2  # pylint: enable=unused-import
     HAS_BOTO = True
 except ImportError:
     HAS_BOTO = False
diff --git a/tests/unit/modules/boto_vpc_test.py b/tests/unit/modules/boto_vpc_test.py
index ac96831..a543c2e 100644
--- a/tests/unit/modules/boto_vpc_test.py
+++ b/tests/unit/modules/boto_vpc_test.py
@@ -112,6 +112,13 @@ def _has_required_moto():
         return True
 
 
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+@skipIf(HAS_BOTO is False, 'The boto module must be installed.')
+@skipIf(HAS_MOTO is False, 'The moto module must be installed.')
+@skipIf(_has_required_boto() is False, 'The boto module must be greater than'
+                                       ' or equal to version {0}'
+        .format(required_boto_version))
+@skipIf(_has_required_moto() is False, 'The moto version must be >= to version {0}'.format(required_moto_version))
 class BotoVpcTestCaseBase(TestCase):
     def setUp(self):
         boto_vpc.__context__ = {}
@@ -224,13 +231,6 @@ class BotoVpcTestCaseMixin(object):
         return rtbl
 
 
-@skipIf(NO_MOCK, NO_MOCK_REASON)
-@skipIf(HAS_BOTO is False, 'The boto module must be installed.')
-@skipIf(HAS_MOTO is False, 'The moto module must be installed.')
-@skipIf(_has_required_boto() is False, 'The boto module must be greater than'
-                                       ' or equal to version {0}'
-        .format(required_boto_version))
-@skipIf(_has_required_moto() is False, 'The moto version must be >= to version {0}'.format(required_moto_version))
 class BotoVpcTestCase(BotoVpcTestCaseBase, BotoVpcTestCaseMixin):
     '''
     TestCase for salt.modules.boto_vpc module
diff --git a/tests/unit/modules/cron_test.py b/tests/unit/modules/cron_test.py
index 1231487..89c3e82 100644
--- a/tests/unit/modules/cron_test.py
+++ b/tests/unit/modules/cron_test.py
@@ -577,7 +577,7 @@ class PsTestCase(TestCase):
                                     '# Lines below here are managed by Salt, do not edit\n',
                                     '@hourly echo Hi!\n'])
         ret = cron.set_special('DUMMY_USER', '@hourly', 'echo Hi!')
-        write_cron_lines_mock.assert_has_calls(expected_write_call)
+        write_cron_lines_mock.assert_has_calls((expected_write_call,), any_order=True)
 
     def test__get_cron_date_time(self):
         ret = cron._get_cron_date_time(minute=STUB_CRON_TIMESTAMP['minute'],
diff --git a/tests/unit/modules/darwin_sysctl_test.py b/tests/unit/modules/darwin_sysctl_test.py
deleted file mode 100644
index 9b8e9ff..0000000
--- a/tests/unit/modules/darwin_sysctl_test.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-    :codeauthor: :email:`Nicole Thomas <nicole@saltstack.com>`
-'''
-
-# Import Python libs
-from __future__ import absolute_import
-
-# Import Salt Libs
-from salt.modules import darwin_sysctl
-from salt.exceptions import CommandExecutionError
-
-# Import Salt Testing Libs
-from salttesting import skipIf, TestCase
-from salttesting.helpers import ensure_in_syspath
-from salttesting.mock import (
-    MagicMock,
-    mock_open,
-    patch,
-    call,
-    NO_MOCK,
-    NO_MOCK_REASON
-)
-
-ensure_in_syspath('../../')
-
-# Globals
-darwin_sysctl.__salt__ = {}
-
-
-@skipIf(NO_MOCK, NO_MOCK_REASON)
-class DarwinSysctlTestCase(TestCase):
-    '''
-    TestCase for salt.modules.darwin_sysctl module
-    '''
-
-    def test_get(self):
-        '''
-        Tests the return of get function
-        '''
-        mock_cmd = MagicMock(return_value='foo')
-        with patch.dict(darwin_sysctl.__salt__, {'cmd.run': mock_cmd}):
-            self.assertEqual(darwin_sysctl.get('kern.ostype'), 'foo')
-
-    def test_assign_cmd_failed(self):
-        '''
-        Tests if the assignment was successful or not
-        '''
-        cmd = {'pid': 3548, 'retcode': 1, 'stderr': '',
-               'stdout': 'net.inet.icmp.icmplim: 250 -> 50'}
-        mock_cmd = MagicMock(return_value=cmd)
-        with patch.dict(darwin_sysctl.__salt__, {'cmd.run_all': mock_cmd}):
-            self.assertRaises(CommandExecutionError,
-                              darwin_sysctl.assign,
-                              'net.inet.icmp.icmplim', 50)
-
-    def test_assign(self):
-        '''
-        Tests the return of successful assign function
-        '''
-        cmd = {'pid': 3548, 'retcode': 0, 'stderr': '',
-               'stdout': 'net.inet.icmp.icmplim: 250 -> 50'}
-        ret = {'net.inet.icmp.icmplim': '50'}
-        mock_cmd = MagicMock(return_value=cmd)
-        with patch.dict(darwin_sysctl.__salt__, {'cmd.run_all': mock_cmd}):
-            self.assertEqual(darwin_sysctl.assign(
-                'net.inet.icmp.icmplim', 50), ret)
-
-    @patch('os.path.isfile', MagicMock(return_value=False))
-    def test_persist_no_conf_failure(self):
-        '''
-        Tests adding of config file failure
-        '''
-        with patch('salt.utils.fopen', mock_open()) as m_open:
-            helper_open = m_open()
-            helper_open.write.assertRaises(CommandExecutionError,
-                                           darwin_sysctl.persist,
-                                           'net.inet.icmp.icmplim',
-                                           50, config=None)
-
-    @patch('os.path.isfile', MagicMock(return_value=False))
-    def test_persist_no_conf_success(self):
-        '''
-        Tests successful add of config file when previously not one
-        '''
-        with patch('salt.utils.fopen', mock_open()) as m_open:
-            darwin_sysctl.persist('net.inet.icmp.icmplim', 50)
-            helper_open = m_open()
-            helper_open.write.assert_called_once_with(
-                '#\n# Kernel sysctl configuration\n#\n')
-
-    @patch('os.path.isfile', MagicMock(return_value=True))
-    def test_persist_success(self):
-        '''
-        Tests successful write to existing sysctl file
-        '''
-        to_write = '#\n# Kernel sysctl configuration\n#\n'
-        m_calls_list = [call.writelines(['net.inet.icmp.icmplim=50', '\n'])]
-        with patch('salt.utils.fopen', mock_open(read_data=to_write)) as m_open:
-            darwin_sysctl.persist('net.inet.icmp.icmplim', 50, config=to_write)
-            helper_open = m_open()
-            calls_list = helper_open.method_calls
-            self.assertEqual(calls_list, m_calls_list)
-
-
-if __name__ == '__main__':
-    from integration import run_tests
-    run_tests(DarwinSysctlTestCase, needs_daemon=False)
diff --git a/tests/unit/modules/linux_sysctl_test.py b/tests/unit/modules/linux_sysctl_test.py
index ca93749..6931464 100644
--- a/tests/unit/modules/linux_sysctl_test.py
+++ b/tests/unit/modules/linux_sysctl_test.py
@@ -84,17 +84,22 @@ class LinuxSysctlTestCase(TestCase):
             self.assertEqual(linux_sysctl.assign(
                 'net.ipv4.ip_forward', 1), ret)
 
-    @patch('os.path.isfile', MagicMock(return_value=False))
     def test_persist_no_conf_failure(self):
         '''
         Tests adding of config file failure
         '''
-        with patch('salt.utils.fopen', mock_open()) as m_open:
-            helper_open = m_open()
-            helper_open.write.assertRaises(CommandExecutionError,
-                                           linux_sysctl.persist,
-                                           'net.ipv4.ip_forward',
-                                           1, config=None)
+        asn_cmd = {'pid': 1337, 'retcode': 0,
+            'stderr': "sysctl: permission denied", 'stdout': ''}
+        mock_asn_cmd = MagicMock(return_value=asn_cmd)
+        cmd = "sysctl -w net.ipv4.ip_forward=1"
+        mock_cmd = MagicMock(return_value=cmd)
+        with patch.dict(linux_sysctl.__salt__, {'cmd.run_stdout': mock_cmd,
+                                                'cmd.run_all': mock_asn_cmd}):
+            with patch('salt.utils.fopen', mock_open()) as m_open:
+                self.assertRaises(CommandExecutionError,
+                                  linux_sysctl.persist,
+                                  'net.ipv4.ip_forward',
+                                  1, config=None)
 
     @patch('os.path.isfile', MagicMock(return_value=False))
     def test_persist_no_conf_success(self):
diff --git a/tests/unit/modules/mac_sysctl_test.py b/tests/unit/modules/mac_sysctl_test.py
new file mode 100644
index 0000000..533397b
--- /dev/null
+++ b/tests/unit/modules/mac_sysctl_test.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+'''
+    :codeauthor: :email:`Nicole Thomas <nicole@saltstack.com>`
+'''
+
+# Import Python libs
+from __future__ import absolute_import
+
+# Import Salt Libs
+from salt.modules import mac_sysctl
+from salt.exceptions import CommandExecutionError
+
+# Import Salt Testing Libs
+from salttesting import skipIf, TestCase
+from salttesting.helpers import ensure_in_syspath
+from salttesting.mock import (
+    MagicMock,
+    mock_open,
+    patch,
+    call,
+    NO_MOCK,
+    NO_MOCK_REASON
+)
+
+ensure_in_syspath('../../')
+
+# Globals
+mac_sysctl.__salt__ = {}
+
+
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+class DarwinSysctlTestCase(TestCase):
+    '''
+    TestCase for salt.modules.mac_sysctl module
+    '''
+
+    def test_get(self):
+        '''
+        Tests the return of get function
+        '''
+        mock_cmd = MagicMock(return_value='foo')
+        with patch.dict(mac_sysctl.__salt__, {'cmd.run': mock_cmd}):
+            self.assertEqual(mac_sysctl.get('kern.ostype'), 'foo')
+
+    def test_assign_cmd_failed(self):
+        '''
+        Tests if the assignment was successful or not
+        '''
+        cmd = {'pid': 3548, 'retcode': 1, 'stderr': '',
+               'stdout': 'net.inet.icmp.icmplim: 250 -> 50'}
+        mock_cmd = MagicMock(return_value=cmd)
+        with patch.dict(mac_sysctl.__salt__, {'cmd.run_all': mock_cmd}):
+            self.assertRaises(CommandExecutionError,
+                              mac_sysctl.assign,
+                              'net.inet.icmp.icmplim', 50)
+
+    def test_assign(self):
+        '''
+        Tests the return of successful assign function
+        '''
+        cmd = {'pid': 3548, 'retcode': 0, 'stderr': '',
+               'stdout': 'net.inet.icmp.icmplim: 250 -> 50'}
+        ret = {'net.inet.icmp.icmplim': '50'}
+        mock_cmd = MagicMock(return_value=cmd)
+        with patch.dict(mac_sysctl.__salt__, {'cmd.run_all': mock_cmd}):
+            self.assertEqual(mac_sysctl.assign(
+                'net.inet.icmp.icmplim', 50), ret)
+
+    @patch('os.path.isfile', MagicMock(return_value=False))
+    def test_persist_no_conf_failure(self):
+        '''
+        Tests adding of config file failure
+        '''
+        with patch('salt.utils.fopen', mock_open()) as m_open:
+            m_open.side_effect = IOError(13, 'Permission denied', '/file')
+            self.assertRaises(CommandExecutionError,
+                              mac_sysctl.persist,
+                              'net.inet.icmp.icmplim',
+                              50, config=None)
+
+    @patch('os.path.isfile', MagicMock(return_value=False))
+    def test_persist_no_conf_success(self):
+        '''
+        Tests successful add of config file when previously not one
+        '''
+        with patch('salt.utils.fopen', mock_open()) as m_open:
+            mac_sysctl.persist('net.inet.icmp.icmplim', 50)
+            helper_open = m_open()
+            helper_open.write.assert_called_once_with(
+                '#\n# Kernel sysctl configuration\n#\n')
+
+    @patch('os.path.isfile', MagicMock(return_value=True))
+    def test_persist_success(self):
+        '''
+        Tests successful write to existing sysctl file
+        '''
+        to_write = '#\n# Kernel sysctl configuration\n#\n'
+        m_calls_list = [call.writelines(['net.inet.icmp.icmplim=50', '\n'])]
+        with patch('salt.utils.fopen', mock_open(read_data=to_write)) as m_open:
+            mac_sysctl.persist('net.inet.icmp.icmplim', 50, config=to_write)
+            helper_open = m_open()
+            calls_list = helper_open.method_calls
+            self.assertEqual(calls_list, m_calls_list)
+
+
+if __name__ == '__main__':
+    from integration import run_tests
+    run_tests(DarwinSysctlTestCase, needs_daemon=False)
diff --git a/tests/unit/modules/mount_test.py b/tests/unit/modules/mount_test.py
index 282539d..b2b23bf 100644
--- a/tests/unit/modules/mount_test.py
+++ b/tests/unit/modules/mount_test.py
@@ -100,15 +100,16 @@ class MountTestCase(TestCase):
         '''
         mock = MagicMock(return_value={})
         with patch.object(mount, 'fstab', mock):
-            self.assertTrue(mount.rm_fstab('name', 'device'))
+            with patch('salt.utils.fopen', mock_open()) as m_open:
+                self.assertTrue(mount.rm_fstab('name', 'device'))
 
-        mock = MagicMock(return_value={'name': 'name'})
-        with patch.object(mount, 'fstab', mock):
+        mock_fstab = MagicMock(return_value={'name': 'name'})
+        with patch.object(mount, 'fstab', mock_fstab):
             with patch('salt.utils.fopen', mock_open()) as m_open:
-                helper_open = m_open()
-                helper_open.write.assertRaises(CommandExecutionError,
-                                               mount.rm_fstab,
-                                               config=None)
+                m_open.side_effect = IOError(13, 'Permission denied:', '/file')
+                self.assertRaises(CommandExecutionError,
+                                  mount.rm_fstab,
+                                  'name', 'device')
 
     def test_set_fstab(self):
         '''
@@ -144,11 +145,7 @@ class MountTestCase(TestCase):
 
         mock = MagicMock(return_value={'name': 'name'})
         with patch.object(mount, 'fstab', mock):
-            with patch('salt.utils.fopen', mock_open()) as m_open:
-                helper_open = m_open()
-                helper_open.write.assertRaises(CommandExecutionError,
-                                               mount.rm_automaster,
-                                               'name', 'device')
+            self.assertTrue(mount.rm_automaster('name', 'device'))
 
     def test_set_automaster(self):
         '''
diff --git a/tests/unit/modules/mysql_test.py b/tests/unit/modules/mysql_test.py
index f8d1daa..860ab19 100644
--- a/tests/unit/modules/mysql_test.py
+++ b/tests/unit/modules/mysql_test.py
@@ -282,10 +282,10 @@ class MySQLTestCase(TestCase):
         with patch.dict(mysql.__salt__, {'config.option': MagicMock()}):
             function(*args, **kwargs)
             if isinstance(expected_sql, dict):
-                calls = (call().cursor().execute('{0}'.format(expected_sql['sql']), expected_sql['sql_args']))
+                calls = call().cursor().execute('{0}'.format(expected_sql['sql']), expected_sql['sql_args'])
             else:
-                calls = (call().cursor().execute('{0}'.format(expected_sql)))
-            connect_mock.assert_has_calls(calls)
+                calls = call().cursor().execute('{0}'.format(expected_sql))
+            connect_mock.assert_has_calls((calls,), True)
 
 
 if __name__ == '__main__':
diff --git a/tests/unit/modules/puppet_test.py b/tests/unit/modules/puppet_test.py
index 6a43fd4..dcc488a 100644
--- a/tests/unit/modules/puppet_test.py
+++ b/tests/unit/modules/puppet_test.py
@@ -91,10 +91,12 @@ class PuppetTestCase(TestCase):
                     with patch('salt.utils.fopen', mock_open()):
                         self.assertTrue(puppet.disable())
 
-                    with patch('salt.utils.fopen', mock_open()) as m_open:
-                        helper_open = m_open()
-                        helper_open.write.assertRaises(CommandExecutionError,
-                                                       puppet.disable)
+                    try:
+                        with patch('salt.utils.fopen', mock_open()) as m_open:
+                            m_open.side_effect = IOError(13, 'Permission denied:', '/file')
+                            self.assertRaises(CommandExecutionError, puppet.disable)
+                    except StopIteration:
+                        pass
 
     def test_status(self):
         '''
@@ -155,9 +157,8 @@ class PuppetTestCase(TestCase):
                     self.assertDictEqual(puppet.summary(), {'resources': 1})
 
                 with patch('salt.utils.fopen', mock_open()) as m_open:
-                    helper_open = m_open()
-                    helper_open.write.assertRaises(CommandExecutionError,
-                                                   puppet.summary)
+                    m_open.side_effect = IOError(13, 'Permission denied:', '/file')
+                    self.assertRaises(CommandExecutionError, puppet.summary)
 
     def test_plugin_sync(self):
         '''
diff --git a/tests/unit/netapi/rest_tornado/test_utils.py b/tests/unit/netapi/rest_tornado/test_utils.py
index 1dd18d5..c22c288 100644
--- a/tests/unit/netapi/rest_tornado/test_utils.py
+++ b/tests/unit/netapi/rest_tornado/test_utils.py
@@ -103,7 +103,8 @@ class TestEventListener(AsyncTestCase):
             event_listener = saltnado.EventListener({},  # we don't use mod_opts, don't save?
                                                     {'sock_dir': SOCK_DIR,
                                                      'transport': 'zeromq'})
-            event_future = event_listener.get_event(1, 'evt1', self.stop)  # get an event future
+            self._finished = False  # fit to event_listener's behavior
+            event_future = event_listener.get_event(self, 'evt1', self.stop)  # get an event future
             me.fire_event({'data': 'foo2'}, 'evt2')  # fire an event we don't want
             me.fire_event({'data': 'foo1'}, 'evt1')  # fire an event we do want
             self.wait()  # wait for the future
@@ -113,6 +114,27 @@ class TestEventListener(AsyncTestCase):
             self.assertEqual(event_future.result()['tag'], 'evt1')
             self.assertEqual(event_future.result()['data']['data'], 'foo1')
 
+    def test_set_event_handler(self):
+        '''
+        Test subscribing events using set_event_handler
+        '''
+        with eventpublisher_process():
+            me = event.MasterEvent(SOCK_DIR)
+            event_listener = saltnado.EventListener({},  # we don't use mod_opts, don't save?
+                                                    {'sock_dir': SOCK_DIR,
+                                                     'transport': 'zeromq'})
+            self._finished = False  # fit to event_listener's behavior
+            event_future = event_listener.get_event(self,
+                                                    tag='evt',
+                                                    callback=self.stop,
+                                                    timeout=1,
+                                                    )  # get an event future
+            me.fire_event({'data': 'foo'}, 'evt')  # fire an event we do want
+            self.wait()
+
+            # check that we subscribed the event we wanted
+            self.assertEqual(len(event_listener.timeout_map), 0)
+
     def test_timeout(self):
         '''
         Make sure timeouts work correctly
@@ -121,7 +143,8 @@ class TestEventListener(AsyncTestCase):
             event_listener = saltnado.EventListener({},  # we don't use mod_opts, don't save?
                                                     {'sock_dir': SOCK_DIR,
                                                      'transport': 'zeromq'})
-            event_future = event_listener.get_event(1,
+            self._finished = False  # fit to event_listener's behavior
+            event_future = event_listener.get_event(self,
                                                     tag='evt1',
                                                     callback=self.stop,
                                                     timeout=1,
diff --git a/tests/unit/spm.py b/tests/unit/spm.py
deleted file mode 100644
index d2c0bf7..0000000
--- a/tests/unit/spm.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# coding: utf-8
-
-# Import Python libs
-from __future__ import absolute_import
-import os
-import shutil
-import tempfile
-
-# Import Salt Testing libs
-from salttesting import TestCase
-from salttesting.helpers import ensure_in_syspath, destructiveTest
-
-import salt.config
-import salt.spm
-
-ensure_in_syspath('../')
-
-
-_TMP_SPM = tempfile.mkdtemp()
-
-config = salt.config.minion_config(None)
-config['file_roots'] = {'base': [os.path.join(_TMP_SPM, 'salt')]}
-config['pillar_roots'] = {'base': [os.path.join(_TMP_SPM, 'pillar')]}
-
-__opts__ = {
-    'spm_logfile': os.path.join(_TMP_SPM, 'log'),
-    'spm_repos_config': os.path.join(_TMP_SPM, 'etc', 'spm.repos'),
-    'spm_cache_dir': os.path.join(_TMP_SPM, 'cache'),
-    'spm_build_dir': os.path.join(_TMP_SPM, 'build'),
-    'spm_build_exclude': ['.git'],
-    'spm_db_provider': 'sqlite3',
-    'spm_files_provider': 'local',
-    'spm_db': os.path.join(_TMP_SPM, 'packages.db'),
-    'extension_modules': os.path.join(_TMP_SPM, 'modules'),
-    'file_roots': {'base': [_TMP_SPM, ]},
-    'formula_path': os.path.join(_TMP_SPM, 'spm'),
-    'pillar_path': os.path.join(_TMP_SPM, 'pillar'),
-    'reactor_path': os.path.join(_TMP_SPM, 'reactor'),
-    'assume_yes': True,
-    'force': False,
-}
-
-_F1 = {
-    'definition': {
-        'name': 'formula1',
-        'version': '1.2',
-        'release': '2',
-        'summary': 'test',
-        'description': 'testing, nothing to see here',
-    }
-}
-
-_F1['contents'] = (
-    ('FORMULA', ('name: {name}\n'
-                 'version: {version}\n'
-                 'release: {release}\n'
-                 'summary: {summary}\n'
-                 'description: {description}').format(**_F1['definition'])),
-    ('modules/mod1.py', '# mod1.py'),
-    ('modules/mod2.py', '# mod2.py'),
-    ('states/state1.sls', '# state1.sls'),
-    ('states/state2.sls', '# state2.sls'),
-)
-
-
-@destructiveTest
-class SPMTestUserInterface(salt.spm.SPMUserInterface):
-    '''
-    Unit test user interface to SPMClient
-    '''
-    def __init__(self):
-        self._status = []
-        self._confirm = []
-        self._error = []
-
-    def status(self, msg):
-        self._status.append(msg)
-
-    def confirm(self, action):
-        self._confirm.append(action)
-
-    def error(self, msg):
-        self._error.append(msg)
-
-
-class SPMTest(TestCase):
-    def setUp(self):
-        shutil.rmtree(_TMP_SPM, ignore_errors=True)
-        os.mkdir(_TMP_SPM)
-        self.ui = SPMTestUserInterface()
-        self.client = salt.spm.SPMClient(self.ui, __opts__)
-
-    def tearDown(self):
-        shutil.rmtree(_TMP_SPM, ignore_errors=True)
-
-    def _create_formula_files(self, formula):
-        fdir = os.path.join(_TMP_SPM, formula['definition']['name'])
-        shutil.rmtree(fdir, ignore_errors=True)
-        os.mkdir(fdir)
-        for path, contents in formula['contents']:
-            path = os.path.join(fdir, path)
-            dirname, _ = os.path.split(path)
-            if not os.path.exists(dirname):
-                os.makedirs(dirname)
-            with open(path, 'w') as f:
-                f.write(contents)
-        return fdir
-
-    def test_build_install(self):
-        # Build package
-        fdir = self._create_formula_files(_F1)
-        self.client.run(['build', fdir])
-        pkgpath = self.ui._status[-1].split()[-1]
-        assert os.path.exists(pkgpath)
-        # Install package
-        self.client.run(['local', 'install', pkgpath])
-        # Check filesystem
-        for path, contents in _F1['contents']:
-            path = os.path.join(__opts__['file_roots']['base'][0], _F1['definition']['name'], path)
-            assert os.path.exists(path)
-            assert open(path, 'r').read() == contents
-        # Check database
-        self.client.run(['info', _F1['definition']['name']])
-        lines = self.ui._status[-1].split('\n')
-        for key, line in (
-                ('name', 'Name: {0}'),
-                ('version', 'Version: {0}'),
-                ('release', 'Release: {0}'),
-                ('summary', 'Summary: {0}')):
-            assert line.format(_F1['definition'][key]) in lines
-        # Reinstall with force=False, should fail
-        self.ui._error.clear()
-        self.client.run(['local', 'install', pkgpath])
-        assert len(self.ui._error) > 0
-        # Reinstall with force=True, should succeed
-        __opts__['force'] = True
-        self.ui._error.clear()
-        self.client.run(['local', 'install', pkgpath])
-        assert len(self.ui._error) == 0
-        __opts__['force'] = False
-
-    def test_failure_paths(self):
-        fail_args = (
-            ['bogus', 'command'],
-            ['create_repo'],
-            ['build'],
-            ['build', '/nonexistent/path'],
-            ['info'],
-            ['info', 'not_installed'],
-            ['files'],
-            ['files', 'not_installed'],
-            ['install'],
-            ['install', 'nonexistent.spm'],
-            ['remove'],
-            ['remove', 'not_installed'],
-            ['local', 'bogus', 'command'],
-            ['local', 'info'],
-            ['local', 'info', '/nonexistent/path/junk.spm'],
-            ['local', 'files'],
-            ['local', 'files', '/nonexistent/path/junk.spm'],
-            ['local', 'install'],
-            ['local', 'install', '/nonexistent/path/junk.spm'],
-            ['local', 'list'],
-            ['local', 'list', '/nonexistent/path/junk.spm'],
-            # XXX install failure due to missing deps
-            # XXX install failure due to missing field
-        )
-
-        for args in fail_args:
-            self.ui._error.clear()
-            self.client.run(args)
-            assert len(self.ui._error) > 0
-
-
-if __name__ == '__main__':
-    from integration import run_tests
-    run_tests(SPMTest, needs_daemon=False)
diff --git a/tests/unit/spm_test.py b/tests/unit/spm_test.py
new file mode 100644
index 0000000..1adc377
--- /dev/null
+++ b/tests/unit/spm_test.py
@@ -0,0 +1,177 @@
+# coding: utf-8
+
+# Import Python libs
+from __future__ import absolute_import
+import os
+import shutil
+import tempfile
+
+# Import Salt Testing libs
+from salttesting import TestCase
+from salttesting.helpers import ensure_in_syspath, destructiveTest
+
+import salt.config
+import salt.spm
+
+ensure_in_syspath('../')
+
+
+_TMP_SPM = tempfile.mkdtemp()
+
+config = salt.config.minion_config(None)
+config['file_roots'] = {'base': [os.path.join(_TMP_SPM, 'salt')]}
+config['pillar_roots'] = {'base': [os.path.join(_TMP_SPM, 'pillar')]}
+
+__opts__ = {
+    'spm_logfile': os.path.join(_TMP_SPM, 'log'),
+    'spm_repos_config': os.path.join(_TMP_SPM, 'etc', 'spm.repos'),
+    'spm_cache_dir': os.path.join(_TMP_SPM, 'cache'),
+    'spm_build_dir': os.path.join(_TMP_SPM, 'build'),
+    'spm_build_exclude': ['.git'],
+    'spm_db_provider': 'sqlite3',
+    'spm_files_provider': 'local',
+    'spm_db': os.path.join(_TMP_SPM, 'packages.db'),
+    'extension_modules': os.path.join(_TMP_SPM, 'modules'),
+    'file_roots': {'base': [_TMP_SPM, ]},
+    'formula_path': os.path.join(_TMP_SPM, 'spm'),
+    'pillar_path': os.path.join(_TMP_SPM, 'pillar'),
+    'reactor_path': os.path.join(_TMP_SPM, 'reactor'),
+    'assume_yes': True,
+    'force': False,
+}
+
+_F1 = {
+    'definition': {
+        'name': 'formula1',
+        'version': '1.2',
+        'release': '2',
+        'summary': 'test',
+        'description': 'testing, nothing to see here',
+    }
+}
+
+_F1['contents'] = (
+    ('FORMULA', ('name: {name}\n'
+                 'version: {version}\n'
+                 'release: {release}\n'
+                 'summary: {summary}\n'
+                 'description: {description}').format(**_F1['definition'])),
+    ('modules/mod1.py', '# mod1.py'),
+    ('modules/mod2.py', '# mod2.py'),
+    ('states/state1.sls', '# state1.sls'),
+    ('states/state2.sls', '# state2.sls'),
+)
+
+
+@destructiveTest
+class SPMTestUserInterface(salt.spm.SPMUserInterface):
+    '''
+    Unit test user interface to SPMClient
+    '''
+    def __init__(self):
+        self._status = []
+        self._confirm = []
+        self._error = []
+
+    def status(self, msg):
+        self._status.append(msg)
+
+    def confirm(self, action):
+        self._confirm.append(action)
+
+    def error(self, msg):
+        self._error.append(msg)
+
+
+class SPMTest(TestCase):
+    def setUp(self):
+        shutil.rmtree(_TMP_SPM, ignore_errors=True)
+        os.mkdir(_TMP_SPM)
+        self.ui = SPMTestUserInterface()
+        self.client = salt.spm.SPMClient(self.ui, __opts__)
+
+    def tearDown(self):
+        shutil.rmtree(_TMP_SPM, ignore_errors=True)
+
+    def _create_formula_files(self, formula):
+        fdir = os.path.join(_TMP_SPM, formula['definition']['name'])
+        shutil.rmtree(fdir, ignore_errors=True)
+        os.mkdir(fdir)
+        for path, contents in formula['contents']:
+            path = os.path.join(fdir, path)
+            dirname, _ = os.path.split(path)
+            if not os.path.exists(dirname):
+                os.makedirs(dirname)
+            with open(path, 'w') as f:
+                f.write(contents)
+        return fdir
+
+    def test_build_install(self):
+        # Build package
+        fdir = self._create_formula_files(_F1)
+        self.client.run(['build', fdir])
+        pkgpath = self.ui._status[-1].split()[-1]
+        assert os.path.exists(pkgpath)
+        # Install package
+        self.client.run(['local', 'install', pkgpath])
+        # Check filesystem
+        for path, contents in _F1['contents']:
+            path = os.path.join(__opts__['file_roots']['base'][0], _F1['definition']['name'], path)
+            assert os.path.exists(path)
+            assert open(path, 'r').read() == contents
+        # Check database
+        self.client.run(['info', _F1['definition']['name']])
+        lines = self.ui._status[-1].split('\n')
+        for key, line in (
+                ('name', 'Name: {0}'),
+                ('version', 'Version: {0}'),
+                ('release', 'Release: {0}'),
+                ('summary', 'Summary: {0}')):
+            assert line.format(_F1['definition'][key]) in lines
+        # Reinstall with force=False, should fail
+        self.ui._error = []
+        self.client.run(['local', 'install', pkgpath])
+        assert len(self.ui._error) > 0
+        # Reinstall with force=True, should succeed
+        __opts__['force'] = True
+        self.ui._error = []
+        self.client.run(['local', 'install', pkgpath])
+        assert len(self.ui._error) == 0
+        __opts__['force'] = False
+
+    def test_failure_paths(self):
+        fail_args = (
+            ['bogus', 'command'],
+            ['create_repo'],
+            ['build'],
+            ['build', '/nonexistent/path'],
+            ['info'],
+            ['info', 'not_installed'],
+            ['files'],
+            ['files', 'not_installed'],
+            ['install'],
+            ['install', 'nonexistent.spm'],
+            ['remove'],
+            ['remove', 'not_installed'],
+            ['local', 'bogus', 'command'],
+            ['local', 'info'],
+            ['local', 'info', '/nonexistent/path/junk.spm'],
+            ['local', 'files'],
+            ['local', 'files', '/nonexistent/path/junk.spm'],
+            ['local', 'install'],
+            ['local', 'install', '/nonexistent/path/junk.spm'],
+            ['local', 'list'],
+            ['local', 'list', '/nonexistent/path/junk.spm'],
+            # XXX install failure due to missing deps
+            # XXX install failure due to missing field
+        )
+
+        for args in fail_args:
+            self.ui._error = []
+            self.client.run(args)
+            assert len(self.ui._error) > 0
+
+
+if __name__ == '__main__':
+    from integration import run_tests
+    run_tests(SPMTest, needs_daemon=False)
diff --git a/tests/unit/states/dockerio.py b/tests/unit/states/dockerio.py
deleted file mode 100644
index c73b633..0000000
--- a/tests/unit/states/dockerio.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Import Python libs
-from __future__ import absolute_import
-from contextlib import contextmanager
-
-# Import Salt Testing libs
-from salttesting import skipIf, TestCase
-from salttesting.mock import NO_MOCK, NO_MOCK_REASON, MagicMock
-
-
-@contextmanager
-def provision_state(module, fixture):
-    previous_dict = getattr(module, '__salt__', {}).copy()
-    try:
-        module.__dict__.setdefault('__salt__', {}).update(fixture)
-        yield
-    finally:
-        setattr(module, '__salt__', previous_dict)
-
-
-@skipIf(NO_MOCK, NO_MOCK_REASON)
-class DockerStateTestCase(TestCase):
-    def test_docker_run_success(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
-                        'docker.run_all': MagicMock(
-                            return_value={'stdout': '.\n..\n',
-                                          'stderr': '',
-                                          'status': True,
-                                          'comment': 'Success',
-                                          'retcode': 0})}
-
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu')
-
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': True,
-                                  'comment': 'Success',
-                                  'changes': {}})
-
-    def test_docker_run_failure(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
-                        'docker.run_all': MagicMock(
-                            return_value={'stdout': '',
-                                          'stderr': 'Error',
-                                          'status': False,
-                                          'comment': 'Failure',
-                                          'retcode': 1})}
-
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu')
-
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': False,
-                                  'comment': 'Failure',
-                                  'changes': {}})
-
-    def test_docker_run_onlyif(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=1),
-                        'docker.run_all': None}
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu',
-                                  onlyif='ls -l')
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': True,
-                                  'comment': 'onlyif execution failed',
-                                  'changes': {}})
-
-    def test_docker_run_unless(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
-                        'docker.run_all': None}
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu',
-                                  unless='ls -l')
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': True,
-                                  'comment': 'unless execution succeeded',
-                                  'changes': {}})
-
-    def test_docker_run_docked_onlyif(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=1),
-                        'docker.run_all': None}
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu',
-                                  docked_onlyif='ls -l')
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': True,
-                                  'comment': 'docked_onlyif execution failed',
-                                  'changes': {}})
-
-    def test_docker_run_docked_unless(self):
-        from salt.states import dockerio
-        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
-                        'docker.run_all': None}
-        with provision_state(dockerio, salt_fixture):
-            result = dockerio.run('ls /', 'ubuntu',
-                                  docked_unless='ls -l')
-        self.assertEqual(result, {'name': 'ls /',
-                                  'result': True,
-                                  'comment': ('docked_unless execution'
-                                              ' succeeded'),
-                                  'changes': {}})
-
-
-if __name__ == '__main__':
-    from integration import run_tests
-    run_tests(DockerStateTestCase, needs_daemon=False)
diff --git a/tests/unit/states/dockerio_test.py b/tests/unit/states/dockerio_test.py
new file mode 100644
index 0000000..54f51be
--- /dev/null
+++ b/tests/unit/states/dockerio_test.py
@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+
+# Import Python libs
+from __future__ import absolute_import
+from contextlib import contextmanager
+
+# Import Salt Testing libs
+from salttesting import skipIf, TestCase
+from salttesting.mock import NO_MOCK, NO_MOCK_REASON, MagicMock
+
+
+@contextmanager
+def provision_state(module, fixture):
+    previous_dict = getattr(module, '__salt__', {}).copy()
+    try:
+        module.__dict__.setdefault('__salt__', {}).update(fixture)
+        yield
+    finally:
+        setattr(module, '__salt__', previous_dict)
+
+
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+@skipIf(True, 'Skipped: This module has been deprecated.')
+class DockerStateTestCase(TestCase):
+    def test_docker_run_success(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
+                        'docker.run_all': MagicMock(
+                            return_value={'stdout': '.\n..\n',
+                                          'stderr': '',
+                                          'status': True,
+                                          'comment': 'Success',
+                                          'retcode': 0})}
+
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu')
+
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': True,
+                                  'comment': 'Success',
+                                  'changes': {}})
+
+    def test_docker_run_failure(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
+                        'docker.run_all': MagicMock(
+                            return_value={'stdout': '',
+                                          'stderr': 'Error',
+                                          'status': False,
+                                          'comment': 'Failure',
+                                          'retcode': 1})}
+
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu')
+
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': False,
+                                  'comment': 'Failure',
+                                  'changes': {}})
+
+    def test_docker_run_onlyif(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=1),
+                        'docker.run_all': None}
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu',
+                                  onlyif='ls -l')
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': True,
+                                  'comment': 'onlyif execution failed',
+                                  'changes': {}})
+
+    def test_docker_run_unless(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
+                        'docker.run_all': None}
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu',
+                                  unless='ls -l')
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': True,
+                                  'comment': 'unless execution succeeded',
+                                  'changes': {}})
+
+    def test_docker_run_docked_onlyif(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=1),
+                        'docker.run_all': None}
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu',
+                                  docked_onlyif='ls -l')
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': True,
+                                  'comment': 'docked_onlyif execution failed',
+                                  'changes': {}})
+
+    def test_docker_run_docked_unless(self):
+        from salt.states import dockerio
+        salt_fixture = {'docker.retcode': MagicMock(return_value=0),
+                        'docker.run_all': None}
+        with provision_state(dockerio, salt_fixture):
+            result = dockerio.run('ls /', 'ubuntu',
+                                  docked_unless='ls -l')
+        self.assertEqual(result, {'name': 'ls /',
+                                  'result': True,
+                                  'comment': ('docked_unless execution'
+                                              ' succeeded'),
+                                  'changes': {}})
+
+
+if __name__ == '__main__':
+    from integration import run_tests
+    run_tests(DockerStateTestCase, needs_daemon=False)
diff --git a/tests/unit/states/file_test.py b/tests/unit/states/file_test.py
index 722eef8..bbf2df7 100644
--- a/tests/unit/states/file_test.py
+++ b/tests/unit/states/file_test.py
@@ -923,6 +923,7 @@ class FileTestCase(TestCase):
 
     # 'comment' function tests: 1
 
+    @patch.object(os.path, 'exists', MagicMock(return_value=True))
     def test_comment(self):
         '''
         Test to comment out specified lines in a file.
@@ -979,6 +980,7 @@ class FileTestCase(TestCase):
 
     # 'uncomment' function tests: 1
 
+    @patch.object(os.path, 'exists', MagicMock(return_value=True))
     def test_uncomment(self):
         '''
         Test to uncomment specified commented lines in a file
@@ -1396,26 +1398,6 @@ class FileTestCase(TestCase):
                                                      (name, source,
                                                       preserve=True), ret)
 
-                    with patch.object(os.path, 'isdir', mock_t):
-                        with patch.dict(filestate.__opts__, {'test': False}):
-                            with patch.object(shutil, 'copy',
-                                              MagicMock(side_effect=[IOError,
-                                                                     True])):
-                                comt = ('Failed to copy "{0}" to "{1}"'
-                                        .format(source, name))
-                                ret.update({'comment': comt, 'result': False})
-                                self.assertDictEqual(filestate.copy
-                                                     (name, source,
-                                                      preserve=True), ret)
-
-                                comt = ('Copied "{0}" to "{1}"'.format(source,
-                                                                       name))
-                                ret.update({'comment': comt, 'result': True,
-                                            'changes': {name: source}})
-                                self.assertDictEqual(filestate.copy
-                                                     (name, source,
-                                                      preserve=True), ret)
-
     # 'rename' function tests: 1
 
     def test_rename(self):
Index: salt-2015.8.7/tests/unit/utils/network.py
===================================================================
--- salt-2015.8.7.orig/tests/unit/utils/network.py
+++ salt-2015.8.7/tests/unit/utils/network.py
@@ -151,6 +151,9 @@ class NetworkTestCase(TestCase):
             self.assertEqual(interfaces,
                              {'ilbext0': {'inet': [{'address': '10.10.11.11',
                                                     'broadcast': '10.10.11.31',
+                                                    'netmask': '255.255.255.224'},
+                                                    {'address': '10.10.11.12',
+                                                    'broadcast': '10.10.11.31',
                                                     'netmask': '255.255.255.224'}],
                                           'inet6': [{'address': '::',
                                                      'prefixlen': '0'}],
diff --git a/tests/unit/utils/utils_test.py b/tests/unit/utils/utils_test.py
index 261af69..11f0baf 100644
--- a/tests/unit/utils/utils_test.py
+++ b/tests/unit/utils/utils_test.py
@@ -527,14 +527,9 @@ class UtilsTestCase(TestCase):
             ret = utils.date_cast('Mon Dec 23 10:19:15 MST 2013')
             expected_ret = datetime.datetime(2013, 12, 23, 10, 19, 15)
             self.assertEqual(ret, expected_ret)
-        except ImportError:
-            try:
-                ret = utils.date_cast('Mon Dec 23 10:19:15 MST 2013')
-                expected_ret = datetime.datetime(2013, 12, 23, 10, 19, 15)
-                self.assertEqual(ret, expected_ret)
-            except RuntimeError:
-                # Unparseable without timelib installed
-                self.skipTest('\'timelib\' is not installed')
+        except RuntimeError:
+            # Unparseable without timelib installed
+            self.skipTest('\'timelib\' is not installed')
 
     @skipIf(not HAS_TIMELIB, '\'timelib\' is not installed')
     def test_date_format(self):
-- 
2.8.2

