mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Rewrite the tests_valid_docs test
This uses a function in the runtests_helpers custom module to perform all the logic, and only returns what failed the test. This saves us from having to return the entire contents of sys.doc (as well as log all of the function calls), and also removes the need to run sys.doc in batches to get around the "max message size" issue.
This commit is contained in:
parent
a29a7be7f8
commit
5a3c099e4f
6 changed files with 102 additions and 79 deletions
|
@ -679,7 +679,13 @@ class SMinion(MinionBase):
|
|||
|
||||
def gen_modules(self, initial_load=False):
|
||||
'''
|
||||
Load all of the modules for the minion
|
||||
Tell the minion to reload the execution modules
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' sys.reload_modules
|
||||
'''
|
||||
self.opts['pillar'] = salt.pillar.get_pillar(
|
||||
self.opts,
|
||||
|
@ -734,7 +740,13 @@ class MasterMinion(object):
|
|||
|
||||
def gen_modules(self, initial_load=False):
|
||||
'''
|
||||
Load all of the modules for the minion
|
||||
Tell the minion to reload the execution modules
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' sys.reload_modules
|
||||
'''
|
||||
self.utils = salt.loader.utils(self.opts)
|
||||
self.functions = salt.loader.minion_mods(
|
||||
|
|
|
@ -421,8 +421,10 @@ def reload_modules():
|
|||
|
||||
salt '*' sys.reload_modules
|
||||
'''
|
||||
# This is handled inside the minion.py file, the function is caught before
|
||||
# it ever gets here
|
||||
# This function is actually handled inside the minion.py file, the function
|
||||
# is caught before it ever gets here. Therefore, the docstring above is
|
||||
# only for the online docs, and ANY CHANGES made to it must also be made in
|
||||
# each of the gen_modules() funcs in minion.py.
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
@ -1138,6 +1138,13 @@ class TestDaemon(object):
|
|||
TMP_PRODENV_STATE_TREE
|
||||
]
|
||||
}
|
||||
master_opts.setdefault('reactor', []).append(
|
||||
{
|
||||
'salt/minion/*/start': [
|
||||
os.path.join(FILES, 'reactor-sync-minion.sls')
|
||||
],
|
||||
}
|
||||
)
|
||||
for opts_dict in (master_opts, syndic_master_opts):
|
||||
if 'ext_pillar' not in opts_dict:
|
||||
opts_dict['ext_pillar'] = []
|
||||
|
|
|
@ -9,12 +9,16 @@
|
|||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
# Import 3rd-party libs
|
||||
import salt.ext.six as six
|
||||
|
||||
SYS_TMP_DIR = os.path.realpath(
|
||||
# Avoid ${TMPDIR} and gettempdir() on MacOS as they yield a base path too long
|
||||
|
@ -29,9 +33,75 @@ TMP = os.path.join(SYS_TMP_DIR, 'salt-tests-tmpdir')
|
|||
def get_salt_temp_dir():
|
||||
return TMP
|
||||
|
||||
|
||||
def get_salt_temp_dir_for_path(*path):
|
||||
return os.path.join(TMP, *path)
|
||||
|
||||
|
||||
def get_sys_temp_dir_for_path(*path):
|
||||
return os.path.join(SYS_TMP_DIR, *path)
|
||||
|
||||
|
||||
def get_invalid_docs():
|
||||
'''
|
||||
Outputs the functions which do not have valid CLI example, or are missing a
|
||||
docstring.
|
||||
'''
|
||||
allow_failure = (
|
||||
'cmd.win_runas',
|
||||
'cp.recv',
|
||||
'glance.warn_until',
|
||||
'ipset.long_range',
|
||||
'libcloud_dns.get_driver',
|
||||
'log.critical',
|
||||
'log.debug',
|
||||
'log.error',
|
||||
'log.exception',
|
||||
'log.info',
|
||||
'log.warning',
|
||||
'lowpkg.bin_pkg_info',
|
||||
'lxc.run_cmd',
|
||||
'nspawn.restart',
|
||||
'nspawn.stop',
|
||||
'pkg.expand_repo_def',
|
||||
'pip.iteritems',
|
||||
'runtests_decorators.depends',
|
||||
'runtests_decorators.depends_will_fallback',
|
||||
'runtests_decorators.missing_depends',
|
||||
'runtests_decorators.missing_depends_will_fallback',
|
||||
'state.apply',
|
||||
'status.list2cmdline',
|
||||
'swift.head',
|
||||
'travisci.parse_qs',
|
||||
'vsphere.clean_kwargs',
|
||||
'vsphere.disconnect',
|
||||
'vsphere.get_service_instance_via_proxy',
|
||||
'vsphere.gets_service_instance_via_proxy',
|
||||
'vsphere.supports_proxies',
|
||||
'vsphere.test_vcenter_connection',
|
||||
'vsphere.wraps',
|
||||
)
|
||||
allow_failure_glob = (
|
||||
'runtests_helpers.*',
|
||||
)
|
||||
nodoc = set()
|
||||
noexample = set()
|
||||
for fun, docstring in six.iteritems(__salt__['sys.doc']()):
|
||||
if fun in allow_failure:
|
||||
continue
|
||||
else:
|
||||
for pat in allow_failure_glob:
|
||||
if fnmatch.fnmatch(fun, pat):
|
||||
matched_glob = True
|
||||
break
|
||||
else:
|
||||
matched_glob = False
|
||||
if matched_glob:
|
||||
continue
|
||||
if not isinstance(docstring, six.string_types):
|
||||
nodoc.add(fun)
|
||||
elif not re.search(r'([E|e]xample(?:s)?)+(?:.*):?', docstring):
|
||||
noexample.add(fun)
|
||||
|
||||
return {'missing_docstring': sorted(nodoc),
|
||||
'missing_cli_example': sorted(noexample)}
|
||||
|
|
3
tests/integration/files/reactor-sync-minion.sls
Normal file
3
tests/integration/files/reactor-sync-minion.sls
Normal file
|
@ -0,0 +1,3 @@
|
|||
sync_minion:
|
||||
local.saltutil.sync_all:
|
||||
- tgt: {{ data['id'] }}
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
import re
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Import Salt Testing libs
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
@ -14,9 +10,6 @@ ensure_in_syspath('../../')
|
|||
# Import salt libs
|
||||
import integration
|
||||
|
||||
# Import 3rd-party libs
|
||||
import salt.ext.six as six
|
||||
|
||||
|
||||
class SysModuleTest(integration.ModuleCase):
|
||||
'''
|
||||
|
@ -26,79 +19,15 @@ class SysModuleTest(integration.ModuleCase):
|
|||
'''
|
||||
Make sure no functions are exposed that don't have valid docstrings
|
||||
'''
|
||||
mods = self.run_function('sys.list_modules')
|
||||
nodoc = set()
|
||||
noexample = set()
|
||||
allow_failure = (
|
||||
'cp.recv',
|
||||
'libcloud_dns.get_driver',
|
||||
'lxc.run_cmd',
|
||||
'ipset.long_range',
|
||||
'pkg.expand_repo_def',
|
||||
'runtests_decorators.depends',
|
||||
'runtests_decorators.depends_will_fallback',
|
||||
'runtests_decorators.missing_depends',
|
||||
'runtests_decorators.missing_depends_will_fallback',
|
||||
'swift.head',
|
||||
'glance.warn_until',
|
||||
'yumpkg.expand_repo_def',
|
||||
'yumpkg5.expand_repo_def',
|
||||
'container_resource.run',
|
||||
'nspawn.stop',
|
||||
'nspawn.restart',
|
||||
'lowpkg.bin_pkg_info',
|
||||
'state.apply',
|
||||
'pip.iteritems',
|
||||
'cmd.win_runas',
|
||||
'status.list2cmdline'
|
||||
)
|
||||
|
||||
batches = 2
|
||||
mod_count = len(mods)
|
||||
batch_size = mod_count / float(batches)
|
||||
if batch_size.is_integer():
|
||||
batch_size = int(batch_size)
|
||||
else:
|
||||
# Check if the module count is evenly divisible by the number of
|
||||
# batches. If not, increase the batch_size by the number of batches
|
||||
# being run. This ensures that we get the correct number of
|
||||
# batches, and that we don't end up running sys.doc an extra time
|
||||
# to cover the remainder. For example, if we had a batch count of 2
|
||||
# and 121 modules, if we just divided by 2 we'd end up running
|
||||
# sys.doc 3 times.
|
||||
batch_size = int(batch_size) + batches
|
||||
|
||||
log.debug('test_valid_docs batch size = %s', batch_size)
|
||||
start = 0
|
||||
end = batch_size
|
||||
while start <= mod_count:
|
||||
log.debug('running sys.doc on mods[%s:%s]', start, end)
|
||||
docs = self.run_function('sys.doc', mods[start:end])
|
||||
if docs == 'VALUE TRIMMED':
|
||||
self.fail(
|
||||
'sys.doc output trimmed. It may be necessary to increase '
|
||||
'the number of batches'
|
||||
)
|
||||
for fun in docs:
|
||||
if fun.startswith('runtests_helpers'):
|
||||
continue
|
||||
if fun in allow_failure:
|
||||
continue
|
||||
if not isinstance(docs[fun], six.string_types):
|
||||
nodoc.add(fun)
|
||||
elif not re.search(r'([E|e]xample(?:s)?)+(?:.*)::?', docs[fun]):
|
||||
noexample.add(fun)
|
||||
start += batch_size
|
||||
end += batch_size
|
||||
|
||||
if not nodoc and not noexample:
|
||||
ret = self.run_function('runtests_helpers.get_invalid_docs')
|
||||
if ret == {'missing_docstring': [], 'missing_cli_example': []}:
|
||||
return
|
||||
|
||||
raise AssertionError(
|
||||
'There are some functions which do not have a docstring or do not '
|
||||
'have an example:\nNo docstring:\n{0}\nNo example:\n{1}\n'.format(
|
||||
'\n'.join([' - {0}'.format(f) for f in sorted(nodoc)]),
|
||||
'\n'.join([' - {0}'.format(f) for f in sorted(noexample)]),
|
||||
'\n'.join([' - {0}'.format(f) for f in ret['missing_docstring']]),
|
||||
'\n'.join([' - {0}'.format(f) for f in ret['missing_cli_example']]),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue