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 7 import jinja2 8 import json 9 import os 10 import re 11 import sys 12 import webapp2 13 14 import ispy_api 15 from common import constants 16 from common import ispy_utils 17 18 import gs_bucket 19 import views 20 21 JINJA = jinja2.Environment( 22 loader=jinja2.FileSystemLoader(os.path.dirname(views.__file__)), 23 extensions=['jinja2.ext.autoescape']) 24 25 26 class 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 max_keys = 1000 54 marker = 'failures/%s' % self.request.get('marker') 55 test_runs = list([path.split('/')[1] for path in 56 ispy.GetAllPaths('failures/', max_keys=max_keys, 57 marker=marker, delimiter='/')]) 58 base_url = '/?test_run=%s' 59 next_url = '/?marker=%s' % test_runs[-1] 60 data['next_url'] = next_url 61 data['links'] = [(test_run, base_url % test_run) for test_run in test_runs] 62 self.response.write(template.render(data)) 63 64 def _GetForTestRun(self, test_run, ispy): 65 """Renders a sorted list of failure-rows for a given test_run. 66 67 This method will produce a list of failure-rows that are sorted 68 in descending order by number of different pixels. 69 70 Args: 71 test_run: The name of the test_run to render failure rows from. 72 ispy: An instance of ispy_api.ISpyApi. 73 """ 74 paths = set([path for path in ispy.GetAllPaths('failures/' + test_run) 75 if path.endswith('actual.png')]) 76 can_rebaseline = ispy_api.ISpyApi( 77 ispy.cloud_bucket).CanRebaselineToTestRun(test_run) 78 rows = [self._CreateRow(test_run, path, ispy) for path in paths] 79 80 # Function that sorts by the different_pixels field in the failure-info. 81 def _Sorter(a, b): 82 return cmp(b['percent_different'], 83 a['percent_different']) 84 template = JINJA.get_template('main_view.html') 85 self.response.write( 86 template.render({'comparisons': sorted(rows, _Sorter), 87 'test_run': test_run, 88 'can_rebaseline': can_rebaseline})) 89 90 def _CreateRow(self, test_run, path, ispy): 91 """Creates one failure-row. 92 93 This method builds a dictionary with the data necessary to display a 94 failure in the main_view html template. 95 96 Args: 97 test_run: The name of the test_run the failure is in. 98 path: A path to the failure's actual.png file. 99 ispy: An instance of ispy_api.ISpyApi. 100 101 Returns: 102 A dictionary with fields necessary to render a failure-row 103 in the main_view html template. 104 """ 105 res = {} 106 res['expectation'] = path.lstrip('/').split('/')[2] 107 res['test_run'] = test_run 108 res['info'] = json.loads(ispy.cloud_bucket.DownloadFile( 109 ispy_utils.GetFailurePath(res['test_run'], res['expectation'], 110 'info.txt'))) 111 expected = ispy_utils.GetExpectationPath( 112 res['expectation'], 'expected.png') 113 diff = ispy_utils.GetFailurePath(test_run, res['expectation'], 'diff.png') 114 res['percent_different'] = res['info']['fraction_different'] * 100 115 res['expected_path'] = expected 116 res['diff_path'] = diff 117 res['actual_path'] = path 118 res['expected'] = ispy.cloud_bucket.GetImageURL(expected) 119 res['diff'] = ispy.cloud_bucket.GetImageURL(diff) 120 res['actual'] = ispy.cloud_bucket.GetImageURL(path) 121 return res 122