From cfa4ce0a6fe82ed8578fe4668998012ad3833e05 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 5 Feb 2013 11:36:49 -0500 Subject: added support for wildcard XInclude in XMLFileBacked --- .../Testlib/TestServer/TestPlugin/Testhelpers.py | 53 +++++++++++++++------- .../Testlib/TestServer/TestPlugins/TestMetadata.py | 1 + 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'testsuite') 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/TestMetadata.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py index f627e4465..ab7123fa7 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py @@ -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, -- cgit v1.2.3-1-g7c22 From 9d0e6991fc23c073efc0db6bf10e1081f6725e55 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 5 Feb 2013 12:13:20 -0500 Subject: abstracted similar digit range classes in POSIXUsers/GroupPatterns into Bcfg2.Utils --- .../Testlib/TestClient/TestTools/TestPOSIXUsers.py | 38 +++-------------- .../TestServer/TestPlugins/TestGroupPatterns.py | 21 ---------- testsuite/Testsrc/Testlib/TestUtils.py | 48 ++++++++++++++++++++++ 3 files changed, 54 insertions(+), 53 deletions(-) create mode 100644 testsuite/Testsrc/Testlib/TestUtils.py (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py index bcf6cf133..8ab279a50 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 @@ -19,33 +20,6 @@ while path != "/": from common import * -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 @@ -177,19 +151,19 @@ class TestPOSIXUsers(Bcfg2TestCase): 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")) 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/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)) -- cgit v1.2.3-1-g7c22 From ff0048a3a26c9076c8052a8c7be171e4364f0d09 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 7 Feb 2013 10:00:37 -0500 Subject: moved common file locking code into Bcfg2.Utils --- testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py index ab7123fa7..35847b2c2 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py @@ -327,7 +327,7 @@ class TestXMLMetadataConfig(TestXMLFileBacked): "clients.xml"), "") - @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') -- cgit v1.2.3-1-g7c22 From fb723b0164318459e337911cf243ba497d8f6683 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 7 Feb 2013 10:14:31 -0500 Subject: Metadata: process default client bootstrap mode properly --- .../Testlib/TestServer/TestPlugins/TestMetadata.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py index 35847b2c2..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(): @@ -463,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 @@ -495,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) @@ -1217,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): @@ -1504,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. """ -- cgit v1.2.3-1-g7c22 From 43984bc5ebc59bd8c5890ed6ba3de162e6698dcc Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 12 Feb 2013 16:02:24 -0500 Subject: better Executor class for client tools --- .../Testlib/TestClient/TestTools/TestPOSIXUsers.py | 84 +++------------------- testsuite/Testsrc/test_code_checks.py | 6 +- 2 files changed, 10 insertions(+), 80 deletions(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py index 8ab279a50..582f0ac99 100644 --- a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py +++ b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIXUsers.py @@ -20,78 +20,6 @@ while path != "/": from common import * -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(Bcfg2TestCase): test_obj = POSIXUsers @@ -419,6 +347,10 @@ class TestPOSIXUsers(Bcfg2TestCase): 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)) @@ -438,7 +370,7 @@ class TestPOSIXUsers(Bcfg2TestCase): 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", @@ -536,19 +468,21 @@ class TestPOSIXUsers(Bcfg2TestCase): 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/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py index ded9cd8e3..3404c19ce 100644 --- a/testsuite/Testsrc/test_code_checks.py +++ b/testsuite/Testsrc/test_code_checks.py @@ -62,13 +62,9 @@ error_checks = { "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", -- cgit v1.2.3-1-g7c22 From b7995e7b2cb8e527ab8bb8bd3f01c8fb2fce736a Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 13 Feb 2013 16:08:08 -0500 Subject: extended usage of Executor class, added client-side timeout options --- testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py index 4048be7ca..bf7f1eecc 100644 --- a/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py +++ b/testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/Test__init.py @@ -37,6 +37,8 @@ def get_posix_object(logger=None, setup=None, config=None): logger.debug = Mock(side_effect=print_msg) if not setup: setup = MagicMock() + if 'command_timeout' not in setup: + setup['command_timeout'] = None return Bcfg2.Client.Tools.POSIX.POSIX(logger, setup, config) -- cgit v1.2.3-1-g7c22 From 439e72b36f66855cfb66de111147a4b92e80da19 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 11 Mar 2013 08:01:39 -0400 Subject: added PEP-8 style checks to test suite --- testsuite/Testsrc/test_code_checks.py | 258 +++++++++++++++++++++------------- 1 file changed, 159 insertions(+), 99 deletions(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py index 3404c19ce..2f49134fa 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 = { @@ -136,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) @@ -154,118 +141,183 @@ 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): env = copy.copy(os.environ) - if 'PYTHONPATH' in os.environ: - env['PYTHONPATH'] = '%s:%s' % (env['PYTHONPATH'], testdir) - else: - env['PYTHONPATH'] = testdir + env['PYTHONPATH'] = ':'.join([env.get("PYTHONPATH", ""), + testdir]) return env + 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() @@ -276,3 +328,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 -- cgit v1.2.3-1-g7c22 From 7754f95f93aa0aa9dc31b017a793b27d172b645f Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 11 Mar 2013 08:42:25 -0400 Subject: full pylint tests on bcfg2-reports --- testsuite/Testsrc/test_code_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py index 2f49134fa..7d168af75 100644 --- a/testsuite/Testsrc/test_code_checks.py +++ b/testsuite/Testsrc/test_code_checks.py @@ -49,7 +49,7 @@ 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", -- cgit v1.2.3-1-g7c22