blob: 3d82e239c92ec0dbaf900419665713ad359c12da [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""Implements the coverage tracker dashboard and reporting facilities."""
__author__ = 'phoglund@webrtc.org (Patrik Hoglund)'
import datetime
from google.appengine.api import oauth
from google.appengine.api import users
from google.appengine.ext import db
import webapp2
import gviz_api
class UserNotAuthenticatedException(Exception):
"""Gets thrown if a user is not permitted to store coverage data."""
pass
class CoverageData(db.Model):
"""This represents one coverage report from the build bot."""
date = db.DateTimeProperty(required=True)
line_coverage = db.FloatProperty(required=True)
function_coverage = db.FloatProperty(required=True)
class ShowDashboard(webapp2.RequestHandler):
"""Shows the dashboard page.
The page is shown by grabbing data we have stored previously
in the App Engine database using the AddCoverageData handler.
"""
def get(self):
page_template_filename = 'templates/dashboard_template.html'
# Load the page HTML template.
try:
template_file = open(page_template_filename)
page_template = template_file.read()
template_file.close()
except IOError as exception:
self._show_error_page('Cannot open page template file: %s<br>Details: %s'
% (page_template_filename, exception))
return
coverage_entries = db.GqlQuery('SELECT * '
'FROM CoverageData '
'ORDER BY date ASC')
data = []
for coverage_entry in coverage_entries:
data.append({'date': coverage_entry.date,
'line_coverage': coverage_entry.line_coverage,
'function_coverage': coverage_entry.function_coverage,
})
description = {
'date': ('datetime', 'Date'),
'line_coverage': ('number', 'Line Coverage'),
'function_coverage': ('number', 'Function Coverage')
}
coverage_data = gviz_api.DataTable(description, data)
coverage_json_data = coverage_data.ToJSon(order_by='date')
# Fill in the template with the data and respond:
self.response.write(page_template % vars())
def _show_error_page(self, error_message):
self.response.write('<html><body>%s</body></html>' % error_message)
class AddCoverageData(webapp2.RequestHandler):
"""Used to report coverage data.
The user is required to have obtained an OAuth access token from an
administrator for this application earlier.
"""
def post(self):
try:
self._authenticate_user()
except UserNotAuthenticatedException as exception:
self._show_error_page('Failed to authenticate user: %s' % exception)
return
try:
posix_time = int(self.request.get('date'))
parsed_date = datetime.datetime.fromtimestamp(posix_time)
line_coverage = float(self.request.get('line_coverage'))
function_coverage = float(self.request.get('function_coverage'))
except ValueError as exception:
self._show_error_page('Invalid parameter in request. Details: %s' %
exception)
return
item = CoverageData(date=parsed_date,
line_coverage=line_coverage,
function_coverage=function_coverage)
item.put()
def _authenticate_user(self):
try:
if oauth.is_current_user_admin():
# The user on whose behalf we are acting is indeed an administrator
# of this application, so we're good to go.
return
else:
raise UserNotAuthenticatedException('We are acting on behalf of '
'user %s, but that user is not '
'an administrator.' %
oauth.get_current_user())
except oauth.OAuthRequestError as exception:
raise UserNotAuthenticatedException('Invalid OAuth request: %s' %
exception)
def _show_error_page(self, error_message):
self.response.write('<html><body>%s</body></html>' % error_message)
app = webapp2.WSGIApplication([('/', ShowDashboard),
('/add_coverage_data', AddCoverageData)],
debug=True)