diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py
index 5c1455f5..b1ae3576 100644
--- a/tests/test_git_superproject.py
+++ b/tests/test_git_superproject.py
@@ -23,6 +23,7 @@ from unittest import mock
import git_superproject
import manifest_xml
import platform_utils
+from test_manifest_xml import sort_attributes
class SuperprojectTestCase(unittest.TestCase):
@@ -140,12 +141,12 @@ class SuperprojectTestCase(unittest.TestCase):
with open(manifest_path, 'r') as fp:
manifest_xml = fp.read()
self.assertEqual(
- manifest_xml,
+ sort_attributes(manifest_xml),
''
- ''
+ ''
''
- ''
+ ''
''
'')
@@ -167,13 +168,13 @@ class SuperprojectTestCase(unittest.TestCase):
with open(manifest_path, 'r') as fp:
manifest_xml = fp.read()
self.assertEqual(
- manifest_xml,
+ sort_attributes(manifest_xml),
''
- ''
+ ''
''
- ''
+ ''
''
'')
@@ -208,16 +209,17 @@ class SuperprojectTestCase(unittest.TestCase):
with open(manifest_path, 'r') as fp:
manifest_xml = fp.read()
self.assertEqual(
- manifest_xml,
+ sort_attributes(manifest_xml),
''
- ''
- ''
+ ''
+ ''
''
- ''
- ''
+ ''
+ ''
''
'')
diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py
index 99848e57..bd74780d 100644
--- a/tests/test_manifest_xml.py
+++ b/tests/test_manifest_xml.py
@@ -16,6 +16,7 @@
import os
import platform
+import re
import shutil
import tempfile
import unittest
@@ -63,6 +64,30 @@ if os.path.sep != '/':
INVALID_FS_PATHS += tuple(x.replace('/', os.path.sep) for x in INVALID_FS_PATHS)
+def sort_attributes(manifest):
+ """Sort the attributes of all elements alphabetically.
+
+ This is needed because different versions of the toxml() function from
+ xml.dom.minidom outputs the attributes of elements in different orders.
+ Before Python 3.8 they were output alphabetically, later versions preserve
+ the order specified by the user.
+
+ Args:
+ manifest: String containing an XML manifest.
+
+ Returns:
+ The XML manifest with the attributes of all elements sorted alphabetically.
+ """
+ new_manifest = ''
+ # This will find every element in the XML manifest, whether they have
+ # attributes or not. This simplifies recreating the manifest below.
+ matches = re.findall(r'(<[/?]?[a-z-]+\s*)((?:\S+?="[^"]+"\s*?)*)(\s*[/?]?>)', manifest)
+ for head, attrs, tail in matches:
+ m = re.findall(r'\S+?="[^"]+"', attrs)
+ new_manifest += head + ' '.join(sorted(m)) + tail
+ return new_manifest
+
+
class ManifestParseTestCase(unittest.TestCase):
"""TestCase for parsing manifests."""
@@ -254,9 +279,9 @@ class XmlManifestTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(
- manifest.ToXml().toxml(),
+ sort_attributes(manifest.ToXml().toxml()),
''
- ''
+ ''
''
''
'')
@@ -408,9 +433,9 @@ class ProjectElementTests(ManifestParseTestCase):
project = manifest.projects[0]
project.SetRevisionId('ABCDEF')
self.assertEqual(
- manifest.ToXml().toxml(),
+ sort_attributes(manifest.ToXml().toxml()),
''
- ''
+ ''
''
''
'')
@@ -516,9 +541,9 @@ class SuperProjectElementTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
self.assertEqual(
- manifest.ToXml().toxml(),
+ sort_attributes(manifest.ToXml().toxml()),
''
- ''
+ ''
''
''
'')
@@ -537,10 +562,10 @@ class SuperProjectElementTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['remote'].name, 'superproject-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/platform/superproject')
self.assertEqual(
- manifest.ToXml().toxml(),
+ sort_attributes(manifest.ToXml().toxml()),
''
- ''
- ''
+ ''
+ ''
''
''
'')
@@ -557,9 +582,9 @@ class SuperProjectElementTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'default-remote')
self.assertEqual(
- manifest.ToXml().toxml(),
+ sort_attributes(manifest.ToXml().toxml()),
''
- ''
+ ''
''
''
'')