From e1331b44f56bf8db583c4cdf426021cdb1e3b7df Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Mon, 24 Dec 2012 15:29:49 +0400 Subject: [PATCH 1/2] Wrote script generating timing table --- modules/ts/misc/perf_tests_timing.py | 108 +++++++++++++++++++++++++++ modules/ts/misc/testlog_parser.py | 3 + 2 files changed, 111 insertions(+) create mode 100644 modules/ts/misc/perf_tests_timing.py diff --git a/modules/ts/misc/perf_tests_timing.py b/modules/ts/misc/perf_tests_timing.py new file mode 100644 index 0000000000..d3e2c571e7 --- /dev/null +++ b/modules/ts/misc/perf_tests_timing.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +import testlog_parser, sys, os, xml, glob, re +from table_formatter import * +from optparse import OptionParser +from operator import itemgetter, attrgetter +from summary import getSetName, alphanum_keyselector + +if __name__ == "__main__": + usage = "%prog .xml" + parser = OptionParser(usage = usage) + + for arg in sys.argv: + print arg + + parser.add_option("-o", "--output", dest="format", + help="output results in text format (can be 'txt', 'html' or 'auto' - default)", + metavar="FMT", default="auto") + + (options, args) = parser.parse_args() + + options.generateHtml = detectHtmlOutputType(options.format) + + if 1 != len(args): + parser.print_help() + exit(0) + + # expand wildcards and filter duplicates + file = os.path.abspath(args[0]) + if not os.path.isfile(file): + print 'Incorrect file name!' + parser.print_help() + exit(0) + + # read all passed files + test_sets = [] + try: + tests = testlog_parser.parseLogFile(file) + if tests: + test_sets.append((os.path.basename(file), tests)) + except IOError as err: + sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) + except xml.parsers.expat.ExpatError as err: + sys.stderr.write("ExpatError reading \"" + file + "\" - " + str(err) + os.linesep) + + if not test_sets: + sys.stderr.write("Error: no test data found" + os.linesep) + quit() + + # find matches + setsCount = len(test_sets) + test_cases = {} + + name_extractor = lambda name: str(name) + + for i in range(setsCount): + for case in test_sets[i][1]: + name = name_extractor(case) + if name not in test_cases: + test_cases[name] = [None] * setsCount + test_cases[name][i] = case + + testsuits = [] # testsuit name, time, flag for failed tests + + prevGroupName = None + suit_time = 0 + has_failed = False + for name in sorted(test_cases.iterkeys(), key=alphanum_keyselector): + cases = test_cases[name] + + groupName = next(c for c in cases if c).shortName() + if groupName != prevGroupName: + if prevGroupName != None: + testsuits.append((prevGroupName, suit_time, has_failed)) + has_failed = False + suit_time = 0 + prevGroupName = groupName + + for i in range(setsCount): + case = cases[i] + if not case is None: + if case.get("status") == "run": + suit_time += case.get("time") + if case.get("status") == "failed": + has_failed = True + + tbl = table() + + # header + tbl.newColumn("name", "Name", align = "left", cssclass = "col_name") + tbl.newColumn("time", "Time (ms)", align = "left", cssclass = "col_name") + tbl.newColumn("failed", "Failed tests", align = "center", cssclass = "col_name") + + # rows + for suit in sorted(testsuits, key=lambda suit: suit[1], reverse=True): + tbl.newRow() + tbl.newCell("name", suit[0]) + tbl.newCell("time", formatValue(suit[1], "", ""), suit[1]) + if (suit[2]): + tbl.newCell("failed", "Yes") + + # output table + if options.generateHtml: + htmlPrintHeader(sys.stdout, "Timings of %s tests from %s test logs" % (len(test_cases), setsCount)) + tbl.htmlPrintTable(sys.stdout) + htmlPrintFooter(sys.stdout) + else: + tbl.consolePrintTable(sys.stdout) \ No newline at end of file diff --git a/modules/ts/misc/testlog_parser.py b/modules/ts/misc/testlog_parser.py index ce55b8b1de..f61b47bba9 100755 --- a/modules/ts/misc/testlog_parser.py +++ b/modules/ts/misc/testlog_parser.py @@ -30,6 +30,7 @@ class TestInfo(object): self.parseLongMetric(xmlnode, "mean"); self.parseLongMetric(xmlnode, "stddev"); self.parseFloatMetric(xmlnode, "gstddev"); + self.parseFloatMetric(xmlnode, "time"); def parseLongMetric(self, xmlnode, name, default = 0): if xmlnode.hasAttribute(name): @@ -78,6 +79,8 @@ class TestInfo(object): val = self.metrix.get(name, None) if not val: return val + if name == "time": + return self.metrix.get("time") if name in ["gmean", "min", "mean", "median", "stddev"]: scale = 1.0 frequency = self.metrix.get("frequency", 1.0) or 1.0 From f57d692cd785672221111bb50c1d2360ce929581 Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Mon, 24 Dec 2012 16:47:30 +0400 Subject: [PATCH 2/2] Improved code --- modules/ts/misc/perf_tests_timing.py | 46 +++++++++++++--------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/modules/ts/misc/perf_tests_timing.py b/modules/ts/misc/perf_tests_timing.py index d3e2c571e7..70d2aa2f03 100644 --- a/modules/ts/misc/perf_tests_timing.py +++ b/modules/ts/misc/perf_tests_timing.py @@ -7,28 +7,24 @@ from operator import itemgetter, attrgetter from summary import getSetName, alphanum_keyselector if __name__ == "__main__": - usage = "%prog .xml" + usage = "%prog .xml [...]" parser = OptionParser(usage = usage) - for arg in sys.argv: - print arg - - 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("-o", "--output", dest = "format", + help = "output results in text format (can be 'txt', 'html' or 'auto' - default)", + metavar = 'FMT', default = 'auto') (options, args) = parser.parse_args() - - options.generateHtml = detectHtmlOutputType(options.format) - if 1 != len(args): parser.print_help() exit(0) + options.generateHtml = detectHtmlOutputType(options.format) + # expand wildcards and filter duplicates file = os.path.abspath(args[0]) if not os.path.isfile(file): - print 'Incorrect file name!' + sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) parser.print_help() exit(0) @@ -71,7 +67,8 @@ if __name__ == "__main__": groupName = next(c for c in cases if c).shortName() if groupName != prevGroupName: if prevGroupName != None: - testsuits.append((prevGroupName, suit_time, has_failed)) + testsuits.append({'name': prevGroupName, 'time': suit_time, \ + 'failed': has_failed}) has_failed = False suit_time = 0 prevGroupName = groupName @@ -79,29 +76,30 @@ if __name__ == "__main__": for i in range(setsCount): case = cases[i] if not case is None: - if case.get("status") == "run": - suit_time += case.get("time") - if case.get("status") == "failed": + if case.get('status') == 'run': + suit_time += case.get('time') + if case.get('status') == 'failed': has_failed = True tbl = table() # header - tbl.newColumn("name", "Name", align = "left", cssclass = "col_name") - tbl.newColumn("time", "Time (ms)", align = "left", cssclass = "col_name") - tbl.newColumn("failed", "Failed tests", align = "center", cssclass = "col_name") + tbl.newColumn('name', 'Name of testsuit', align = 'left', cssclass = 'col_name') + tbl.newColumn('time', 'Time (ms)', align = 'left', cssclass = 'col_name') + tbl.newColumn('failed', 'Failed tests', align = 'center', cssclass = 'col_name') # rows - for suit in sorted(testsuits, key=lambda suit: suit[1], reverse=True): + for suit in sorted(testsuits, key = lambda suit: suit['time'], reverse = True): tbl.newRow() - tbl.newCell("name", suit[0]) - tbl.newCell("time", formatValue(suit[1], "", ""), suit[1]) - if (suit[2]): - tbl.newCell("failed", "Yes") + tbl.newCell('name', suit['name']) + tbl.newCell('time', formatValue(suit['time'], '', ''), suit['time']) + if (suit['failed']): + tbl.newCell('failed', 'Yes') + else: + tbl.newCell('failed', ' ') # output table if options.generateHtml: - htmlPrintHeader(sys.stdout, "Timings of %s tests from %s test logs" % (len(test_cases), setsCount)) tbl.htmlPrintTable(sys.stdout) htmlPrintFooter(sys.stdout) else: