summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbligh <mbligh@592f7852-d20e-0410-864c-8624ca9c26a4>2008-04-16 23:12:12 +0000
committermbligh <mbligh@592f7852-d20e-0410-864c-8624ca9c26a4>2008-04-16 23:12:12 +0000
commit244de5669f672711af7023ab6e3967d8652a0661 (patch)
tree0895acaa4b9f342c028b02b6c2639c1a484c4350
parent7344c0955705832c436ac8affce92f8ed59509c5 (diff)
implementing request: reasons of failure should be displayed in non header cells
- reasons are retrieved from the database and displayed in cells only when either columns or rows are grouped by status (because of performance reasons) - reasons are displayed in cell below GOOD / TOTAL ratio and only if GOOD is less then TOTAL i.e. when some problems occured From: Vladimir Samarskiy <vsamarsk@google.com> Signed-off-by: Martin Bligh <mbligh@google.com> git-svn-id: svn://test.kernel.org/autotest/trunk@1441 592f7852-d20e-0410-864c-8624ca9c26a4
-rwxr-xr-xtko/compose_query.cgi18
-rwxr-xr-xtko/display.py22
-rwxr-xr-xtko/frontend.py45
3 files changed, 66 insertions, 19 deletions
diff --git a/tko/compose_query.cgi b/tko/compose_query.cgi
index 8b66145a..d609fa2e 100755
--- a/tko/compose_query.cgi
+++ b/tko/compose_query.cgi
@@ -238,7 +238,21 @@ def gen_matrix():
return [[display.box(msg)]]
try:
- test_data = frontend.get_matrix_data(db_obj, column, row, where)
+ ## Unfortunately, we can not request reasons of failure always
+ ## because it may result in an inflated size of data transfer
+ ## (at the moment we fetch 500 bytes of reason descriptions into
+ ## each cell )
+ ## If 'status' in [row,column] then either width or height
+ ## of the table <=7, hence table is not really 2D, and
+ ## query_reason is relatively save.
+ ## At the same time view when either rows or columns grouped
+ ## by status is when users need reasons of failures the most.
+
+ ## TO DO: implement [Show/Hide reasons] button or link in
+ ## all views and make thorough performance testing
+ test_data = frontend.get_matrix_data(db_obj, column, row, where,
+ query_reasons = ('status' in [row,column])
+ )
except db.MySQLTooManyRows, error:
return [[display.box(str(error))]]
@@ -280,7 +294,7 @@ def gen_matrix():
if x==datetime.datetime(1970,1,1): x = None
if y==datetime.datetime(1970,1,1): y = None
try:
- box_data = test_data.data[x][y].status_count
+ box_data = test_data.data[x][y]
except:
cur_row.append(display.box(None, None))
continue
diff --git a/tko/display.py b/tko/display.py
index 6458e072..78688d69 100755
--- a/tko/display.py
+++ b/tko/display.py
@@ -147,19 +147,29 @@ def shade_from_status_count(status_count):
return shade
-def status_html(db, status_count, shade):
+def status_html(db, box_data, shade):
"""
status_count: dict mapping from status (integer key) to count
eg. { 'GOOD' : 4, 'FAIL' : 1 }
"""
+ status_count = box_data.status_count
if 6 in status_count.keys():
html = "%d&nbsp;/&nbsp;%d " \
%(status_count[6],sum(status_count.values()))
else:
html = "%d&nbsp;/&nbsp;%d " % \
(0, sum(status_count.values()))
- tooltip = ""
+ if box_data.reasons_list:
+ box_data.reasons_list.sort()
+ for reason in box_data.reasons_list:
+ reason = reason.replace('<br>','\n')
+ reason = reason.replace('<','[').replace('>',']')
+ reason = reason.replace('|','\n').replace('&',' AND ')
+ reason = reason.replace('\n','<br>')
+ html += '<br>' + reason
+
+ tooltip = ""
for status in sorted(status_count.keys(), reverse = True):
status_word = db.status_word[status]
tooltip += "%d %s " % (status_count[status], status_word)
@@ -182,20 +192,22 @@ def status_count_box(db, tests, link = None):
return status_precounted_box(db, status_count, link)
-def status_precounted_box(db, status_count, link = None):
+def status_precounted_box(db, box_data, link = None):
"""
Display a ratio of total number of GOOD tests
to total number of all tests in the group of tests.
More info (e.g. 10 GOOD, 2 WARN, 3 FAIL) is in tooltips
- """
+ """
+ status_count = box_data.status_count
if not status_count:
return box(None, None)
shade = shade_from_status_count(status_count)
- html,tooltip = status_html(db, status_count, shade)
+ html,tooltip = status_html(db, box_data, shade)
precounted_box = box(html, shade, False, link, tooltip)
return precounted_box
+
def print_table(matrix):
"""
matrix: list of lists of boxes, giving a matrix of data
diff --git a/tko/frontend.py b/tko/frontend.py
index 0861bcbd..d496fe9d 100755
--- a/tko/frontend.py
+++ b/tko/frontend.py
@@ -20,11 +20,12 @@ class status_cell:
def __init__(self):
# Count is a dictionary: status -> count of tests with status
self.status_count = {}
+ self.reasons_list = []
self.job_tag = None
self.job_tag_count = 0
- def add(self, status, count, job_tags):
+ def add(self, status, count, job_tags, reasons = None):
assert count > 0
self.job_tag = job_tags
@@ -33,21 +34,31 @@ class status_cell:
self.job_tag = None
self.status_count[status] = count
+ ### status == 6 means 'GOOD'
+ if status != 6:
+ ## None implies sorting problems and extra CRs in a cell
+ if reasons:
+ self.reasons_list.append(reasons)
class status_data:
- def __init__(self, sql_rows, x_field, y_field):
+ def __init__(self, sql_rows, x_field, y_field, query_reasons = False):
data = {}
y_values = set()
# Walk through the query, filing all results by x, y info
- for (x, y, status, count, job_tags) in sql_rows:
+ for row in sql_rows:
+ if query_reasons:
+ (x,y, status, count, job_tags, reasons) = row
+ else:
+ (x,y, status, count, job_tags) = row
+ reasons = None
if not data.has_key(x):
data[x] = {}
if not data[x].has_key(y):
y_values.add(y)
data[x][y] = status_cell()
- data[x][y].add(status, count, job_tags)
+ data[x][y].add(status, count, job_tags, reasons)
# 2-d hash of data - [x-value][y-value]
self.data = data
@@ -61,18 +72,24 @@ class status_data:
raise db.MySQLTooManyRows(msg)
-def get_matrix_data(db_obj, x_axis, y_axis, where = None):
+def get_matrix_data(db_obj, x_axis, y_axis, where = None,
+ query_reasons = False):
# Searches on the test_view table - x_axis and y_axis must both be
# column names in that table.
x_field = test_view_field_dict[x_axis]
y_field = test_view_field_dict[y_axis]
- fields = ( '%s, %s, status, COUNT(status), ' +
- 'LEFT(GROUP_CONCAT(job_tag), 100)' # limit what's returned
- ) % (x_field, y_field)
+ query_fields_list = [x_field, y_field, 'status','COUNT(status)']
+ query_fields_list.append("LEFT(GROUP_CONCAT(job_tag),100)")
+ if query_reasons:
+ query_fields_list.append(
+ "LEFT(GROUP_CONCAT(DISTINCT reason SEPARATOR '|'),500)"
+ )
+ fields = ','.join(query_fields_list)
+
group_by = '%s, %s, status' % (x_field, y_field)
rows = db_obj.select(fields, 'test_view',
where=where, group_by=group_by, max_rows = MAX_RECORDS)
- return status_data(rows, x_field, y_field)
+ return status_data(rows, x_field, y_field, query_reasons)
# Dictionary used simply for fast lookups from short reference names for users
@@ -91,6 +108,7 @@ test_view_field_dict = {
'time_daily' : 'DATE(test_finished_time)'
}
+
def smart_sort(list, field):
if field == 'kernel_printable':
def kernel_encode(kernel):
@@ -130,7 +148,8 @@ class group:
def tests(self, where = {}):
values = [self.name]
- sql = 't inner join machines m on m.machine_idx=t.machine_idx where m.machine_group=%s'
+ sql = 't inner join machines m on m.machine_idx=t.machine_idx'
+ sql += ' where m.machine_group=%s'
for key in where.keys():
sql += ' and %s=%%s' % key
values.append(where[key])
@@ -178,7 +197,8 @@ class test:
fields = ['test_idx', 'job_idx', 'test', 'subdir',
'kernel_idx', 'status', 'reason', 'machine_idx']
tests = []
- for row in db.select(','.join(fields), 'tests', where, wherein,distinct):
+ for row in db.select(','.join(fields), 'tests', where,
+ wherein,distinct):
tests.append(klass(db, *row))
return tests
@@ -192,7 +212,8 @@ class test:
return [klass(db, *row) for row in rows]
- def __init__(self, db, test_idx, job_idx, testname, subdir, kernel_idx, status_num, reason, machine_idx):
+ def __init__(self, db, test_idx, job_idx, testname, subdir, kernel_idx,
+ status_num, reason, machine_idx):
self.idx = test_idx
self.job = job(db, job_idx)
self.testname = testname