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

Side by Side Diff: chrome/test/functional/ispy/common/ispy_utils.py

Issue 222873002: Remove pyauto tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: sync Created 6 years, 8 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 | Annotate | Revision Log
OLDNEW
(Empty)
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 """Internal utilities for managing I-Spy test results in Google Cloud Storage.
6
7 See the ispy.ispy_api module for the external API.
8 """
9
10 import collections
11 import itertools
12 import json
13 import os
14 import sys
15
16 import image_tools
17
18
19 _INVALID_EXPECTATION_CHARS = ['/', '\\', ' ', '"', '\'']
20
21
22 def IsValidExpectationName(expectation_name):
23 return not any(c in _INVALID_EXPECTATION_CHARS for c in expectation_name)
24
25
26 def GetExpectationPath(expectation, file_name=''):
27 """Get the path to a test file in the given test run and expectation.
28
29 Args:
30 expectation: name of the expectation.
31 file_name: name of the file.
32
33 Returns:
34 the path as a string relative to the bucket.
35 """
36 return 'expectations/%s/%s' % (expectation, file_name)
37
38
39 def GetFailurePath(test_run, expectation, file_name=''):
40 """Get the path to a failure file in the given test run and test.
41
42 Args:
43 test_run: name of the test run.
44 expectation: name of the expectation.
45 file_name: name of the file.
46
47 Returns:
48 the path as a string relative to the bucket.
49 """
50 return GetTestRunPath(test_run, '%s/%s' % (expectation, file_name))
51
52
53 def GetTestRunPath(test_run, file_name=''):
54 """Get the path to a the given test run.
55
56 Args:
57 test_run: name of the test run.
58 file_name: name of the file.
59
60 Returns:
61 the path as a string relative to the bucket.
62 """
63 return 'failures/%s/%s' % (test_run, file_name)
64
65
66 class ISpyUtils(object):
67 """Utility functions for working with an I-Spy google storage bucket."""
68
69 def __init__(self, cloud_bucket):
70 """Initialize with a cloud bucket instance to supply GS functionality.
71
72 Args:
73 cloud_bucket: An object implementing the cloud_bucket.BaseCloudBucket
74 interface.
75 """
76 self.cloud_bucket = cloud_bucket
77
78 def UploadImage(self, full_path, image):
79 """Uploads an image to a location in GS.
80
81 Args:
82 full_path: the path to the file in GS including the file extension.
83 image: a RGB PIL.Image to be uploaded.
84 """
85 self.cloud_bucket.UploadFile(
86 full_path, image_tools.EncodePNG(image), 'image/png')
87
88 def DownloadImage(self, full_path):
89 """Downloads an image from a location in GS.
90
91 Args:
92 full_path: the path to the file in GS including the file extension.
93
94 Returns:
95 The downloaded RGB PIL.Image.
96
97 Raises:
98 cloud_bucket.NotFoundError: if the path to the image is not valid.
99 """
100 return image_tools.DecodePNG(self.cloud_bucket.DownloadFile(full_path))
101
102 def UpdateImage(self, full_path, image):
103 """Updates an existing image in GS, preserving permissions and metadata.
104
105 Args:
106 full_path: the path to the file in GS including the file extension.
107 image: a RGB PIL.Image.
108 """
109 self.cloud_bucket.UpdateFile(full_path, image_tools.EncodePNG(image))
110
111 def GenerateExpectation(self, expectation, images):
112 """Creates and uploads an expectation to GS from a set of images and name.
113
114 This method generates a mask from the uploaded images, then
115 uploads the mask and first of the images to GS as a expectation.
116
117 Args:
118 expectation: name for this expectation, any existing expectation with the
119 name will be replaced.
120 images: a list of RGB encoded PIL.Images
121
122 Raises:
123 ValueError: if the expectation name is invalid.
124 """
125 if not IsValidExpectationName(expectation):
126 raise ValueError("Expectation name contains an illegal character: %s." %
127 str(_INVALID_EXPECTATION_CHARS))
128
129 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7)
130 self.UploadImage(
131 GetExpectationPath(expectation, 'expected.png'), images[0])
132 self.UploadImage(GetExpectationPath(expectation, 'mask.png'), mask)
133
134 def PerformComparison(self, test_run, expectation, actual):
135 """Runs an image comparison, and uploads discrepancies to GS.
136
137 Args:
138 test_run: the name of the test_run.
139 expectation: the name of the expectation to use for comparison.
140 actual: an RGB-encoded PIL.Image that is the actual result.
141
142 Raises:
143 cloud_bucket.NotFoundError: if the given expectation is not found.
144 ValueError: if the expectation name is invalid.
145 """
146 if not IsValidExpectationName(expectation):
147 raise ValueError("Expectation name contains an illegal character: %s." %
148 str(_INVALID_EXPECTATION_CHARS))
149
150 expectation_tuple = self.GetExpectation(expectation)
151 if not image_tools.SameImage(
152 actual, expectation_tuple.expected, mask=expectation_tuple.mask):
153 self.UploadImage(
154 GetFailurePath(test_run, expectation, 'actual.png'), actual)
155 diff, diff_pxls = image_tools.VisualizeImageDifferences(
156 expectation_tuple.expected, actual, mask=expectation_tuple.mask)
157 self.UploadImage(GetFailurePath(test_run, expectation, 'diff.png'), diff)
158 self.cloud_bucket.UploadFile(
159 GetFailurePath(test_run, expectation, 'info.txt'),
160 json.dumps({
161 'different_pixels': diff_pxls,
162 'fraction_different':
163 diff_pxls / float(actual.size[0] * actual.size[1])}),
164 'application/json')
165
166 def GetExpectation(self, expectation):
167 """Returns the given expectation from GS.
168
169 Args:
170 expectation: the name of the expectation to get.
171
172 Returns:
173 A named tuple: 'Expectation', containing two images: expected and mask.
174
175 Raises:
176 cloud_bucket.NotFoundError: if the test is not found in GS.
177 """
178 Expectation = collections.namedtuple('Expectation', ['expected', 'mask'])
179 return Expectation(self.DownloadImage(GetExpectationPath(expectation,
180 'expected.png')),
181 self.DownloadImage(GetExpectationPath(expectation,
182 'mask.png')))
183
184 def ExpectationExists(self, expectation):
185 """Returns whether the given expectation exists in GS.
186
187 Args:
188 expectation: the name of the expectation to check.
189
190 Returns:
191 A boolean indicating whether the test exists.
192 """
193 expected_image_exists = self.cloud_bucket.FileExists(
194 GetExpectationPath(expectation, 'expected.png'))
195 mask_image_exists = self.cloud_bucket.FileExists(
196 GetExpectationPath(expectation, 'mask.png'))
197 return expected_image_exists and mask_image_exists
198
199 def FailureExists(self, test_run, expectation):
200 """Returns whether a failure for the expectation exists for the given run.
201
202 Args:
203 test_run: the name of the test_run.
204 expectation: the name of the expectation that failed.
205
206 Returns:
207 A boolean indicating whether the failure exists.
208 """
209 actual_image_exists = self.cloud_bucket.FileExists(
210 GetFailurePath(test_run, expectation, 'actual.png'))
211 test_exists = self.ExpectationExists(expectation)
212 info_exists = self.cloud_bucket.FileExists(
213 GetFailurePath(test_run, expectation, 'info.txt'))
214 return test_exists and actual_image_exists and info_exists
215
216 def RemoveExpectation(self, expectation):
217 """Removes an expectation and all associated failures with that test.
218
219 Args:
220 expectation: the name of the expectation to remove.
221 """
222 test_paths = self.cloud_bucket.GetAllPaths(
223 GetExpectationPath(expectation))
224 for path in test_paths:
225 self.cloud_bucket.RemoveFile(path)
226
227 def GenerateExpectationPinkOut(self, expectation, images, pint_out, rgb):
228 """Uploads an ispy-test to GS with the pink_out workaround.
229
230 Args:
231 expectation: the name of the expectation to be uploaded.
232 images: a json encoded list of base64 encoded png images.
233 pink_out: an image.
234 RGB: a json list representing the RGB values of a color to mask out.
235
236 Raises:
237 ValueError: if expectation name is invalid.
238 """
239 if not IsValidExpectationName(expectation):
240 raise ValueError("Expectation name contains an illegal character: %s." %
241 str(_INVALID_EXPECTATION_CHARS))
242
243 # convert the pink_out into a mask
244 black = (0, 0, 0, 255)
245 white = (255, 255, 255, 255)
246 pink_out.putdata(
247 [black if px == (rgb[0], rgb[1], rgb[2], 255) else white
248 for px in pink_out.getdata()])
249 mask = image_tools.CreateMask(images)
250 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7)
251 combined_mask = image_tools.AddMasks([mask, pink_out])
252 self.UploadImage(GetExpectationPath(expectation, 'expected.png'), images[0])
253 self.UploadImage(GetExpectationPath(expectation, 'mask.png'), combined_mask)
254
255 def RemoveFailure(self, test_run, expectation):
256 """Removes a failure from GS.
257
258 Args:
259 test_run: the name of the test_run.
260 expectation: the expectation on which the failure to be removed occured.
261 """
262 failure_paths = self.cloud_bucket.GetAllPaths(
263 GetFailurePath(test_run, expectation))
264 for path in failure_paths:
265 self.cloud_bucket.RemoveFile(path)
266
267 def GetFailure(self, test_run, expectation):
268 """Returns a given test failure's expected, diff, and actual images.
269
270 Args:
271 test_run: the name of the test_run.
272 expectation: the name of the expectation the result corresponds to.
273
274 Returns:
275 A named tuple: Failure containing three images: expected, diff, and
276 actual.
277
278 Raises:
279 cloud_bucket.NotFoundError: if the result is not found in GS.
280 """
281 expected = self.DownloadImage(
282 GetExpectationPath(expectation, 'expected.png'))
283 actual = self.DownloadImage(
284 GetFailurePath(test_run, expectation, 'actual.png'))
285 diff = self.DownloadImage(
286 GetFailurePath(test_run, expectation, 'diff.png'))
287 info = json.loads(self.cloud_bucket.DownloadFile(
288 GetFailurePath(test_run, expectation, 'info.txt')))
289 Failure = collections.namedtuple(
290 'Failure', ['expected', 'diff', 'actual', 'info'])
291 return Failure(expected, diff, actual, info)
292
293 def GetAllPaths(self, prefix):
294 """Gets urls to all files in GS whose path starts with a given prefix.
295
296 Args:
297 prefix: the prefix to filter files in GS by.
298
299 Returns:
300 a list containing urls to all objects that started with
301 the prefix.
302 """
303 return self.cloud_bucket.GetAllPaths(prefix)
304
OLDNEW
« no previous file with comments | « chrome/test/functional/ispy/common/image_tools_unittest.py ('k') | chrome/test/functional/ispy/common/ispy_utils_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698