diff --git a/qubes/tests/__init__.py b/qubes/tests/__init__.py
index 73b02e4f..ee378fba 100644
--- a/qubes/tests/__init__.py
+++ b/qubes/tests/__init__.py
@@ -417,20 +417,29 @@ class QubesTestCase(unittest.TestCase):
callableObj(*args, **kwargs)
- def assertXMLEqual(self, xml1, xml2):
+ def assertXMLEqual(self, xml1, xml2, msg=''):
'''Check for equality of two XML objects.
:param xml1: first element
:param xml2: second element
:type xml1: :py:class:`lxml.etree._Element`
:type xml2: :py:class:`lxml.etree._Element`
- ''' # pylint: disable=invalid-name
+ '''
self.assertEqual(xml1.tag, xml2.tag)
- self.assertEqual(xml1.text, xml2.text)
- self.assertCountEqual(xml1.keys(), xml2.keys())
+ msg += '/' + str(xml1.tag)
+
+ if xml1.text is not None and xml2.text is not None:
+ self.assertEqual(xml1.text.strip(), xml2.text.strip(), msg)
+ else:
+ self.assertEqual(xml1.text, xml2.text, msg)
+ self.assertCountEqual(xml1.keys(), xml2.keys(), msg)
for key in xml1.keys():
- self.assertEqual(xml1.get(key), xml2.get(key))
+ self.assertEqual(xml1.get(key), xml2.get(key), msg)
+
+ self.assertEqual(len(xml1), len(xml2), msg + ' children count')
+ for child1, child2 in zip(xml1, xml2):
+ self.assertXMLEqual(child1, child2, msg=msg)
def assertDevicesEqual(self, devices1, devices2, msg=None):
self.assertEqual(devices1.keys(), devices2.keys(), msg)
diff --git a/qubes/tests/vm/__init__.py b/qubes/tests/vm/__init__.py
index 463389ce..16b82870 100644
--- a/qubes/tests/vm/__init__.py
+++ b/qubes/tests/vm/__init__.py
@@ -20,6 +20,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
+import jinja2
import qubes.tests
@@ -60,3 +61,11 @@ class TestApp(qubes.tests.TestEmitter):
self.host = TestHost()
self.pools = {}
self.domains = {}
+ #: jinja2 environment for libvirt XML templates
+ self.env = jinja2.Environment(
+ loader=jinja2.FileSystemLoader([
+ 'templates',
+ '/etc/qubes/templates',
+ '/usr/share/qubes/templates',
+ ]),
+ undefined=jinja2.StrictUndefined)
diff --git a/qubes/tests/vm/qubesvm.py b/qubes/tests/vm/qubesvm.py
index 23da01c0..a7b2171e 100644
--- a/qubes/tests/vm/qubesvm.py
+++ b/qubes/tests/vm/qubesvm.py
@@ -27,6 +27,7 @@ import unittest
import uuid
import datetime
import lxml.etree
+import unittest.mock
import qubes
import qubes.exc
@@ -500,3 +501,101 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
self.assertEqual(vm.virt_mode, 'pv')
with self.assertRaises(AttributeError):
vm.hvm
+
+ def test_600_libvirt_xml_pv(self):
+ expected = '''
+ test-inst-test
+ 7db78950-c467-4863-94d1-af59806384ea
+ 500
+ 400
+ 4
+
+ linux
+ /tmp/kernel/vmlinuz
+ /tmp/kernel/initramfs
+ root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 nopat
+
+
+
+
+
+
+ destroy
+ destroy
+ destroy
+
+
+
+
+
+
+
+
+
+
+
+
+ '''
+ my_uuid = '7db78950-c467-4863-94d1-af59806384ea'
+ vm = self.get_vm(uuid=my_uuid)
+ vm.netvm = None
+ vm.virt_mode = 'pv'
+ # tests for storage are later
+ vm.volumes['kernel'] = unittest.mock.Mock(**{
+ 'kernels_dir': '/tmp/kernel',
+ 'block_device.return_value.domain': 'dom0',
+ 'block_device.return_value.script': None,
+ 'block_device.return_value.path': '/tmp/kernel/modules.img',
+ 'block_device.return_value.devtype': 'disk',
+ 'block_device.return_value.name': 'kernel',
+ })
+ libvirt_xml = vm.create_config_file()
+ self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
+ lxml.etree.XML(expected))
+
+ def test_600_libvirt_xml_hvm(self):
+ expected = '''
+ test-inst-test
+ 7db78950-c467-4863-94d1-af59806384ea
+ 500
+ 400
+ 4
+
+
+
+
+
+
+
+
+ hvm
+ hvmloader
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ destroy
+ destroy
+
+
+
+
+
+
+
+ '''
+ my_uuid = '7db78950-c467-4863-94d1-af59806384ea'
+ vm = self.get_vm(uuid=my_uuid)
+ vm.netvm = None
+ vm.virt_mode = 'hvm'
+ libvirt_xml = vm.create_config_file()
+ self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
+ lxml.etree.XML(expected))