OLD | NEW |
(Empty) | |
| 1 # Copyright 2017 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 import logging |
| 6 import os |
| 7 import random |
| 8 |
| 9 from gpu_tests import gpu_integration_test |
| 10 from gpu_tests import path_util |
| 11 from gpu_tests import screenshot_sync_expectations |
| 12 |
| 13 from telemetry.util import image_util |
| 14 from telemetry.util import rgba_color |
| 15 |
| 16 data_path = os.path.join( |
| 17 path_util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu') |
| 18 |
| 19 class ScreenshotSyncIntegrationTest(gpu_integration_test.GpuIntegrationTest): |
| 20 """Tests that screenshots are properly synchronized with the frame on |
| 21 which they were requested. |
| 22 """ |
| 23 |
| 24 # We store a deep copy of the original browser finder options in |
| 25 # order to be able to restart the browser multiple times, with a |
| 26 # different set of command line arguments each time. |
| 27 _original_finder_options = None |
| 28 |
| 29 # We keep track of the set of command line arguments used to launch |
| 30 # the browser most recently in order to figure out whether we need |
| 31 # to relaunch it, if a new pixel test requires a different set of |
| 32 # arguments. |
| 33 _last_launched_browser_args = set() |
| 34 |
| 35 @classmethod |
| 36 def Name(cls): |
| 37 """The name by which this test is invoked on the command line.""" |
| 38 return 'screenshot_sync' |
| 39 |
| 40 @classmethod |
| 41 def setUpClass(cls): |
| 42 super(cls, ScreenshotSyncIntegrationTest).setUpClass() |
| 43 cls._original_finder_options = cls._finder_options.Copy() |
| 44 cls.CustomizeBrowserArgs([]) |
| 45 cls.StartBrowser() |
| 46 cls.SetStaticServerDirs([data_path]) |
| 47 |
| 48 @classmethod |
| 49 def CustomizeBrowserArgs(cls, browser_args): |
| 50 if not browser_args: |
| 51 browser_args = [] |
| 52 cls._finder_options = cls._original_finder_options.Copy() |
| 53 browser_options = cls._finder_options.browser_options |
| 54 # All tests receive the following options. They aren't recorded in |
| 55 # the _last_launched_browser_args. |
| 56 # |
| 57 # --test-type=gpu is used only to suppress the "Google API Keys are missing" |
| 58 # infobar, which causes flakiness in tests. |
| 59 browser_options.AppendExtraBrowserArgs(['--test-type=gpu']) |
| 60 # Append the new arguments. |
| 61 browser_options.AppendExtraBrowserArgs(browser_args) |
| 62 cls._last_launched_browser_args = set(browser_args) |
| 63 cls.SetBrowserOptions(cls._finder_options) |
| 64 |
| 65 @classmethod |
| 66 def RestartBrowserIfNecessaryWithArgs(cls, browser_args): |
| 67 if not browser_args: |
| 68 browser_args = [] |
| 69 if set(browser_args) != cls._last_launched_browser_args: |
| 70 logging.info('Restarting browser with arguments: ' + str(browser_args)) |
| 71 cls.StopBrowser() |
| 72 cls.CustomizeBrowserArgs(browser_args) |
| 73 cls.StartBrowser() |
| 74 cls.tab = cls.browser.tabs[0] |
| 75 |
| 76 @classmethod |
| 77 def _CreateExpectations(cls): |
| 78 return screenshot_sync_expectations.ScreenshotSyncExpectations() |
| 79 |
| 80 @classmethod |
| 81 def GenerateGpuTests(cls, options): |
| 82 yield('ScreenshotSync_SWRasterWithCanvas', |
| 83 'screenshot_sync_canvas.html', |
| 84 ('--disable-gpu-rasterization')) |
| 85 yield('ScreenshotSync_SWRasterWithDivs', |
| 86 'screenshot_sync_divs.html', |
| 87 ('--disable-gpu-rasterization')) |
| 88 yield('ScreenshotSync_GPURasterWithCanvas', |
| 89 'screenshot_sync_canvas.html', |
| 90 ('--force-gpu-rasterization')) |
| 91 yield('ScreenshotSync_GPURasterWithDivs', |
| 92 'screenshot_sync_divs.html', |
| 93 ('--force-gpu-rasterization')) |
| 94 |
| 95 def _Navigate(self, test_path): |
| 96 url = self.UrlOfStaticFilePath(test_path) |
| 97 # It's crucial to use the action_runner, rather than the tab's |
| 98 # Navigate method directly. It waits for the document ready state |
| 99 # to become interactive or better, avoiding critical race |
| 100 # conditions. |
| 101 self.tab.action_runner.Navigate(url) |
| 102 |
| 103 def _CheckColorMatchAtLocation(self, expectedRGB, screenshot, x, y): |
| 104 pixel_value = image_util.GetPixelColor(screenshot, x, y) |
| 105 if not expectedRGB.IsEqual(pixel_value): |
| 106 error_message = ('Color mismatch at (%d, %d): expected (%d, %d, %d), ' + |
| 107 'got (%d, %d, %d)') % ( |
| 108 x, y, expectedRGB.r, expectedRGB.g, expectedRGB.b, |
| 109 pixel_value.r, pixel_value.g, pixel_value.b) |
| 110 self.fail(error_message) |
| 111 |
| 112 def _CheckScreenshot(self): |
| 113 canvasRGB = rgba_color.RgbaColor(random.randint(0, 255), |
| 114 random.randint(0, 255), |
| 115 random.randint(0, 255), |
| 116 255) |
| 117 tab = self.tab |
| 118 tab.EvaluateJavaScript("window.draw(%d, %d, %d);" % ( |
| 119 canvasRGB.r, canvasRGB.g, canvasRGB.b)) |
| 120 screenshot = tab.Screenshot(5) |
| 121 start_x = 10 |
| 122 start_y = 0 |
| 123 outer_size = 256 |
| 124 skip = 10 |
| 125 for y in range(start_y, outer_size, skip): |
| 126 for x in range(start_x, outer_size, skip): |
| 127 self._CheckColorMatchAtLocation(canvasRGB, screenshot, x, y) |
| 128 |
| 129 def RunActualGpuTest(self, test_path, *args): |
| 130 browser_arg = args[0] |
| 131 self.RestartBrowserIfNecessaryWithArgs([browser_arg]) |
| 132 self._Navigate(test_path) |
| 133 repetitions = 20 |
| 134 for _ in range(0, repetitions): |
| 135 self._CheckScreenshot() |
OLD | NEW |