Initial commit of serialization library code

Change-Id: Ie09a7245176aa799e59622e5118b145833b23590
Signed-off-by: Eric Kunze <eric.kunze@arm.com>
diff --git a/test/scripts/xunit/xunit.py b/test/scripts/xunit/xunit.py
new file mode 100644
index 0000000..2de0d5c
--- /dev/null
+++ b/test/scripts/xunit/xunit.py
@@ -0,0 +1,109 @@
+# Copyright (c) 2020-2021, ARM Limited.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+
+import xml.etree.ElementTree as ET
+from xml.dom import minidom
+
+
+class xunit_results:
+    def __init__(self):
+        self.name = "testsuites"
+        self.suites = []
+
+    def create_suite(self, name):
+        s = xunit_suite(name)
+        self.suites.append(s)
+        return s
+
+    def write_results(self, filename):
+        suites = ET.Element(self.name)
+        tree = ET.ElementTree(suites)
+        for s in self.suites:
+            testsuite = ET.SubElement(
+                suites, "testsuite", {"name": s.name, "errors": "0"}
+            )
+            tests = 0
+            failures = 0
+            skip = 0
+            for t in s.tests:
+                test = ET.SubElement(
+                    testsuite,
+                    "testcase",
+                    {"name": t.name, "classname": t.classname, "time": t.time},
+                )
+                tests += 1
+                if t.skip:
+                    skip += 1
+                    ET.SubElement(test, "skipped", {"type": "Skipped test"})
+                if t.fail:
+                    failures += 1
+                    fail = ET.SubElement(test, "failure", {"type": "Test failed"})
+                    fail.text = t.fail
+                if t.sysout:
+                    sysout = ET.SubElement(test, "system-out")
+                    sysout.text = t.sysout
+                if t.syserr:
+                    syserr = ET.SubElement(test, "system-err")
+                    syserr.text = t.syserr
+            testsuite.attrib["tests"] = str(tests)
+            testsuite.attrib["failures"] = str(failures)
+            testsuite.attrib["skip"] = str(skip)
+        xmlstr = minidom.parseString(ET.tostring(tree.getroot())).toprettyxml(
+            indent="  "
+        )
+        with open(filename, "w") as f:
+            f.write(xmlstr)
+
+
+class xunit_suite:
+    def __init__(self, name):
+        self.name = name
+        self.tests = []
+
+
+# classname should be of the form suite.class/subclass/subclass2/... It appears
+# you can have an unlimited number of subclasses in this manner
+
+
+class xunit_test:
+    def __init__(self, name, classname=None):
+        self.name = name
+        if classname:
+            self.classname = classname
+        else:
+            self.classname = name
+        self.time = "0.000"
+        self.fail = None
+        self.skip = False
+        self.sysout = None
+        self.syserr = None
+
+    def failed(self, text):
+        self.fail = text
+
+    def skipped(self):
+        self.skip = True
+
+
+if __name__ == "__main__":
+    r = xunit_results()
+    s = r.create_suite("selftest")
+    for i in range(0, 10):
+        t = xunit_test("atest" + str(i), "selftest")
+        if i == 3:
+            t.failed("Unknown failure foo")
+        if i == 7:
+            t.skipped()
+        s.tests.append(t)
+    r.write_results("foo.xml")