cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# -*- coding: utf-8 -*-
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# $Id$
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncXML reader module.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThis produces a test result tree that can be processed and passed to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncreporting.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync__copyright__ = \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCopyright (C) 2010-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncavailable from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncyou can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncGeneral Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThe contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncof the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync(CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncYou may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncterms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync__version__ = "$Revision$"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync__all__ = ['ParseTestResult', ]
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Standard python imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport os
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport traceback
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# pylint: disable=C0111
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncclass Value(object):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Represents a value. Usually this is benchmark result or parameter.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def __init__(self, oTest, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest = oTest;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sName = hsAttrs['name'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sUnit = hsAttrs['unit'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sTimestamp = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sValue = '';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sDiff = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # parsing
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def addData(self, sData):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sValue += sData;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # debug
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def printValue(self, cIndent):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync print '%sValue: name=%s timestamp=%s unit=%s value="%s"' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % (''.ljust(cIndent*2), self.sName, self.sTimestamp, self.sUnit, self.sValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncclass Test(object):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Nested test result.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def __init__(self, oParent, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoChildren = [];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoValues = [];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oParent = oParent;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sName = hsAttrs['name'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStartTS = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sEndTS = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatus = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrors = -1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatusDiff = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrorsDiff = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # parsing
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def addChild(self, oChild):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoChildren.append(oChild);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return oChild;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def addValue(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oValue = hsAttrs['value'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoValues.append(oValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return oValue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def markPassed(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: self.sEndTS = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatus = 'passed';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrors = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def markSkipped(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: self.sEndTS = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatus = 'skipped';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrors = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def markFailed(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: self.sEndTS = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatus = 'failed';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrors = int(hsAttrs['errors']);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def markEnd(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: self.sEndTS = hsAttrs['timestamp'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if self.sStatus is None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sStatus = 'end';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.cErrors = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def mergeInIncludedTest(self, oTest):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ oTest will be robbed. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if oTest is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oChild in oTest.aoChildren:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oChild.oParent = self;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoChildren.append(oChild);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oValue in oTest.aoValues:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oValue.oTest = self;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoValues.append(oValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTest.aoChildren = [];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTest.aoValues = [];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # debug
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def printTree(self, iLevel = 0):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync print '%sTest: name=%s start=%s end=%s' % (''.ljust(iLevel*2), self.sName, self.sStartTS, self.sEndTS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oChild in self.aoChildren:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oChild.printTree(iLevel + 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oValue in self.aoValues:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oValue.printValue(iLevel + 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # getters / queries
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def getFullNameWorker(self, cSkipUpper):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if self.oParent is None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return (self.sName, 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName, iLevel = self.oParent.getFullNameWorker(cSkipUpper);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if iLevel < cSkipUpper:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName = self.sName;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName += ', ' + self.sName;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return (sName, iLevel + 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def getFullName(self, cSkipUpper = 2):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self.getFullNameWorker(cSkipUpper)[0];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def matchFilters(self, asFilters):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Checks if the all of the specified filter strings are substrings
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync of the full test name. Returns True / False.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName = self.getFullName();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for sFilter in asFilters:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sName.find(sFilter) < 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # manipulation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def filterTestsWorker(self, asFilters):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # depth first
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync i = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while i < len(self.aoChildren):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if self.aoChildren[i].filterTestsWorker(asFilters):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync i += 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.aoChildren[i].oParent = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync del self.aoChildren[i];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # If we have children, they must've matched up.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if len(self.aoChildren) != 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self.matchFilters(asFilters);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def filterTests(self, asFilters):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if len(asFilters) > 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.filterTestsWorker(asFilters)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncclass XmlLogReader(object):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync XML log reader class.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def __init__(self, sXmlFile):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.sXmlFile = sXmlFile;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oRoot = Test(None, {'name': 'root', 'timestamp': ''});
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest = self.oRoot;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.iLevel = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oValue = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def parse(self):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oFile = open(self.sXmlFile, 'r');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync traceback.print_exc();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from xml.parsers.expat import ParserCreate
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oParser = ParserCreate();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oParser.StartElementHandler = self.handleElementStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oParser.CharacterDataHandler = self.handleElementData;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oParser.EndElementHandler = self.handleElementEnd;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oParser.ParseFile(oFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync traceback.print_exc();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oFile.close();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oFile.close();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def handleElementStart(self, sName, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync #print '%s%s: %s' % (''.ljust(self.iLevel * 2), sName, str(hsAttrs));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sName == 'Test' or sName == 'SubTest':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.iLevel += 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest = self.oTest.addChild(Test(self.oTest, hsAttrs));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Value':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oValue = self.oTest.addValue(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'End':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest.markEnd(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Passed':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest.markPassed(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Skipped':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest.markSkipped(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Failed':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest.markFailed(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Include':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.handleInclude(hsAttrs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync print 'Unknonwn element "%s"' % (sName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def handleElementData(self, sData):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if self.oValue is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oValue.addData(sData);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sData.strip() != '':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync print 'Unexpected data "%s"' % (sData);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def handleElementEnd(self, sName):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sName == 'Test' or sName == 'Subtest':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.iLevel -= 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest = self.oTest.oParent;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif sName == 'Value':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oValue = None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def handleInclude(self, hsAttrs):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # relative or absolute path.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sXmlFile = hsAttrs['filename'];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if not os.path.isabs(sXmlFile):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sXmlFile = os.path.join(os.path.dirname(self.sXmlFile), sXmlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Try parse it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSub = parseTestResult(sXmlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if oSub is None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync print 'error: failed to parse include "%s"' % (sXmlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Skip the root and the next level before merging it the subtest and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # values in to the current test. The reason for this is that the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # include is the output of some sub-program we've run and we don't need
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # the extra test level it automatically adds.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync #
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # More benchmark heuristics: Walk down until we find more than one
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # test or values.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSub2 = oSub;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while len(oSub2.aoChildren) == 1 and len(oSub2.aoValues) == 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSub2 = oSub2.aoChildren[0];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if len(oSub2.aoValues) == 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSub2 = oSub;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oTest.mergeInIncludedTest(oSub2);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef parseTestResult(sXmlFile):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Parses the test results in the XML.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns result tree.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns None on failure.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oXlr = XmlLogReader(sXmlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if oXlr.parse():
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return oXlr.oRoot;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync