Until now “TestRunIf” and “TestEnabled” could only handle AND. With this
patch a new class named “Either” is added to “qa_config” and allows OR.
The name “Either” was chosen instead of “Or” as the latter is very close
to the reserved keyword “or”.
Examples:
["rapi", Either(["instance-rename", "instance-reboot"])]
Either(["node-list", "instance-list", "job-list"])
---
Makefile.am | 2 +
autotools/run-in-tempdir | 2 +-
qa/qa_config.py | 71 +++++++++++++++++++--
test/qa.qa_config_unittest.py | 137 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 204 insertions(+), 8 deletions(-)
create mode 100755 test/qa.qa_config_unittest.py
diff --git a/Makefile.am b/Makefile.am
index f769518..7ae9071 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -498,6 +498,7 @@ PYTHON_BOOTSTRAP = \
tools/ensure-dirs
qa_scripts = \
+ qa/__init__.py \
qa/ganeti-qa.py \
qa/qa_cluster.py \
qa/qa_config.py \
@@ -846,6 +847,7 @@ python_tests = \
test/ganeti.utils.x509_unittest.py \
test/ganeti.utils_unittest.py \
test/ganeti.workerpool_unittest.py \
+ test/qa.qa_config_unittest.py \
test/cfgupgrade_unittest.py \
test/docs_unittest.py \
test/pycurl_reset_unittest.py \
diff --git a/autotools/run-in-tempdir b/autotools/run-in-tempdir
index 6e0b758..9c949e4 100755
--- a/autotools/run-in-tempdir
+++ b/autotools/run-in-tempdir
@@ -8,7 +8,7 @@ set -e
tmpdir=$(mktemp -d -t gntbuild.XXXXXXXX)
trap "rm -rf $tmpdir" EXIT
-cp -r autotools daemons scripts lib tools test $tmpdir
+cp -r autotools daemons scripts lib tools test qa $tmpdir
mv $tmpdir/lib $tmpdir/ganeti
ln -T -s $tmpdir/ganeti $tmpdir/lib
mkdir -p $tmpdir/htools
diff --git a/qa/qa_config.py b/qa/qa_config.py
index e058a71..5e19c5e 100644
--- a/qa/qa_config.py
+++ b/qa/qa_config.py
@@ -60,22 +60,79 @@ def get(name, default=None):
return cfg.get(name, default)
-def TestEnabled(tests):
+class Either:
+ def __init__(self, tests):
+ """Initializes this class.
+
+ @type tests: list or string
+ @param tests: List of test names
+ @see: L{TestEnabled} for details
+
+ """
+ self.tests = tests
+
+
+def _MakeSequence(value):
+ """Make sequence of single argument.
+
+ If the single argument is not already a list or tuple, a list with the
+ argument as a single item is returned.
+
+ """
+ if isinstance(value, (list, tuple)):
+ return value
+ else:
+ return [value]
+
+
+def _TestEnabledInner(check_fn, names, fn):
+ """Evaluate test conditions.
+
+ @type check_fn: callable
+ @param check_fn: Callback to check whether a test is enabled
+ @type names: sequence or string
+ @param names: Test name(s)
+ @type fn: callable
+ @param fn: Aggregation function
+ @rtype: bool
+ @return: Whether test is enabled
+
+ """
+ names = _MakeSequence(names)
+
+ result = []
+
+ for name in names:
+ if isinstance(name, Either):
+ value = _TestEnabledInner(check_fn, name.tests, compat.any)
+ elif isinstance(name, (list, tuple)):
+ value = _TestEnabledInner(check_fn, name, compat.all)
+ else:
+ value = check_fn(name)
+
+ result.append(value)
+
+ return fn(result)
+
+
+def TestEnabled(tests, _cfg=None):
"""Returns True if the given tests are enabled.
- @param tests: a single test, or a list of tests to check
+ @param tests: A single test as a string, or a list of tests to check; can
+ contain L{Either} for OR conditions, AND is default
"""
- if isinstance(tests, basestring):
- tests = [tests]
+ if _cfg is None:
+ _cfg = cfg
# Get settings for all tests
- all_tests = cfg.get("tests", {})
+ cfg_tests = _cfg.get("tests", {})
# Get default setting
- default = all_tests.get("default", True)
+ default = cfg_tests.get("default", True)
- return compat.all(all_tests.get(name, default) for name in tests)
+ return _TestEnabledInner(lambda name: cfg_tests.get(name, default),
+ tests, compat.all)
def GetMasterNode():
diff --git a/test/qa.qa_config_unittest.py b/test/qa.qa_config_unittest.py
new file mode 100755
index 0000000..fd73322
--- /dev/null
+++ b/test/qa.qa_config_unittest.py
@@ -0,0 +1,137 @@
+#!/usr/bin/python
+#
+
+# Copyright (C) 2012 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+
+"""Script for testing qa.qa_config"""
+
+import unittest
+
+from qa import qa_config
+
+import testutils
+
+
+class TestTestEnabled(unittest.TestCase):
+ def testSimple(self):
+ for name in ["test", ["foobar"], ["a", "b"]]:
+ self.assertTrue(qa_config.TestEnabled(name, _cfg={}))
+
+ for default in [False, True]:
+ self.assertFalse(qa_config.TestEnabled("foo", _cfg={
+ "tests": {
+ "default": default,
+ "foo": False,
+ },
+ }))
+
+ self.assertTrue(qa_config.TestEnabled("bar", _cfg={
+ "tests": {
+ "default": default,
+ "bar": True,
+ },
+ }))
+
+ def testEitherWithDefault(self):
+ names = qa_config.Either("one")
+
+ self.assertTrue(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ },
+ }))
+
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": False,
+ },
+ }))
+
+ def testEither(self):
+ names = [qa_config.Either(["one", "two"]),
+ qa_config.Either("foo"),
+ "hello",
+ ["bar", "baz"]]
+
+ self.assertTrue(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ },
+ }))
+
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": False,
+ },
+ }))
+
+ for name in ["foo", "bar", "baz", "hello"]:
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ name: False,
+ },
+ }))
+
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ "one": False,
+ "two": False,
+ },
+ }))
+
+ self.assertTrue(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ "one": False,
+ "two": True,
+ },
+ }))
+
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ "one": True,
+ "two": True,
+ "foo": False,
+ },
+ }))
+
+ def testEitherNestedWithAnd(self):
+ names = qa_config.Either([["one", "two"], "foo"])
+
+ self.assertTrue(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ },
+ }))
+
+ for name in ["one", "two"]:
+ self.assertFalse(qa_config.TestEnabled(names, _cfg={
+ "tests": {
+ "default": True,
+ "foo": False,
+ name: False,
+ },
+ }))
+
+
+if __name__ == "__main__":
+ testutils.GanetiTestProgram()
--
1.7.6