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

Side by Side Diff: content/test/gpu/gpu_tests/pixel_integration_test.py

Issue 2363343002: Ported pixel_test to new gpu_integration_test harness. (Closed)
Patch Set: Update revision for OffscreenCanvasWebGLGreenBox. 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
OLDNEW
(Empty)
1 # Copyright 2016 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 import glob
5 import logging
6 import os
7 import re
8 import sys
9
10 from gpu_tests import cloud_storage_integration_test_base
11 from gpu_tests import pixel_expectations
12 from gpu_tests import pixel_test_pages
13
14 from py_utils import cloud_storage
15 from telemetry.util import image_util
16
17
18 test_data_dir = os.path.abspath(os.path.join(
19 os.path.dirname(__file__), '..', '..', 'data', 'gpu'))
20
21 default_reference_image_dir = os.path.join(test_data_dir, 'gpu_reference')
22
23 test_harness_script = r"""
24 var domAutomationController = {};
25
26 domAutomationController._succeeded = false;
27 domAutomationController._finished = false;
28
29 domAutomationController.setAutomationId = function(id) {}
30
31 domAutomationController.send = function(msg) {
32 domAutomationController._finished = true;
33
34 if(msg.toLowerCase() == "success") {
35 domAutomationController._succeeded = true;
36 } else {
37 domAutomationController._succeeded = false;
38 }
39 }
40
41 window.domAutomationController = domAutomationController;
42 """
43
44
45 class PixelIntegrationTest(
46 cloud_storage_integration_test_base.CloudStorageIntegrationTestBase):
47
48 # We store a deep copy of the original browser finder options in
49 # order to be able to restart the browser multiple times, with a
50 # different set of command line arguments each time.
51 _original_finder_options = None
52
53 # We keep track of the set of command line arguments used to launch
54 # the browser most recently in order to figure out whether we need
55 # to relaunch it, if a new pixel test requires a different set of
56 # arguments.
57 _last_launched_browser_args = set()
58
59 @classmethod
60 def Name(cls):
61 """The name by which this test is invoked on the command line."""
62 return 'pixel'
63
64 @classmethod
65 def setUpClass(cls):
66 super(cls, PixelIntegrationTest).setUpClass()
67 cls._original_finder_options = cls._finder_options.Copy()
68 cls.CustomizeBrowserArgs([])
69 cls.StartBrowser()
70 cls.SetStaticServerDirs([test_data_dir])
71
72 @classmethod
73 def CustomizeBrowserArgs(cls, browser_args):
74 if not browser_args:
75 browser_args = []
76 cls._finder_options = cls._original_finder_options.Copy()
77 browser_options = cls._finder_options.browser_options
78 # All tests receive these options. They aren't recorded in the
79 # _last_launched_browser_args.
80 browser_options.AppendExtraBrowserArgs(['--enable-gpu-benchmarking',
81 '--test-type=gpu'])
82 # Append the new arguments.
83 browser_options.AppendExtraBrowserArgs(browser_args)
84 cls._last_launched_browser_args = set(browser_args)
85 cls.SetBrowserOptions(cls._finder_options)
86
87 @classmethod
88 def RestartBrowserIfNecessaryWithArgs(cls, browser_args):
89 if not browser_args:
90 browser_args = []
91 if set(browser_args) != cls._last_launched_browser_args:
92 logging.warning('Restarting browser with arguments: ' + str(browser_args))
93 cls.StopBrowser()
94 cls.ResetGpuInfo()
95 cls.CustomizeBrowserArgs(browser_args)
96 cls.StartBrowser()
97 cls.tab = cls.browser.tabs[0]
98
99 @classmethod
100 def AddCommandlineArgs(cls, parser):
101 super(PixelIntegrationTest, cls).AddCommandlineArgs(parser)
102 parser.add_option(
103 '--reference-dir',
104 help='Overrides the default on-disk location for reference images '
105 '(only used for local testing without a cloud storage account)',
106 default=default_reference_image_dir)
107
108 @classmethod
109 def _CreateExpectations(cls):
110 return pixel_expectations.PixelExpectations()
111
112 @classmethod
113 def GenerateGpuTests(cls, options):
114 cls.SetParsedCommandLineOptions(options)
115 name = 'Pixel'
116 pages = pixel_test_pages.ES2AndES3Pages(name)
117 pages += pixel_test_pages.ExperimentalCanvasFeaturesPages(name)
118 if sys.platform.startswith('darwin'):
119 # TOOD(kbr): replace this with CopyPagesWithNewBrowserArgsAndPrefix,
120 # and removeCopyPagesWithNewBrowserArgsAndSuffix. This renaming
121 # will cause all of the ES3 tests to be run back-to-back,
122 # reducing the number of browser restarts and speeding up the
123 # tests. Note that this will require all the ES3 tests to be
124 # temporarily marked failing on macOS, and is too big a change
125 # to do along with the port to the new harness.
126 pages += pixel_test_pages.CopyPagesWithNewBrowserArgsAndSuffix(
127 pixel_test_pages.ES2AndES3Pages(name),
128 ['--enable-unsafe-es3-apis'], 'ES3')
129 pages += pixel_test_pages.MacSpecificPages(name)
130 for p in pages:
131 yield(p.name, p.url, (p))
132
133 def RunActualGpuTest(self, test_path, *args):
134 page = args[0]
135 # Some pixel tests require non-standard browser arguments. Need to
136 # check before running each page that it can run in the current
137 # browser instance.
138 self.RestartBrowserIfNecessaryWithArgs(page.browser_args)
139 url = self.UrlOfStaticFilePath(test_path)
140 # This property actually comes off the class, not 'self'.
141 tab = self.tab
142 tab.Navigate(url, script_to_evaluate_on_commit=test_harness_script)
143 tab.action_runner.WaitForJavaScriptCondition(
144 'domAutomationController._finished', timeout_in_seconds=300)
145 if not tab.EvaluateJavaScript('domAutomationController._succeeded'):
146 self.fail('page indicated test failure')
147 if not tab.screenshot_supported:
148 self.fail('Browser does not support screenshot capture')
149 screenshot = tab.Screenshot(5)
150 if screenshot is None:
151 self.fail('Could not capture screenshot')
152 dpr = tab.EvaluateJavaScript('window.devicePixelRatio')
153 if page.test_rect:
154 screenshot = image_util.Crop(
155 screenshot, page.test_rect[0] * dpr, page.test_rect[1] * dpr,
156 page.test_rect[2] * dpr, page.test_rect[3] * dpr)
157 if page.expected_colors:
158 # Use expected colors instead of ref images for validation.
159 self._ValidateScreenshotSamples(
160 tab, page.name, screenshot, page.expected_colors, dpr)
161 return
162 image_name = self._UrlToImageName(page.name)
163 if self.GetParsedCommandLineOptions().upload_refimg_to_cloud_storage:
164 if self._ConditionallyUploadToCloudStorage(image_name, page, tab,
165 screenshot):
166 # This is the new reference image; there's nothing to compare against.
167 ref_png = screenshot
168 else:
169 # There was a preexisting reference image, so we might as well
170 # compare against it.
171 ref_png = self._DownloadFromCloudStorage(image_name, page, tab)
172 elif self.GetParsedCommandLineOptions().download_refimg_from_cloud_storage:
173 # This bot doesn't have the ability to properly generate a
174 # reference image, so download it from cloud storage.
175 try:
176 ref_png = self._DownloadFromCloudStorage(image_name, page, tab)
177 except cloud_storage.NotFoundError:
178 # There is no reference image yet in cloud storage. This
179 # happens when the revision of the test is incremented or when
180 # a new test is added, because the trybots are not allowed to
181 # produce reference images, only the bots on the main
182 # waterfalls. Report this as a failure so the developer has to
183 # take action by explicitly suppressing the failure and
184 # removing the suppression once the reference images have been
185 # generated. Otherwise silent failures could happen for long
186 # periods of time.
187 self.fail('Could not find image %s in cloud storage' % image_name)
188 else:
189 # Legacy path using on-disk results.
190 ref_png = self._GetReferenceImage(
191 self.GetParsedCommandLineOptions().reference_dir,
192 image_name, page.revision, screenshot)
193
194 # Test new snapshot against existing reference image
195 if not image_util.AreEqual(ref_png, screenshot, tolerance=page.tolerance):
196 if self.GetParsedCommandLineOptions().test_machine_name:
197 self._UploadErrorImagesToCloudStorage(image_name, screenshot, ref_png)
198 else:
199 self._WriteErrorImages(
200 self.GetParsedCommandLineOptions().generated_dir, image_name,
201 screenshot, ref_png)
202 self.fail('Reference image did not match captured screen')
203
204 def _DeleteOldReferenceImages(self, ref_image_path, cur_revision):
205 if not cur_revision:
206 return
207
208 old_revisions = glob.glob(ref_image_path + "_*.png")
209 for rev_path in old_revisions:
210 m = re.match(r'^.*_(\d+)\.png$', rev_path)
211 if m and int(m.group(1)) < cur_revision:
212 print 'Found deprecated reference image. Deleting rev ' + m.group(1)
213 os.remove(rev_path)
214
215 def _GetReferenceImage(self, img_dir, img_name, cur_revision, screenshot):
216 if not cur_revision:
217 cur_revision = 0
218
219 image_path = os.path.join(img_dir, img_name)
220
221 self._DeleteOldReferenceImages(image_path, cur_revision)
222
223 image_path = image_path + '_v' + str(cur_revision) + '.png'
224
225 try:
226 ref_png = image_util.FromPngFile(image_path)
227 # This can raise a couple of exceptions including IOError and ValueError.
228 except Exception:
229 ref_png = None
230
231 if ref_png is not None:
232 return ref_png
233
234 print ('Reference image not found. Writing tab contents as reference to: ' +
235 image_path)
236
237 self._WriteImage(image_path, screenshot)
238 return screenshot
OLDNEW
« no previous file with comments | « content/test/gpu/gpu_tests/pixel_expectations.py ('k') | content/test/gpu/gpu_tests/pixel_test_pages.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698