blob: 820df3c60f3dcaf8d0996457e245bba0dee2fb94 [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Provides the web interface for reporting a graph of traces."""
import json
from google.appengine.ext import ndb
from dashboard import chart_handler
from dashboard import list_tests
from dashboard import short_uri
from dashboard import update_test_suites
from dashboard.models import page_state
class ReportHandler(chart_handler.ChartHandler):
"""URL endpoint for /report page."""
def get(self):
"""Renders the static UI for selecting graphs."""
query_string = self._GetQueryStringForOldUri()
if query_string:
self.redirect('/report?' + query_string)
return
self.RenderStaticHtml('report.html')
def post(self):
"""Gets dynamic data for selecting graphs"""
values = {}
self.GetDynamicVariables(values)
self.response.out.write(json.dumps({
'is_internal_user': values['is_internal_user'],
'login_url': values['login_url'],
'revision_info': values['revision_info'],
'warning_bug': values['warning_bug'],
'warning_message': values['warning_message'],
'xsrf_token': values['xsrf_token'],
'test_suites': update_test_suites.FetchCachedTestSuites(),
}))
def _GetQueryStringForOldUri(self):
"""Gets a new query string if old URI parameters are present.
SID is a hash string generated from a page state dictionary which is
created here from old URI request parameters.
Returns:
A query string if request parameters are from old URI, otherwise None.
"""
masters = self.request.get('masters')
bots = self.request.get('bots')
tests = self.request.get('tests')
checked = self.request.get('checked')
if not (masters and bots and tests):
return None
# Page state is a list of chart state. Chart state is
# a list of pair of test path and selected series which is used
# to generate a chart on /report page.
state = _CreatePageState(masters, bots, tests, checked)
# Replace default separators to remove whitespace.
state_json = json.dumps(state, separators=(',', ':'))
state_id = short_uri.GenerateHash(state_json)
# Save page state.
if not ndb.Key(page_state.PageState, state_id).get():
page_state.PageState(id=state_id, value=state_json).put()
query_string = 'sid=' + state_id
if self.request.get('start_rev'):
query_string += '&start_rev=' + self.request.get('start_rev')
if self.request.get('end_rev'):
query_string += '&end_rev=' + self.request.get('end_rev')
if self.request.get('rev'):
query_string += '&rev=' + self.request.get('rev')
return query_string
def _CreatePageState(masters, bots, tests, checked):
"""Creates a page state dictionary for old URI parameters.
Based on original /report page, each combination of masters, bots, and
tests is a chart; therefor we create a list of chart states for those
combinations.
Args:
masters: A string with comma separated list of masters.
bots: A string with comma separated list of bots.
tests: A string with comma separated list of tests.
checked: A string with comma separated list of checked series.
Returns:
Page state dictionary.
"""
selected_series = []
if checked:
if checked == 'all':
selected_series = ['all']
else:
selected_series = checked.split(',')
masters = masters.split(',')
bots = bots.split(',')
tests = tests.split(',')
test_paths = []
for master in masters:
for bot in bots:
for test in tests:
test_parts = test.split('/')
if len(test_parts) == 1:
first_test_parts = _GetFirstTest(test, master + '/' + bot)
if first_test_parts:
test += '/' + '/'.join(first_test_parts)
if not selected_series:
selected_series.append(first_test_parts[-1])
test_paths.append(master + '/' + bot + '/' + test)
chart_states = []
for path in test_paths:
chart_states.append([[path, selected_series]])
return {
'charts': chart_states
}
def _GetFirstTest(test_suite, bot_path):
"""Gets the first test.
Args:
test_suite: Test suite name.
bot_path: Master and bot name separated by a slash.
Returns:
A list of test path parts of the first test that has rows, otherwise
returns None.
"""
sub_test_tree = list_tests.GetSubTests(test_suite, [bot_path])
test_parts = []
while sub_test_tree:
first_test = sorted(sub_test_tree.keys())[0]
test_parts.append(first_test)
if sub_test_tree[first_test]['has_rows']:
return test_parts
sub_test_tree = sub_test_tree[first_test]['sub_tests']
return None