blob: f82dc78fea3b0e040a2750aed47df2fb840e151b [file] [log] [blame]
# Copyright 2013 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.
"""Request handler to serve the main_view page."""
import jinja2
import json
import os
import re
import sys
import webapp2
import ispy_api
from common import constants
from common import ispy_utils
import gs_bucket
import views
JINJA = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(views.__file__)),
extensions=['jinja2.ext.autoescape'])
class MainViewHandler(webapp2.RequestHandler):
"""Request handler to serve the main_view page."""
def get(self):
"""Handles a get request to the main_view page.
If the test_run parameter is specified, then a page displaying all of
the failed runs in the test_run will be shown. Otherwise a view listing
all of the test_runs available for viewing will be displayed.
"""
test_run = self.request.get('test_run')
bucket = gs_bucket.GoogleCloudStorageBucket(constants.BUCKET)
ispy = ispy_utils.ISpyUtils(bucket)
# Load the view.
if test_run:
self._GetForTestRun(test_run, ispy)
return
self._GetAllTestRuns(ispy)
def _GetAllTestRuns(self, ispy):
"""Renders a list view of all of the test_runs available in GS.
Args:
ispy: An instance of ispy_api.ISpyApi.
"""
template = JINJA.get_template('list_view.html')
data = {}
max_keys = 1000
marker = 'failures/%s' % self.request.get('marker')
test_runs = list([path.split('/')[1] for path in
ispy.GetAllPaths('failures/', max_keys=max_keys,
marker=marker, delimiter='/')])
base_url = '/?test_run=%s'
next_url = '/?marker=%s' % test_runs[-1]
data['next_url'] = next_url
data['links'] = [(test_run, base_url % test_run) for test_run in test_runs]
self.response.write(template.render(data))
def _GetForTestRun(self, test_run, ispy):
"""Renders a sorted list of failure-rows for a given test_run.
This method will produce a list of failure-rows that are sorted
in descending order by number of different pixels.
Args:
test_run: The name of the test_run to render failure rows from.
ispy: An instance of ispy_api.ISpyApi.
"""
paths = set([path for path in ispy.GetAllPaths('failures/' + test_run)
if path.endswith('actual.png')])
can_rebaseline = ispy_api.ISpyApi(
ispy.cloud_bucket).CanRebaselineToTestRun(test_run)
rows = [self._CreateRow(test_run, path, ispy) for path in paths]
# Function that sorts by the different_pixels field in the failure-info.
def _Sorter(a, b):
return cmp(b['percent_different'],
a['percent_different'])
template = JINJA.get_template('main_view.html')
self.response.write(
template.render({'comparisons': sorted(rows, _Sorter),
'test_run': test_run,
'can_rebaseline': can_rebaseline}))
def _CreateRow(self, test_run, path, ispy):
"""Creates one failure-row.
This method builds a dictionary with the data necessary to display a
failure in the main_view html template.
Args:
test_run: The name of the test_run the failure is in.
path: A path to the failure's actual.png file.
ispy: An instance of ispy_api.ISpyApi.
Returns:
A dictionary with fields necessary to render a failure-row
in the main_view html template.
"""
res = {}
res['expectation'] = path.lstrip('/').split('/')[2]
res['test_run'] = test_run
res['info'] = json.loads(ispy.cloud_bucket.DownloadFile(
ispy_utils.GetFailurePath(res['test_run'], res['expectation'],
'info.txt')))
expected = ispy_utils.GetExpectationPath(
res['expectation'], 'expected.png')
diff = ispy_utils.GetFailurePath(test_run, res['expectation'], 'diff.png')
res['percent_different'] = res['info']['fraction_different'] * 100
res['expected_path'] = expected
res['diff_path'] = diff
res['actual_path'] = path
res['expected'] = ispy.cloud_bucket.GetImageURL(expected)
res['diff'] = ispy.cloud_bucket.GetImageURL(diff)
res['actual'] = ispy.cloud_bucket.GetImageURL(path)
return res