Boost logo

Boost-Commit :

From: daniel_at_[hidden]
Date: 2007-11-19 11:01:23


Author: danielw
Date: 2007-11-19 11:01:23 EST (Mon, 19 Nov 2007)
New Revision: 41230
URL: http://svn.boost.org/trac/boost/changeset/41230

Log:
Support for Boost.Build XML output.

Added:
   branches/bitten/tools/regression/src/test_results.py (contents, props changed)
Text files modified:
   branches/bitten/tools/regression/src/regression.py | 25 +++++++++++++++++++------
   1 files changed, 19 insertions(+), 6 deletions(-)

Modified: branches/bitten/tools/regression/src/regression.py
==============================================================================
--- branches/bitten/tools/regression/src/regression.py (original)
+++ branches/bitten/tools/regression/src/regression.py 2007-11-19 11:01:23 EST (Mon, 19 Nov 2007)
@@ -183,7 +183,10 @@
             'build_dir' : os.path.join(self.tools_regression_root,'build'),
             'build_args' : 'process_jam_log -d2'
             }
-
+
+ self.boost_build_use_xml = ('create-bitten-report' in self.actions and
+ 'test-process' not in self.actions)
+
         if self.debug_level > 0:
             self.log('Regression root = %s'%self.regression_root)
             self.log('Boost root = %s'%self.boost_root)
@@ -313,9 +316,17 @@
 
         utils.makedirs( self.regression_results )
         redirect = '>' * (2 - self.clean_log);
- test_cmd = '%s -d2 --dump-tests %s "--build-dir=%s" %s"%s" 2>&1' % (
+
+ if self.boost_build_use_xml:
+ xml_out = '--out-xml=%s' % os.path.join(self.regression_results,
+ 'test_results.xml')
+ else:
+ xml_out = ''
+
+ test_cmd = '%s -d2 --dump-tests %s %s "--build-dir=%s" %s"%s" 2>&1' % (
             self.bjam_cmd( self.toolsets ),
             self.bjam_options,
+ xml_out,
             self.regression_results,
             redirect,
             self.regression_log )
@@ -397,8 +408,8 @@
         
     def command_create_bitten_report(self):
         self.import_utils()
- from collect_and_upload_logs import create_bitten_report
-
+ from collect_and_upload_logs import create_bitten_reports
+
         if self.library:
             xml_root = os.path.join( self.regression_results, 'boost',
                                          'bin.v2', 'libs', self.library
@@ -407,13 +418,15 @@
             xml_root = os.path.join( self.regression_results, 'boost',
                                          'bin.v2' )
 
- report = create_bitten_report( xml_root ).toxml('utf-8')
+ report = create_bitten_reports(os.path.join(self.regression_results,
+ 'test_results.xml'))
 
         dir = os.path.split(self.bitten_report)[0]
         if not os.path.exists(dir):
             os.makedirs(dir)
             
- open(self.bitten_report, 'w').write(report)
+ open(self.bitten_report, 'w').write(
+ '\n'.join(('<?xml version="1.0" encoding="UTF-8"?>', report)))
     
     def command_upload_logs(self):
         self.import_utils()

Added: branches/bitten/tools/regression/src/test_results.py
==============================================================================
--- (empty file)
+++ branches/bitten/tools/regression/src/test_results.py 2007-11-19 11:01:23 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,131 @@
+# Copyright (c) Daniel Wallin 2007
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os.path
+import StringIO
+import re
+
+try:
+ import xml.etree.cElementTree as ET
+except ImportError:
+ import elementtree.cElementTree as ET
+
+try:
+ set
+except:
+ from Sets import set
+
+class TestResults(object):
+
+ def __init__(self, source):
+ self.dependencies = {}
+ self.dependents = {}
+ self.tests = set()
+ self.results = {}
+ if isinstance(source, basestring):
+ source = StringIO.StringIO(source)
+ self._read_xml(source)
+
+ def _read_xml(self, source):
+ i = iter(ET.iterparse(source, events=('start', 'end')))
+ event, root = i.next()
+
+ for event, elem in i:
+ if event == 'end' and elem.tag == 'targets':
+ break
+
+ self.jam_version = root.find('jam').get('version')
+ self.os = root.find('os')
+ self.os = self.os.get('name'), self.os.get('platform'), self.os.text
+ self.timestamp = root.find('timestamp').text
+ self.directory = root.find('directory').text
+ self.command = root.find('command').text
+
+ self._read_targets(elem)
+ root.clear()
+ self._read_actions(i)
+
+ def _read_targets(self, targets):
+ for target in targets:
+ name = target.find('name').text
+ path = target.find('path')
+ if path is None:
+ continue
+ path = path.text
+ jam_target = target.find('jam-target').text
+ jam_target = self._as_absolute_path(jam_target)
+ self.dependencies[jam_target] = [self._as_absolute_path(d.text)
+ for d in target.find('dependencies')]
+ for d in self.dependencies[jam_target]:
+ self.dependents.setdefault(d, []).append(jam_target)
+ if jam_target.endswith('.test'):
+ self.tests.add(jam_target)
+
+ gristed_re = re.compile('^<p([^>]+)>(.*)$')
+
+ def _as_absolute_path(self, jam_target):
+ m = self.gristed_re.match(jam_target)
+ if m:
+ result = os.path.join(self.directory, m.group(1), m.group(2))
+ else:
+ result = os.path.join(self.directory, jam_target)
+ return os.path.normpath(result)
+
+ def _read_actions(self, i):
+ for event, elem in i:
+ if event == 'end' and elem.tag == 'action':
+ status = elem.get('status')
+ target = elem.find('jam-target')
+ command = elem.find('command')
+ output = elem.find('output')
+ if target is None:
+ continue
+
+ properties = {}
+ for p in elem.find('properties') or []:
+ properties[p.get('name')] = p.text
+
+ name = self._as_absolute_path(target.text)
+ self.results[name] = (status == '0', command.text, output.text, properties)
+ elem.clear()
+
+ def _follow_dependencies(self, target):
+ if target in self.results:
+ result = self.results[target]
+ if not result[0]:
+ return [(target, result[1], result[2], result[3])]
+ else:
+ return []
+ else:
+ dependencies = self.dependencies.get(target, None)
+ if dependencies:
+ result = []
+ for d in self.dependencies.get(target, []):
+ result.extend(self._follow_dependencies(d))
+ return result
+ return []
+
+ # TOOD:
+ # Compute the duration of the tests. It's not entirely
+ # clear what this should consist of. We should probably
+ # add up all the durations for the different stages in
+ # the test. Ideally we would also factor in the duration
+ # of building dependencies, but it's not clear how that
+ # would work.
+
+ def __iter__(self):
+ return iter(self.result())
+
+ def result(self):
+ for test in self.tests:
+ if test in self.results:
+ yield (test, 'success', None)
+ else:
+ failures = self._follow_dependencies(test)
+ if failures:
+ yield (test, 'failed', failures)
+ else:
+ yield (test, 'skipped', None)
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk