summaryrefslogtreecommitdiffstats
path: root/testsuite
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-03-21 14:35:04 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-03-21 14:35:04 -0400
commit38f99b402d3118e2c26ff42d72ddf9b666adac13 (patch)
tree705d18bed66337192816325facb1733280291ff5 /testsuite
parenta3f2a731bbef5d9c2033eed23432aa7792d47989 (diff)
parent71d7285c405bd639f1f9f2642ea8fb567b97caec (diff)
downloadbcfg2-38f99b402d3118e2c26ff42d72ddf9b666adac13.tar.gz
bcfg2-38f99b402d3118e2c26ff42d72ddf9b666adac13.tar.bz2
bcfg2-38f99b402d3118e2c26ff42d72ddf9b666adac13.zip
Merge branch '1.3.2' into maint
Conflicts: src/lib/Bcfg2/Client/Tools/__init__.py src/sbin/bcfg2-test testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py testsuite/Testsrc/test_code_checks.py
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py122
-rw-r--r--testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py53
-rw-r--r--testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestGroupPatterns.py21
-rw-r--r--testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py22
-rw-r--r--testsuite/Testsrc/Testlib/TestUtils.py48
-rw-r--r--testsuite/Testsrc/test_code_checks.py260
6 files changed, 272 insertions, 254 deletions
diff --git a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py
index b42dc57d8..4fcd63a60 100644
--- a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py
+++ b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py
@@ -6,6 +6,7 @@ import subprocess
from mock import Mock, MagicMock, patch
import Bcfg2.Client.Tools
from Bcfg2.Client.Tools.POSIXUsers import *
+from Bcfg2.Utils import PackedDigitRange
# add all parent testsuite directories to sys.path to allow (most)
# relative imports in python 2.4
@@ -20,105 +21,6 @@ from common import *
from TestTools.Test_init import TestTool
-class TestIDRangeSet(Bcfg2TestCase):
- def test_ranges(self):
- # test cases. tuples of (ranges, included numbers, excluded
- # numbers)
- # tuples of (range description, numbers that are included,
- # numebrs that are excluded)
- tests = [(["0-3"], ["0", 1, "2", 3], [4]),
- (["1"], [1], [0, "2"]),
- (["10-11"], [10, 11], [0, 1]),
- (["9-9"], [9], [8, 10]),
- (["0-100"], [0, 10, 99, 100], []),
- (["1", "3", "5"], [1, 3, 5], [0, 2, 4, 6]),
- (["1-5", "7"], [1, 3, 5, 7], [0, 6, 8]),
- (["1-5", 7, "9-11"], [1, 3, 5, 7, 9, 11], [0, 6, 8, 12]),
- (["852-855", "321-497", 763], [852, 855, 321, 400, 497, 763],
- [851, 320, 766, 999]),
- (["0-"], [0, 1, 100, 100000], []),
- ([1, "5-10", "1000-"], [1, 5, 10, 1000, 10000000],
- [4, 11, 999])]
- for ranges, inc, exc in tests:
- rng = IDRangeSet(*ranges)
- for test in inc:
- self.assertIn(test, rng)
- for test in exc:
- self.assertNotIn(test, rng)
-
-
-class TestExecutor(Bcfg2TestCase):
- test_obj = Executor
-
- def get_obj(self, logger=None):
- if not logger:
- def print_msg(msg):
- print(msg)
- logger = Mock()
- logger.error = Mock(side_effect=print_msg)
- logger.warning = Mock(side_effect=print_msg)
- logger.info = Mock(side_effect=print_msg)
- logger.debug = Mock(side_effect=print_msg)
- return self.test_obj(logger)
-
- @patch("subprocess.Popen")
- def test_run(self, mock_Popen):
- exc = self.get_obj()
- cmd = ["/bin/test", "-a", "foo"]
- proc = Mock()
- proc.wait = Mock()
- proc.wait.return_value = 0
- proc.communicate = Mock()
- proc.communicate.return_value = (MagicMock(), MagicMock())
- mock_Popen.return_value = proc
-
- self.assertTrue(exc.run(cmd))
- args = mock_Popen.call_args
- self.assertEqual(args[0][0], cmd)
- self.assertEqual(args[1]['shell'], False)
- self.assertEqual(args[1]['stdin'], subprocess.PIPE)
- self.assertEqual(args[1]['stdout'], subprocess.PIPE)
- self.assertEqual(args[1]['stderr'], subprocess.PIPE)
- proc.communicate.assert_called_with()
- proc.wait.assert_called_with()
- self.assertEqual(proc.communicate.return_value,
- (exc.stdout, exc.stderr))
- self.assertEqual(proc.wait.return_value,
- exc.retval)
-
- mock_Popen.reset_mock()
- inputdata = "foo\n\nbar"
- self.assertTrue(exc.run(cmd, inputdata=inputdata, shell=True))
- args = mock_Popen.call_args
- self.assertEqual(args[0][0], cmd)
- self.assertEqual(args[1]['shell'], True)
- self.assertEqual(args[1]['stdin'], subprocess.PIPE)
- self.assertEqual(args[1]['stdout'], subprocess.PIPE)
- self.assertEqual(args[1]['stderr'], subprocess.PIPE)
- proc.communicate.assert_called_with(inputdata)
- proc.wait.assert_called_with()
- self.assertEqual(proc.communicate.return_value,
- (exc.stdout, exc.stderr))
- self.assertEqual(proc.wait.return_value,
- exc.retval)
-
- mock_Popen.reset_mock()
- proc.wait.return_value = 1
- self.assertRaises(ExecutionError, exc.run, cmd)
- args = mock_Popen.call_args
- self.assertEqual(args[0][0], cmd)
- self.assertEqual(args[1]['shell'], False)
- self.assertEqual(args[1]['stdin'], subprocess.PIPE)
- self.assertEqual(args[1]['stdout'], subprocess.PIPE)
- self.assertEqual(args[1]['stderr'], subprocess.PIPE)
- proc.communicate.assert_called_with()
- proc.wait.assert_called_with()
- self.assertEqual(proc.communicate.return_value,
- (exc.stdout, exc.stderr))
- self.assertEqual(proc.wait.return_value,
- exc.retval)
-
-
class TestPOSIXUsers(TestTool):
test_obj = POSIXUsers
@@ -166,19 +68,19 @@ class TestPOSIXUsers(TestTool):
def test__in_managed_range(self):
users = self.get_obj()
- users._whitelist = dict(POSIXGroup=IDRangeSet("1-10"))
- users._blacklist = dict(POSIXGroup=IDRangeSet("8-100"))
+ users._whitelist = dict(POSIXGroup=PackedDigitRange("1-10"))
+ users._blacklist = dict(POSIXGroup=PackedDigitRange("8-100"))
self.assertTrue(users._in_managed_range("POSIXGroup", "9"))
users._whitelist = dict(POSIXGroup=None)
- users._blacklist = dict(POSIXGroup=IDRangeSet("8-100"))
+ users._blacklist = dict(POSIXGroup=PackedDigitRange("8-100"))
self.assertFalse(users._in_managed_range("POSIXGroup", "9"))
users._whitelist = dict(POSIXGroup=None)
- users._blacklist = dict(POSIXGroup=IDRangeSet("100-"))
+ users._blacklist = dict(POSIXGroup=PackedDigitRange("100-"))
self.assertTrue(users._in_managed_range("POSIXGroup", "9"))
- users._whitelist = dict(POSIXGroup=IDRangeSet("1-10"))
+ users._whitelist = dict(POSIXGroup=PackedDigitRange("1-10"))
users._blacklist = dict(POSIXGroup=None)
self.assertFalse(users._in_managed_range("POSIXGroup", "25"))
@@ -434,6 +336,10 @@ class TestPOSIXUsers(TestTool):
setter.reset_mock()
users.modified = []
+ cmd_rv = Mock()
+ cmd_rv.success = True
+ users.cmd.run.return_value = cmd_rv
+
reset()
entry = lxml.etree.Element("POSIXUser", name="test2")
self.assertTrue(users._install(entry))
@@ -453,7 +359,7 @@ class TestPOSIXUsers(TestTool):
self.assertIn(entry, users.modified)
reset()
- users.cmd.run.side_effect = ExecutionError(None)
+ cmd_rv.success = False
self.assertFalse(users._install(entry))
users.set_defaults[entry.tag].assert_called_with(entry)
users._get_cmd.assert_called_with("mod",
@@ -551,19 +457,21 @@ class TestPOSIXUsers(TestTool):
users = self.get_obj()
users._get_cmd = Mock()
users.cmd = Mock()
+ cmd_rv = Mock()
+ cmd_rv.success = True
+ users.cmd.run.return_value = cmd_rv
def reset():
users._get_cmd.reset_mock()
users.cmd.reset_mock()
-
entry = lxml.etree.Element("POSIXUser", name="test2")
self.assertTrue(users._remove(entry))
users._get_cmd.assert_called_with("del", entry)
users.cmd.run.assert_called_with(users._get_cmd.return_value)
reset()
- users.cmd.run.side_effect = ExecutionError(None)
+ cmd_rv.success = False
self.assertFalse(users._remove(entry))
users._get_cmd.assert_called_with("del", entry)
users.cmd.run.assert_called_with(users._get_cmd.return_value)
diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py
index 22c53c63e..fb51eb1fe 100644
--- a/testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py
+++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugin/Testhelpers.py
@@ -417,21 +417,22 @@ class TestXMLFileBacked(TestFileBacked):
xfb = self.get_obj(fam=fam, should_monitor=True)
fam.AddMonitor.assert_called_with(self.path, xfb)
- @patch("os.path.exists")
+ @patch("glob.glob")
@patch("lxml.etree.parse")
- def test_follow_xincludes(self, mock_parse, mock_exists):
+ def test_follow_xincludes(self, mock_parse, mock_glob):
xfb = self.get_obj()
xfb.add_monitor = Mock()
+ xfb.add_monitor.side_effect = lambda p: xfb.extras.append(p)
def reset():
xfb.add_monitor.reset_mock()
+ mock_glob.reset_mock()
mock_parse.reset_mock()
- mock_exists.reset_mock()
xfb.extras = []
- mock_exists.return_value = True
xdata = dict()
mock_parse.side_effect = lambda p: xdata[p]
+ mock_glob.side_effect = lambda g: [g]
base = os.path.dirname(self.path)
@@ -465,7 +466,7 @@ class TestXMLFileBacked(TestFileBacked):
xfb.add_monitor.assert_called_with(test2)
self.assertItemsEqual(mock_parse.call_args_list,
[call(f) for f in xdata.keys()])
- mock_exists.assert_called_with(test2)
+ mock_glob.assert_called_with(test2)
reset()
xfb._follow_xincludes(fname=self.path, xdata=xdata[self.path])
@@ -473,7 +474,7 @@ class TestXMLFileBacked(TestFileBacked):
self.assertItemsEqual(mock_parse.call_args_list,
[call(f) for f in xdata.keys()
if f != self.path])
- mock_exists.assert_called_with(test2)
+ mock_glob.assert_called_with(test2)
# test two-deep level of xinclude, with some files in another
# directory
@@ -501,21 +502,41 @@ class TestXMLFileBacked(TestFileBacked):
reset()
xfb._follow_xincludes(fname=self.path)
- self.assertItemsEqual(xfb.add_monitor.call_args_list,
- [call(f) for f in xdata.keys() if f != self.path])
+ expected = [call(f) for f in xdata.keys() if f != self.path]
+ self.assertItemsEqual(xfb.add_monitor.call_args_list, expected)
self.assertItemsEqual(mock_parse.call_args_list,
[call(f) for f in xdata.keys()])
- self.assertItemsEqual(mock_exists.call_args_list,
- [call(f) for f in xdata.keys() if f != self.path])
+ self.assertItemsEqual(mock_glob.call_args_list, expected)
reset()
xfb._follow_xincludes(fname=self.path, xdata=xdata[self.path])
- self.assertItemsEqual(xfb.add_monitor.call_args_list,
- [call(f) for f in xdata.keys() if f != self.path])
- self.assertItemsEqual(mock_parse.call_args_list,
- [call(f) for f in xdata.keys() if f != self.path])
- self.assertItemsEqual(mock_exists.call_args_list,
- [call(f) for f in xdata.keys() if f != self.path])
+ expected = [call(f) for f in xdata.keys() if f != self.path]
+ self.assertItemsEqual(xfb.add_monitor.call_args_list, expected)
+ self.assertItemsEqual(mock_parse.call_args_list, expected)
+ self.assertItemsEqual(mock_glob.call_args_list, expected)
+
+ # test wildcard xinclude
+ reset()
+ xdata[self.path] = lxml.etree.Element("Test").getroottree()
+ lxml.etree.SubElement(xdata[self.path].getroot(),
+ Bcfg2.Server.XI_NAMESPACE + "include",
+ href="*.xml")
+
+ def glob_rv(path):
+ if path == os.path.join(base, '*.xml'):
+ return [self.path, test2, test3]
+ else:
+ return [path]
+ mock_glob.side_effect = glob_rv
+
+ xfb._follow_xincludes(xdata=xdata[self.path])
+ expected = [call(f) for f in xdata.keys() if f != self.path]
+ self.assertItemsEqual(xfb.add_monitor.call_args_list, expected)
+ self.assertItemsEqual(mock_parse.call_args_list, expected)
+ self.assertItemsEqual(mock_glob.call_args_list,
+ [call(os.path.join(base, '*.xml')), call(test4),
+ call(test5), call(test6)])
+
@patch("lxml.etree._ElementTree", FakeElementTree)
@patch("Bcfg2.Server.Plugin.helpers.%s._follow_xincludes" %
diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestGroupPatterns.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestGroupPatterns.py
index a7a6b3d6e..a9346156c 100644
--- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestGroupPatterns.py
+++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestGroupPatterns.py
@@ -18,27 +18,6 @@ from common import *
from TestPlugin import TestXMLFileBacked, TestPlugin, TestConnector
-class TestPackedDigitRange(Bcfg2TestCase):
- def test_includes(self):
- # tuples of (range description, numbers that are included,
- # numebrs that are excluded)
- tests = [("1-3", [1, "2", 3], [4]),
- ("1", [1], [0, "2"]),
- ("10-11", [10, 11], [0, 1]),
- ("9-9", [9], [8, 10]),
- ("0-100", [0, 10, 99, 100], []),
- ("1,3,5", [1, 3, 5], [0, 2, 4, 6]),
- ("1-5,7", [1, 3, 5, 7], [0, 6, 8]),
- ("1-5,7,9-11", [1, 3, 5, 7, 9, 11], [0, 6, 8, 12]),
- ("852-855,321-497,763", [852, 855, 321, 400, 497, 763], [])]
- for rng, inc, exc in tests:
- r = PackedDigitRange(rng)
- for test in inc:
- self.assertTrue(r.includes(test))
- for test in exc:
- self.assertFalse(r.includes(test))
-
-
class TestPatternMap(Bcfg2TestCase):
def test_ranges(self):
""" test processing NameRange patterns """
diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py
index f627e4465..69ea45de6 100644
--- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py
+++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py
@@ -20,7 +20,7 @@ while path != "/":
path = os.path.dirname(path)
from common import *
from TestPlugin import TestXMLFileBacked, TestMetadata as _TestMetadata, \
- TestStatistics, TestDatabaseBacked
+ TestClientRunHooks, TestDatabaseBacked
def get_clients_test_tree():
@@ -198,6 +198,7 @@ if HAS_DJANGO or can_skip:
class TestXMLMetadataConfig(TestXMLFileBacked):
test_obj = XMLMetadataConfig
+ path = os.path.join(datastore, 'Metadata', 'clients.xml')
def get_obj(self, basefile="clients.xml", core=None, watch_clients=False):
self.metadata = get_metadata_object(core=core,
@@ -326,7 +327,7 @@ class TestXMLMetadataConfig(TestXMLFileBacked):
"clients.xml"),
"<test/>")
- @patch('Bcfg2.Server.Plugins.Metadata.locked', Mock(return_value=False))
+ @patch('Bcfg2.Utils.locked', Mock(return_value=False))
@patch('fcntl.lockf', Mock())
@patch('os.open')
@patch('os.fdopen')
@@ -462,7 +463,7 @@ class TestClientMetadata(Bcfg2TestCase):
self.assertFalse(cm.inGroup("group3"))
-class TestMetadata(_TestMetadata, TestStatistics, TestDatabaseBacked):
+class TestMetadata(_TestMetadata, TestClientRunHooks, TestDatabaseBacked):
test_obj = Metadata
use_db = False
@@ -494,7 +495,7 @@ class TestMetadata(_TestMetadata, TestStatistics, TestDatabaseBacked):
metadata = self.get_obj(core=core)
self.assertIsInstance(metadata, Bcfg2.Server.Plugin.Plugin)
self.assertIsInstance(metadata, Bcfg2.Server.Plugin.Metadata)
- self.assertIsInstance(metadata, Bcfg2.Server.Plugin.Statistics)
+ self.assertIsInstance(metadata, Bcfg2.Server.Plugin.ClientRunHooks)
self.assertIsInstance(metadata.clients_xml, XMLMetadataConfig)
self.assertIsInstance(metadata.groups_xml, XMLMetadataConfig)
self.assertIsInstance(metadata.query, MetadataQuery)
@@ -1216,17 +1217,16 @@ class TestMetadata(_TestMetadata, TestStatistics, TestDatabaseBacked):
@patch("Bcfg2.Server.Plugins.Metadata.XMLMetadataConfig.load_xml", Mock())
@patch("Bcfg2.Server.Plugins.Metadata.Metadata.update_client")
- def test_process_statistics(self, mock_update_client):
+ def test_end_statistics(self, mock_update_client):
metadata = self.load_clients_data(metadata=self.load_groups_data())
md = Mock()
md.hostname = "client6"
- metadata.process_statistics(md, None)
- mock_update_client.assert_called_with(md.hostname,
- dict(auth='cert'))
+ metadata.end_statistics(md)
+ mock_update_client.assert_called_with(md.hostname, dict(auth='cert'))
mock_update_client.reset_mock()
md.hostname = "client5"
- metadata.process_statistics(md, None)
+ metadata.end_statistics(md)
self.assertFalse(mock_update_client.called)
def test_viz(self):
@@ -1503,6 +1503,10 @@ class TestMetadata_NoClientsXML(TestMetadataBase):
def test_handle_clients_xml_event(self):
pass
+ def test_end_statistics(self):
+ # bootstrap mode, which is what is being tested here, doesn't
+ # work without clients.xml
+ pass
class TestMetadata_ClientsXML(TestMetadataBase):
""" test Metadata with a clients.xml. """
diff --git a/testsuite/Testsrc/Testlib/TestUtils.py b/testsuite/Testsrc/Testlib/TestUtils.py
new file mode 100644
index 000000000..349d6cd40
--- /dev/null
+++ b/testsuite/Testsrc/Testlib/TestUtils.py
@@ -0,0 +1,48 @@
+import os
+import sys
+import copy
+import lxml.etree
+import subprocess
+from mock import Mock, MagicMock, patch
+from Bcfg2.Utils import *
+
+# add all parent testsuite directories to sys.path to allow (most)
+# relative imports in python 2.4
+path = os.path.dirname(__file__)
+while path != "/":
+ if os.path.basename(path).lower().startswith("test"):
+ sys.path.append(path)
+ if os.path.basename(path) == "testsuite":
+ break
+ path = os.path.dirname(path)
+from common import *
+
+
+class TestPackedDigitRange(Bcfg2TestCase):
+ def test_ranges(self):
+ # test cases. tuples of (ranges, included numbers, excluded
+ # numbers)
+ # tuples of (range description, numbers that are included,
+ # numebrs that are excluded)
+ tests = [(["0-3"], ["0", 1, "2", 3], [4]),
+ (["1"], [1], [0, "2"]),
+ (["10-11"], [10, 11], [0, 1]),
+ (["9-9"], [9], [8, 10]),
+ (["0-100"], [0, 10, 99, 100], []),
+ (["1", "3", "5"], [1, 3, 5], [0, 2, 4, 6]),
+ (["1-5", "7"], [1, 3, 5, 7], [0, 6, 8]),
+ (["1-5", 7, "9-11"], [1, 3, 5, 7, 9, 11], [0, 6, 8, 12]),
+ (["1-5, 7,9-11 "], [1, 3, 5, 7, 9, 11], [0, 6, 8, 12]),
+ (["852-855", "321-497", 763], [852, 855, 321, 400, 497, 763],
+ [851, 320, 766, 999]),
+ (["0-"], [0, 1, 100, 100000], []),
+ ([1, "5-10", "1000-"], [1, 5, 10, 1000, 10000000],
+ [4, 11, 999])]
+ for ranges, inc, exc in tests:
+ rng = PackedDigitRange(*ranges)
+ for test in inc:
+ self.assertIn(test, rng)
+ self.assertTrue(rng.includes(test))
+ for test in exc:
+ self.assertNotIn(test, rng)
+ self.assertFalse(rng.includes(test))
diff --git a/testsuite/Testsrc/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py
index 3036397b6..85aea29d6 100644
--- a/testsuite/Testsrc/test_code_checks.py
+++ b/testsuite/Testsrc/test_code_checks.py
@@ -25,14 +25,6 @@ srcpath = os.path.abspath(os.path.join(testdir, "..", "src"))
# path to pylint rc file
rcfile = os.path.join(testdir, "pylintrc.conf")
-# test for pylint existence
-try:
- Popen(['pylint'], stdout=PIPE, stderr=STDOUT).wait()
- HAS_PYLINT = True
-except OSError:
- HAS_PYLINT = False
-
-
# perform checks on the listed files only if the module listed in the
# keys can be imported
contingent_checks = {
@@ -57,18 +49,14 @@ contingent_checks = {
# perform only error checking on the listed files
error_checks = {
- "sbin": ["bcfg2-build-reports", "bcfg2-reports"],
+ "sbin": ["bcfg2-build-reports"],
"lib/Bcfg2": ["Proxy.py", "SSLServer.py", "Reporting"],
"lib/Bcfg2/Server": ["Reports", "SchemaUpdater"],
"lib/Bcfg2/Server/Admin": ["Compare.py",
"Snapshots.py"],
- "lib/Bcfg2/Client/Tools": ["launchd.py",
- "OpenCSW.py",
+ "lib/Bcfg2/Client/Tools": ["OpenCSW.py",
"Blast.py",
- "SYSV.py",
"FreeBSDInit.py",
- "DebInit.py",
- "RcUpdate.py",
"VCS.py",
"YUM24.py"],
"lib/Bcfg2/Server/Plugins": ["Deps.py",
@@ -140,13 +128,8 @@ def blacklist_filter(filelist, blacklist):
return rv
-class TestPylint(Bcfg2TestCase):
- pylint_cmd = ["pylint", "--rcfile", rcfile, "--init-hook",
- "import sys;sys.path.append('%s')" %
- os.path.join(srcpath, "lib")]
-
- # regex to find errors and fatal errors
- error_re = re.compile(r':\d+:\s+\[[EF]\d{4}')
+class CodeTestCase(Bcfg2TestCase):
+ __test__ = False
# build the blacklists
blacklist = expand_path_dict(no_checks)
@@ -158,6 +141,34 @@ class TestPylint(Bcfg2TestCase):
full_blacklist = expand_path_dict(error_checks) + contingent_blacklist + \
blacklist
+ command = [None]
+
+ has_command = None
+
+ # extra arguments when running tests on sbin/*
+ sbin_args = []
+
+ # extra arguments when running tests on lib/*
+ lib_args = []
+
+ # extra arguments for full tests
+ full_args = []
+
+ # extra arguments for error tests
+ error_args = []
+
+ def has_exec(self):
+ if self.has_command is None:
+ try:
+ proc = Popen(self.command,
+ stdin=PIPE, stdout=PIPE, stderr=STDOUT)
+ proc.communicate(input="\n")
+ proc.wait()
+ self.has_command = True
+ except OSError:
+ self.has_command = False
+ return self.has_command
+
def get_env(self):
if ('PYTHONPATH' not in os.environ or
testdir not in os.environ['PYTHONPATH'].split(":")):
@@ -168,110 +179,149 @@ class TestPylint(Bcfg2TestCase):
else:
return os.environ
+ def _test_full(self, files, extra_args=None):
+ """ test select files for all problems """
+ if not len(files):
+ return
+ if extra_args is None:
+ extra_args = []
+ cmd = self.command + self.full_args + extra_args + \
+ [os.path.join(srcpath, f) for f in files]
+ proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, env=self.get_env())
+ print(proc.communicate()[0])
+ self.assertEqual(proc.wait(), 0)
+
+ def _test_errors(self, files, extra_args=None):
+ """ test select files for errors """
+ if not len(files):
+ return
+ if extra_args is None:
+ extra_args = []
+ cmd = self.command + self.error_args + extra_args + \
+ [os.path.join(srcpath, f) for f in files]
+ proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, env=self.get_env())
+ print(proc.communicate()[0])
+ self.assertEqual(proc.wait(), 0)
+
@skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
@skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
def test_lib_full(self):
- full_list = []
- for root, _, files in os.walk(os.path.join(srcpath, "lib")):
- full_list.extend(blacklist_filter([os.path.join(root, f)
- for f in files
- if f.endswith(".py")],
- self.full_blacklist))
- self._pylint_full(full_list)
+ @skipUnless(self.has_exec(),
+ "%s not found, skipping" % self.command[0])
+ def inner():
+ full_list = []
+ for root, _, files in os.walk(os.path.join(srcpath, "lib")):
+ full_list.extend(blacklist_filter([os.path.join(root, f)
+ for f in files
+ if f.endswith(".py")],
+ self.full_blacklist))
+ self._test_full(full_list, extra_args=self.lib_args)
+
+ inner()
@skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
@skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
def test_contingent_full(self):
- blacklist = set(expand_path_dict(error_checks) + self.blacklist)
- for (mods, filedict) in contingent_checks.items():
- if "django" in mods:
- # there's some issue with running pylint on modules
- # that use django in Travis CI (but not elsewhere), so
- # skip these for now
- continue
- try:
- for mod in mods:
- __import__(mod)
- except ImportError:
- continue
- self._pylint_full(blacklist_filter(expand_path_dict(filedict),
- blacklist))
+ @skipUnless(self.has_exec(),
+ "%s not found, skipping" % self.command[0])
+ def inner():
+ filelist = []
+ blacklist = set(expand_path_dict(error_checks) + self.blacklist)
+ for (mods, filedict) in contingent_checks.items():
+ try:
+ for mod in mods:
+ __import__(mod)
+ except ImportError:
+ continue
+ filelist.extend(expand_path_dict(filedict))
+ self._test_full(blacklist_filter(filelist, blacklist),
+ extra_args=self.lib_args)
+
+ inner()
@skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
@skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
- def test_sbin_full(self):
- all_sbin = [os.path.join(srcpath, "sbin", f)
- for f in glob.glob(os.path.join(srcpath, "sbin", "*"))]
- sbin_list = blacklist_filter([f for f in all_sbin
- if not os.path.islink(f)],
- self.full_blacklist)
- self._pylint_full(sbin_list,
- extra_args=["--module-rgx",
- "[a-z_-][a-z0-9_-]*$"])
-
- def _pylint_full(self, paths, extra_args=None):
- """ test select files for all pylint errors """
- if extra_args is None:
- extra_args = []
- args = self.pylint_cmd + extra_args + \
- [os.path.join(srcpath, p) for p in paths]
- pylint = Popen(args, stdout=PIPE, stderr=STDOUT, env=self.get_env())
- print(pylint.communicate()[0])
- self.assertEqual(pylint.wait(), 0)
+ def test_sbin(self):
+ @skipUnless(self.has_exec(),
+ "%s not found, skipping" % self.command[0])
+ def inner():
+ all_sbin = [os.path.join(srcpath, "sbin", f)
+ for f in glob.glob(os.path.join(srcpath, "sbin", "*"))]
+ full_list = blacklist_filter([f for f in all_sbin
+ if not os.path.islink(f)],
+ self.full_blacklist)
+ self._test_full(full_list, extra_args=self.sbin_args)
+
+ errors_list = blacklist_filter([f for f in all_sbin
+ if not os.path.islink(f)],
+ self.contingent_blacklist)
+ self._test_errors(errors_list, extra_args=self.sbin_args)
+
+ inner()
@skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
@skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
- def test_sbin_errors(self):
- all_sbin = [os.path.join(srcpath, "sbin", f)
- for f in glob.glob(os.path.join(srcpath, "sbin", "*"))]
- sbin_list = blacklist_filter([f for f in all_sbin
- if not os.path.islink(f)],
- self.contingent_blacklist)
- self._pylint_errors(sbin_list,
- extra_args=["--module-rgx",
- "[a-z_-][a-z0-9_-]*$"])
+ def test_contingent_errors(self):
+ @skipUnless(self.has_exec(),
+ "%s not found, skipping" % self.command[0])
+ def inner():
+ filelist = []
+ whitelist = expand_path_dict(error_checks)
+ for (mods, filedict) in contingent_checks.items():
+ try:
+ for mod in mods:
+ __import__(mod)
+ except ImportError:
+ continue
+ filelist.extend(expand_path_dict(filedict))
+ flist = blacklist_filter(whitelist_filter(filelist, whitelist),
+ self.blacklist)
+ self._test_errors(flist, extra_args=self.lib_args)
+
+ inner()
@skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
@skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
- def test_contingent_errors(self):
- whitelist = expand_path_dict(error_checks)
- for (mods, filedict) in contingent_checks.items():
+ def test_lib_errors(self):
+ @skipUnless(self.has_exec(),
+ "%s not found, skipping" % self.command[0])
+ def inner():
+ filelist = blacklist_filter(expand_path_dict(error_checks),
+ self.contingent_blacklist)
+ return self._test_errors(filelist, extra_args=self.lib_args)
+
+ inner()
+
+
+class TestPylint(CodeTestCase):
+ __test__ = True
+ command = ["pylint", "--rcfile", rcfile, "--init-hook",
+ "import sys;sys.path.append('%s')" %
+ os.path.join(srcpath, "lib")]
+
+ sbin_args = ["--module-rgx", "[a-z_-][a-z0-9_-]*$"]
+ error_args = ["-f", "parseable", "-d", "R0801,E1103"]
+
+ # regex to find errors and fatal errors
+ error_re = re.compile(r':\d+:\s+\[[EF]\d{4}')
+
+ def __init__(self, *args, **kwargs):
+ CodeTestCase.__init__(self, *args, **kwargs)
+ for mods, filedict in contingent_checks.items():
if "django" in mods:
# there's some issue with running pylint on modules
# that use django in Travis CI (but not elsewhere), so
# skip these for now
- continue
- try:
- for mod in mods:
- __import__(mod)
- except ImportError:
- continue
- flist = \
- blacklist_filter(whitelist_filter(expand_path_dict(filedict),
- whitelist),
- self.blacklist)
- self._pylint_errors(flist)
-
- @skipIf(not os.path.exists(srcpath), "%s does not exist" % srcpath)
- @skipIf(not os.path.exists(rcfile), "%s does not exist" % rcfile)
- @skipUnless(HAS_PYLINT, "pylint not found, skipping")
- def test_lib_errors(self):
- filelist = blacklist_filter(expand_path_dict(error_checks),
- self.contingent_blacklist)
- return self._pylint_errors(filelist)
+ self.blacklist += expand_path_dict(filedict)
- def _pylint_errors(self, paths, extra_args=None):
+ def _test_errors(self, files, extra_args=None):
""" test all files for fatals and errors """
+ if not len(files):
+ return
if extra_args is None:
extra_args = []
- args = self.pylint_cmd + extra_args + \
- ["-f", "parseable", "-d", "R0801,E1103"] + \
- [os.path.join(srcpath, p) for p in paths]
+ args = self.command + self.error_args + extra_args + \
+ [os.path.join(srcpath, p) for p in files]
pylint = Popen(args, stdout=PIPE, stderr=STDOUT, env=self.get_env())
output = pylint.communicate()[0]
rv = pylint.wait()
@@ -282,3 +332,11 @@ class TestPylint(Bcfg2TestCase):
# pylint returns a bitmask, where 1 means fatal errors
# were encountered and 2 means errors were encountered.
self.assertEqual(rv & 3, 0)
+
+
+class TestPEP8(CodeTestCase):
+ __test__ = True
+ command = ["pep8", "--ignore=E125,E501"]
+
+ def _test_errors(self, files, extra_args=None):
+ pass