Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: build/android/render_tests/process_render_test_results.py

Issue 2406593002: Add script to process results from Android render tests. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | build/android/render_tests/render_webpage.html.jinja2 » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright 2016 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 import argparse
8 import logging
9 import os
10 import re
11 import shutil
12 import sys
13 import tempfile
14 from PIL import ImageChops
15 from PIL import Image
16
17 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
18 import devil_chromium
19 from devil.android import device_utils
20 from devil.utils import cmd_helper
21 from pylib.constants import host_paths
22
23 sys.path.append(os.path.abspath(
24 os.path.join(host_paths.DIR_SOURCE_ROOT, 'build')))
25 import find_depot_tools # pylint: disable=import-error,unused-import
26 import download_from_google_storage
27
28 sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'))
29 import jinja2 # pylint: disable=F0401
30
31 _RE_IMAGE_NAME = re.compile(
32 r'(?P<test_class>\w+)\.(?P<description>\w+)\.'
33 r'(?P<device_model>\w+)\.(?P<orientation>port|land)\.png')
34
35 _RENDER_TEST_BASE_URL = 'https://storage.googleapis.com/chromium-render-tests/'
36 _RENDER_TEST_BUCKET = 'gs://chromium-render-tests/'
37
38 _JINJA_TEMPLATE_DIR = os.path.dirname(os.path.abspath(__file__))
39 _JINJA_TEMPLATE_FILENAME = 'render_webpage.html.jinja2'
40
41
42 def _UploadImage(upload_dir, image_file):
43 """Upload image to the render tests GS bucket."""
mikecase (-- gone --) 2016/10/07 20:37:28 Add doc about Return value here. (its just a url t
44 google_storage_path = os.path.join(
45 _RENDER_TEST_BUCKET, upload_dir, os.path.basename(image_file))
46 google_storage_url = os.path.join(
47 _RENDER_TEST_BASE_URL, upload_dir, os.path.basename(image_file))
48 cmd_helper.RunCmd(
49 [download_from_google_storage.GSUTIL_DEFAULT_PATH,
50 'cp', image_file, google_storage_path])
51 return google_storage_url
52
53
54 def _ComputeImageDiff(failure_image, golden_image):
55 """Compute mask showing which pixels are different between two images."""
56 diff_image = ImageChops.difference(failure_image, golden_image)
57 diff_image = diff_image.convert('L')
58 diff_image = diff_image.point(lambda i: 255 if i else 0)
59 return diff_image
60
61
62 def ProcessRenderTestResults(devices, render_results_dir,
63 upload_dir, html_file):
64 """Grabs render results from device and generates webpage displaying results.
65
66 Args:
67 devices: List of DeviceUtils objects to grab results from.
68 render_results_dir: Directory on the devices to look for results. Assumes
69 directory given contains the golden images for the tests and a directory
70 "failures" containing images for failed tests.
71 upload_dir: Directory to upload the render test results to.
72 html_file: File to write the test results to.
73 """
74 results_dict = {}
75
76 temp_dir = None
77 try:
78 temp_dir = tempfile.mkdtemp()
79 for device in devices:
80 device.adb.Pull(render_results_dir, temp_dir)
81
82 failure_dir = os.path.join(temp_dir, 'failures')
83
84 for failure_filename in os.listdir(failure_dir):
85 m = _RE_IMAGE_NAME.match(failure_filename)
86 if not m:
87 continue
88
89 # Check to make sure we have golden image for this failure.
90 golden_file = os.path.join(temp_dir, failure_filename)
91 if not os.path.exists(golden_file):
92 logging.error('Cannot find golden image for %s', failure_filename)
93 continue
94
95 failure_file = os.path.join(failure_dir, failure_filename)
96
97 # Compute image diff between failure and golden.
98 diff_image = _ComputeImageDiff(
99 Image.open(failure_file), Image.open(golden_file))
100 diff_filename = '_diff'.join(
101 os.path.splitext(os.path.basename(failure_file)))
102 diff_file = os.path.join(temp_dir, diff_filename)
103 diff_image.save(diff_file)
104
105 failure_image_url = _UploadImage(upload_dir, failure_file)
106 golden_image_url = _UploadImage(upload_dir, golden_file)
107 diff_image_url = _UploadImage(upload_dir, diff_file)
108
109 test_class = m.group('test_class')
110 device_model = m.group('device_model')
111
112 if test_class not in results_dict:
113 results_dict[test_class] = {}
114
115 if device_model not in results_dict[test_class]:
116 results_dict[test_class][device_model] = []
117
118 results_dict[test_class][device_model].append({
119 'description': m.group('description'),
120 'orientation': m.group('orientation'),
121 'failure_image': failure_image_url,
122 'golden_image': golden_image_url,
123 'diff_image': diff_image_url,
124 })
125
126 jinja2_env = jinja2.Environment(
127 loader=jinja2.FileSystemLoader(_JINJA_TEMPLATE_DIR),
128 trim_blocks=True)
129 template = jinja2_env.get_template(_JINJA_TEMPLATE_FILENAME)
130 processed_template_output = template.render(full_results=results_dict)
131 with open(html_file, "wb") as f:
132 f.write(processed_template_output)
133 finally:
134 if temp_dir:
135 shutil.rmtree(temp_dir)
136
137 def main():
138 parser = argparse.ArgumentParser()
139
140 parser.add_argument('--render-results-dir',
141 required=True,
142 help='Path on device to look for render test images')
143 parser.add_argument('--output-html-file',
144 required=True,
145 help='File to output the results webpage.')
146 parser.add_argument('-d', '--device', dest='devices', action='append',
147 default=[],
148 help='Device to look for render test results on. '
149 'Default is to look on all connected devices.')
150 parser.add_argument('--adb-path', type=os.path.abspath,
151 help='Absolute path to the adb binary to use.')
152 parser.add_argument('--upload-dir',
153 help='Root path to upload files to GS. Recommend this '
154 'be set to a combination of buildername and build '
155 'number for bots.')
156
157 args = parser.parse_args()
158 devil_chromium.Initialize(adb_path=args.adb_path)
159 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=args.devices)
160 ProcessRenderTestResults(
161 devices, args.render_results_dir, args.upload_dir, args.output_html_file)
162
163
164 if __name__ == '__main__':
165 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | build/android/render_tests/render_webpage.html.jinja2 » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698