import mock from builtins import bytes from lxml import etree from .test_helper import * from collections import namedtuple from kiwi.exceptions import ( KiwiSchemaImportError, KiwiValidationError, KiwiDescriptionInvalid, KiwiDataStructureError, KiwiDescriptionConflict, KiwiCommandNotFound, KiwiExtensionError ) from kiwi.xml_description import XMLDescription class TestSchema(object): def setup(self): test_xml = bytes( b""" John Doe john@example.com say hello zypper 1.1.1 """ ) test_xml_extension = bytes( b""" John Doe john@example.com say hello zypper 1.1.1 """ ) test_xml_extension_not_unique = bytes( b""" John Doe john@example.com say hello zypper 1.1.1 """ ) test_xml_extension_invalid = bytes( b""" John Doe john@example.com say hello zypper 1.1.1 """ ) self.description_from_file = XMLDescription(description='description') self.description_from_data = XMLDescription(xml_content=test_xml) self.extension_description_from_data = XMLDescription( xml_content=test_xml_extension ) self.extension_multiple_toplevel_description_from_data = XMLDescription( xml_content=test_xml_extension_not_unique ) self.extension_invalid_description_from_data = XMLDescription( xml_content=test_xml_extension_invalid ) @raises(KiwiDescriptionConflict) def test_constructor_conflict(self): XMLDescription(description='description', xml_content='content') def test_load_schema_from_xml_content(self): schema = etree.parse('../../kiwi/schema/kiwi.rng') lookup = '{http://relaxng.org/ns/structure/1.0}attribute' for attribute in schema.iter(lookup): if attribute.get('name') == 'schemaversion': schemaversion = attribute.find( '{http://relaxng.org/ns/structure/1.0}value' ).text parsed = self.description_from_data.load() assert parsed.get_schemaversion() == schemaversion @raises(KiwiSchemaImportError) @patch('lxml.etree.RelaxNG') @patch.object(XMLDescription, '_xsltproc') def test_load_schema_import_error(self, mock_xslt, mock_relax): mock_relax.side_effect = KiwiSchemaImportError( 'ImportError' ) self.description_from_file.load() @raises(KiwiValidationError) @patch('lxml.isoschematron.Schematron') @patch('lxml.etree.RelaxNG') @patch('lxml.etree.parse') @patch.object(XMLDescription, '_xsltproc') def test_load_schema_validation_error_from_file( self, mock_xslt, mock_parse, mock_relax, mock_schematron ): mock_validate = mock.Mock() mock_validate.validate.side_effect = KiwiValidationError( 'ValidationError' ) mock_relax.return_value = mock_validate mock_schematron.return_value = mock_validate self.description_from_file.load() @raises(KiwiDescriptionInvalid) @patch('lxml.isoschematron.Schematron') @patch('lxml.etree.RelaxNG') @patch('lxml.etree.parse') @patch('kiwi.system.setup.Command.run') @patch.object(XMLDescription, '_xsltproc') def test_load_schema_description_from_file_invalid( self, mock_xslt, mock_command, mock_parse, mock_relax, mock_schematron ): mock_rng_validate = mock.Mock() mock_rng_validate.validate = mock.Mock( return_value=False ) mock_sch_validate = mock.Mock() mock_sch_validate.validate = mock.Mock( return_value=False ) validation_report = namedtuple( 'report', ['text'] ) name_spaces = namedtuple( 'nspaces', ['nsmap'] ) mock_validation_report = mock.Mock() mock_validation_report.getroot = mock.Mock( return_value = name_spaces(nsmap="") ) mock_validation_report.xpath = mock.Mock( return_value = [ validation_report(text='wrong attribute 1'), validation_report(text='wrong attribute 2') ] ) mock_sch_validate.validation_report = mock_validation_report mock_relax.return_value = mock_rng_validate mock_schematron.return_value = mock_sch_validate command_run = namedtuple( 'command', ['output', 'error', 'returncode'] ) mock_command.return_value = command_run( output='jing output\n', error='', returncode=1 ) self.description_from_file.load() @raises(KiwiDescriptionInvalid) @patch('lxml.isoschematron.Schematron') @patch('lxml.etree.RelaxNG') @patch('lxml.etree.parse') @patch('kiwi.system.setup.Command.run') @patch.object(XMLDescription, '_xsltproc') def test_load_schema_description_from_data_invalid( self, mock_xslt, mock_command, mock_parse, mock_relax, mock_schematron ): mock_rng_validate = mock.Mock() mock_rng_validate.validate = mock.Mock( return_value=False ) mock_sch_validate = mock.Mock() mock_sch_validate.validate = mock.Mock( return_value=False ) validation_report = namedtuple( 'report', ['text'] ) name_spaces = namedtuple( 'nspaces', ['nsmap'] ) mock_validation_report = mock.Mock() mock_validation_report.getroot = mock.Mock( return_value = name_spaces(nsmap="") ) mock_validation_report.xpath = mock.Mock( return_value = [ validation_report(text='wrong attribute 1'), validation_report(text='wrong attribute 2') ] ) mock_sch_validate.validation_report = mock_validation_report mock_relax.return_value = mock_rng_validate mock_schematron.return_value = mock_sch_validate command_run = namedtuple( 'command', ['output', 'error', 'returncode'] ) mock_command.return_value = command_run( output='jing output\n', error='', returncode=1 ) self.description_from_data.load() @raises(KiwiDescriptionInvalid) @patch('lxml.isoschematron.Schematron') @patch('lxml.etree.RelaxNG') @patch('lxml.etree.parse') @patch('kiwi.system.setup.Command.run') @patch.object(XMLDescription, '_xsltproc') def test_load_schema_description_from_data_invalid_no_jing( self, mock_xslt, mock_command, mock_parse, mock_relax, mock_schematron ): mock_rng_validate = mock.Mock() mock_rng_validate.validate = mock.Mock( return_value=False ) mock_sch_validate = mock.Mock() mock_sch_validate.validate = mock.Mock( return_value=True ) mock_relax.return_value = mock_rng_validate mock_schematron.return_value = mock_sch_validate mock_command.side_effect = KiwiCommandNotFound('No jing command') self.description_from_data.load() @raises(KiwiDataStructureError) @patch('lxml.isoschematron.Schematron') @patch('lxml.etree.RelaxNG') @patch('lxml.etree.parse') @patch('kiwi.xml_parse.parse') @patch.object(XMLDescription, '_xsltproc') def test_load_data_structure_error( self, mock_xsltproc, mock_xml_parse, mock_etree_parse, mock_relax, mock_schematron ): mock_rng_validate = mock.Mock() mock_rng_validate.validate = mock.Mock( return_value=True ) mock_sch_validate = mock.Mock() mock_sch_validate.validate = mock.Mock( return_value=True ) mock_relax.return_value = mock_rng_validate mock_schematron.return_value = mock_sch_validate mock_xml_parse.side_effect = KiwiDataStructureError( 'DataStructureError' ) self.description_from_file.load() @patch('kiwi.xml_description.Command.run') def test_load_extension(self, mock_command): command_output = mock.Mock() command_output.output = 'file://../data/my_plugin.rng' mock_command.return_value = command_output self.extension_description_from_data.load() mock_command.assert_called_once_with( ['xmlcatalog', '/etc/xml/catalog', 'http://www.my_plugin.com'] ) xml_data = self.extension_description_from_data.get_extension_xml_data( 'my_plugin' ) assert xml_data.getroot()[0].get('name') == 'cool stuff' @raises(KiwiExtensionError) def test_load_extension_multiple_toplevel_error(self): self.extension_multiple_toplevel_description_from_data.load() @raises(KiwiExtensionError) @patch('kiwi.xml_description.Command.run') def test_load_extension_schema_error(self, mock_command): mock_command.side_effect = Exception self.extension_description_from_data.load() @patch('kiwi.xml_description.Command.run') @raises(KiwiExtensionError) def test_load_extension_validation_error(self, mock_command): command_output = mock.Mock() command_output.output = 'file://../data/my_plugin.rng' mock_command.return_value = command_output self.extension_invalid_description_from_data.load()