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.
5 """Request handler to serve the main_view page."""
15 from common
import constants
16 from common
import ispy_utils
21 JINJA
= jinja2
.Environment(
22 loader
=jinja2
.FileSystemLoader(os
.path
.dirname(views
.__file
__)),
23 extensions
=['jinja2.ext.autoescape'])
26 class MainViewHandler(webapp2
.RequestHandler
):
27 """Request handler to serve the main_view page."""
30 """Handles a get request to the main_view page.
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.
36 test_run
= self
.request
.get('test_run')
37 bucket
= gs_bucket
.GoogleCloudStorageBucket(constants
.BUCKET
)
38 ispy
= ispy_utils
.ISpyUtils(bucket
)
41 self
._GetForTestRun
(test_run
, ispy
)
43 self
._GetAllTestRuns
(ispy
)
45 def _GetAllTestRuns(self
, ispy
):
46 """Renders a list view of all of the test_runs available in GS.
49 ispy: An instance of ispy_api.ISpyApi.
51 template
= JINJA
.get_template('list_view.html')
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
))
64 def _GetForTestRun(self
, test_run
, ispy
):
65 """Renders a sorted list of failure-rows for a given test_run.
67 This method will produce a list of failure-rows that are sorted
68 in descending order by number of different pixels.
71 test_run: The name of the test_run to render failure rows from.
72 ispy: An instance of ispy_api.ISpyApi.
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
]
80 # Function that sorts by the different_pixels field in the failure-info.
82 return cmp(b
['percent_different'],
83 a
['percent_different'])
84 template
= JINJA
.get_template('main_view.html')
86 template
.render({'comparisons': sorted(rows
, _Sorter
),
88 'can_rebaseline': can_rebaseline
}))
90 def _CreateRow(self
, test_run
, path
, ispy
):
91 """Creates one failure-row.
93 This method builds a dictionary with the data necessary to display a
94 failure in the main_view html template.
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.
102 A dictionary with fields necessary to render a failure-row
103 in the main_view html template.
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'],
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
)