Move mixins to tests.support.mixins.

The adapted config mixin get config methods are not static methods
This commit is contained in:
Pedro Algarvio 2017-04-02 16:21:06 +01:00
parent 6056ee302a
commit 8031ac0209
No known key found for this signature in database
GPG key ID: BB36BF6584A298FF
51 changed files with 439 additions and 662 deletions

View file

@ -446,7 +446,7 @@ to test states:
HFILE = os.path.join(integration.TMP, 'hosts')
class HostTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class HostTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate the host state
'''

View file

@ -49,10 +49,14 @@ from tests.support.paths import * # pylint: disable=wildcard-import
from tests.support.processes import * # pylint: disable=wildcard-import
from tests.support.unit import TestCase
from tests.support.case import ShellTestCase
from tests.support.mixins import CheckShellBinaryNameAndVersionMixin, ShellCaseCommonTestsMixin
from tests.support.parser import PNUM, print_header, SaltTestcaseParser
from tests.support.helpers import requires_sshd_server, RedirectStdStreams
from tests.support.paths import ScriptPathMixin
from tests.support.mixins import RUNTIME_CONFIGS
from tests.support.mixins import CheckShellBinaryNameAndVersionMixin, ShellCaseCommonTestsMixin
from tests.support.mixins import AdaptedConfigurationTestCaseMixin, SaltClientTestCaseMixin
from tests.support.mixins import SaltMinionEventAssertsMixin, SaltReturnAssertsMixin
from tests.support.runtests import RUNTIME_VARS
# Import Salt libs
import salt
import salt.config
@ -98,17 +102,12 @@ try:
except ImportError:
import socketserver
if salt.utils.is_windows():
import win32api
from tornado import gen
from tornado import ioloop
# Import salt tests support libs
from tests.support.processes import SaltMaster, SaltMinion, SaltSyndic
RUNTIME_CONFIGS = {}
log = logging.getLogger(__name__)
@ -123,11 +122,6 @@ atexit.register(cleanup_runtime_config_instance, RUNTIME_CONFIGS)
_RUNTESTS_PORTS = {}
if salt.utils.is_windows():
RUNNING_TESTS_USER = win32api.GetUserName()
else:
RUNNING_TESTS_USER = pwd.getpwuid(os.getuid()).pw_name
def get_unused_localhost_port():
'''
@ -691,7 +685,7 @@ class TestDaemon(object):
roster_path = os.path.join(FILES, 'conf/_ssh/roster')
shutil.copy(roster_path, TMP_CONF_DIR)
with salt.utils.fopen(os.path.join(TMP_CONF_DIR, 'roster'), 'a') as roster:
roster.write(' user: {0}\n'.format(RUNNING_TESTS_USER))
roster.write(' user: {0}\n'.format(RUNTIME_VARS.RUNNING_TESTS_USER))
roster.write(' priv: {0}/{1}'.format(TMP_CONF_DIR, 'key_test'))
sys.stdout.write(
' {LIGHT_GREEN}STARTED!\n{ENDC}'.format(
@ -750,7 +744,7 @@ class TestDaemon(object):
master_opts = salt.config._read_conf_file(os.path.join(CONF_DIR, 'master'))
master_opts['known_hosts_file'] = tests_known_hosts_file
master_opts['cachedir'] = os.path.join(TMP, 'rootdir', 'cache')
master_opts['user'] = RUNNING_TESTS_USER
master_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
master_opts['config_dir'] = TMP_CONF_DIR
master_opts['root_dir'] = os.path.join(TMP, 'rootdir')
master_opts['pki_dir'] = os.path.join(TMP, 'rootdir', 'pki', 'master')
@ -766,7 +760,7 @@ class TestDaemon(object):
# This minion connects to master
minion_opts = salt.config._read_conf_file(os.path.join(CONF_DIR, 'minion'))
minion_opts['cachedir'] = os.path.join(TMP, 'rootdir', 'cache')
minion_opts['user'] = RUNNING_TESTS_USER
minion_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
minion_opts['config_dir'] = TMP_CONF_DIR
minion_opts['root_dir'] = os.path.join(TMP, 'rootdir')
minion_opts['pki_dir'] = os.path.join(TMP, 'rootdir', 'pki')
@ -776,7 +770,7 @@ class TestDaemon(object):
# This sub_minion also connects to master
sub_minion_opts = salt.config._read_conf_file(os.path.join(CONF_DIR, 'sub_minion'))
sub_minion_opts['cachedir'] = os.path.join(TMP, 'rootdir-sub-minion', 'cache')
sub_minion_opts['user'] = RUNNING_TESTS_USER
sub_minion_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
sub_minion_opts['config_dir'] = TMP_SUB_MINION_CONF_DIR
sub_minion_opts['root_dir'] = os.path.join(TMP, 'rootdir-sub-minion')
sub_minion_opts['pki_dir'] = os.path.join(TMP, 'rootdir-sub-minion', 'pki', 'minion')
@ -786,7 +780,7 @@ class TestDaemon(object):
# This is the master of masters
syndic_master_opts = salt.config._read_conf_file(os.path.join(CONF_DIR, 'syndic_master'))
syndic_master_opts['cachedir'] = os.path.join(TMP, 'rootdir-syndic-master', 'cache')
syndic_master_opts['user'] = RUNNING_TESTS_USER
syndic_master_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
syndic_master_opts['config_dir'] = TMP_SYNDIC_MASTER_CONF_DIR
syndic_master_opts['root_dir'] = os.path.join(TMP, 'rootdir-syndic-master')
syndic_master_opts['pki_dir'] = os.path.join(TMP, 'rootdir-syndic-master', 'pki', 'master')
@ -980,7 +974,7 @@ class TestDaemon(object):
TMP_PRODENV_STATE_TREE,
TMP,
],
RUNNING_TESTS_USER)
RUNTIME_VARS.RUNNING_TESTS_USER)
cls.master_opts = master_opts
cls.minion_opts = minion_opts
@ -1291,191 +1285,7 @@ class TestDaemon(object):
self.sync_minion_modules_('grains', targets, timeout=timeout)
class AdaptedConfigurationTestCaseMixIn(object):
__slots__ = ()
def get_temp_config(self, config_for, **config_overrides):
rootdir = tempfile.mkdtemp(dir=TMP)
self.addCleanup(shutil.rmtree, rootdir)
for key in ('cachedir', 'pki_dir', 'sock_dir'):
if key not in config_overrides:
config_overrides[key] = key
if 'log_file' not in config_overrides:
config_overrides['log_file'] = 'logs/{}.log'.format(config_for)
if 'user' not in config_overrides:
config_overrides['user'] = RUNNING_TESTS_USER
config_overrides['root_dir'] = rootdir
cdict = self.get_config(config_for, from_scratch=True)
if config_for in ('master', 'client_config'):
rdict = salt.config.apply_master_config(config_overrides, cdict)
if config_for == 'minion':
rdict = salt.config.apply_minion_config(config_overrides, cdict)
verify_env([os.path.join(rdict['pki_dir'], 'minions'),
os.path.join(rdict['pki_dir'], 'minions_pre'),
os.path.join(rdict['pki_dir'], 'minions_rejected'),
os.path.join(rdict['pki_dir'], 'minions_denied'),
os.path.join(rdict['cachedir'], 'jobs'),
os.path.join(rdict['cachedir'], 'raet'),
os.path.join(rdict['cachedir'], 'tokens'),
os.path.join(rdict['root_dir'], 'cache', 'tokens'),
os.path.join(rdict['pki_dir'], 'accepted'),
os.path.join(rdict['pki_dir'], 'rejected'),
os.path.join(rdict['pki_dir'], 'pending'),
os.path.dirname(rdict['log_file']),
rdict['sock_dir'],
],
RUNNING_TESTS_USER)
return rdict
def get_config(self, config_for, from_scratch=False):
if from_scratch:
if config_for in ('master', 'syndic_master'):
return salt.config.master_config(self.get_config_file_path(config_for))
elif config_for in ('minion', 'sub_minion'):
return salt.config.minion_config(self.get_config_file_path(config_for))
elif config_for in ('syndic',):
return salt.config.syndic_config(
self.get_config_file_path(config_for),
self.get_config_file_path('minion')
)
elif config_for == 'client_config':
return salt.config.client_config(self.get_config_file_path('master'))
if config_for not in RUNTIME_CONFIGS:
if config_for in ('master', 'syndic_master'):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.master_config(self.get_config_file_path(config_for))
)
elif config_for in ('minion', 'sub_minion'):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.minion_config(self.get_config_file_path(config_for))
)
elif config_for in ('syndic',):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.syndic_config(
self.get_config_file_path(config_for),
self.get_config_file_path('minion')
)
)
elif config_for == 'client_config':
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.client_config(self.get_config_file_path('master'))
)
return RUNTIME_CONFIGS[config_for]
def get_config_dir(self):
return TMP_CONF_DIR
def get_config_file_path(self, filename):
if filename == 'syndic_master':
return os.path.join(TMP_SYNDIC_MASTER_CONF_DIR, 'master')
if filename == 'syndic':
return os.path.join(TMP_SYNDIC_MINION_CONF_DIR, 'minion')
if filename == 'sub_minion':
return os.path.join(TMP_SUB_MINION_CONF_DIR, 'minion')
return os.path.join(TMP_CONF_DIR, filename)
@property
def master_opts(self):
'''
Return the options used for the master
'''
return self.get_config('master')
@property
def minion_opts(self):
'''
Return the options used for the minion
'''
return self.get_config('minion')
@property
def sub_minion_opts(self):
'''
Return the options used for the sub_minion
'''
return self.get_config('sub_minion')
class SaltMinionEventAssertsMixIn(object):
'''
Asserts to verify that a given event was seen
'''
def __new__(cls, *args, **kwargs):
# We have to cross-call to re-gen a config
cls.q = multiprocessing.Queue()
cls.fetch_proc = multiprocessing.Process(target=cls._fetch, args=(cls.q,))
cls.fetch_proc.start()
return object.__new__(cls)
def __exit__(self, *args, **kwargs):
self.fetch_proc.join()
@staticmethod
def _fetch(q):
'''
Collect events and store them
'''
def _clean_queue():
print('Cleaning queue!')
while not q.empty():
queue_item = q.get()
queue_item.task_done()
atexit.register(_clean_queue)
a_config = AdaptedConfigurationTestCaseMixIn()
event = salt.utils.event.get_event('minion', sock_dir=a_config.get_config('minion')['sock_dir'], opts=a_config.get_config('minion'))
while True:
try:
events = event.get_event(full=False)
except Exception:
# This is broad but we'll see all kinds of issues right now
# if we drop the proc out from under the socket while we're reading
pass
q.put(events)
def assertMinionEventFired(self, tag):
#TODO
raise salt.exceptions.NotImplemented('assertMinionEventFired() not implemented')
def assertMinionEventReceived(self, desired_event):
queue_wait = 5 # 2.5s
while self.q.empty():
time.sleep(0.5) # Wait for events to be pushed into the queue
queue_wait -= 1
if queue_wait <= 0:
raise AssertionError('Queue wait timer expired')
while not self.q.empty(): # This is not thread-safe and may be inaccurate
event = self.q.get()
if isinstance(event, dict):
event.pop('_stamp')
if desired_event == event:
self.fetch_proc.terminate()
return True
self.fetch_proc.terminate()
raise AssertionError('Event {0} was not received by minion'.format(desired_event))
class SaltClientTestCaseMixIn(AdaptedConfigurationTestCaseMixIn):
_salt_client_config_file_name_ = 'master'
__slots__ = ()
@property
def client(self):
if 'runtime_client' not in RUNTIME_CONFIGS:
RUNTIME_CONFIGS['runtime_client'] = salt.client.get_local_client(
mopts=self.get_config(self._salt_client_config_file_name_, from_scratch=True)
)
return RUNTIME_CONFIGS['runtime_client']
class ModuleCase(TestCase, SaltClientTestCaseMixIn):
class ModuleCase(TestCase, SaltClientTestCaseMixin):
'''
Execute a module function
'''
@ -1570,7 +1380,7 @@ class ModuleCase(TestCase, SaltClientTestCaseMixIn):
return ret
class SyndicCase(TestCase, SaltClientTestCaseMixIn):
class SyndicCase(TestCase, SaltClientTestCaseMixin):
'''
Execute a syndic based execution test
'''
@ -1590,7 +1400,7 @@ class SyndicCase(TestCase, SaltClientTestCaseMixIn):
return orig['minion']
class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase, ScriptPathMixin):
class ShellCase(ShellTestCase, AdaptedConfigurationTestCaseMixin, ScriptPathMixin):
'''
Execute a test for a shell command
'''
@ -1717,161 +1527,3 @@ class SSHCase(ShellCase):
return json.loads(ret)['localhost']
except Exception:
return ret
class SaltReturnAssertsMixIn(object):
def assertReturnSaltType(self, ret):
try:
self.assertTrue(isinstance(ret, dict))
except AssertionError:
raise AssertionError(
'{0} is not dict. Salt returned: {1}'.format(
type(ret).__name__, ret
)
)
def assertReturnNonEmptySaltType(self, ret):
self.assertReturnSaltType(ret)
try:
self.assertNotEqual(ret, {})
except AssertionError:
raise AssertionError(
'{} is equal to {}. Salt returned an empty dictionary.'
)
def __return_valid_keys(self, keys):
if isinstance(keys, tuple):
# If it's a tuple, turn it into a list
keys = list(keys)
elif isinstance(keys, six.string_types):
# If it's a string, make it a one item list
keys = [keys]
elif not isinstance(keys, list):
# If we've reached here, it's a bad type passed to keys
raise RuntimeError('The passed keys need to be a list')
return keys
def __getWithinSaltReturn(self, ret, keys):
self.assertReturnNonEmptySaltType(ret)
keys = self.__return_valid_keys(keys)
okeys = keys[:]
for part in six.itervalues(ret):
try:
ret_item = part[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[\'{0}\']'.format(k) for k in keys]), part
)
)
while okeys:
try:
ret_item = ret_item[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[\'{0}\']'.format(k) for k in keys]), part
)
)
return ret_item
def assertSaltTrueReturn(self, ret):
try:
self.assertTrue(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not True. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned:\n{0}'.format(
pprint.pformat(ret)
)
)
def assertSaltFalseReturn(self, ret):
try:
self.assertFalse(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not False. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertSaltNoneReturn(self, ret):
try:
self.assertIsNone(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not None. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertInSaltComment(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertNotInSaltComment(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertSaltCommentRegexpMatches(self, ret, pattern):
return self.assertInSaltReturnRegexpMatches(ret, pattern, 'comment')
def assertInSaltStateWarning(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertNotInSaltStateWarning(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertInSaltReturn(self, item_to_check, ret, keys):
return self.assertIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertNotInSaltReturn(self, item_to_check, ret, keys):
return self.assertNotIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertInSaltReturnRegexpMatches(self, ret, pattern, keys=()):
return self.assertRegex(
self.__getWithinSaltReturn(ret, keys), pattern
)
def assertSaltStateChangesEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)
def assertSaltStateChangesNotEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertNotEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)

View file

@ -10,7 +10,7 @@ import tests.integration as integration
import salt.runner
class RunnerModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixIn):
class RunnerModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixin):
eauth_creds = {
'username': 'saltdev_auto',
'password': 'saltdev',

View file

@ -29,7 +29,7 @@ except ImportError:
'openstack integration tests.'
)
class OpenstackTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the keystone state
'''

View file

@ -20,7 +20,7 @@ import salt.utils
# @requires_salt_modules('acl')
# @requires_salt_modules('linux_acl')
class LinuxAclModuleTest(integration.ModuleCase,
integration.AdaptedConfigurationTestCaseMixIn):
integration.AdaptedConfigurationTestCaseMixin):
'''
Validate the linux_acl module
'''

View file

@ -35,7 +35,7 @@ if not salt.utils.which('mysqladmin'):
'MySQL integration tests.'
)
class MysqlModuleDbTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Module testing database creation on a real MySQL Server.
'''
@ -616,7 +616,7 @@ class MysqlModuleDbTest(integration.ModuleCase,
'MySQL integration tests.'
)
class MysqlModuleUserTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
User Creation and connection tests
'''
@ -1270,7 +1270,7 @@ class MysqlModuleUserTest(integration.ModuleCase,
'MySQL integration tests.'
)
class MysqlModuleUserGrantTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
User Creation and connection tests
'''

View file

@ -12,7 +12,7 @@ from tests.support.helpers import (
class PkgModuleTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the pkg module
'''

View file

@ -8,7 +8,7 @@ import tests.integration as integration
class PublishModuleTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the publish module
'''

View file

@ -21,7 +21,7 @@ import salt.ext.six as six
class StateModuleTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the state module
'''

View file

@ -12,7 +12,7 @@ import salt.config
class TestModuleTest(integration.ModuleCase,
integration.AdaptedConfigurationTestCaseMixIn):
integration.AdaptedConfigurationTestCaseMixin):
'''
Validate the test module
'''

View file

@ -18,7 +18,7 @@ from tests.support.helpers import flaky
import salt.utils.event
class ReactorTest(integration.ModuleCase, integration.SaltMinionEventAssertsMixIn):
class ReactorTest(integration.ModuleCase, integration.SaltMinionEventAssertsMixin):
'''
Test Salt's reactor system
'''

View file

@ -16,7 +16,7 @@ STATE_DIR = os.path.join(integration.FILES, 'file', 'base')
class EnvTestCase(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
def setUp(self):
self.state_name = 'test_sdb_env'

View file

@ -19,7 +19,7 @@ if not os.path.exists('/etc/alternatives'):
@skipIf(NO_ALTERNATIVES, '/etc/alternatives does not exist on the system')
class AlterantivesStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
@destructiveTest
def test_install_set_and_remove(self):
ret = self.run_state('alternatives.set', name='alt-test', path='/bin/true')

View file

@ -35,7 +35,7 @@ STATE_DIR = os.path.join(integration.FILES, 'file', 'base')
class ArchiveTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the archive state
'''

View file

@ -35,7 +35,7 @@ except ImportError:
'Please setup boto AWS credentials before running boto integration tests.'
)
class BotoSNSTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
def setUp(self):
# The name of the topic you want to create.

View file

@ -17,7 +17,7 @@ import salt.utils
@skipIf(salt.utils.which('bower') is None, 'bower not installed')
class BowerStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
@destructiveTest
def test_bower_installed_removed(self):

View file

@ -19,7 +19,7 @@ IS_WINDOWS = salt.utils.is_windows()
class CMDTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the cmd state
'''
@ -41,7 +41,7 @@ class CMDTest(integration.ModuleCase,
class CMDRunRedirectTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the cmd state of run_redirect
'''
@ -159,7 +159,7 @@ class CMDRunRedirectTest(integration.ModuleCase,
class CMDRunWatchTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the cmd state of run_watch
'''

View file

@ -50,7 +50,7 @@ def with_random_name(func):
@skipIf(not salt.utils.which('busybox'), 'Busybox not installed')
@skipIf(not salt.utils.which('dockerd'), 'Docker not installed')
class DockerContainerTestCase(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Test docker_container states
'''

View file

@ -139,7 +139,7 @@ def _test_managed_file_mode_keep_helper(testcase, local=False):
os.chmod(grail_fs_path, grail_fs_mode)
class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate the file state
'''
@ -2431,7 +2431,7 @@ FILE_SOURCE = 'http://localhost:{0}/grail/scene33'.format(PORT)
FILE_HASH = 'd2feb3beb323c79fc7a0f44f1408b4a3'
class RemoteFileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class RemoteFileTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Uses a local tornado webserver to test http(s) file.managed states with and
without skip_verify

View file

@ -21,7 +21,7 @@ import salt.utils
@skip_if_binaries_missing('git')
class GitTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class GitTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate the git state
'''
@ -462,7 +462,7 @@ class GitTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
@skip_if_binaries_missing('git')
class LocalRepoGitTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class LocalRepoGitTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Tests which do no require connectivity to github.com
'''

View file

@ -17,7 +17,7 @@ import salt.utils
HFILE = os.path.join(integration.TMP, 'hosts')
class HostTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class HostTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate the host state
'''

View file

@ -27,7 +27,7 @@ except ImportError:
'keystone integration tests.'
)
class KeystoneStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the keystone state
'''

View file

@ -35,7 +35,7 @@ if not salt.utils.which('mysqladmin'):
'MySQL integration tests.'
)
class MysqlDatabaseStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the mysql_database state
'''
@ -241,7 +241,7 @@ class MysqlDatabaseStateTest(integration.ModuleCase,
'MySQL integration tests.'
)
class MysqlGrantsStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the mysql_grants states
'''

View file

@ -14,7 +14,7 @@ from tests.support.helpers import destructiveTest
@destructiveTest
class NetworkTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class NetworkTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate network state module
'''

View file

@ -17,7 +17,7 @@ import salt.utils
@skipIf(salt.utils.which('npm') is None, 'npm not installed')
class NpmStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class NpmStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
@requires_network()
@destructiveTest

View file

@ -33,7 +33,7 @@ import salt.ext.six as six
@skipIf(salt.utils.which_bin(KNOWN_BINARY_NAMES) is None, 'virtualenv not installed')
class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
def test_pip_installed_removed(self):
'''

View file

@ -145,7 +145,7 @@ def latest_version(run_function, *names):
@destructiveTest
@requires_salt_modules('pkg.version', 'pkg.latest_version')
class PkgTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
pkg.installed state tests
'''

View file

@ -22,7 +22,7 @@ import salt.ext.six as six
class PkgrepoTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
pkgrepo state tests
'''

View file

@ -11,7 +11,7 @@ import tests.integration as integration
class RabbitUserTestCase(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the rabbitmq user states.
'''

View file

@ -12,7 +12,7 @@ import tests.integration as integration
class RabbitVHostTestCase(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the rabbitmq virtual host states.
'''

View file

@ -20,7 +20,7 @@ SERVICE_NAME = 'crond'
@destructiveTest
@skipIf(salt.utils.which('crond') is None, 'crond not installed')
class ServiceTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the service state
'''

View file

@ -27,7 +27,7 @@ GITHUB_IP = '192.30.253.113'
@skip_if_binaries_missing(['ssh', 'ssh-keygen'], check_all=True)
class SSHKnownHostsStateTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the ssh state
'''
@ -156,7 +156,7 @@ class SSHKnownHostsStateTest(integration.ModuleCase,
class SSHAuthStateTests(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
@destructiveTest
@skipIf(os.geteuid() != 0, 'you must be root to run this test')

View file

@ -26,7 +26,7 @@ import salt.ext.six as six
@skipIf(salt.utils.which_bin(KNOWN_BINARY_NAMES) is None, 'virtualenv not installed')
@skipIf(salt.utils.which('supervisorctl') is None, 'supervisord not installed')
class SupervisordTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
Validate the supervisord states.
'''

View file

@ -14,7 +14,7 @@ import socket
import tests.integration as integration
class SvnTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
class SvnTest(integration.ModuleCase, integration.SaltReturnAssertsMixin):
'''
Validate the svn state
'''

View file

@ -37,7 +37,7 @@ else:
@destructiveTest
@skipIf(os.geteuid() != 0, 'you must be root to run this test')
class UserTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
'''
test for user absent
'''

View file

@ -24,7 +24,7 @@ from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
@skipIf(salt.utils.which_bin(KNOWN_BINARY_NAMES) is None, 'virtualenv not installed')
class VirtualenvTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
integration.SaltReturnAssertsMixin):
@destructiveTest
@skipIf(os.geteuid() != 0, 'you must be root to run this test')
def test_issue_1959_virtualenv_runas(self):

View file

@ -13,7 +13,7 @@ import salt.wheel
import salt.utils
class WheelModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixIn):
class WheelModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixin):
eauth_creds = {
'username': 'saltdev_auto',

View file

@ -8,7 +8,7 @@ import tests.integration as integration
import salt.wheel
class KeyWheelModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixIn):
class KeyWheelModuleTest(integration.TestCase, integration.AdaptedConfigurationTestCaseMixin):
def setUp(self):
self.wheel = salt.wheel.Wheel(dict(self.get_config('client_config')))

View file

@ -14,26 +14,43 @@
from __future__ import absolute_import
import os
import sys
import time
import types
import atexit
import pprint
import logging
import warnings
import tempfile
import functools
import subprocess
import multiprocessing
# Import Salt Testing Libs
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, patch
from tests.support.paths import CODE_DIR
from tests.support.runtests import RUNTIME_VARS
from tests.support.paths import CODE_DIR
# Import salt libs
#import salt.config
import salt.version
from salt.utils.verify import verify_env
from salt.utils.immutabletypes import freeze
from salt._compat import ElementTree as etree
# Import 3rd-party libs
import salt.ext.six as six
from salt.ext.six.moves import zip # pylint: disable=import-error,redefined-builtin
RUNTIME_CONFIGS = {}
def cleanup_runtime_config_instance(to_cleanup):
# Explicit and forced cleanup
for key in list(to_cleanup):
instance = to_cleanup.pop(key)
del instance
atexit.register(cleanup_runtime_config_instance, RUNTIME_CONFIGS)
log = logging.getLogger(__name__)
@ -59,251 +76,130 @@ class CheckShellBinaryNameAndVersionMixin(object):
self.assertIn(self._call_binary_expected_version_, out)
class SaltReturnAssertsMixin(object):
'''
Mix-in class to add as a companion to the TestCase class or it's subclasses which
adds test assertions for Salt's return data.
.. code-block: python
from tests.support.case import ModuleCase
from tests.support.mixins import SaltReturnAssertsMixin
class FooTestCase(ModuleCase, SaltReturnAssertsMixin):
def test_bar(self):
ret = self.run_function('publish.publish', ['minion', 'test.ping'])
self.assertReturnSaltType(ret)
'''
def assertReturnSaltType(self, ret):
try:
self.assertTrue(isinstance(ret, dict))
except AssertionError:
raise AssertionError(
'{0} is not dict. Salt returned: {1}'.format(
type(ret).__name__, ret
)
)
def assertReturnNonEmptySaltType(self, ret):
self.assertReturnSaltType(ret)
try:
self.assertNotEqual(ret, {})
except AssertionError:
raise AssertionError(
'{} is equal to {}. Salt returned an empty dictionary.'
)
def __return_valid_keys(self, keys):
if isinstance(keys, tuple):
# If it's a tuple, turn it into a list
keys = list(keys)
elif isinstance(keys, six.string_types):
# If it's a basestring , make it a one item list
keys = [keys]
elif not isinstance(keys, list):
# If we've reached here, it's a bad type passed to keys
raise RuntimeError('The passed keys need to be a list')
return keys
def __getWithinSaltReturn(self, ret, keys):
self.assertReturnNonEmptySaltType(ret)
keys = self.__return_valid_keys(keys)
okeys = keys[:]
for part in six.itervalues(ret):
try:
ret_item = part[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[{0!r}]'.format(k) for k in keys]), part
)
)
while okeys:
try:
ret_item = ret_item[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[{0!r}]'.format(k) for k in keys]), part
)
)
return ret_item
def assertSaltTrueReturn(self, ret):
try:
self.assertTrue(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not True. Salt Comment:\n{comment}'.format(
**(ret.values()[0])
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned:\n{0}'.format(
pprint.pformat(ret)
)
)
def assertSaltFalseReturn(self, ret):
try:
self.assertFalse(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not False. Salt Comment:\n{comment}'.format(
**(ret.values()[0])
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertSaltNoneReturn(self, ret):
try:
self.assertIsNone(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not None. Salt Comment:\n{comment}'.format(
**(ret.values()[0])
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertInSaltComment(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertNotInSaltComment(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertSaltCommentRegexpMatches(self, ret, pattern):
return self.assertInSaltReturnRegexpMatches(ret, pattern, 'comment')
def assertInSalStatetWarning(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertNotInSaltStateWarning(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertInSaltReturn(self, item_to_check, ret, keys):
return self.assertIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertNotInSaltReturn(self, item_to_check, ret, keys):
return self.assertNotIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertInSaltReturnRegexpMatches(self, ret, pattern, keys=()):
return self.assertRegex(
self.__getWithinSaltReturn(ret, keys), pattern
)
def assertSaltStateChangesEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)
def assertSaltStateChangesNotEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertNotEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)
class AdaptedConfigurationTestCaseMixin(object):
__slots__ = ()
def get_config_dir(self):
@staticmethod
def get_temp_config(config_for, **config_overrides):
rootdir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
#self.addCleanup(shutil.rmtree, rootdir)
for key in ('cachedir', 'pki_dir', 'sock_dir'):
if key not in config_overrides:
config_overrides[key] = key
if 'log_file' not in config_overrides:
config_overrides['log_file'] = 'logs/{}.log'.format(config_for)
if 'user' not in config_overrides:
config_overrides['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
config_overrides['root_dir'] = rootdir
cdict = AdaptedConfigurationTestCaseMixin.get_config(config_for, from_scratch=True)
if config_for in ('master', 'client_config'):
rdict = salt.config.apply_master_config(config_overrides, cdict)
if config_for == 'minion':
rdict = salt.config.apply_minion_config(config_overrides, cdict)
verify_env([os.path.join(rdict['pki_dir'], 'minions'),
os.path.join(rdict['pki_dir'], 'minions_pre'),
os.path.join(rdict['pki_dir'], 'minions_rejected'),
os.path.join(rdict['pki_dir'], 'minions_denied'),
os.path.join(rdict['cachedir'], 'jobs'),
os.path.join(rdict['cachedir'], 'raet'),
os.path.join(rdict['cachedir'], 'tokens'),
os.path.join(rdict['root_dir'], 'cache', 'tokens'),
os.path.join(rdict['pki_dir'], 'accepted'),
os.path.join(rdict['pki_dir'], 'rejected'),
os.path.join(rdict['pki_dir'], 'pending'),
os.path.dirname(rdict['log_file']),
rdict['sock_dir'],
],
RUNTIME_VARS.RUNNING_TESTS_USER)
return rdict
@staticmethod
def get_config(config_for, from_scratch=False):
if from_scratch:
if config_for in ('master', 'syndic_master'):
return salt.config.master_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for)
)
elif config_for in ('minion', 'sub_minion'):
return salt.config.minion_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for)
)
elif config_for in ('syndic',):
return salt.config.syndic_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for),
AdaptedConfigurationTestCaseMixin.get_config_file_path('minion')
)
elif config_for == 'client_config':
return salt.config.client_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path('master')
)
if config_for not in RUNTIME_CONFIGS:
if config_for in ('master', 'syndic_master'):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.master_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for)
)
)
elif config_for in ('minion', 'sub_minion'):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.minion_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for)
)
)
elif config_for in ('syndic',):
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.syndic_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path(config_for),
AdaptedConfigurationTestCaseMixin.get_config_file_path('minion')
)
)
elif config_for == 'client_config':
RUNTIME_CONFIGS[config_for] = freeze(
salt.config.client_config(
AdaptedConfigurationTestCaseMixin.get_config_file_path('master')
)
)
return RUNTIME_CONFIGS[config_for]
@staticmethod
def get_config_dir():
return RUNTIME_VARS.TMP_CONF_DIR
def get_config_file_path(self, filename):
@staticmethod
def get_config_file_path(filename):
if filename == 'syndic_master':
return os.path.join(RUNTIME_VARS.TMP_SYNDIC_MASTER_CONF_DIR, 'master')
if filename == 'syndic':
return os.path.join(RUNTIME_VARS.TMP_SYNDIC_MINION_CONF_DIR, 'minion')
if filename == 'sub_minion':
return os.path.join(RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR, 'minion')
return os.path.join(RUNTIME_VARS.TMP_CONF_DIR, filename)
@property
def master_opts(self):
# Late import
import salt.config
warnings.warn(
'Please stop using the \'master_opts\' attribute in \'{0}.{1}\' and instead '
'import \'RUNTIME_VARS\' from {2!r} and instantiate the master configuration like '
'\'salt.config.master_config(os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master"))\''.format(
self.__class__.__module__,
self.__class__.__name__,
__name__
),
DeprecationWarning,
)
return salt.config.master_config(
self.get_config_file_path('master')
)
'''
Return the options used for the master
'''
return self.get_config('master')
@property
def minion_opts(self):
'''
Return the options used for the minion
'''
# Late import
import salt.config
warnings.warn(
'Please stop using the \'minion_opts\' attribute in \'{0}.{1}\' and instead '
'import \'RUNTIME_VARS\' from {2!r} and instantiate the minion configuration like '
'\'salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "minion"))\''.format(
self.__class__.__module__,
self.__class__.__name__,
__name__
),
DeprecationWarning,
)
return salt.config.minion_config(
self.get_config_file_path('minion')
)
return self.get_config('minion')
@property
def sub_minion_opts(self):
'''
Return the options used for the sub-minion
Return the options used for the sub_minion
'''
# Late import
import salt.config
warnings.warn(
'Please stop using the \'sub_minion_opts\' attribute in \'{0}.{1}\' and instead '
'import \'RUNTIME_VARS\' from {2!r} and instantiate the sub-minion configuration like '
'\'salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "sub_minion_opts"))\''.format(
self.__class__.__module__,
self.__class__.__name__,
__name__
),
DeprecationWarning,
)
return salt.config.minion_config(
self.get_config_file_path('sub_minion')
)
return self.get_config('sub_minion')
class SaltClientTestCaseMixin(AdaptedConfigurationTestCaseMixin):
@ -337,9 +233,11 @@ class SaltClientTestCaseMixin(AdaptedConfigurationTestCaseMixin):
def client(self):
# Late import
import salt.client
return salt.client.get_local_client(
self.get_config_file_path(self._salt_client_config_file_name_)
)
if 'runtime_client' not in RUNTIME_CONFIGS:
RUNTIME_CONFIGS['runtime_client'] = salt.client.get_local_client(
mopts=self.get_config(self._salt_client_config_file_name_, from_scratch=True)
)
return RUNTIME_CONFIGS['runtime_client']
class ShellCaseCommonTestsMixin(CheckShellBinaryNameAndVersionMixin):
@ -582,3 +480,221 @@ class XMLEqualityMixin(object):
if len(e1) != len(e2):
return False
return all(self.assertEqualXML(c1, c2) for c1, c2 in zip(e1, e2))
class SaltReturnAssertsMixin(object):
def assertReturnSaltType(self, ret):
try:
self.assertTrue(isinstance(ret, dict))
except AssertionError:
raise AssertionError(
'{0} is not dict. Salt returned: {1}'.format(
type(ret).__name__, ret
)
)
def assertReturnNonEmptySaltType(self, ret):
self.assertReturnSaltType(ret)
try:
self.assertNotEqual(ret, {})
except AssertionError:
raise AssertionError(
'{} is equal to {}. Salt returned an empty dictionary.'
)
def __return_valid_keys(self, keys):
if isinstance(keys, tuple):
# If it's a tuple, turn it into a list
keys = list(keys)
elif isinstance(keys, six.string_types):
# If it's a string, make it a one item list
keys = [keys]
elif not isinstance(keys, list):
# If we've reached here, it's a bad type passed to keys
raise RuntimeError('The passed keys need to be a list')
return keys
def __getWithinSaltReturn(self, ret, keys):
self.assertReturnNonEmptySaltType(ret)
keys = self.__return_valid_keys(keys)
okeys = keys[:]
for part in six.itervalues(ret):
try:
ret_item = part[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[\'{0}\']'.format(k) for k in keys]), part
)
)
while okeys:
try:
ret_item = ret_item[okeys.pop(0)]
except (KeyError, TypeError):
raise AssertionError(
'Could not get ret{0} from salt\'s return: {1}'.format(
''.join(['[\'{0}\']'.format(k) for k in keys]), part
)
)
return ret_item
def assertSaltTrueReturn(self, ret):
try:
self.assertTrue(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not True. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned:\n{0}'.format(
pprint.pformat(ret)
)
)
def assertSaltFalseReturn(self, ret):
try:
self.assertFalse(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not False. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertSaltNoneReturn(self, ret):
try:
self.assertIsNone(self.__getWithinSaltReturn(ret, 'result'))
except AssertionError:
log.info('Salt Full Return:\n{0}'.format(pprint.pformat(ret)))
try:
raise AssertionError(
'{result} is not None. Salt Comment:\n{comment}'.format(
**(next(six.itervalues(ret)))
)
)
except (AttributeError, IndexError):
raise AssertionError(
'Failed to get result. Salt Returned: {0}'.format(ret)
)
def assertInSaltComment(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertNotInSaltComment(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'comment')
)
def assertSaltCommentRegexpMatches(self, ret, pattern):
return self.assertInSaltReturnRegexpMatches(ret, pattern, 'comment')
def assertInSaltStateWarning(self, in_comment, ret):
return self.assertIn(
in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertNotInSaltStateWarning(self, not_in_comment, ret):
return self.assertNotIn(
not_in_comment, self.__getWithinSaltReturn(ret, 'warnings')
)
def assertInSaltReturn(self, item_to_check, ret, keys):
return self.assertIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertNotInSaltReturn(self, item_to_check, ret, keys):
return self.assertNotIn(
item_to_check, self.__getWithinSaltReturn(ret, keys)
)
def assertInSaltReturnRegexpMatches(self, ret, pattern, keys=()):
return self.assertRegex(
self.__getWithinSaltReturn(ret, keys), pattern
)
def assertSaltStateChangesEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)
def assertSaltStateChangesNotEqual(self, ret, comparison, keys=()):
keys = ['changes'] + self.__return_valid_keys(keys)
return self.assertNotEqual(
self.__getWithinSaltReturn(ret, keys), comparison
)
class SaltMinionEventAssertsMixin(object):
'''
Asserts to verify that a given event was seen
'''
def __new__(cls, *args, **kwargs):
# We have to cross-call to re-gen a config
cls.q = multiprocessing.Queue()
cls.fetch_proc = multiprocessing.Process(target=cls._fetch, args=(cls.q,))
cls.fetch_proc.start()
return object.__new__(cls)
def __exit__(self, *args, **kwargs):
self.fetch_proc.join()
@staticmethod
def _fetch(q):
'''
Collect events and store them
'''
def _clean_queue():
print('Cleaning queue!')
while not q.empty():
queue_item = q.get()
queue_item.task_done()
atexit.register(_clean_queue)
a_config = AdaptedConfigurationTestCaseMixin()
event = salt.utils.event.get_event('minion', sock_dir=a_config.get_config('minion')['sock_dir'], opts=a_config.get_config('minion'))
while True:
try:
events = event.get_event(full=False)
except Exception:
# This is broad but we'll see all kinds of issues right now
# if we drop the proc out from under the socket while we're reading
pass
q.put(events)
def assertMinionEventFired(self, tag):
#TODO
raise NotImplementedError('assertMinionEventFired() not implemented')
def assertMinionEventReceived(self, desired_event):
queue_wait = 5 # 2.5s
while self.q.empty():
time.sleep(0.5) # Wait for events to be pushed into the queue
queue_wait -= 1
if queue_wait <= 0:
raise AssertionError('Queue wait timer expired')
while not self.q.empty(): # This is not thread-safe and may be inaccurate
event = self.q.get()
if isinstance(event, dict):
event.pop('_stamp')
if desired_event == event:
self.fetch_proc.terminate()
return True
self.fetch_proc.terminate()
raise AssertionError('Event {0} was not received by minion'.format(desired_event))

View file

@ -49,6 +49,7 @@
# Import Python modules
from __future__ import absolute_import, print_function
import os
import sys
import json
import shutil
import logging
@ -102,6 +103,13 @@ try:
except ImportError:
pass
if sys.platform.startswith('win'):
import win32api # pylint: disable=import-error
RUNNING_TESTS_USER = win32api.GetUserName()
else:
import pwd
RUNNING_TESTS_USER = pwd.getpwuid(os.getuid()).pw_name
log = logging.getLogger(__name__)
@ -200,6 +208,7 @@ RUNTIME_VARS = RuntimeVars(
TMP_BASEENV_STATE_TREE=os.path.join(paths.TMP, 'integration-files', 'file', 'base'),
TMP_PRODENV_STATE_TREE=os.path.join(paths.TMP, 'integration-files', 'file', 'prod'),
TMP_BASEENV_PILLAR_TREE=os.path.join(paths.TMP, 'integration-files', 'pillar', 'base'),
TMP_PRODENV_PILLAR_TREE=os.path.join(paths.TMP, 'integration-files', 'pillar', 'prod')
TMP_PRODENV_PILLAR_TREE=os.path.join(paths.TMP, 'integration-files', 'pillar', 'prod'),
RUNNING_TESTS_USER=RUNNING_TESTS_USER
)
# <---- Tests Runtime Variables --------------------------------------------------------------------------------------

View file

@ -73,7 +73,7 @@ def _salt_configuration_error(filename):
raise SaltConfigurationError('Configuration error in {0}'.format(filename))
class ConfigTestCase(TestCase, integration.AdaptedConfigurationTestCaseMixIn):
class ConfigTestCase(TestCase, integration.AdaptedConfigurationTestCaseMixin):
def test_sha256_is_default_for_master(self):
fpath = tempfile.mktemp()

View file

@ -10,7 +10,7 @@ import os
import shutil
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.paths import TMP
from tests.support.unit import TestCase, skipIf
@ -45,7 +45,7 @@ MOCKED_OPTS = {
@skipIf(NO_MOCK, NO_MOCK_REASON)
class FileClientTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class FileClientTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {fileclient: {'__opts__': MOCKED_OPTS}}
@ -79,7 +79,7 @@ class FileClientTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMo
@skipIf(NO_MOCK, NO_MOCK_REASON)
class FileclientCacheTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class FileclientCacheTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
'''
Tests for the fileclient caching. The LocalClient is the only thing we can
test as it is the only way we can mock the fileclient (the tests run from

View file

@ -9,7 +9,7 @@ import os
import tempfile
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.paths import FILES, TMP, TMP_STATE_TREE
from tests.support.unit import TestCase, skipIf
@ -27,7 +27,7 @@ except ImportError:
@skipIf(NO_MOCK, NO_MOCK_REASON)
class RootsTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
@ -171,7 +171,7 @@ class RootsTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMix
self.assertDictEqual(ret, {'dest_sym': 'source_sym'})
class RootsLimitTraversalTest(TestCase, AdaptedConfigurationTestCaseMixIn):
class RootsLimitTraversalTest(TestCase, AdaptedConfigurationTestCaseMixin):
def test_limit_traversal(self):
'''

View file

@ -8,7 +8,7 @@ import copy
import hashlib
# Import Salt Testing Libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.unit import TestCase, skipIf
# Import Salt libs
@ -46,7 +46,7 @@ from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
@skipIf(HAS_TORNADO is False, 'The tornado package needs to be installed') # pylint: disable=W0223
class SaltnadoTestCase(TestCase, AdaptedConfigurationTestCaseMixIn, AsyncHTTPTestCase):
class SaltnadoTestCase(TestCase, AdaptedConfigurationTestCaseMixin, AsyncHTTPTestCase):
'''
Mixin to hold some shared things
'''

View file

@ -18,7 +18,7 @@ import subprocess
import yaml
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.paths import TMP
from tests.support.unit import TestCase, skipIf
@ -40,7 +40,7 @@ import salt.pillar.git_pillar as git_pillar
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(not git_pillar.HAS_GITPYTHON, 'no GitPython')
class GitPillarTestCase(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class GitPillarTestCase(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
'test git_pillar pillar'
maxDiff = None

View file

@ -11,7 +11,7 @@ import subprocess
import yaml
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON
@ -33,7 +33,7 @@ HGLIB = hg_pillar.hglib
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(HGLIB is None, 'python-hglib library not installed')
class HgPillarTestCase(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class HgPillarTestCase(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
'test hg_pillar pillar'
maxDiff = None

View file

@ -14,7 +14,7 @@ import logging
import tempfile
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.paths import TMP
from tests.support.unit import TestCase, skipIf
@ -166,7 +166,7 @@ class LocalCacheCleanOldJobsTestCase(TestCase, LoaderModuleMockMixin):
return temp_dir, jid_file_path
class Local_CacheTest(TestCase, AdaptedConfigurationTestCaseMixIn, LoaderModuleMockMixin):
class Local_CacheTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
'''
Test the local cache returner
'''

View file

@ -11,7 +11,7 @@
from __future__ import absolute_import
# Import Salt Testing libs
from tests.integration import SaltReturnAssertsMixIn
from tests.integration import SaltReturnAssertsMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
@ -30,7 +30,7 @@ except ImportError:
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(not HAS_PIP,
'The \'pip\' library is not importable(installed system-wide)')
class PipStateTest(TestCase, SaltReturnAssertsMixIn, LoaderModuleMockMixin):
class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {

View file

@ -18,7 +18,7 @@ from salt.exceptions import EauthAuthenticationError, SaltInvocationError, SaltC
@skipIf(NO_MOCK, NO_MOCK_REASON)
class LocalClientTestCase(TestCase,
integration.SaltClientTestCaseMixIn):
integration.SaltClientTestCaseMixin):
def test_create_local_client(self):
local_client = client.LocalClient(mopts=self.get_temp_config('master'))

View file

@ -5,15 +5,15 @@
# Import python libs
from __future__ import absolute_import
import multiprocessing
# Import Salt Testing libs
from tests.support.unit import TestCase, skipIf
from tests.support.mock import patch, MagicMock, NO_MOCK, NO_MOCK_REASON
from tests.support.mixins import SaltClientTestCaseMixin
# Import Salt libs
import tests.integration as integration
import multiprocessing
from salt.cli import daemons
import salt.cli.daemons as daemons
class LoggerMock(object):
@ -69,7 +69,7 @@ class LoggerMock(object):
@skipIf(NO_MOCK, NO_MOCK_REASON)
class DaemonsStarterTestCase(TestCase, integration.SaltClientTestCaseMixIn):
class DaemonsStarterTestCase(TestCase, SaltClientTestCaseMixin):
'''
Unit test for the daemons starter classes.
'''

View file

@ -11,7 +11,7 @@ from contextlib import contextmanager
from salt.utils.process import clean_proc
import salt.utils.reactor as reactor
from tests.integration import AdaptedConfigurationTestCaseMixIn
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.paths import TMP
from tests.support.unit import TestCase, skipIf
from tests.support.mock import patch, MagicMock
@ -39,7 +39,7 @@ def _args_sideffect(*args, **kwargs):
@skipIf(True, 'Skipping until its clear what and how is this supposed to be testing')
class TestReactor(TestCase, AdaptedConfigurationTestCaseMixIn):
class TestReactor(TestCase, AdaptedConfigurationTestCaseMixin):
def setUp(self):
self.opts = self.get_temp_config('master')
self.tempdir = tempfile.mkdtemp(dir=TMP)