| # Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import os |
| import random |
| import sys |
| |
| from telemetry.internal.backends.chrome import cast_browser_finder |
| from telemetry.internal.browser import browser_finder |
| from telemetry.internal.browser import browser_finder_exceptions |
| from telemetry.internal.platform import cast_device |
| from telemetry.testing import serially_executed_browser_test_case |
| from telemetry.util import image_util |
| from telemetry.util import rgba_color |
| |
| |
| class ScreenshotTest( |
| serially_executed_browser_test_case.SeriallyExecutedBrowserTestCase): |
| @classmethod |
| def Name(cls): |
| return 'screenshot' |
| |
| @classmethod |
| def SetUpProcess(cls): |
| super(cls, ScreenshotTest).SetUpProcess() |
| cls.SetBrowserOptions(cls._finder_options) |
| cls.StartBrowser() |
| cls.tab = cls.browser.tabs[0] |
| cls._cast_receiver_to_create.SetCastSender(cls.tab) |
| cls.StartCastReceiver() |
| cls.SetStaticServerDirs([os.path.join(os.path.dirname(__file__), 'data')]) |
| |
| @classmethod |
| def StartCastReceiver(cls): |
| """ Navigates sending tab to about:blank and cast to receiver.""" |
| |
| try: |
| # TODO(crbug.com/803104): Note cls._browser_options actually is a |
| # FinderOptions object, and we need to access the real browser_option's |
| # contained inside. |
| cls._cast_receiver_to_create.SetUpEnvironment( |
| cls._browser_options.browser_options) |
| cls.cast_receiver = cls._cast_receiver_to_create.Create() |
| except Exception: |
| cls._cast_receiver_to_create.CleanUpEnvironment() |
| raise |
| |
| @classmethod |
| def SetBrowserOptions(cls, browser_options): |
| """Sets the browser option for the browser to create. |
| |
| Args: |
| browser_options: Browser options object for the browser we want to test. |
| """ |
| cls._browser_options = browser_options |
| if browser_options.local_cast: |
| cls._local_cast = True |
| else: |
| cls._local_cast = False |
| cls._browser_to_create = browser_finder.FindBrowser(browser_options) |
| if not cls._browser_to_create: |
| raise browser_finder_exceptions.BrowserFinderException( |
| 'Cannot find browser of type %s. \n\nAvailable browsers:\n%s\n' % ( |
| browser_options.browser_options.browser_type, |
| '\n'.join(browser_finder.GetAllAvailableBrowserTypes( |
| browser_options)))) |
| |
| cast_devices = cast_device.FindAllAvailableDevices(browser_options) |
| cast_browsers = [] |
| for device in cast_devices: |
| cast_browsers.extend( |
| cast_browser_finder.FindAllAvailableBrowsers( |
| browser_options, device)) |
| cls._cast_receiver_to_create = \ |
| cast_browser_finder.SelectDefaultBrowser(cast_browsers) |
| |
| if not cls.platform: |
| cls.platform = cls._browser_to_create.platform |
| cls.platform.network_controller.Open( |
| browser_options.browser_options.wpr_mode) |
| assert cls.platform == cls._browser_to_create.platform, ( |
| 'All browser launches within same test suite must use browsers on ' |
| 'the same platform') |
| |
| @classmethod |
| def TearDownProcess(cls): |
| """ Tear down the testing logic after running the test cases. |
| This is guaranteed to be called only once for all the tests after the test |
| suite finishes running. |
| """ |
| |
| if cls.browser: |
| cls.StopBrowser() |
| |
| if cls.cast_receiver: |
| cls.StopCastReceiver() |
| |
| @classmethod |
| def StopCastReceiver(cls): |
| assert cls.cast_receiver, 'Cast receiver is not started' |
| try: |
| cls.cast_receiver.Close() |
| cls.cast_receiver = None |
| finally: |
| cls._cast_receiver_to_create.CleanUpEnvironment() |
| |
| def TestFling(self): |
| """Fling a Youtube video to the Cast receiver and confirm that rendering |
| is correctly performed via screenshot.""" |
| self.cast_receiver._browser_backend.FlingVideo( |
| 'https://youtu.be/zBeWNaNWtIM') |
| self.receiver_tab = self.cast_receiver.tabs[0] |
| screenshot = self.receiver_tab.Screenshot(10) |
| logging.warning(screenshot) |
| pixel_value = image_util.GetPixelColor(screenshot, 100, 100) |
| |
| if self._local_cast: |
| # For Cast Core on Linux, no rendering is available yet so the screen |
| # should display the Youtube icon. |
| videoRGB = rgba_color.RgbaColor(40, 40, 40) |
| else: |
| videoRGB = rgba_color.RgbaColor(37, 150, 190) |
| |
| # Allow for off-by-one errors due to color conversion. |
| tolerance = 1 |
| |
| if not videoRGB.IsEqual(pixel_value, tolerance): |
| error_message = ('Color mismatch : expected (%d, %d, %d), ' + |
| 'got (%d, %d, %d)') % ( |
| videoRGB.r, videoRGB.g, videoRGB.b, |
| pixel_value.r, pixel_value.g, pixel_value.b) |
| self.fail(error_message) |
| |
| def TestMirroring(self): |
| """Draw a square of random color on the sending tab, take a screenshot on |
| the Cast receiver and confirm that the colors match.""" |
| |
| canvasRGB = rgba_color.RgbaColor( |
| random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), |
| 255) |
| tab = self.tab |
| tab.action_runner.Navigate(self.UrlOfStaticFilePath('screenshot.html')) |
| tab.EvaluateJavaScript('window.draw({{ red }}, {{ green }}, {{ blue }});', |
| red=canvasRGB.r, |
| green=canvasRGB.g, |
| blue=canvasRGB.b) |
| self.cast_receiver._browser_backend.MirrorTab() |
| self.receiver_tab = self.cast_receiver.tabs[0] |
| |
| ### TODO(crbug/1320089): Investigate issues grabbing a screenshot |
| ### with tab mirroring. |
| # screenshot = self.receiver_tab.Screenshot(10) |
| # pixel_value = image_util.GetPixelColor(screenshot, 0, 0) |
| |
| # # Allow for off-by-one errors due to color conversion. |
| # tolerance = 1 |
| |
| # if not canvasRGB.IsEqual(pixel_value, tolerance): |
| # error_message = ('Color mismatch : expected (%d, %d, %d), ' + |
| # 'got (%d, %d, %d)') % ( |
| # canvasRGB.r, canvasRGB.g, canvasRGB.b, |
| # pixel_value.r, pixel_value.g, pixel_value.b) |
| # self.fail(error_message) |
| |
| |
| def load_tests(loader, tests, pattern): |
| del loader, tests, pattern # Unused. |
| return serially_executed_browser_test_case \ |
| .LoadAllTestsInModule(sys.modules[__name__]) |