This patch similarly changes the junit backend to have atomic writes, like the json backend.
Signed-off-by: Dylan Baker <[email protected]> --- framework/backends/junit.py | 64 +++++++++++++++++++++++++++++---------- framework/programs/run.py | 4 --- framework/tests/backends_tests.py | 23 ++++++++++++++ 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/framework/backends/junit.py b/framework/backends/junit.py index 10f65b3..ed21471 100644 --- a/framework/backends/junit.py +++ b/framework/backends/junit.py @@ -23,6 +23,8 @@ import os import re import posixpath +import itertools +import shutil try: from lxml import etree except ImportError: @@ -43,25 +45,53 @@ class JUnitBackend(FSyncMixin, Backend): """ _REPLACE = re.compile(r'[/\\]') - def __init__(self, dest, junit_test_suffix='', **options): - self._file = open(os.path.join(dest, 'results.xml'), 'w') + def __init__(self, dest, junit_test_suffix='', start_count=0, **options): FSyncMixin.__init__(self, **options) + self._dest = dest self._test_suffix = junit_test_suffix + self._counter = itertools.count(start_count) def initialize(self, metadata): - # Write initial headers and other data that etree cannot write for us - self._file.write('<?xml version="1.0" encoding="UTF-8" ?>\n') - self._file.write('<testsuites>\n') - self._file.write( - '<testsuite name="piglit" tests="{}">\n'.format( - metadata['test_count'])) - self._fsync(self._file) + """ Do nothing + + Junit doesn't support restore, and doesn't have an initial metadata + block to write, so all this method does is create the tests directory + + """ + tests = os.path.join(self._dest, 'tests') + if os.path.exists(tests): + shutil.rmtree(tests) + os.mkdir(tests) def finalize(self, metadata=None): - self._file.write('</testsuite>\n') - self._file.write('</testsuites>\n') - self._fsync(self._file) - self._file.close() + """ Scoop up all of the individual peices and put them together """ + root = etree.Element('testsuites') + piglit = etree.Element('testsuite', name='piglit') + root.append(piglit) + for each in os.listdir(os.path.join(self._dest, 'tests')): + with open(os.path.join(self._dest, 'tests', each), 'r') as f: + # parse returns an element tree, and that's not what we want, + # we want the first (and only) Element node + # If the element cannot be properly parsed then consider it a + # failed transaction and ignore it. + try: + piglit.append(etree.parse(f).getroot()) + except etree.XMLSyntaxError: + continue + + # set the test count by counting the number of tests. + # This must be bytes or unicode + piglit.attrib['tests'] = str(len(piglit)) + + with open(os.path.join(self._dest, 'results.xml'), 'w') as f: + f.write("<?xml version='1.0' encoding='utf-8'?>\n") + # lxml has a pretty print we want to use + if etree.__name__ == 'lxml.etree': + f.write(etree.tostring(root, pretty_print=True)) + else: + f.write(etree.tostring(root)) + + shutil.rmtree(os.path.join(self._dest, 'tests')) def write_test(self, name, data): # Split the name of the test and the group (what junit refers to as @@ -102,6 +132,8 @@ class JUnitBackend(FSyncMixin, Backend): elif data['result'] == 'crash': etree.SubElement(element, 'error') - self._file.write(etree.tostring(element)) - self._file.write('\n') - self._fsync(self._file) + t = os.path.join(self._dest, 'tests', + '{}.xml'.format(self._counter.next())) + with open(t, 'w') as f: + f.write(etree.tostring(element)) + self._fsync(f) diff --git a/framework/programs/run.py b/framework/programs/run.py index 749fb07..e7ec65f 100644 --- a/framework/programs/run.py +++ b/framework/programs/run.py @@ -250,10 +250,6 @@ def run(input_): options['platform'] = args.platform options['name'] = results.name options['env'] = core.collect_system_info() - # FIXME: this should be the actual count, but profile needs to be - # refactored to make that possible because of the flattening pass that is - # part of profile.run - options['test_count'] = 0 backend = backends.get_backend(args.backend)( args.results_path, diff --git a/framework/tests/backends_tests.py b/framework/tests/backends_tests.py index d1b3d23..177225d 100644 --- a/framework/tests/backends_tests.py +++ b/framework/tests/backends_tests.py @@ -272,3 +272,26 @@ class TestJSONTestFinalize(utils.StaticDirectory): test = json.load(f) nt.assert_equal(baseline, test) + + +def test_junit_skips_bad_tests(): + """ backends.JUnitBackend skips illformed tests """ + with utils.tempdir() as tdir: + test = backends.JUnitBackend(tdir) + test.initialize(BACKEND_INITIAL_META) + test.write_test( + 'a/test/group/test1', + results.TestResult({ + 'time': 1.2345, + 'result': 'pass', + 'out': 'this is stdout', + 'err': 'this is stderr', + }) + ) + with open(os.path.join(tdir, 'tests', '1.xml'), 'w') as f: + f.write('bad data') + + try: + test.finalize() + except etree.XMLSyntaxError as e: + raise AssertionError(e) -- 2.1.1 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
