• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Request handler to serve the main_view page."""
6
7import jinja2
8import json
9import os
10import re
11import sys
12import webapp2
13
14import ispy_api
15from common import constants
16from common import ispy_utils
17
18import gs_bucket
19import views
20
21JINJA = jinja2.Environment(
22    loader=jinja2.FileSystemLoader(os.path.dirname(views.__file__)),
23    extensions=['jinja2.ext.autoescape'])
24
25
26class MainViewHandler(webapp2.RequestHandler):
27  """Request handler to serve the main_view page."""
28
29  def get(self):
30    """Handles a get request to the main_view page.
31
32    If the test_run parameter is specified, then a page displaying all of
33    the failed runs in the test_run will be shown. Otherwise a view listing
34    all of the test_runs available for viewing will be displayed.
35    """
36    test_run = self.request.get('test_run')
37    bucket = gs_bucket.GoogleCloudStorageBucket(constants.BUCKET)
38    ispy = ispy_utils.ISpyUtils(bucket)
39    # Load the view.
40    if test_run:
41      self._GetForTestRun(test_run, ispy)
42      return
43    self._GetAllTestRuns(ispy)
44
45  def _GetAllTestRuns(self, ispy):
46    """Renders a list view of all of the test_runs available in GS.
47
48    Args:
49      ispy: An instance of ispy_api.ISpyApi.
50    """
51    template = JINJA.get_template('list_view.html')
52    data = {}
53    test_runs = set([path.lstrip('/').split('/')[1] for path in
54                    ispy.GetAllPaths('failures/')])
55    base_url = '/?test_run=%s'
56    data['links'] = [(test_run, base_url % test_run) for test_run in test_runs]
57    self.response.write(template.render(data))
58
59  def _GetForTestRun(self, test_run, ispy):
60    """Renders a sorted list of failure-rows for a given test_run.
61
62    This method will produce a list of failure-rows that are sorted
63    in descending order by number of different pixels.
64
65    Args:
66      test_run: The name of the test_run to render failure rows from.
67      ispy: An instance of ispy_api.ISpyApi.
68    """
69    paths = set([path for path in ispy.GetAllPaths('failures/' + test_run)
70                 if path.endswith('actual.png')])
71    can_rebaseline = ispy_api.ISpyApi(
72        ispy.cloud_bucket).CanRebaselineToTestRun(test_run)
73    rows = [self._CreateRow(test_run, path, ispy) for path in paths]
74
75    # Function that sorts by the different_pixels field in the failure-info.
76    def _Sorter(a, b):
77      return cmp(b['percent_different'],
78                 a['percent_different'])
79    template = JINJA.get_template('main_view.html')
80    self.response.write(
81        template.render({'comparisons': sorted(rows, _Sorter),
82                         'test_run': test_run,
83                         'can_rebaseline': can_rebaseline}))
84
85  def _CreateRow(self, test_run, path, ispy):
86    """Creates one failure-row.
87
88    This method builds a dictionary with the data necessary to display a
89    failure in the main_view html template.
90
91    Args:
92      test_run: The name of the test_run the failure is in.
93      path: A path to the failure's actual.png file.
94      ispy: An instance of ispy_api.ISpyApi.
95
96    Returns:
97      A dictionary with fields necessary to render a failure-row
98        in the main_view html template.
99    """
100    res = {}
101    res['expectation'] = path.lstrip('/').split('/')[2]
102    res['test_run'] = test_run
103    res['info'] = json.loads(ispy.cloud_bucket.DownloadFile(
104        ispy_utils.GetFailurePath(res['test_run'], res['expectation'],
105                                  'info.txt')))
106    expected = ispy_utils.GetExpectationPath(
107        res['expectation'], 'expected.png')
108    diff = ispy_utils.GetFailurePath(test_run, res['expectation'], 'diff.png')
109    res['percent_different'] = res['info']['fraction_different'] * 100
110    res['expected_path'] = expected
111    res['diff_path'] = diff
112    res['actual_path'] = path
113    res['expected'] = ispy.cloud_bucket.GetImageURL(expected)
114    res['diff'] = ispy.cloud_bucket.GetImageURL(diff)
115    res['actual'] = ispy.cloud_bucket.GetImageURL(path)
116    return res
117