Home | History | Annotate | Download | only in utils
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (C) 2013 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the 'License');
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #    http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an 'AS IS' BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 import os
     18 import re
     19 import subprocess
     20 import sys
     21 from xml.dom import Node
     22 from xml.dom import minidom
     23 
     24 def getChildrenWithTag(parent, tagName):
     25   children = []
     26   for child in  parent.childNodes:
     27     if (child.nodeType == Node.ELEMENT_NODE) and (child.tagName == tagName):
     28       #print "parent " + parent.getAttribute("name") + " " + tagName +\
     29       #  " " + child.getAttribute("name")
     30       children.append(child)
     31   return children
     32 
     33 def getText(tag):
     34   return str(tag.firstChild.nodeValue)
     35 
     36 class TestCase(object):
     37   def __init__(self, name, summary, details, result):
     38     self.name = name
     39     self.summary = summary
     40     self.details = details
     41     self.result = result
     42 
     43   def getName(self):
     44     return self.name
     45 
     46   def getSummary(self):
     47     return self.summary
     48 
     49   def getDetails(self):
     50     return self.details
     51 
     52   def getResult(self):
     53     return self.result
     54 
     55 def parseSuite(suite, parentName):
     56   if parentName != "":
     57     parentName += '.'
     58   cases = {}
     59   childSuites = getChildrenWithTag(suite, "TestSuite")
     60   for child in childSuites:
     61     cases.update(parseSuite(child, parentName + child.getAttribute("name")))
     62   childTestCases = getChildrenWithTag(suite, "TestCase")
     63   for child in childTestCases:
     64     className = parentName + child.getAttribute("name")
     65     for test in getChildrenWithTag(child, "Test"):
     66       methodName = test.getAttribute("name")
     67       # do not include this
     68       if methodName == "testAndroidTestCaseSetupProperly":
     69         continue
     70       caseName = str(className + "#" + methodName)
     71       result = str(test.getAttribute("result"))
     72       summary = {}
     73       details = {}
     74       if result == "pass":
     75         sts = getChildrenWithTag(test, "Summary")
     76         dts = getChildrenWithTag(test, "Details")
     77         if len(sts) == len(dts) == 1:
     78           summary[sts[0].getAttribute("message")] = getText(sts[0])
     79           for d in getChildrenWithTag(dts[0], "ValueArray"):
     80             values = []
     81             for c in getChildrenWithTag(d, "Value"):
     82               values.append(getText(c))
     83             details[d.getAttribute("message")] = values
     84         else:
     85           result = "no results"
     86       testCase = TestCase(caseName, summary, details, result)
     87       cases[caseName] = testCase
     88   return cases
     89 
     90 
     91 class Result(object):
     92   def __init__(self, reportXml):
     93     self.results = {}
     94     self.infoKeys = []
     95     self.infoValues = []
     96     doc = minidom.parse(reportXml)
     97     testResult = doc.getElementsByTagName("TestResult")[0]
     98     buildInfos = testResult.getElementsByTagName("BuildInfo")
     99     if buildInfos != None and len(buildInfos) > 0:
    100       buildInfo = buildInfos[0]
    101       buildId = buildInfo.getAttribute("buildID")
    102       deviceId = buildInfo.getAttribute("deviceID")
    103       deviceName = buildInfo.getAttribute("build_device")
    104       boardName = buildInfo.getAttribute("build_board")
    105       partitions = buildInfo.getAttribute("partitions")
    106       m = re.search(r'.*;/data\s+([\w\.]+)\s+([\w\.]+)\s+([\w\.]+)\s+([\w\.]+);', partitions)
    107       dataPartitionSize = m.group(1)
    108       self.addKV("device", deviceName)
    109       self.addKV("board", boardName)
    110       self.addKV("serial", deviceId)
    111       self.addKV("build", buildId)
    112       self.addKV("data size", dataPartitionSize)
    113     packages = getChildrenWithTag(testResult, "TestPackage")
    114     for package in packages:
    115       casesFromChild = parseSuite(package, "")
    116       self.results.update(casesFromChild)
    117     #print self.results.keys()
    118 
    119   def addKV(self, key, value):
    120     self.infoKeys.append(key)
    121     self.infoValues.append(value)
    122 
    123   def getResults(self):
    124     return self.results
    125 
    126   def getKeys(self):
    127     return self.infoKeys
    128 
    129   def getValues(self):
    130     return self.infoValues
    131 
    132   def getDeviceName(self):
    133     return self.getInfoV("device")
    134 
    135   def getInfoV(self, key):
    136     if key in self.infoKeys:
    137       return self.infoValues[self.infoKeys.index(key)]
    138     else:
    139       return "unknown"
    140 
    141 def executeWithResult(command):
    142   p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    143   out, err = p.communicate()
    144   return out
    145 
    146 def parseReports(path):
    147   deviceResults = []
    148   xmls = executeWithResult("find " + path + " -name testResult.xml -print")
    149   print "xml files found :"
    150   print xmls
    151   for xml in xmls.splitlines():
    152     result = Result(xml)
    153     deviceResults.append(result)
    154   reportInfo = {}
    155   keys = ["device", "board", "serial", "build", "data size"]
    156   numDevices = len(deviceResults)
    157   for i in xrange(len(keys)):
    158     values = []
    159     for j in xrange(numDevices):
    160       values.append(str(deviceResults[j].getInfoV(keys[i])))
    161     reportInfo[keys[i]] = values
    162   #print reportInfo
    163 
    164   tests = []
    165   for deviceResult in deviceResults:
    166     for key in deviceResult.getResults().keys():
    167       if not key in tests:
    168         tests.append(key)
    169   #print tests
    170 
    171   reportTests = {}
    172   for i in xrange(len(tests)):
    173     test = tests[i]
    174     reportTests[test] = []
    175     for j in xrange(numDevices):
    176       values = {}
    177       if deviceResults[j].getResults().has_key(test):
    178         result = deviceResults[j].getResults()[test]
    179         values["result"] = result.getResult()
    180         values["summary"] = result.getSummary()
    181         values["details"] = result.getDetails()
    182         values["device"] = deviceResults[j].getDeviceName()
    183       # even if report does not have test, put empty dict
    184       # otherwise, there is no way to distinguish results from the same device
    185       reportTests[test].append(values)
    186   #print reportTests
    187   return (reportInfo, reportTests)
    188 
    189 def main(argv):
    190   if len(argv) < 3:
    191     print "get_csv_report.py cts_report_dir output_file"
    192     sys.exit(1)
    193   reportPath = os.path.abspath(argv[1])
    194   outputCsv = os.path.abspath(argv[2])
    195 
    196   (reportInfo, reportTests) = parseReports(reportPath)
    197 
    198   with open(outputCsv, 'w') as f:
    199     for key in reportInfo:
    200       f.write(key)
    201       for value in reportInfo[key]:
    202         f.write(',')
    203         f.write(value)
    204       f.write('\n')
    205     sortedTest = sorted(reportTests)
    206     for test in sortedTest:
    207       f.write(test)
    208       for report in reportTests[test]:
    209         f.write(',')
    210         if 'summary' in report:
    211           summaryValues = report['summary'].values()
    212           if len(summaryValues) > 0:
    213             f.write(summaryValues[0])
    214         # else: no data printed but just empty cell
    215       # close a test with line
    216       f.write('\n')
    217 
    218 if __name__ == '__main__':
    219   main(sys.argv)
    220