OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Utilities for managing I-Spy test results in Google Cloud Storage.""" | 5 """Utilities for managing I-Spy test results in Google Cloud Storage.""" |
6 | 6 |
7 import collections | 7 import collections |
8 import itertools | 8 import itertools |
9 import json | 9 import json |
10 import os | 10 import os |
11 import sys | 11 import sys |
12 | 12 |
13 import image_tools | 13 import image_tools |
14 | 14 |
15 | 15 |
| 16 _INVALID_EXPECTATION_CHARS = ['/', '\\', ' ', '"', '\''] |
| 17 |
| 18 |
| 19 def IsValidExpectationName(expectation_name): |
| 20 return not any(c in _INVALID_EXPECTATION_CHARS for c in expectation_name) |
| 21 |
| 22 |
16 def GetExpectationPath(expectation, file_name=''): | 23 def GetExpectationPath(expectation, file_name=''): |
17 """Get the path to a test file in the given test run and expectation. | 24 """Get the path to a test file in the given test run and expectation. |
18 | 25 |
19 Args: | 26 Args: |
20 expectation: name of the expectation. | 27 expectation: name of the expectation. |
21 file_name: name of the file. | 28 file_name: name of the file. |
22 | 29 |
23 Returns: | 30 Returns: |
24 the path as a string relative to the bucket. | 31 the path as a string relative to the bucket. |
25 """ | 32 """ |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 def GenerateExpectation(self, expectation, images): | 96 def GenerateExpectation(self, expectation, images): |
90 """Creates and uploads an expectation to GS from a set of images and name. | 97 """Creates and uploads an expectation to GS from a set of images and name. |
91 | 98 |
92 This method generates a mask from the uploaded images, then | 99 This method generates a mask from the uploaded images, then |
93 uploads the mask and first of the images to GS as a expectation. | 100 uploads the mask and first of the images to GS as a expectation. |
94 | 101 |
95 Args: | 102 Args: |
96 expectation: name for this expectation, any existing expectation with the | 103 expectation: name for this expectation, any existing expectation with the |
97 name will be replaced. | 104 name will be replaced. |
98 images: a list of RGB encoded PIL.Images | 105 images: a list of RGB encoded PIL.Images |
| 106 |
| 107 Raises: |
| 108 ValueError: if the expectation name is invalid. |
99 """ | 109 """ |
| 110 if not IsValidExpectationName(expectation): |
| 111 raise ValueError("Expectation name contains an illegal character: %s." % |
| 112 str(_INVALID_EXPECTATION_CHARS)) |
| 113 |
100 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7) | 114 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7) |
101 self.UploadImage( | 115 self.UploadImage( |
102 GetExpectationPath(expectation, 'expected.png'), images[0]) | 116 GetExpectationPath(expectation, 'expected.png'), images[0]) |
103 self.UploadImage(GetExpectationPath(expectation, 'mask.png'), mask) | 117 self.UploadImage(GetExpectationPath(expectation, 'mask.png'), mask) |
104 | 118 |
105 def PerformComparison(self, test_run, expectation, actual): | 119 def PerformComparison(self, test_run, expectation, actual): |
106 """Runs an image comparison, and uploads discrepancies to GS. | 120 """Runs an image comparison, and uploads discrepancies to GS. |
107 | 121 |
108 Args: | 122 Args: |
109 test_run: the name of the test_run. | 123 test_run: the name of the test_run. |
110 expectation: the name of the expectation to use for comparison. | 124 expectation: the name of the expectation to use for comparison. |
111 actual: an RGB-encoded PIL.Image that is the actual result. | 125 actual: an RGB-encoded PIL.Image that is the actual result. |
112 | 126 |
113 Raises: | 127 Raises: |
114 cloud_bucket.NotFoundError: if the given expectation is not found. | 128 cloud_bucket.NotFoundError: if the given expectation is not found. |
| 129 ValueError: if the expectation name is invalid. |
115 """ | 130 """ |
| 131 if not IsValidExpectationName(expectation): |
| 132 raise ValueError("Expectation name contains an illegal character: %s." % |
| 133 str(_INVALID_EXPECTATION_CHARS)) |
| 134 |
116 expectation_tuple = self.GetExpectation(expectation) | 135 expectation_tuple = self.GetExpectation(expectation) |
117 if not image_tools.SameImage( | 136 if not image_tools.SameImage( |
118 actual, expectation_tuple.expected, mask=expectation_tuple.mask): | 137 actual, expectation_tuple.expected, mask=expectation_tuple.mask): |
119 self.UploadImage( | 138 self.UploadImage( |
120 GetFailurePath(test_run, expectation, 'actual.png'), actual) | 139 GetFailurePath(test_run, expectation, 'actual.png'), actual) |
121 diff, diff_pxls = image_tools.VisualizeImageDifferences( | 140 diff, diff_pxls = image_tools.VisualizeImageDifferences( |
122 expectation_tuple.expected, actual, mask=expectation_tuple.mask) | 141 expectation_tuple.expected, actual, mask=expectation_tuple.mask) |
123 self.UploadImage(GetFailurePath(test_run, expectation, 'diff.png'), diff) | 142 self.UploadImage(GetFailurePath(test_run, expectation, 'diff.png'), diff) |
124 self.cloud_bucket.UploadFile( | 143 self.cloud_bucket.UploadFile( |
125 GetFailurePath(test_run, expectation, 'info.txt'), | 144 GetFailurePath(test_run, expectation, 'info.txt'), |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 self.cloud_bucket.RemoveFile(path) | 210 self.cloud_bucket.RemoveFile(path) |
192 | 211 |
193 def GenerateExpectationPinkOut(self, expectation, images, pint_out, rgb): | 212 def GenerateExpectationPinkOut(self, expectation, images, pint_out, rgb): |
194 """Uploads an ispy-test to GS with the pink_out workaround. | 213 """Uploads an ispy-test to GS with the pink_out workaround. |
195 | 214 |
196 Args: | 215 Args: |
197 expectation: the name of the expectation to be uploaded. | 216 expectation: the name of the expectation to be uploaded. |
198 images: a json encoded list of base64 encoded png images. | 217 images: a json encoded list of base64 encoded png images. |
199 pink_out: an image. | 218 pink_out: an image. |
200 RGB: a json list representing the RGB values of a color to mask out. | 219 RGB: a json list representing the RGB values of a color to mask out. |
| 220 |
| 221 Raises: |
| 222 ValueError: if expectation name is invalid. |
201 """ | 223 """ |
| 224 if not IsValidExpectationName(expectation): |
| 225 raise ValueError("Expectation name contains an illegal character: %s." % |
| 226 str(_INVALID_EXPECTATION_CHARS)) |
| 227 |
202 # convert the pink_out into a mask | 228 # convert the pink_out into a mask |
203 black = (0, 0, 0, 255) | 229 black = (0, 0, 0, 255) |
204 white = (255, 255, 255, 255) | 230 white = (255, 255, 255, 255) |
205 pink_out.putdata( | 231 pink_out.putdata( |
206 [black if px == (rgb[0], rgb[1], rgb[2], 255) else white | 232 [black if px == (rgb[0], rgb[1], rgb[2], 255) else white |
207 for px in pink_out.getdata()]) | 233 for px in pink_out.getdata()]) |
208 mask = image_tools.CreateMask(images) | 234 mask = image_tools.CreateMask(images) |
209 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7) | 235 mask = image_tools.InflateMask(image_tools.CreateMask(images), 7) |
210 combined_mask = image_tools.AddMasks([mask, pink_out]) | 236 combined_mask = image_tools.AddMasks([mask, pink_out]) |
211 self.UploadImage(GetExpectationPath(expectation, 'expected.png'), images[0]) | 237 self.UploadImage(GetExpectationPath(expectation, 'expected.png'), images[0]) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 280 |
255 Args: | 281 Args: |
256 prefix: the prefix to filter files in GS by. | 282 prefix: the prefix to filter files in GS by. |
257 | 283 |
258 Returns: | 284 Returns: |
259 a list containing urls to all objects that started with | 285 a list containing urls to all objects that started with |
260 the prefix. | 286 the prefix. |
261 """ | 287 """ |
262 return self.cloud_bucket.GetAllPaths(prefix) | 288 return self.cloud_bucket.GetAllPaths(prefix) |
263 | 289 |
OLD | NEW |