diff --git a/tests/common.py b/tests/common.py
index 16715006..5521c412 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -42,6 +42,30 @@ def urlcompare(url, *args):
return True
+
+def xml_equal(actual, exp):
+ try:
+ actual_xml = ET.fromstring(actual)
+ exp_xml = ET.fromstring(exp)
+ except ET.ParseError:
+ return False
+ todo = [(actual_xml, exp_xml)]
+ while todo:
+ actual_xml, exp_xml = todo.pop(0)
+ if actual_xml.tag != exp_xml.tag:
+ return False
+ if actual_xml.attrib != exp_xml.attrib:
+ return False
+ if actual_xml.text != exp_xml.text:
+ return False
+ if actual_xml.tail != exp_xml.tail:
+ return False
+ if len(actual_xml) != len(exp_xml):
+ return False
+ todo.extend(list(zip(actual_xml, exp_xml)))
+ return True
+
+
class RequestWrongOrder(Exception):
"""raised if an unexpected request is issued to urllib2"""
def __init__(self, url, exp_url, method, exp_method):
@@ -98,7 +122,14 @@ class MyHTTPHandler(HTTPHandler):
if hasattr(data, 'read'):
data = data.read()
if data != exp:
- raise RequestDataMismatch(req.get_full_url(), repr(data), repr(exp))
+ # We do not have a notion to explicitly mark xml content. In case
+ # of xml, we do not care about the exact xml representation (for
+ # now). Hence, if both, data and exp, are xml and are "equal",
+ # everything is fine (for now); otherwise, error out
+ # (of course, this is problematic if we want to ensure that XML
+ # documents are bit identical...)
+ if not xml_equal(data, exp):
+ raise RequestDataMismatch(req.get_full_url(), repr(data), repr(exp))
return self.__get_response(req.get_full_url(), **kwargs)
def __get_response(self, url, **kwargs):
@@ -192,14 +223,27 @@ class OscTestCase(unittest.TestCase):
def _check_digests(self, fname, *skipfiles):
fname = os.path.join(self._get_fixtures_dir(), fname)
- self.assertEqual(open(os.path.join('.osc', '_files'), 'r').read(), open(fname, 'r').read())
- root = ET.parse(fname).getroot()
+ with open(os.path.join('.osc', '_files'), 'r') as f:
+ files_act = f.read()
+ with open(fname, 'r') as f:
+ files_exp = f.read()
+ self.assertXMLEqual(files_act, files_exp)
+ root = ET.fromstring(files_act)
for i in root.findall('entry'):
if i.get('name') in skipfiles:
continue
self.assertTrue(os.path.exists(os.path.join('.osc', i.get('name'))))
self.assertEqual(osc.core.dgst(os.path.join('.osc', i.get('name'))), i.get('md5'))
+ def assertXMLEqual(self, act, exp):
+ if xml_equal(act, exp):
+ return
+ # ok, xmls are different, hence, assertEqual is expected to fail
+ # (we just use it in order to get a "nice" error message)
+ self.assertEqual(act, exp)
+ # not reached (unless assertEqual is overridden in an incompatible way)
+ raise RuntimeError('assertEqual assumptions violated')
+
def assertEqualMultiline(self, got, exp):
if (got + exp).find('\n') == -1:
self.assertEqual(got, exp)
diff --git a/tests/test_request.py b/tests/test_request.py
index 96b5ba40..aa05aab7 100644
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -38,7 +38,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_createsr_with_option(self):
"""create a submitrequest with option"""
@@ -67,7 +67,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_createsr_missing_tgt_package(self):
"""create a submitrequest with missing target package"""
@@ -88,7 +88,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_createsr_invalid_argument(self):
"""create a submitrequest with invalid action argument"""
@@ -117,7 +117,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_add_role_group(self):
"""create an add_role request (group element)"""
@@ -138,7 +138,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_add_role_person_group(self):
"""create an add_role request (person+group element)"""
@@ -161,7 +161,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_set_bugowner_project(self):
"""create a set_bugowner request for a project"""
@@ -179,7 +179,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_set_bugowner_package(self):
"""create a set_bugowner request for a package"""
@@ -197,7 +197,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_delete_project(self):
"""create a delete request for a project"""
@@ -213,7 +213,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_delete_package(self):
"""create a delete request for a package"""
@@ -229,7 +229,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_create_change_devel(self):
"""create a change devel request"""
@@ -248,7 +248,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_action_from_xml1(self):
"""create action from xml"""
@@ -266,7 +266,7 @@ class TestRequest(OscTestCase):
self.assertEqual(action.person_role, 'reader')
self.assertEqual(action.group_name, 'group')
self.assertEqual(action.group_role, 'reviewer')
- self.assertEqual(xml, action.to_str())
+ self.assertXMLEqual(xml, action.to_str())
def test_action_from_xml2(self):
"""create action from xml"""
@@ -288,7 +288,7 @@ class TestRequest(OscTestCase):
self.assertEqual(action.opt_sourceupdate, 'cleanup')
self.assertEqual(action.opt_updatelink, '1')
self.assertTrue(action.src_rev is None)
- self.assertEqual(xml, action.to_str())
+ self.assertXMLEqual(xml, action.to_str())
def test_action_from_xml3(self):
"""create action from xml (with acceptinfo element)"""
@@ -312,7 +312,7 @@ class TestRequest(OscTestCase):
self.assertEqual(action.acceptinfo_xsrcmd5, 'ffffffffffffffffffffffffffffffff')
self.assertTrue(action.acceptinfo_osrcmd5 is None)
self.assertTrue(action.acceptinfo_oxsrcmd5 is None)
- self.assertEqual(xml, action.to_str())
+ self.assertXMLEqual(xml, action.to_str())
def test_action_from_xml_unknown_type(self):
"""try to create action from xml with unknown type"""
@@ -350,7 +350,7 @@ class TestRequest(OscTestCase):
self.assertEqual(r.description, 'this is a\nvery long\ndescription')
self.assertTrue(len(r.statehistory) == 1)
self.assertTrue(len(r.reviews) == 0)
- self.assertEqual(xml, r.to_str())
+ self.assertXMLEqual(xml, r.to_str())
def test_read_request2(self):
"""read in a request (with reviews)"""
@@ -389,7 +389,7 @@ class TestRequest(OscTestCase):
self.assertEqual(r.creator, 'creator')
self.assertTrue(len(r.statehistory) == 1)
self.assertTrue(len(r.reviews) == 1)
- self.assertEqual(xml, r.to_str())
+ self.assertXMLEqual(xml, r.to_str())
def test_read_request3(self):
"""read in a request (with an "empty" comment+description)"""
@@ -426,7 +426,7 @@ class TestRequest(OscTestCase):
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_request_list_view1(self):
"""test the list_view method"""
@@ -559,7 +559,7 @@ Comment: """
"""
- self.assertEqual(exp, r.to_str())
+ self.assertXMLEqual(exp, r.to_str())
def test_get_actions(self):
"""test get_actions method"""