# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import re

from telemetry.testing import serially_executed_browser_test_case
from telemetry.util import screenshot
from typ import json_results

from gpu_tests import exception_formatter
from gpu_tests import gpu_helper

_START_BROWSER_RETRIES = 3

ResultType = json_results.ResultType

# Please expand the following lists when we expand to new bot configs.
_SUPPORTED_WIN_VERSIONS = ['win7', 'win10']
_SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION = ['win10']
_SUPPORTED_WIN_GPU_VENDORS = [0x8086, 0x10de, 0x1002]
_SUPPORTED_WIN_INTEL_GPUS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS = [0x5912]

class GpuIntegrationTest(
    serially_executed_browser_test_case.SeriallyExecutedBrowserTestCase):

  _cached_expectations = None
  _also_run_disabled_tests = False
  _disable_log_uploads = False

  # Several of the tests in this directory need to be able to relaunch
  # the browser on demand with a new set of command line arguments
  # than were originally specified. To enable this, the necessary
  # static state is hoisted here.

  # We store a deep copy of the original browser finder options in
  # order to be able to restart the browser multiple times, with a
  # different set of command line arguments each time.
  _original_finder_options = None

  # We keep track of the set of command line arguments used to launch
  # the browser most recently in order to figure out whether we need
  # to relaunch it, if a new pixel test requires a different set of
  # arguments.
  _last_launched_browser_args = set()

  @classmethod
  def SetUpProcess(cls):
    super(GpuIntegrationTest, cls).SetUpProcess()
    cls._original_finder_options = cls._finder_options.Copy()

  @classmethod
  def AddCommandlineArgs(cls, parser):
    """Adds command line arguments understood by the test harness.

    Subclasses overriding this method must invoke the superclass's
    version!"""
    parser.add_option(
      '--disable-log-uploads',
      dest='disable_log_uploads',
      action='store_true', default=False,
      help='Disables uploads of logs to cloud storage')

  @classmethod
  def CustomizeBrowserArgs(cls, browser_args):
    """Customizes the browser's command line arguments.

    NOTE that redefining this method in subclasses will NOT do what
    you expect! Do not attempt to redefine this method!
    """
    if not browser_args:
      browser_args = []
    cls._finder_options = cls._original_finder_options.Copy()
    browser_options = cls._finder_options.browser_options

    # If requested, disable uploading of failure logs to cloud storage.
    if cls._disable_log_uploads:
      browser_options.logs_cloud_bucket = None

    # A non-sandboxed, 15-seconds-delayed gpu process is currently running in
    # the browser to collect gpu info. A command line switch is added here to
    # skip this gpu process for all gpu integration tests to prevent any
    # interference with the test results.
    browser_args.append(
      '--disable-gpu-process-for-dx12-vulkan-info-collection')

    # Append the new arguments.
    browser_options.AppendExtraBrowserArgs(browser_args)
    cls._last_launched_browser_args = set(browser_args)
    cls.SetBrowserOptions(cls._finder_options)

  @classmethod
  def RestartBrowserIfNecessaryWithArgs(cls, browser_args, force_restart=False):
    if not browser_args:
      browser_args = []
    elif '--disable-gpu' in browser_args:
      # Some platforms require GPU process, so browser fails to launch with
      # --disable-gpu mode, therefore, even test expectations fail to evaluate.
      browser_args = list(browser_args)
      os_name = cls.browser.platform.GetOSName()
      if os_name == 'android' or os_name == 'chromeos':
        browser_args.remove('--disable-gpu')
    if force_restart or set(browser_args) != cls._last_launched_browser_args:
      logging.info('Restarting browser with arguments: ' + str(browser_args))
      cls.StopBrowser()
      cls.CustomizeBrowserArgs(browser_args)
      cls.StartBrowser()

  @classmethod
  def RestartBrowserWithArgs(cls, browser_args):
    cls.RestartBrowserIfNecessaryWithArgs(browser_args, force_restart=True)

  # The following is the rest of the framework for the GPU integration tests.

  @classmethod
  def GenerateTestCases__RunGpuTest(cls, options):
    cls._disable_log_uploads = options.disable_log_uploads
    for test_name, url, args in cls.GenerateGpuTests(options):
      yield test_name, (url, test_name, args)

  @classmethod
  def StartBrowser(cls):
    # We still need to retry the browser's launch even though
    # desktop_browser_finder does so too, because it wasn't possible
    # to push the fetch of the first tab into the lower retry loop
    # without breaking Telemetry's unit tests, and that hook is used
    # to implement the gpu_integration_test_unittests.
    for x in range(1, _START_BROWSER_RETRIES+1):  # Index from 1 instead of 0.
      try:
        super(GpuIntegrationTest, cls).StartBrowser()
        cls.tab = cls.browser.tabs[0]
        return
      except Exception:
        logging.exception('Browser start failed (attempt %d of %d). Backtrace:',
                          x, _START_BROWSER_RETRIES)
        # If we are on the last try and there is an exception take a screenshot
        # to try and capture more about the browser failure and raise
        if x == _START_BROWSER_RETRIES:
          url = screenshot.TryCaptureScreenShotAndUploadToCloudStorage(
            cls.platform)
          if url is not None:
            logging.info("GpuIntegrationTest screenshot of browser failure " +
              "located at " + url)
          else:
            logging.warning("GpuIntegrationTest unable to take screenshot.")
        # Stop the browser to make sure it's in an
        # acceptable state to try restarting it.
        if cls.browser:
          cls.StopBrowser()
    # Re-raise the last exception thrown. Only happens if all the retries
    # fail.
    raise

  @classmethod
  def _RestartBrowser(cls, reason):
    logging.warning('Restarting browser due to '+ reason)
    cls.StopBrowser()
    cls.SetBrowserOptions(cls._finder_options)
    cls.StartBrowser()

  def _RunGpuTest(self, url, test_name, *args):
    expected_results, should_retry_on_failure = (
        self.GetExpectationsForTest())
    try:
      # TODO(nednguyen): For some reason the arguments are getting wrapped
      # in another tuple sometimes (like in the WebGL extension tests).
      # Perhaps only if multiple arguments are yielded in the test
      # generator?
      if len(args) == 1 and isinstance(args[0], tuple):
        args = args[0]
      self.RunActualGpuTest(url, *args)
    except Exception:
      if ResultType.Failure in expected_results or should_retry_on_failure:
        if should_retry_on_failure:
          # For robustness, shut down the browser and restart it
          # between flaky test failures, to make sure any state
          # doesn't propagate to the next iteration.
          self._RestartBrowser('flaky test failure')
        else:
          msg = 'Expected exception while running %s' % test_name
          exception_formatter.PrintFormattedException(msg=msg)
          # Even though this is a known failure, the browser might still
          # be in a bad state; for example, certain kinds of timeouts
          # will affect the next test. Restart the browser to prevent
          # these kinds of failures propagating to the next test.
          self._RestartBrowser('expected test failure')
      else:
        # This is not an expected exception or test failure, so print
        # the detail to the console.
        exception_formatter.PrintFormattedException()
        # Symbolize any crash dump (like from the GPU process) that
        # might have happened but wasn't detected above. Note we don't
        # do this for either 'fail' or 'flaky' expectations because
        # there are still quite a few flaky failures in the WebGL test
        # expectations, and since minidump symbolization is slow
        # (upwards of one minute on a fast laptop), symbolizing all the
        # stacks could slow down the tests' running time unacceptably.
        self.browser.LogSymbolizedUnsymbolizedMinidumps(logging.ERROR)
        # This failure might have been caused by a browser or renderer
        # crash, so restart the browser to make sure any state doesn't
        # propagate to the next test iteration.
        self._RestartBrowser('unexpected test failure')
      self.fail()
    else:
      if ResultType.Failure in expected_results:
        logging.warning(
          '%s was expected to fail, but passed.\n', test_name)

  @classmethod
  def GenerateGpuTests(cls, options):
    """Subclasses must implement this to yield (test_name, url, args)
    tuples of tests to run."""
    raise NotImplementedError

  def RunActualGpuTest(self, file_path, *args):
    """Subclasses must override this to run the actual test at the given
    URL. file_path is a path on the local file system that may need to
    be resolved via UrlOfStaticFilePath.
    """
    raise NotImplementedError

  def GetOverlayBotConfig(self):
    """Returns expected bot config for DirectComposition and overlay support.

    This is only meaningful on Windows platform.

    The rules to determine bot config are:
      1) Only win10 or newer supports DirectComposition
      2) Only Intel supports hardware overlays with DirectComposition
      3) Currently the Win/Intel GPU bot supports YUY2 and NV12 overlays
    """
    if self.browser is None:
      raise Exception("Browser doesn't exist")
    system_info = self.browser.GetSystemInfo()
    if system_info is None:
      raise Exception("Browser doesn't support GetSystemInfo")
    gpu = system_info.gpu.devices[0]
    if gpu is None:
      raise Exception("System Info doesn't have a gpu")
    gpu_vendor_id = gpu.vendor_id
    gpu_device_id = gpu.device_id
    os_version = self.browser.platform.GetOSVersionName()
    if os_version is None:
      raise Exception("browser.platform.GetOSVersionName() returns None")
    os_version = os_version.lower()

    config = {
      'direct_composition': False,
      'supports_overlays': False,
      'yuy2_overlay_support': 'NONE',
      'nv12_overlay_support': 'NONE',
    }
    assert os_version in _SUPPORTED_WIN_VERSIONS
    assert gpu_vendor_id in _SUPPORTED_WIN_GPU_VENDORS
    if os_version in _SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION:
      config['direct_composition'] = True
      if gpu_vendor_id == 0x8086:
        config['supports_overlays'] = True
        assert gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS
        if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS:
          config['yuy2_overlay_support'] = 'SCALING'
        if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS:
          config['nv12_overlay_support'] = 'SCALING'
    return config

  @classmethod
  def GenerateTags(cls, finder_options, possible_browser):
    # If no expectations file paths are returned from cls.ExpectationsFiles()
    # then an empty list will be returned from this function. If tags are
    # returned and there are no expectations files, then Typ will raise
    # an exception.
    if not cls.ExpectationsFiles():
      return []
    with possible_browser.BrowserSession(
        finder_options.browser_options) as browser:
      return cls.GetPlatformTags(browser)

  @classmethod
  def GetPlatformTags(cls, browser):
    """This function will take a Browser instance as an argument.
    It will call the super classes implementation of GetPlatformTags() to get
    a list of tags. Then it will add the gpu vendor, gpu device id,
    angle renderer, and command line decoder tags to that list before
    returning it.
    """
    tags = super(GpuIntegrationTest, cls).GetPlatformTags(browser)
    system_info = browser.GetSystemInfo()
    if system_info:
      gpu_info = system_info.gpu
      gpu_vendor = gpu_helper.GetGpuVendorString(gpu_info)
      gpu_device_id = gpu_helper.GetGpuDeviceId(gpu_info)
      # The gpu device id tag will contain both the vendor and device id
      # separated by a '-'.
      try:
        # If the device id is an integer then it will be added as
        # a hexadecimal to the tag
        gpu_device_tag = '%s-0x%x' % (gpu_vendor, gpu_device_id)
      except TypeError:
        # if the device id is not an integer it will be added as
        # a string to the tag.
        gpu_device_tag = '%s-%s' % (gpu_vendor, gpu_device_id)
      angle_renderer = gpu_helper.GetANGLERenderer(gpu_info)
      cmd_decoder = gpu_helper.GetCommandDecoder(gpu_info)
      # all spaces and underscores in the tag will be replaced by dashes
      tags.extend([re.sub('[ _]', '-', tag) for tag in [
          gpu_vendor, gpu_device_tag, angle_renderer, cmd_decoder]])
    # If additional options have been set via '--extra-browser-args' check for
    # those which map to expectation tags. The '_browser_backend' attribute may
    # not exist in unit tests.
    if (hasattr(browser, '_browser_backend') and
        browser._browser_backend.browser_options.extra_browser_args):
      skia_renderer = gpu_helper.GetSkiaRenderer(\
          browser._browser_backend.browser_options.extra_browser_args)
      tags.extend([skia_renderer])
      use_vulkan = gpu_helper.GetVulkan(\
          browser._browser_backend.browser_options.extra_browser_args)
      tags.extend([use_vulkan])
    return tags

  @classmethod
  def _EnsureTabIsAvailable(cls):
    try:
      cls.tab = cls.browser.tabs[0]
    except Exception:
      # restart the browser to make sure a failure in a test doesn't
      # propagate to the next test iteration.
      logging.exception("Failure during browser startup")
      cls._RestartBrowser('failure in setup')
      raise

  def setUp(self):
    self._EnsureTabIsAvailable()

  @staticmethod
  def GetJSONResultsDelimiter():
    return '/'


def LoadAllTestsInModule(module):
  # Just delegates to serially_executed_browser_test_case to reduce the
  # number of imports in other files.
  return serially_executed_browser_test_case.LoadAllTestsInModule(module)
