tools/e32test-driver/rtest.py
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 #
       
     5 # This program is free software: you can redistribute it and/or modify
       
     6 # it under the terms of the GNU Lesser General Public License as published by
       
     7 # the Free Software Foundation, either version 3 of the License, or
       
     8 # (at your option) any later version.
       
     9 #
       
    10 # This program is distributed in the hope that it will be useful,
       
    11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 # GNU Lesser General Public License for more details.
       
    14 # 
       
    15 # You should have received a copy of the GNU Lesser General Public License
       
    16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17 
       
    18 # RTestParser represents the results of running an RTest testsuite on the target in terms of RTest
       
    19 # objects. Each RTest object captures the LineTimeInfo associated with the test and can determine
       
    20 # whether the test errored, failed or passed. It also provides further information such as the name of
       
    21 # the test and how long it took to gather the output from the test (which is a crude estimate of how long
       
    22 # it took to run the test. It can provide various useful bits of information like the line number in the
       
    23 # raw test data of a given line and the 'context' of a failure (in terms of the lines in the raw data).
       
    24 
       
    25 import sys
       
    26 
       
    27 import re
       
    28 
       
    29 import qemuruntest
       
    30 
       
    31 startRTestPattern = re.compile('RTEST TITLE:')
       
    32 bmSuiteFailurePattern = re.compile('Error:')
       
    33 endRTestPattern = re.compile('RUNTESTS: Test')
       
    34 failedRTestPattern = re.compile('RUNTESTS: Test .* FAIL')
       
    35 erroredRTestPattern = re.compile('RUNTESTS: Test .* ERROR')
       
    36 nameRTestPattern = re.compile('RUNTESTS: Test (\w+)')
       
    37 testSuiteEndingPattern = re.compile('RUNTESTS: Elapsed')
       
    38 
       
    39 class NoRTestsFound(Exception):
       
    40     def __init__(self, parser):
       
    41         self.parser = parser
       
    42 
       
    43     def __str__(self):
       
    44         return "No test results found in output from running '%s' rom image" % (self.parser.GetRomName())
       
    45     
       
    46     def GetParser(self):
       
    47         return self.parser
       
    48 
       
    49 class RTestEndMissing(Exception):
       
    50     def __init__(self, rtest):
       
    51         self.rtest = rtest
       
    52 
       
    53     def __str__(self):
       
    54         return "Could not find end of test started on line %d: '%s'" % (self.rtest.GetLineNumber(0), self.rtest.GetLine(0))
       
    55     
       
    56     def GetParser(self):
       
    57         return self.parser
       
    58 
       
    59     def GetIndex(self):
       
    60         return self.index
       
    61 
       
    62 class RTestNameMissing(Exception):
       
    63     def __init__(self, rtest, line):
       
    64         self.rtest = rtest
       
    65         self.line = line
       
    66 
       
    67     def GetRTest(self):
       
    68         return self.rtest
       
    69     
       
    70     def __str__(self):
       
    71         return "Could not find RTest name in line '%s'" % (self.line)
       
    72     
       
    73     def GetParser(self):
       
    74         return self.parser
       
    75 
       
    76     def GetLine(self):
       
    77         return self.line
       
    78 
       
    79 class RTest(object):
       
    80     def __init__(self, parser, lineTimeInfo, startLine = 0):
       
    81         """return new RTest instance"""
       
    82         self.parser = parser
       
    83         self.lineTimeInfoList = []
       
    84         self.lineTimeInfoList.append(lineTimeInfo)
       
    85         self.timeTaken = None
       
    86         self.result = None
       
    87         self.name = None
       
    88         self.startLine = startLine
       
    89         #line = lineTimeInfo.GetLine()
       
    90         #print >> sys.stdout, line
       
    91 
       
    92     def __str__(self):
       
    93             return self.GetName() + " " + self.GetResult()
       
    94         
       
    95     def Consume(self,lineTimeInfoList, start):
       
    96         newStart = start;
       
    97         for i in range(start, len(lineTimeInfoList) - 1):
       
    98             lineTimeInfo = lineTimeInfoList[i]
       
    99             self.lineTimeInfoList.append(lineTimeInfo)
       
   100             line = lineTimeInfo.GetLine()
       
   101             newStart = newStart + 1
       
   102             if self.EndOfTestp(line):
       
   103                 break
       
   104         else:
       
   105             raise RTestEndMissing(self)
       
   106         
       
   107         return newStart
       
   108             
       
   109     def EndOfTestp(self,line):
       
   110         return re.match(endRTestPattern, line) != None
       
   111 
       
   112     def FailedTestp(self,line):
       
   113         return re.match(failedRTestPattern, line) != None
       
   114 
       
   115     def ErroredTestp(self,line):
       
   116         return re.match(erroredRTestPattern, line) != None
       
   117 
       
   118     def GetTimeTaken(self):
       
   119         if self.timeTaken == None:
       
   120             self.timeTaken = self.lineTimeInfoList[-1].GetTime() - self.lineTimeInfoList[0].GetTime()
       
   121         return self.timeTaken
       
   122 
       
   123     def GetResult(self):
       
   124         if self.result == None:
       
   125             line = self.lineTimeInfoList[-1].GetLine()
       
   126             if self.FailedTestp(line):
       
   127                 self.result = 'Failed'
       
   128             elif self.ErroredTestp(line):
       
   129                 self.result = 'Errored'
       
   130             else:
       
   131                 self.result = 'Passed'
       
   132         return self.result
       
   133 
       
   134     def Failedp(self):
       
   135         return self.GetResult() == 'Failed'
       
   136 
       
   137     def Erroredp(self):
       
   138         return self.GetResult() == 'Errored'
       
   139     
       
   140     def Passedp(self):
       
   141         return self.GetResult() == 'Passed'
       
   142     
       
   143     def GetName(self):
       
   144         if self.name == None:
       
   145             try:
       
   146                 self.name = self.ParseName()
       
   147             except RTestNameMissing, x:
       
   148                 print >> sys.stderr, "WARNING: ", x
       
   149                 self.name = "RTEST @ line %d" % (x.GetRTest().GetLineNumber(0))
       
   150         return self.name
       
   151 
       
   152     def ParseName(self):
       
   153         line = self.lineTimeInfoList[-1].GetLine()
       
   154         m = re.match(nameRTestPattern, line)
       
   155         if m != None:
       
   156             return m.group(1)
       
   157         else:
       
   158             raise RTestNameMissing(self, line)
       
   159 
       
   160     def GetLineNumber(self, i):
       
   161         return self.startLine + i
       
   162 
       
   163     def GetLine(self, index):
       
   164         return self.lineTimeInfoList[index].GetLine()
       
   165 
       
   166     def ErrorContext(self):
       
   167         if self.Failedp():
       
   168             return map(qemuruntest.LineTimeInfo.GetLine, self.lineTimeInfoList[-5:-1])
       
   169         else:
       
   170             return []
       
   171         
       
   172     
       
   173 class RTestParser(object):
       
   174     def __init__(self, testRunner, lineTimeInfoList = None):
       
   175         self.testRunner = testRunner
       
   176         if lineTimeInfoList == None:
       
   177             self.lineTimeInfoList = testRunner.GetResults()
       
   178         else:
       
   179             self.lineTimeInfoList = lineTimeInfoList
       
   180         self.rtestList = []
       
   181         self.result = None
       
   182         
       
   183     def Parse(self):
       
   184         index = 0
       
   185         end = len(self.lineTimeInfoList)
       
   186         self.rtestList = []
       
   187         testSuiteComplete = False
       
   188         testErroredp = False
       
   189 
       
   190         # find first test
       
   191         while index < end:
       
   192             lineTimeInfo = self.lineTimeInfoList[index]
       
   193             index += 1;
       
   194             line = lineTimeInfo.GetLine()
       
   195             if self.StartOfTestp(line):
       
   196                 break
       
   197             if self.ErroredTestp(line):
       
   198                 self.rtestList.append(RTest(self, lineTimeInfo, index-1))
       
   199         else:
       
   200             raise NoRTestsFound(self)
       
   201 
       
   202         try:
       
   203             while index < end:
       
   204                 # NB making startLine index means that line number are based at 1 rather than 0
       
   205                 rtest = RTest(self, lineTimeInfo, startLine = index)
       
   206                 self.rtestList.append(rtest)
       
   207                 index = rtest.Consume(self.lineTimeInfoList, index)
       
   208 
       
   209                 if self.TestSuiteEnding(self.lineTimeInfoList[index].GetLine()):
       
   210                     testSuiteComplete = True
       
   211                     break
       
   212 
       
   213                 while index < end:
       
   214                     lineTimeInfo = self.lineTimeInfoList[index]
       
   215                     index += 1;
       
   216                     line = lineTimeInfo.GetLine()
       
   217                     if self.StartOfTestp(line):
       
   218                         break
       
   219                     if self.ErroredTestp(line):
       
   220                         self.rtestList.append(RTest(self, lineTimeInfo, startLine = index))
       
   221         except RTestEndMissing, x:
       
   222             print >> sys.stderr, "WARNING: ", x
       
   223         return testSuiteComplete
       
   224     
       
   225     def StartOfTestp(self,line):
       
   226         if re.match(startRTestPattern, line) != None:
       
   227             return True
       
   228         if re.match(bmSuiteFailurePattern, line) != None:
       
   229             return True
       
   230         return False
       
   231 
       
   232     def ErroredTestp(self,line):
       
   233         if re.match(erroredRTestPattern, line) != None:
       
   234             return True
       
   235         
       
   236     def TestSuiteEnding(self,line):
       
   237         return re.match(testSuiteEndingPattern, line) != None
       
   238 
       
   239     def GetRTests(self):
       
   240         return self.rtestList
       
   241 
       
   242     def GetLine(self,index):
       
   243         return self.lineTimeInfoList[index]
       
   244     
       
   245     def GetRomName(self):
       
   246         return self.testRunner.GetRomName()