diff -r 1af5c1be89f8 -r 92d87f2e53c2 tools/e32test-driver/rtest.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/e32test-driver/rtest.py Fri Jan 15 09:07:44 2010 +0000 @@ -0,0 +1,246 @@ +# +# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +# RTestParser represents the results of running an RTest testsuite on the target in terms of RTest +# objects. Each RTest object captures the LineTimeInfo associated with the test and can determine +# whether the test errored, failed or passed. It also provides further information such as the name of +# the test and how long it took to gather the output from the test (which is a crude estimate of how long +# it took to run the test. It can provide various useful bits of information like the line number in the +# raw test data of a given line and the 'context' of a failure (in terms of the lines in the raw data). + +import sys + +import re + +import qemuruntest + +startRTestPattern = re.compile('RTEST TITLE:') +bmSuiteFailurePattern = re.compile('Error:') +endRTestPattern = re.compile('RUNTESTS: Test') +failedRTestPattern = re.compile('RUNTESTS: Test .* FAIL') +erroredRTestPattern = re.compile('RUNTESTS: Test .* ERROR') +nameRTestPattern = re.compile('RUNTESTS: Test (\w+)') +testSuiteEndingPattern = re.compile('RUNTESTS: Elapsed') + +class NoRTestsFound(Exception): + def __init__(self, parser): + self.parser = parser + + def __str__(self): + return "No test results found in output from running '%s' rom image" % (self.parser.GetRomName()) + + def GetParser(self): + return self.parser + +class RTestEndMissing(Exception): + def __init__(self, rtest): + self.rtest = rtest + + def __str__(self): + return "Could not find end of test started on line %d: '%s'" % (self.rtest.GetLineNumber(0), self.rtest.GetLine(0)) + + def GetParser(self): + return self.parser + + def GetIndex(self): + return self.index + +class RTestNameMissing(Exception): + def __init__(self, rtest, line): + self.rtest = rtest + self.line = line + + def GetRTest(self): + return self.rtest + + def __str__(self): + return "Could not find RTest name in line '%s'" % (self.line) + + def GetParser(self): + return self.parser + + def GetLine(self): + return self.line + +class RTest(object): + def __init__(self, parser, lineTimeInfo, startLine = 0): + """return new RTest instance""" + self.parser = parser + self.lineTimeInfoList = [] + self.lineTimeInfoList.append(lineTimeInfo) + self.timeTaken = None + self.result = None + self.name = None + self.startLine = startLine + #line = lineTimeInfo.GetLine() + #print >> sys.stdout, line + + def __str__(self): + return self.GetName() + " " + self.GetResult() + + def Consume(self,lineTimeInfoList, start): + newStart = start; + for i in range(start, len(lineTimeInfoList) - 1): + lineTimeInfo = lineTimeInfoList[i] + self.lineTimeInfoList.append(lineTimeInfo) + line = lineTimeInfo.GetLine() + newStart = newStart + 1 + if self.EndOfTestp(line): + break + else: + raise RTestEndMissing(self) + + return newStart + + def EndOfTestp(self,line): + return re.match(endRTestPattern, line) != None + + def FailedTestp(self,line): + return re.match(failedRTestPattern, line) != None + + def ErroredTestp(self,line): + return re.match(erroredRTestPattern, line) != None + + def GetTimeTaken(self): + if self.timeTaken == None: + self.timeTaken = self.lineTimeInfoList[-1].GetTime() - self.lineTimeInfoList[0].GetTime() + return self.timeTaken + + def GetResult(self): + if self.result == None: + line = self.lineTimeInfoList[-1].GetLine() + if self.FailedTestp(line): + self.result = 'Failed' + elif self.ErroredTestp(line): + self.result = 'Errored' + else: + self.result = 'Passed' + return self.result + + def Failedp(self): + return self.GetResult() == 'Failed' + + def Erroredp(self): + return self.GetResult() == 'Errored' + + def Passedp(self): + return self.GetResult() == 'Passed' + + def GetName(self): + if self.name == None: + try: + self.name = self.ParseName() + except RTestNameMissing, x: + print >> sys.stderr, "WARNING: ", x + self.name = "RTEST @ line %d" % (x.GetRTest().GetLineNumber(0)) + return self.name + + def ParseName(self): + line = self.lineTimeInfoList[-1].GetLine() + m = re.match(nameRTestPattern, line) + if m != None: + return m.group(1) + else: + raise RTestNameMissing(self, line) + + def GetLineNumber(self, i): + return self.startLine + i + + def GetLine(self, index): + return self.lineTimeInfoList[index].GetLine() + + def ErrorContext(self): + if self.Failedp(): + return map(qemuruntest.LineTimeInfo.GetLine, self.lineTimeInfoList[-5:-1]) + else: + return [] + + +class RTestParser(object): + def __init__(self, testRunner, lineTimeInfoList = None): + self.testRunner = testRunner + if lineTimeInfoList == None: + self.lineTimeInfoList = testRunner.GetResults() + else: + self.lineTimeInfoList = lineTimeInfoList + self.rtestList = [] + self.result = None + + def Parse(self): + index = 0 + end = len(self.lineTimeInfoList) + self.rtestList = [] + testSuiteComplete = False + testErroredp = False + + # find first test + while index < end: + lineTimeInfo = self.lineTimeInfoList[index] + index += 1; + line = lineTimeInfo.GetLine() + if self.StartOfTestp(line): + break + if self.ErroredTestp(line): + self.rtestList.append(RTest(self, lineTimeInfo, index-1)) + else: + raise NoRTestsFound(self) + + try: + while index < end: + # NB making startLine index means that line number are based at 1 rather than 0 + rtest = RTest(self, lineTimeInfo, startLine = index) + self.rtestList.append(rtest) + index = rtest.Consume(self.lineTimeInfoList, index) + + if self.TestSuiteEnding(self.lineTimeInfoList[index].GetLine()): + testSuiteComplete = True + break + + while index < end: + lineTimeInfo = self.lineTimeInfoList[index] + index += 1; + line = lineTimeInfo.GetLine() + if self.StartOfTestp(line): + break + if self.ErroredTestp(line): + self.rtestList.append(RTest(self, lineTimeInfo, startLine = index)) + except RTestEndMissing, x: + print >> sys.stderr, "WARNING: ", x + return testSuiteComplete + + def StartOfTestp(self,line): + if re.match(startRTestPattern, line) != None: + return True + if re.match(bmSuiteFailurePattern, line) != None: + return True + return False + + def ErroredTestp(self,line): + if re.match(erroredRTestPattern, line) != None: + return True + + def TestSuiteEnding(self,line): + return re.match(testSuiteEndingPattern, line) != None + + def GetRTests(self): + return self.rtestList + + def GetLine(self,index): + return self.lineTimeInfoList[index] + + def GetRomName(self): + return self.testRunner.GetRomName()