generate_report.py: fixed bug: Total row used all tests available for the config, changed to latest one; added links to the changelog and to the tests source; use the latest db in the current dir if no args provided
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import glob
|
||||||
|
|
||||||
|
REPO_URL = 'http://devel.ag-projects.com/~denis/cgi-bin/hgweb.cgi'
|
||||||
|
|
||||||
def make_table(database):
|
def make_table(database):
|
||||||
c = sqlite3.connect(database)
|
c = sqlite3.connect(database)
|
||||||
@@ -9,16 +12,22 @@ def make_table(database):
|
|||||||
'timeouts, exitcode, stdout from parsed_command_record join '
|
'timeouts, exitcode, stdout from parsed_command_record join '
|
||||||
'command_record on parsed_command_record.id=command_record.id ')).fetchall()
|
'command_record on parsed_command_record.id=command_record.id ')).fetchall()
|
||||||
table = {} # testname -> hub -> test_result (runs, errors, fails, timeouts)
|
table = {} # testname -> hub -> test_result (runs, errors, fails, timeouts)
|
||||||
hub_stats = {} # hub -> cumulative test_result
|
|
||||||
tests = set()
|
tests = set()
|
||||||
for id, testname, hub, runs, errors, fails, timeouts, exitcode, stdout in res:
|
for id, testname, hub, runs, errors, fails, timeouts, exitcode, stdout in res:
|
||||||
tests.add(testname)
|
tests.add(testname)
|
||||||
test_result = TestResult(runs, errors, fails, timeouts, exitcode, id, stdout)
|
test_result = TestResult(runs, errors, fails, timeouts, exitcode, id, stdout)
|
||||||
table.setdefault(testname, {})[hub] = test_result
|
table.setdefault(testname, {})[hub] = test_result
|
||||||
|
return table, sorted(tests)
|
||||||
|
|
||||||
|
def calc_hub_stats(table):
|
||||||
|
hub_stats = {} # hub -> cumulative test_result
|
||||||
|
for testname in table:
|
||||||
|
for hub in table[testname]:
|
||||||
|
test_result = table[testname][hub]
|
||||||
hub_stats.setdefault(hub, TestResult(0,0,0,0)).__iadd__(test_result)
|
hub_stats.setdefault(hub, TestResult(0,0,0,0)).__iadd__(test_result)
|
||||||
hubs = hub_stats.items()
|
hubs = hub_stats.items()
|
||||||
hubs.sort(key=lambda t: t[1].passed, reverse=True)
|
hubs.sort(key=lambda t: (t[1].passed, -t[1].timeouts, -t[1].failed), reverse=True)
|
||||||
return table, [x[0] for x in hubs], sorted(tests), hub_stats
|
return hub_stats, [x[0] for x in hubs]
|
||||||
|
|
||||||
class TestResult:
|
class TestResult:
|
||||||
|
|
||||||
@@ -35,6 +44,14 @@ class TestResult:
|
|||||||
def passed(self):
|
def passed(self):
|
||||||
return self.runs - self.errors - self.fails
|
return self.runs - self.errors - self.fails
|
||||||
|
|
||||||
|
@property
|
||||||
|
def failed(self):
|
||||||
|
return self.errors + self.fails
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total(self):
|
||||||
|
return self.runs + self.timeouts
|
||||||
|
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other):
|
||||||
self.runs += other.runs
|
self.runs += other.runs
|
||||||
self.errors += other.errors
|
self.errors += other.errors
|
||||||
@@ -53,6 +70,23 @@ class TestResult:
|
|||||||
else:
|
else:
|
||||||
return '"#72ff75"'
|
return '"#72ff75"'
|
||||||
|
|
||||||
|
def warnings(self):
|
||||||
|
r = []
|
||||||
|
if not self.failed and not self.timeouts:
|
||||||
|
if self.exitcode in [7, 9, 10]:
|
||||||
|
r += ['TIMEOUT']
|
||||||
|
if self.exitcode:
|
||||||
|
r += ['exitcode=%s' % self.exitcode]
|
||||||
|
if self.output is not None:
|
||||||
|
output = self.output.lower()
|
||||||
|
warning = output.count('warning')
|
||||||
|
if warning:
|
||||||
|
r += ['%s warnings' % warning]
|
||||||
|
tracebacks = output.count('traceback')
|
||||||
|
if tracebacks:
|
||||||
|
r += ['%s tracebacks' % tracebacks]
|
||||||
|
return r
|
||||||
|
|
||||||
def text(self):
|
def text(self):
|
||||||
errors = []
|
errors = []
|
||||||
if self.fails:
|
if self.fails:
|
||||||
@@ -61,28 +95,31 @@ class TestResult:
|
|||||||
errors += ['%s raised' % self.errors]
|
errors += ['%s raised' % self.errors]
|
||||||
if self.timeouts:
|
if self.timeouts:
|
||||||
errors += ['%s timeout' % self.timeouts]
|
errors += ['%s timeout' % self.timeouts]
|
||||||
if not errors:
|
errors += self.warnings()
|
||||||
if self.exitcode in [7, 9, 10]:
|
if self.id is None:
|
||||||
errors += ['TIMEOUT']
|
errors += ['<hr>%s total' % self.total]
|
||||||
if self.exitcode:
|
|
||||||
errors += ['exitcode=%s' % self.exitcode]
|
|
||||||
if self.output is not None:
|
|
||||||
output = self.output.lower()
|
|
||||||
warning = output.count('warning')
|
|
||||||
if warning:
|
|
||||||
errors += ['%s warnings' % warning]
|
|
||||||
tracebacks = output.count('traceback')
|
|
||||||
if tracebacks:
|
|
||||||
errors += ['%s tracebacks' % tracebacks]
|
|
||||||
return '\n'.join(["%s passed" % self.passed] + errors).replace(' ', ' ')
|
return '\n'.join(["%s passed" % self.passed] + errors).replace(' ', ' ')
|
||||||
|
|
||||||
|
# shorter passed/failed/raised/timeout
|
||||||
|
def text_short(self):
|
||||||
|
r = '%s/%s/%s' % (self.passed, self.failed, self.timeouts)
|
||||||
|
if self.warnings():
|
||||||
|
r += '\n' + '\n'.join(self.warnings()).replace(' ', ' ')
|
||||||
|
return r
|
||||||
|
|
||||||
def format(self):
|
def format(self):
|
||||||
text = self.text().replace('\n', '<br>\n')
|
text = self.text().replace('\n', '<br>\n')
|
||||||
if self.id is not None:
|
if self.id is None:
|
||||||
text = '<a href="%s.txt">%s</a>' % (self.id, text)
|
valign = 'bottom'
|
||||||
return '<td align=center bgcolor=%s>%s</td>' % (self.color(), text)
|
else:
|
||||||
|
text = '<a class="x" href="%s.txt">%s</a>' % (self.id, text)
|
||||||
|
valign = 'center'
|
||||||
|
return '<td align=center valign=%s bgcolor=%s>%s</td>' % (valign, self.color(), text)
|
||||||
|
|
||||||
def format_table(table, hubs, tests, hub_stats):
|
def format_testname(changeset, test):
|
||||||
|
return '<a href="%s/file/%s/greentest/%s">%s</a>' % (REPO_URL, changeset, test, test)
|
||||||
|
|
||||||
|
def format_table(table, hubs, tests, hub_stats, changeset):
|
||||||
r = '<table border=1>\n<tr>\n<td/>\n'
|
r = '<table border=1>\n<tr>\n<td/>\n'
|
||||||
for hub in hubs:
|
for hub in hubs:
|
||||||
r += '<td align=center>%s</td>\n' % hub
|
r += '<td align=center>%s</td>\n' % hub
|
||||||
@@ -100,7 +137,7 @@ def format_table(table, hubs, tests, hub_stats):
|
|||||||
r += '<tr><td colspan=%s/></tr>' % (len(hubs)+1)
|
r += '<tr><td colspan=%s/></tr>' % (len(hubs)+1)
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
r += '<tr><td>%s</td>' % test
|
r += '<tr><td>%s</td>' % format_testname(changeset, test)
|
||||||
for hub in hubs:
|
for hub in hubs:
|
||||||
test_result = table[test].get(hub)
|
test_result = table[test].get(hub)
|
||||||
if test_result is None:
|
if test_result is None:
|
||||||
@@ -112,8 +149,13 @@ def format_table(table, hubs, tests, hub_stats):
|
|||||||
r += '</table>'
|
r += '</table>'
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def format_html(table):
|
def format_header(rev, changeset):
|
||||||
r = '<html><head><style type="text/css">a {color: black; text-decoration: none;} </style></head><body>'
|
url = '%s/log/%s' % (REPO_URL, changeset)
|
||||||
|
return '<a href="%s">Eventlet changeset %s: %s</a><p>' % (url, rev, changeset)
|
||||||
|
|
||||||
|
def format_html(table, rev, changeset):
|
||||||
|
r = '<html><head><style type="text/css">a.x {color: black; text-decoration: none;} </style></head><body>'
|
||||||
|
r += format_header(rev, changeset)
|
||||||
r += table
|
r += table
|
||||||
r += '</body></html>'
|
r += '</body></html>'
|
||||||
return r
|
return r
|
||||||
@@ -126,12 +168,13 @@ def generate_raw_results(path, database):
|
|||||||
sys.stderr.write('.')
|
sys.stderr.write('.')
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
|
|
||||||
def main():
|
def main(db):
|
||||||
[db] = sys.argv[1:]
|
full_changeset = db.split('.')[1]
|
||||||
r = make_table(db)
|
rev, changeset = full_changeset.split('_', 1)
|
||||||
report = format_html(format_table(*r))
|
table, tests = make_table(db)
|
||||||
changeset = db.split('.')[1]
|
hub_stats, hubs = calc_hub_stats(table)
|
||||||
path = '../htmlreports/%s' % changeset
|
report = format_html(format_table(table, hubs, tests, hub_stats, changeset), rev, changeset)
|
||||||
|
path = '../htmlreports/%s' % full_changeset
|
||||||
try:
|
try:
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
except OSError, ex:
|
except OSError, ex:
|
||||||
@@ -141,4 +184,10 @@ def main():
|
|||||||
generate_raw_results(path, db)
|
generate_raw_results(path, db)
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
main()
|
if not sys.argv[1:]:
|
||||||
|
latest_db = sorted(glob.glob('results.*.db'))[-1]
|
||||||
|
print latest_db
|
||||||
|
sys.argv.append(latest_db)
|
||||||
|
for db in sys.argv[1:]:
|
||||||
|
main(db)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user