Home | History | Annotate | Download | only in misc
      1 #!/usr/bin/env python
      2 
      3 import collections
      4 import re
      5 import os.path
      6 import sys
      7 from xml.dom.minidom import parse
      8 
      9 class TestInfo(object):
     10 
     11     def __init__(self, xmlnode):
     12         self.fixture = xmlnode.getAttribute("classname")
     13         self.name = xmlnode.getAttribute("name")
     14         self.value_param = xmlnode.getAttribute("value_param")
     15         self.type_param = xmlnode.getAttribute("type_param")
     16 
     17         custom_status = xmlnode.getAttribute("custom_status")
     18         failures = xmlnode.getElementsByTagName("failure")
     19 
     20         if len(custom_status) > 0:
     21             self.status = custom_status
     22         elif len(failures) > 0:
     23             self.status = "failed"
     24         else:
     25             self.status = xmlnode.getAttribute("status")
     26 
     27         if self.name.startswith("DISABLED_"):
     28             self.status = "disabled"
     29             self.fixture = self.fixture.replace("DISABLED_", "")
     30             self.name = self.name.replace("DISABLED_", "")
     31         self.metrix = {}
     32         self.parseLongMetric(xmlnode, "bytesIn");
     33         self.parseLongMetric(xmlnode, "bytesOut");
     34         self.parseIntMetric(xmlnode, "samples");
     35         self.parseIntMetric(xmlnode, "outliers");
     36         self.parseFloatMetric(xmlnode, "frequency", 1);
     37         self.parseLongMetric(xmlnode, "min");
     38         self.parseLongMetric(xmlnode, "median");
     39         self.parseLongMetric(xmlnode, "gmean");
     40         self.parseLongMetric(xmlnode, "mean");
     41         self.parseLongMetric(xmlnode, "stddev");
     42         self.parseFloatMetric(xmlnode, "gstddev");
     43         self.parseFloatMetric(xmlnode, "time");
     44 
     45     def parseLongMetric(self, xmlnode, name, default = 0):
     46         if xmlnode.hasAttribute(name):
     47             tmp = xmlnode.getAttribute(name)
     48             val = long(tmp)
     49             self.metrix[name] = val
     50         else:
     51             self.metrix[name] = default
     52 
     53     def parseIntMetric(self, xmlnode, name, default = 0):
     54         if xmlnode.hasAttribute(name):
     55             tmp = xmlnode.getAttribute(name)
     56             val = int(tmp)
     57             self.metrix[name] = val
     58         else:
     59             self.metrix[name] = default
     60 
     61     def parseFloatMetric(self, xmlnode, name, default = 0):
     62         if xmlnode.hasAttribute(name):
     63             tmp = xmlnode.getAttribute(name)
     64             val = float(tmp)
     65             self.metrix[name] = val
     66         else:
     67             self.metrix[name] = default
     68 
     69     def parseStringMetric(self, xmlnode, name, default = None):
     70         if xmlnode.hasAttribute(name):
     71             tmp = xmlnode.getAttribute(name)
     72             self.metrix[name] = tmp.strip()
     73         else:
     74             self.metrix[name] = default
     75 
     76     def get(self, name, units="ms"):
     77         if name == "classname":
     78             return self.fixture
     79         if name == "name":
     80             return self.name
     81         if name == "fullname":
     82             return self.__str__()
     83         if name == "value_param":
     84             return self.value_param
     85         if name == "type_param":
     86             return self.type_param
     87         if name == "status":
     88             return self.status
     89         val = self.metrix.get(name, None)
     90         if not val:
     91             return val
     92         if name == "time":
     93             return self.metrix.get("time")
     94         if name in ["gmean", "min", "mean", "median", "stddev"]:
     95             scale = 1.0
     96             frequency = self.metrix.get("frequency", 1.0) or 1.0
     97             if units == "ms":
     98                 scale = 1000.0
     99             if units == "mks":
    100                 scale = 1000000.0
    101             if units == "ns":
    102                 scale = 1000000000.0
    103             if units == "ticks":
    104                 frequency = long(1)
    105                 scale = long(1)
    106             return val * scale / frequency
    107         return val
    108 
    109 
    110     def dump(self, units="ms"):
    111         print "%s ->\t\033[1;31m%s\033[0m = \t%.2f%s" % (str(self), self.status, self.get("gmean", units), units)
    112 
    113 
    114     def getName(self):
    115         pos = self.name.find("/")
    116         if pos > 0:
    117             return self.name[:pos]
    118         return self.name
    119 
    120 
    121     def getFixture(self):
    122         if self.fixture.endswith(self.getName()):
    123             fixture = self.fixture[:-len(self.getName())]
    124         else:
    125             fixture = self.fixture
    126         if fixture.endswith("_"):
    127             fixture = fixture[:-1]
    128         return fixture
    129 
    130 
    131     def param(self):
    132         return '::'.join(filter(None, [self.type_param, self.value_param]))
    133 
    134     def shortName(self):
    135         name = self.getName()
    136         fixture = self.getFixture()
    137         return '::'.join(filter(None, [name, fixture]))
    138 
    139 
    140     def __str__(self):
    141         name = self.getName()
    142         fixture = self.getFixture()
    143         return '::'.join(filter(None, [name, fixture, self.type_param, self.value_param]))
    144 
    145 
    146     def __cmp__(self, other):
    147         r = cmp(self.fixture, other.fixture);
    148         if r != 0:
    149             return r
    150         if self.type_param:
    151             if other.type_param:
    152                 r = cmp(self.type_param, other.type_param);
    153                 if r != 0:
    154                      return r
    155             else:
    156                 return -1
    157         else:
    158             if other.type_param:
    159                 return 1
    160         if self.value_param:
    161             if other.value_param:
    162                 r = cmp(self.value_param, other.value_param);
    163                 if r != 0:
    164                      return r
    165             else:
    166                 return -1
    167         else:
    168             if other.value_param:
    169                 return 1
    170         return 0
    171 
    172 # This is a Sequence for compatibility with old scripts,
    173 # which treat parseLogFile's return value as a list.
    174 class TestRunInfo(collections.Sequence):
    175     def __init__(self, properties, tests):
    176         self.properties = properties
    177         self.tests = tests
    178 
    179     def __len__(self):
    180         return len(self.tests)
    181 
    182     def __getitem__(self, key):
    183         return self.tests[key]
    184 
    185 def parseLogFile(filename):
    186     log = parse(filename)
    187 
    188     properties = {
    189         attr_name[3:]: attr_value
    190         for (attr_name, attr_value) in log.documentElement.attributes.items()
    191         if attr_name.startswith('cv_')
    192     }
    193 
    194     tests = map(TestInfo, log.getElementsByTagName("testcase"))
    195 
    196     return TestRunInfo(properties, tests)
    197 
    198 
    199 if __name__ == "__main__":
    200     if len(sys.argv) < 2:
    201         print "Usage:\n", os.path.basename(sys.argv[0]), "<log_name>.xml"
    202         exit(0)
    203 
    204     for arg in sys.argv[1:]:
    205         print "Processing {}...".format(arg)
    206 
    207         run = parseLogFile(arg)
    208 
    209         print "Properties:"
    210 
    211         for (prop_name, prop_value) in run.properties.items():
    212           print "\t{} = {}".format(prop_name, prop_value)
    213 
    214         print "Tests:"
    215 
    216         for t in sorted(run.tests):
    217             t.dump()
    218 
    219         print
    220