import traceback
import unittest
from test import support
+from test.libregrtest.utils import sanitize_xml
class RegressionTestResult(unittest.TextTestResult):
USE_XML = False
if capture:
if self._stdout_buffer is not None:
stdout = self._stdout_buffer.getvalue().rstrip()
- ET.SubElement(e, 'system-out').text = stdout
+ ET.SubElement(e, 'system-out').text = sanitize_xml(stdout)
if self._stderr_buffer is not None:
stderr = self._stderr_buffer.getvalue().rstrip()
- ET.SubElement(e, 'system-err').text = stderr
+ ET.SubElement(e, 'system-err').text = sanitize_xml(stderr)
for k, v in args.items():
if not k or not v:
continue
+
e2 = ET.SubElement(e, k)
if hasattr(v, 'items'):
for k2, v2 in v.items():
if k2:
- e2.set(k2, str(v2))
+ e2.set(k2, sanitize_xml(str(v2)))
else:
- e2.text = str(v2)
+ e2.text = sanitize_xml(str(v2))
else:
- e2.text = str(v)
+ e2.text = sanitize_xml(str(v))
@classmethod
def __makeErrorDict(cls, err_type, err_value, err_tb):
import tempfile
import textwrap
import unittest
+from xml.etree import ElementTree
+
from test import support
from test.support import os_helper
from test.libregrtest import cmdline
self.check_executed_tests(output, testname, stats=1, parallel=True)
self.assertNotIn('SPAM SPAM SPAM', output)
+ def test_xml(self):
+ code = textwrap.dedent(r"""
+ import unittest
+ from test import support
+
+ class VerboseTests(unittest.TestCase):
+ def test_failed(self):
+ print("abc \x1b def")
+ self.fail()
+ """)
+ testname = self.create_test(code=code)
+
+ # Run sequentially
+ filename = os_helper.TESTFN
+ self.addCleanup(os_helper.unlink, filename)
+
+ output = self.run_tests(testname, "--junit-xml", filename,
+ exitcode=EXITCODE_BAD_TEST)
+ self.check_executed_tests(output, testname,
+ failed=testname,
+ stats=TestStats(1, 1, 0))
+
+ # Test generated XML
+ with open(filename, encoding="utf8") as fp:
+ content = fp.read()
+
+ testsuite = ElementTree.fromstring(content)
+ self.assertEqual(int(testsuite.get('tests')), 1)
+ self.assertEqual(int(testsuite.get('errors')), 0)
+ self.assertEqual(int(testsuite.get('failures')), 1)
+
+ testcase = testsuite[0][0]
+ self.assertEqual(testcase.get('status'), 'run')
+ self.assertEqual(testcase.get('result'), 'completed')
+ self.assertGreater(float(testcase.get('time')), 0)
+ for out in testcase.iter('system-out'):
+ self.assertEqual(out.text, r"abc \x1b def")
+
class TestUtils(unittest.TestCase):
def test_format_duration(self):
self.assertTrue(match_test(test_chdir))
self.assertFalse(match_test(test_copy))
+ def test_sanitize_xml(self):
+ sanitize_xml = utils.sanitize_xml
+
+ # escape invalid XML characters
+ self.assertEqual(sanitize_xml('abc \x1b\x1f def'),
+ r'abc \x1b\x1f def')
+ self.assertEqual(sanitize_xml('nul:\x00, bell:\x07'),
+ r'nul:\x00, bell:\x07')
+ self.assertEqual(sanitize_xml('surrogate:\uDC80'),
+ r'surrogate:\udc80')
+ self.assertEqual(sanitize_xml('illegal \uFFFE and \uFFFF'),
+ r'illegal \ufffe and \uffff')
+
+ # no escape for valid XML characters
+ self.assertEqual(sanitize_xml('a\n\tb'),
+ 'a\n\tb')
+ self.assertEqual(sanitize_xml('valid t\xe9xt \u20ac'),
+ 'valid t\xe9xt \u20ac')
+
if __name__ == '__main__':
unittest.main()