238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| 
 | |
| import testlog_parser, sys, os, xml, re
 | |
| from table_formatter import *
 | |
| from optparse import OptionParser
 | |
| 
 | |
| cvsize_re = re.compile("^\d+x\d+$")
 | |
| cvtype_re = re.compile("^(CV_)(8U|8S|16U|16S|32S|32F|64F)(C\d{1,3})?$")
 | |
| 
 | |
| def keyselector(a):
 | |
|     if cvsize_re.match(a):
 | |
|         size = [int(d) for d in a.split('x')]
 | |
|         return size[0] * size[1]
 | |
|     elif cvtype_re.match(a):
 | |
|         if a.startswith("CV_"):
 | |
|             a = a[3:]
 | |
|         depth = 7
 | |
|         if a[0] == '8':
 | |
|             depth = (0, 1) [a[1] == 'S']
 | |
|         elif a[0] == '1':
 | |
|             depth = (2, 3) [a[2] == 'S']
 | |
|         elif a[2] == 'S':
 | |
|             depth = 4
 | |
|         elif a[0] == '3':
 | |
|             depth = 5
 | |
|         elif a[0] == '6':
 | |
|             depth = 6
 | |
|         cidx = a.find('C')
 | |
|         if cidx < 0:
 | |
|             channels = 1
 | |
|         else:
 | |
|             channels = int(a[a.index('C') + 1:])
 | |
|         #return (depth & 7) + ((channels - 1) << 3)
 | |
|         return ((channels-1) & 511) + (depth << 9)
 | |
|     return a
 | |
| 
 | |
| convert = lambda text: int(text) if text.isdigit() else text
 | |
| alphanum_keyselector = lambda key: [ convert(c) for c in re.split('([0-9]+)', str(keyselector(key))) ]
 | |
| 
 | |
| def getValueParams(test):
 | |
|     param = test.get("value_param")
 | |
|     if not param:
 | |
|         return []
 | |
|     if param.startswith("("):
 | |
|         param = param[1:]
 | |
|     if param.endswith(")"):
 | |
|         param = param[:-1]
 | |
|     args = []
 | |
|     prev_pos = 0
 | |
|     start = 0
 | |
|     balance = 0
 | |
|     while True:
 | |
|         idx = param.find(",", prev_pos)
 | |
|         if idx < 0:
 | |
|             break
 | |
|         idxlb = param.find("(", prev_pos, idx)
 | |
|         while idxlb >= 0:
 | |
|             balance += 1
 | |
|             idxlb = param.find("(", idxlb+1, idx)
 | |
|         idxrb = param.find(")", prev_pos, idx)
 | |
|         while idxrb >= 0:
 | |
|             balance -= 1
 | |
|             idxrb = param.find(")", idxrb+1, idx)
 | |
|         assert(balance >= 0)
 | |
|         if balance == 0:
 | |
|             args.append(param[start:idx].strip())
 | |
|             start = idx + 1
 | |
|         prev_pos = idx + 1
 | |
|     args.append(param[start:].strip())
 | |
|     return args
 | |
|     #return [p.strip() for p in param.split(",")]
 | |
| 
 | |
| def nextPermutation(indexes, lists, x, y):
 | |
|     idx = len(indexes)-1
 | |
|     while idx >= 0:
 | |
|         while idx == x or idx == y:
 | |
|             idx -= 1
 | |
|         if idx < 0:
 | |
|             return False
 | |
|         v = indexes[idx] + 1
 | |
|         if v < len(lists[idx]):
 | |
|             indexes[idx] = v;
 | |
|             return True;
 | |
|         else:
 | |
|             indexes[idx] = 0;
 | |
|             idx -= 1
 | |
|     return False
 | |
| 
 | |
| def getTestWideName(sname, indexes, lists, x, y):
 | |
|     name = sname + "::("
 | |
|     for i in range(len(indexes)):
 | |
|         if i > 0:
 | |
|             name += ", "
 | |
|         if i == x:
 | |
|             name += "X"
 | |
|         elif i == y:
 | |
|             name += "Y"
 | |
|         else:
 | |
|             name += lists[i][indexes[i]]
 | |
|     return str(name + ")")
 | |
| 
 | |
| def getTest(stests, x, y, row, col):
 | |
|     for pair in stests:
 | |
|         if pair[1][x] == row and pair[1][y] == col:
 | |
|             return pair[0]
 | |
|     return None
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     parser = OptionParser()
 | |
|     parser.add_option("-o", "--output", dest="format", help="output results in text format (can be 'txt', 'html' or 'auto' - default)", metavar="FMT", default="auto")
 | |
|     parser.add_option("-u", "--units", dest="units", help="units for output values (s, ms (default), mks, ns or ticks)", metavar="UNITS", default="ms")
 | |
|     parser.add_option("-m", "--metric", dest="metric", help="output metric", metavar="NAME", default="gmean")
 | |
|     parser.add_option("-x", "", dest="x", help="argument number for rows", metavar="ROW", default=1)
 | |
|     parser.add_option("-y", "", dest="y", help="argument number for columns", metavar="COL", default=0)
 | |
|     parser.add_option("-f", "--filter", dest="filter", help="regex to filter tests", metavar="REGEX", default=None)
 | |
|     (options, args) = parser.parse_args()
 | |
| 
 | |
|     if len(args) != 1:
 | |
|         print >> sys.stderr, "Usage:\n", os.path.basename(sys.argv[0]), "<log_name1>.xml"
 | |
|         exit(1)
 | |
| 
 | |
|     options.generateHtml = detectHtmlOutputType(options.format)
 | |
|     if options.metric not in metrix_table:
 | |
|         options.metric = "gmean"
 | |
|     if options.metric.endswith("%"):
 | |
|         options.metric = options.metric[:-1]
 | |
|     getter = metrix_table[options.metric][1]
 | |
| 
 | |
|     tests = testlog_parser.parseLogFile(args[0])
 | |
|     if options.filter:
 | |
|         expr = re.compile(options.filter)
 | |
|         tests = [(t,getValueParams(t)) for t in tests if expr.search(str(t))]
 | |
|     else:
 | |
|         tests = [(t,getValueParams(t)) for t in tests]
 | |
| 
 | |
|     args[0] = os.path.basename(args[0])
 | |
| 
 | |
|     if not tests:
 | |
|         print >> sys.stderr, "Error - no tests matched"
 | |
|         exit(1)
 | |
| 
 | |
|     argsnum = len(tests[0][1])
 | |
|     sname = tests[0][0].shortName()
 | |
| 
 | |
|     arglists = []
 | |
|     for i in range(argsnum):
 | |
|         arglists.append({})
 | |
| 
 | |
|     names = set()
 | |
|     names1 = set()
 | |
|     for pair in tests:
 | |
|         sn = pair[0].shortName()
 | |
|         if len(pair[1]) > 1:
 | |
|             names.add(sn)
 | |
|         else:
 | |
|             names1.add(sn)
 | |
|         if sn == sname:
 | |
|             if len(pair[1]) != argsnum:
 | |
|                 print >> sys.stderr, "Error - unable to create chart tables for functions having different argument numbers"
 | |
|                 sys.exit(1)
 | |
|             for i in range(argsnum):
 | |
|                 arglists[i][pair[1][i]] = 1
 | |
| 
 | |
|     if names1 or len(names) != 1:
 | |
|         print >> sys.stderr, "Error - unable to create tables for functions from different test suits:"
 | |
|         i = 1
 | |
|         for name in sorted(names):
 | |
|             print >> sys.stderr, "%4s:   %s" % (i, name)
 | |
|             i += 1
 | |
|         if names1:
 | |
|             print >> sys.stderr, "Other suits in this log (can not be chosen):"
 | |
|             for name in sorted(names1):
 | |
|                 print >> sys.stderr, "%4s:   %s" % (i, name)
 | |
|                 i += 1
 | |
|         sys.exit(1)
 | |
| 
 | |
|     if argsnum < 2:
 | |
|         print >> sys.stderr, "Error - tests from %s have less than 2 parameters" % sname
 | |
|         exit(1)
 | |
| 
 | |
|     for i in range(argsnum):
 | |
|         arglists[i] = sorted([str(key) for key in arglists[i].iterkeys()], key=alphanum_keyselector)
 | |
| 
 | |
|     if options.generateHtml and options.format != "moinwiki":
 | |
|         htmlPrintHeader(sys.stdout, "Report %s for %s" % (args[0], sname))
 | |
| 
 | |
|     indexes = [0] * argsnum
 | |
|     x = int(options.x)
 | |
|     y = int(options.y)
 | |
|     if x == y or x < 0 or y < 0 or x >= argsnum or y >= argsnum:
 | |
|         x = 1
 | |
|         y = 0
 | |
| 
 | |
|     while True:
 | |
|         stests = []
 | |
|         for pair in tests:
 | |
|             t = pair[0]
 | |
|             v = pair[1]
 | |
|             for i in range(argsnum):
 | |
|                 if i != x and i != y:
 | |
|                     if v[i] != arglists[i][indexes[i]]:
 | |
|                         t = None
 | |
|                         break
 | |
|             if t:
 | |
|                 stests.append(pair)
 | |
| 
 | |
|         tbl = table(metrix_table[options.metric][0] + " for\n" + getTestWideName(sname, indexes, arglists, x, y))
 | |
|         tbl.newColumn("x", "X\Y")
 | |
|         for col in arglists[y]:
 | |
|             tbl.newColumn(col, col, align="center")
 | |
|         for row in arglists[x]:
 | |
|             tbl.newRow()
 | |
|             tbl.newCell("x", row)
 | |
|             for col in arglists[y]:
 | |
|                 case = getTest(stests, x, y, row, col)
 | |
|                 if case:
 | |
|                     status = case.get("status")
 | |
|                     if status != "run":
 | |
|                         tbl.newCell(col, status, color = "red")
 | |
|                     else:
 | |
|                         val = getter(case, None, options.units)
 | |
|                         if isinstance(val, float):
 | |
|                             tbl.newCell(col, "%.2f %s" % (val, options.units), val)
 | |
|                         else:
 | |
|                             tbl.newCell(col, val, val)
 | |
|                 else:
 | |
|                     tbl.newCell(col, "-")
 | |
| 
 | |
|         if options.generateHtml:
 | |
|             tbl.htmlPrintTable(sys.stdout, options.format == "moinwiki")
 | |
|         else:
 | |
|             tbl.consolePrintTable(sys.stdout)
 | |
|         if not nextPermutation(indexes, arglists, x, y):
 | |
|             break
 | |
| 
 | |
|     if options.generateHtml and options.format != "moinwiki":
 | |
|         htmlPrintFooter(sys.stdout)
 | 
