From 0106905765ae0305aab5697a170c4609b6a23fa3 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 13 Apr 2012 11:50:35 -0400 Subject: added ability to pass options to nose, ignore tests, test specific clients to bcfg2-test --- src/lib/Bcfg2/Options.py | 10 +++++ src/sbin/bcfg2-test | 104 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py index 6a6b83d61..f6273924a 100644 --- a/src/lib/Bcfg2/Options.py +++ b/src/lib/Bcfg2/Options.py @@ -3,6 +3,7 @@ import getopt import os import sys +import shlex import Bcfg2.Client.Tools # Compatibility imports from Bcfg2.Bcfg2Py3k import ConfigParser @@ -353,6 +354,15 @@ CLIENT_TIMEOUT = Option('Set the client XML-RPC timeout', default=90, cmd='-t', cf=('communication', 'timeout'), odesc='') +# bcfg2-test options +TEST_NOSEOPTS = Option('Options to pass to nosetests', default=[], + cmd='--nose-options', cf=('bcfg2_test', 'nose_options'), + odesc='', long_arg=True, cook=shlex.split) +TEST_IGNORE = Option('Ignore these entries if they fail to build.', default=[], + cmd='--ignore', + cf=('bcfg2_test', 'ignore_entries'), long_arg=True, + odesc=':,:', cook=list_split) + # APT client tool options CLIENT_APT_TOOLS_INSTALL_PATH = Option('Apt tools install path', cf=('APT', 'install_path'), diff --git a/src/sbin/bcfg2-test b/src/sbin/bcfg2-test index af2225245..01a2a4893 100755 --- a/src/sbin/bcfg2-test +++ b/src/sbin/bcfg2-test @@ -1,41 +1,60 @@ #!/usr/bin/env python -"""This tool verifies that all clients known to the server build without failures""" +"""This tool verifies that all clients known to the server build +without failures""" import sys +import fnmatch +import logging +import Bcfg2.Logger import Bcfg2.Server.Core from nose.core import TestProgram +from nose.suite import LazySuite from unittest import TestCase class ClientTest(TestCase): """ - A test case representing the build of all of the configuration for a single host. - Checks that none of the build config entities has had a failure when it is building. - Optionally ignores some config files that we know will cause errors (because they - are private files we don't have access to, for instance) + A test case representing the build of all of the configuration for + a single host. Checks that none of the build config entities has + had a failure when it is building. Optionally ignores some config + files that we know will cause errors (because they are private + files we don't have access to, for instance) """ __test__ = False # Do not collect - def __init__(self, bcfg2_core, client): + def __init__(self, bcfg2_core, client, ignore=None): TestCase.__init__(self) self.bcfg2_core = bcfg2_core self.client = client + if ignore is None: + self.ignore = dict() + else: + self.ignore = ignore + + def ignore_entry(self, tag, name): + if tag in self.ignore: + if name in self.ignore[tag]: + return True + else: + # try wildcard matching + for pattern in self.ignore[tag]: + if fnmatch.fnmatch(name, pattern): + return True + return False def runTest(self): config = self.bcfg2_core.BuildConfiguration(self.client) - failures = config.xpath('//*[@failure]') - def format_failure(failure): - return "%s(%s): %s" % ( - failure.tag, - failure.attrib.get('name'), - failure.attrib.get('failure') - ) + failures = [] + msg = ["Failures:"] + for failure in config.xpath('//*[@failure]'): + if not self.ignore_entry(failure.tag, failure.get('name')): + failures.append(failure) + msg.append("%s:%s: %s" % (failure.tag, failure.get("name"), + failure.get("failure"))) + + assert len(failures) == 0, "\n".join(msg) - assert len(failures) == 0, "Failures:\n%s" % "\n".join( - [format_failure(failure) for failure in failures] - ) - def __str__(self): return "ClientTest(%s)" % self.client @@ -43,26 +62,55 @@ class ClientTest(TestCase): def main(): optinfo = { - 'configfile': Bcfg2.Options.CFILE, - 'help': Bcfg2.Options.HELP, - 'encoding': Bcfg2.Options.ENCODING, - 'repo': Bcfg2.Options.SERVER_REPOSITORY, - 'plugins': Bcfg2.Options.SERVER_PLUGINS, - 'password': Bcfg2.Options.SERVER_PASSWORD, - } + 'configfile': Bcfg2.Options.CFILE, + 'help': Bcfg2.Options.HELP, + 'encoding': Bcfg2.Options.ENCODING, + 'repo': Bcfg2.Options.SERVER_REPOSITORY, + 'plugins': Bcfg2.Options.SERVER_PLUGINS, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'verbose': Bcfg2.Options.VERBOSE, + 'noseopts': Bcfg2.Options.TEST_NOSEOPTS, + 'ignore': Bcfg2.Options.TEST_IGNORE, + } setup = Bcfg2.Options.OptionParser(optinfo) + setup.hm = \ + "bcfg2-test [options] [client] [client] [...]\nOptions:\n %s" % \ + setup.buildHelpMessage() setup.parse(sys.argv[1:]) + + if setup['verbose']: + Bcfg2.Logger.setup_logging("bcfg2-test", to_syslog=False) + core = Bcfg2.Server.Core.Core( setup['repo'], setup['plugins'], setup['password'], setup['encoding'], filemonitor='pseudo' - ) - core.fam.handle_events_in_interval(0.1) - suite = [ClientTest(core, client) for client in core.metadata.clients] + ) + + ignore = dict() + for entry in setup['ignore']: + tag, name = entry.split(":") + try: + ignore[tag].append(name) + except KeyError: + ignore[tag] = [name] + + def run_tests(): + core.fam.handle_events_in_interval(0.1) + + if setup['args']: + clients = setup['args'] + else: + clients = core.metadata.clients + + for client in clients: + logging.info("Building %s" % client) + yield ClientTest(core, client, ignore) - TestProgram(argv=sys.argv[0:1], suite = suite) + TestProgram(argv=sys.argv[0:1] + setup['noseopts'], + suite=LazySuite(run_tests)) if __name__ == "__main__": sys.exit(main()) -- cgit v1.2.3-1-g7c22