From 32536152850a683e18935eb5223a5bd1410e9258 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 15 Oct 2012 10:27:47 -0400 Subject: added support for JSON and YAML properties files --- .../TestServer/TestPlugins/TestProperties.py | 257 ++++++++++++++++----- 1 file changed, 203 insertions(+), 54 deletions(-) (limited to 'testsuite/Testsrc') diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py index fb4773d75..78cb5f52d 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py @@ -15,32 +15,44 @@ while path != "/": break path = os.path.dirname(path) from common import * -from TestPlugin import TestStructFile, TestConnector, TestPlugin, \ - TestDirectoryBacked +from TestPlugin import TestStructFile, TestFileBacked, TestConnector, \ + TestPlugin, TestDirectoryBacked +try: + import json + JSON = "json" +except ImportError: + JSON = "simplejson" -class TestPropertyFile(TestStructFile): + +class TestPropertyFile(Bcfg2TestCase): test_obj = PropertyFile + path = os.path.join(datastore, "test") - @patch("%s.open" % builtins) - def test_write(self, mock_open): + def get_obj(self, path=None): + if path is None: + path = self.path + return self.test_obj(path) + + def test_write(self): Bcfg2.Server.Plugins.Properties.SETUP = Mock() pf = self.get_obj() pf.validate_data = Mock() + pf._write = Mock() xstr = u("\n") pf.xdata = lxml.etree.XML(xstr) def reset(): pf.validate_data.reset_mock() + pf._write.reset_mock() Bcfg2.Server.Plugins.Properties.SETUP.reset_mock() - mock_open.reset_mock() # test writes disabled Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = False self.assertRaises(PluginExecutionError, pf.write) self.assertFalse(pf.validate_data.called) - self.assertFalse(mock_open.called) + self.assertFalse(pf._write.called) Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.assert_called_with("properties", "writes_enabled", default=True) @@ -48,17 +60,16 @@ class TestPropertyFile(TestStructFile): # test successful write reset() Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = True - self.assertTrue(pf.write()) + self.assertEqual(pf.write(), pf._write.return_value) pf.validate_data.assert_called_with() - mock_open.assert_called_with(pf.name, "wb") - mock_open.return_value.write.assert_called_with(xstr) + pf._write.assert_called_with() - # test error from write + # test error from _write reset() - mock_open.side_effect = IOError + pf._write.side_effect = IOError self.assertRaises(PluginExecutionError, pf.write) pf.validate_data.assert_called_with() - mock_open.assert_called_with(pf.name, "wb") + pf._write.assert_called_with() # test error from validate_data reset() @@ -66,6 +77,124 @@ class TestPropertyFile(TestStructFile): self.assertRaises(PluginExecutionError, pf.write) pf.validate_data.assert_called_with() + def test__write(self): + pf = self.get_obj() + self.assertRaises(NotImplementedError, pf._write) + + def test_validate_data(self): + pf = self.get_obj() + self.assertRaises(NotImplementedError, pf.validate_data) + + @patch("copy.copy") + def test_get_additional_data(self, mock_copy): + pf = self.get_obj() + self.assertEqual(pf.get_additional_data(Mock()), + mock_copy.return_value) + mock_copy.assert_called_with(pf) + + +if can_skip or HAS_JSON: + class TestJSONPropertyFile(TestFileBacked, TestPropertyFile): + test_obj = JSONPropertyFile + + def get_obj(self, *args, **kwargs): + return TestFileBacked.get_obj(self, *args, **kwargs) + + @skipUnless(HAS_JSON, "JSON libraries not found, skipping") + def setUp(self): + pass + + @patch("%s.loads" % JSON) + def test_Index(self, mock_loads): + pf = self.get_obj() + pf.Index() + mock_loads.assert_called_with(pf.data) + self.assertEqual(pf.json, mock_loads.return_value) + + mock_loads.reset_mock() + mock_loads.side_effect = ValueError + self.assertRaises(PluginExecutionError, pf.Index) + mock_loads.assert_called_with(pf.data) + + @patch("%s.dump" % JSON) + @patch("%s.open" % builtins) + def test__write(self, mock_open, mock_dump): + pf = self.get_obj() + self.assertTrue(pf._write()) + mock_open.assert_called_with(pf.name, 'wb') + mock_dump.assert_called_with(pf.json, mock_open.return_value) + + @patch("%s.dumps" % JSON) + def test_validate_data(self, mock_dumps): + pf = self.get_obj() + pf.validate_data() + mock_dumps.assert_called_with(pf.json) + + mock_dumps.reset_mock() + mock_dumps.side_effect = ValueError + self.assertRaises(PluginExecutionError, pf.validate_data) + mock_dumps.assert_called_with(pf.json) + + +if can_skip or HAS_YAML: + class TestYAMLPropertyFile(TestFileBacked, TestPropertyFile): + test_obj = YAMLPropertyFile + + def get_obj(self, *args, **kwargs): + return TestFileBacked.get_obj(self, *args, **kwargs) + + @skipUnless(HAS_YAML, "YAML libraries not found, skipping") + def setUp(self): + pass + + @patch("yaml.load") + def test_Index(self, mock_load): + pf = self.get_obj() + pf.Index() + mock_load.assert_called_with(pf.data) + self.assertEqual(pf.yaml, mock_load.return_value) + + mock_load.reset_mock() + mock_load.side_effect = yaml.YAMLError + self.assertRaises(PluginExecutionError, pf.Index) + mock_load.assert_called_with(pf.data) + + @patch("yaml.dump") + @patch("%s.open" % builtins) + def test__write(self, mock_open, mock_dump): + pf = self.get_obj() + self.assertTrue(pf._write()) + mock_open.assert_called_with(pf.name, 'wb') + mock_dump.assert_called_with(pf.yaml, mock_open.return_value) + + @patch("yaml.dump") + def test_validate_data(self, mock_dump): + pf = self.get_obj() + pf.validate_data() + mock_dump.assert_called_with(pf.yaml) + + mock_dump.reset_mock() + mock_dump.side_effect = yaml.YAMLError + self.assertRaises(PluginExecutionError, pf.validate_data) + mock_dump.assert_called_with(pf.yaml) + + +class TestXMLPropertyFile(TestPropertyFile, TestStructFile): + test_obj = XMLPropertyFile + path = TestStructFile.path + + def get_obj(self, *args, **kwargs): + return TestStructFile.get_obj(self, *args, **kwargs) + + @patch("%s.open" % builtins) + def test__write(self, mock_open): + pf = self.get_obj() + pf.xdata = lxml.etree.Element("Test") + self.assertTrue(pf._write()) + mock_open.assert_called_with(pf.name, "wb") + self.assertXMLEqual(pf.xdata, + lxml.etree.XML(mock_open.return_value.write.call_args[0][0])) + @patch("os.path.exists") @patch("lxml.etree.XMLSchema") def test_validate_data(self, mock_XMLSchema, mock_exists): @@ -224,10 +353,63 @@ class TestPropertyFile(TestStructFile): algorithm="bf_cbc") self.assertFalse(mock_ssl.called) + @patch("copy.copy") + def test_get_additional_data(self, mock_copy): + Bcfg2.Server.Plugins.Properties.SETUP = Mock() + pf = self.get_obj() + pf.XMLMatch = Mock() + metadata = Mock() + + def reset(): + mock_copy.reset_mock() + pf.XMLMatch.reset_mock() + Bcfg2.Server.Plugins.Properties.SETUP.reset_mock() + + pf.xdata = lxml.etree.Element("Properties", automatch="true") + for automatch in [True, False]: + reset() + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = automatch + self.assertEqual(pf.get_additional_data(metadata), + pf.XMLMatch.return_value) + pf.XMLMatch.assert_called_with(metadata) + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.assert_called_with("properties", "automatch", default=False) + self.assertFalse(mock_copy.called) + + pf.xdata = lxml.etree.Element("Properties", automatch="false") + for automatch in [True, False]: + reset() + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = automatch + self.assertEqual(pf.get_additional_data(metadata), + mock_copy.return_value) + mock_copy.assert_called_with(pf) + self.assertFalse(pf.XMLMatch.called) + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.assert_called_with("properties", "automatch", default=False) + + pf.xdata = lxml.etree.Element("Properties") + reset() + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = False + self.assertEqual(pf.get_additional_data(metadata), + mock_copy.return_value) + mock_copy.assert_called_with(pf) + self.assertFalse(pf.XMLMatch.called) + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.assert_called_with("properties", "automatch", default=False) + + reset() + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.return_value = True + self.assertEqual(pf.get_additional_data(metadata), + pf.XMLMatch.return_value) + pf.XMLMatch.assert_called_with(metadata) + Bcfg2.Server.Plugins.Properties.SETUP.cfp.getboolean.assert_called_with("properties", "automatch", default=False) + self.assertFalse(mock_copy.called) + class TestPropDirectoryBacked(TestDirectoryBacked): test_obj = PropDirectoryBacked testfiles = ['foo.xml', 'bar.baz.xml'] + if HAS_JSON: + testfiles.extend(["foo.json", "foo.xml.json"]) + if HAS_YAML: + testfiles.extend(["foo.yaml", "foo.yml", "foo.xml.yml"]) ignore = ['foo.xsd', 'bar.baz.xsd', 'quux.xml.xsd'] badevents = ['bogus.txt'] @@ -248,45 +430,12 @@ class TestProperties(TestPlugin, TestConnector): TestConnector.test_get_additional_data(self) p = self.get_obj() - automatch = Mock() - automatch.xdata = lxml.etree.Element("Properties", automatch="true") - automatch.XMLMatch.return_value = "automatch" - raw = Mock() - raw.xdata = lxml.etree.Element("Properties") - raw.XMLMatch.return_value = "raw" - nevermatch = Mock() - nevermatch.xdata = lxml.etree.Element("Properties", automatch="false") - nevermatch.XMLMatch.return_value = "nevermatch" - p.store.entries = { - "/foo/automatch.xml": automatch, - "/foo/raw.xml": raw, - "/foo/nevermatch.xml": nevermatch, - } - - # we make copy just return the object it was asked to copy so - # that we can test the return value of get_additional_data(), - # which copies every object it doesn't XMLMatch() - mock_copy.side_effect = lambda o: o - - # test with automatch default to false - p.core.setup.cfp.getboolean.return_value = False metadata = Mock() - self.assertItemsEqual(p.get_additional_data(metadata), - { - "/foo/automatch.xml": automatch.XMLMatch.return_value, - "/foo/raw.xml": raw, - "/foo/nevermatch.xml": nevermatch}) - automatch.XMLMatch.assert_called_with(metadata) - self.assertFalse(raw.XMLMatch.called) - self.assertFalse(nevermatch.XMLMatch.called) - - # test with automatch default to true - p.core.setup.cfp.getboolean.return_value = True - self.assertItemsEqual(p.get_additional_data(metadata), - { - "/foo/automatch.xml": automatch.XMLMatch.return_value, - "/foo/raw.xml": raw.XMLMatch.return_value, - "/foo/nevermatch.xml": nevermatch}) - automatch.XMLMatch.assert_called_with(metadata) - raw.XMLMatch.assert_called_with(metadata) - self.assertFalse(nevermatch.XMLMatch.called) + p.store.entries = {"foo.xml": Mock(), + "foo.yml": Mock()} + rv = p.get_additional_data(metadata) + expected = dict() + for name, entry in p.store.entries.items(): + entry.get_additional_data.assert_called_with(metadata) + expected[name] = entry.get_additional_data.return_value + self.assertItemsEqual(rv, expected) -- cgit v1.2.3-1-g7c22