# 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.

"""Base classes for a test which uploads results (reference images,
error images) to cloud storage."""

import json
import logging
import os
import re
import subprocess
from subprocess import CalledProcessError

import sys
import tempfile

from py_utils import cloud_storage
from telemetry.util import image_util
from telemetry.util import rgba_color

from gpu_tests import gpu_integration_test

test_data_dir = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..', '..', 'data', 'gpu'))

default_generated_data_dir = os.path.join(test_data_dir, 'generated')

error_image_cloud_storage_bucket = 'chromium-browser-gpu-tests'

chromium_root_dir = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..', '..', '..', '..'))
goldctl_bin = os.path.join(
    chromium_root_dir, 'tools', 'skia_goldctl', 'goldctl')
if sys.platform == 'win32':
  goldctl_bin += '.exe'

SKIA_GOLD_INSTANCE = 'chrome-gpu'

class _ReferenceImageParameters(object):
  def __init__(self):
    # Parameters for cloud storage reference images.
    self.vendor_id = None
    self.device_id = None
    self.vendor_string = None
    self.device_string = None
    self.msaa = False
    self.model_name = None


class CloudStorageIntegrationTestBase(gpu_integration_test.GpuIntegrationTest):
  # This class is abstract; don't warn about the superclass's abstract
  # methods that aren't overridden.
  # pylint: disable=abstract-method

  # This information is class-scoped, so that it can be shared across
  # invocations of tests; but it's zapped every time the browser is
  # restarted with different command line arguments.
  _reference_image_parameters = None

  # The command line options (which are passed to subclasses'
  # GenerateGpuTests) *must* be configured here, via a call to
  # SetParsedCommandLineOptions. If they are not, an error will be
  # raised when running the tests.
  _parsed_command_line_options = None

  _skia_gold_temp_dir = None

  @classmethod
  def SetParsedCommandLineOptions(cls, options):
    cls._parsed_command_line_options = options

  @classmethod
  def GetParsedCommandLineOptions(cls):
    return cls._parsed_command_line_options

  @classmethod
  def AddCommandlineArgs(cls, parser):
    super(CloudStorageIntegrationTestBase, cls).AddCommandlineArgs(parser)
    parser.add_option(
      '--build-revision',
      help='Chrome revision being tested.',
      default="unknownrev")
    parser.add_option(
      '--upload-refimg-to-cloud-storage',
      dest='upload_refimg_to_cloud_storage',
      action='store_true', default=False,
      help='Upload resulting images to cloud storage as reference images')
    parser.add_option(
      '--download-refimg-from-cloud-storage',
      dest='download_refimg_from_cloud_storage',
      action='store_true', default=False,
      help='Download reference images from cloud storage')
    parser.add_option(
      '--refimg-cloud-storage-bucket',
      help='Name of the cloud storage bucket to use for reference images; '
      'required with --upload-refimg-to-cloud-storage and '
      '--download-refimg-from-cloud-storage. Example: '
      '"chromium-gpu-archive/reference-images"')
    parser.add_option(
      '--os-type',
      help='Type of operating system on which the pixel test is being run, '
      'used only to distinguish different operating systems with the same '
      'graphics card. Any value is acceptable, but canonical values are '
      '"win", "mac", and "linux", and probably, eventually, "chromeos" '
      'and "android").',
      default='')
    parser.add_option(
      '--test-machine-name',
      help='Name of the test machine. Specifying this argument causes this '
      'script to upload failure images and diffs to cloud storage directly, '
      'instead of relying on the archive_gpu_pixel_test_results.py script.',
      default='')
    parser.add_option(
      '--generated-dir',
      help='Overrides the default on-disk location for generated test images '
      '(only used for local testing without a cloud storage account)',
      default=default_generated_data_dir)
    parser.add_option(
      '--dont-restore-color-profile-after-test',
      dest='dont_restore_color_profile_after_test',
      action='store_true', default=False,
      help='(Mainly on Mac) don\'t restore the system\'s original color '
      'profile after the test completes; leave the system using the sRGB color '
      'profile. See http://crbug.com/784456.')
    parser.add_option(
      '--review-patch-issue',
      help='For Skia Gold integration. Gerrit issue ID.',
      default='')
    parser.add_option(
      '--review-patch-set',
      help='For Skia Gold integration. Gerrit patch set number.',
      default='')
    parser.add_option(
      '--buildbucket-build-id',
      help='For Skia Gold integration. Buildbucket build ID.',
      default='')
    parser.add_option(
      '--no-skia-gold-failure',
      action='store_true', default=False,
      help='For Skia Gold integration. Always report that the test passed even '
           'if the Skia Gold image comparison reported a failure, but '
           'otherwise perform the same steps as usual.')

  def _CompareScreenshotSamples(self, tab, screenshot, expected_colors,
                                tolerance, device_pixel_ratio,
                                test_machine_name):
    # First scan through the expected_colors and see if there are any scale
    # factor overrides that would preempt the device pixel ratio. This
    # is mainly a workaround for complex tests like the Maps test.
    for expectation in expected_colors:
      if 'scale_factor_overrides' in expectation:
        for override in expectation['scale_factor_overrides']:
          # Require exact matches to avoid confusion, because some
          # machine models and names might be subsets of others
          # (e.g. Nexus 5 vs Nexus 5X).
          if ('device_type' in override and
              (tab.browser.platform.GetDeviceTypeName() ==
               override['device_type'])):
            logging.warning(
              'Overriding device_pixel_ratio ' + str(device_pixel_ratio) +
              ' with scale factor ' + str(override['scale_factor']) +
              ' for device type ' + override['device_type'])
            device_pixel_ratio = override['scale_factor']
            break
          if (test_machine_name and 'machine_name' in override and
              override["machine_name"] == test_machine_name):
            logging.warning(
              'Overriding device_pixel_ratio ' + str(device_pixel_ratio) +
              ' with scale factor ' + str(override['scale_factor']) +
              ' for machine name ' + test_machine_name)
            device_pixel_ratio = override['scale_factor']
            break
        # Only support one "scale_factor_overrides" in the expectation format.
        break
    for expectation in expected_colors:
      if "scale_factor_overrides" in expectation:
        continue
      location = expectation["location"]
      size = expectation["size"]
      x0 = int(location[0] * device_pixel_ratio)
      x1 = int((location[0] + size[0]) * device_pixel_ratio)
      y0 = int(location[1] * device_pixel_ratio)
      y1 = int((location[1] + size[1]) * device_pixel_ratio)
      for x in range(x0, x1):
        for y in range(y0, y1):
          if (x < 0 or y < 0 or x >= image_util.Width(screenshot) or
              y >= image_util.Height(screenshot)):
            self.fail(
                ('Expected pixel location [%d, %d] is out of range on ' +
                 '[%d, %d] image') %
                (x, y, image_util.Width(screenshot),
                 image_util.Height(screenshot)))

          actual_color = image_util.GetPixelColor(screenshot, x, y)
          expected_color = rgba_color.RgbaColor(
              expectation["color"][0],
              expectation["color"][1],
              expectation["color"][2])
          if not actual_color.IsEqual(expected_color, tolerance):
            self.fail('Expected pixel at ' + str(location) +
                ' (actual pixel (' + str(x) + ', ' + str(y) + ')) ' +
                ' to be ' +
                str(expectation["color"]) + " but got [" +
                str(actual_color.r) + ", " +
                str(actual_color.g) + ", " +
                str(actual_color.b) + "]")

  ###
  ### Routines working with the local disk (only used for local
  ### testing without a cloud storage account -- the bots do not use
  ### this code path).
  ###

  def _UrlToImageName(self, url):
    image_name = re.sub(r'^(http|https|file)://(/*)', '', url)
    image_name = re.sub(r'\.\./', '', image_name)
    image_name = re.sub(r'(\.|/|-)', '_', image_name)
    return image_name

  def _WriteImage(self, image_path, png_image):
    output_dir = os.path.dirname(image_path)
    if not os.path.exists(output_dir):
      os.makedirs(output_dir)
    image_util.WritePngFile(png_image, image_path)

  def _WriteErrorImages(self, img_dir, img_name, screenshot, ref_png):
    full_image_name = img_name + '_' + str(
      self.GetParsedCommandLineOptions().build_revision)
    full_image_name = full_image_name + '.png'

    # Always write the failing image.
    self._WriteImage(
        os.path.join(img_dir, 'FAIL_' + full_image_name), screenshot)

    if ref_png is not None:
      # Save the reference image.
      # This ensures that we get the right revision number.
      self._WriteImage(
          os.path.join(img_dir, full_image_name), ref_png)

      # Save the difference image.
      diff_png = image_util.Diff(screenshot, ref_png)
      self._WriteImage(
          os.path.join(img_dir, 'DIFF_' + full_image_name), diff_png)

  ###
  ### Cloud storage code path -- the bots use this.
  ###

  @classmethod
  def ResetGpuInfo(cls):
    cls._reference_image_parameters = None

  @classmethod
  def GetReferenceImageParameters(cls, tab, page):
    if not cls._reference_image_parameters:
      cls._ComputeGpuInfo(tab, page)
    return cls._reference_image_parameters

  @classmethod
  def _ComputeGpuInfo(cls, tab, page):
    if cls._reference_image_parameters:
      return
    browser = cls.browser
    system_info = browser.GetSystemInfo()
    if not system_info:
      raise Exception('System info must be supported by the browser')
    if not system_info.gpu:
      raise Exception('GPU information was absent')
    device = system_info.gpu.devices[0]
    cls._reference_image_parameters = _ReferenceImageParameters()
    params = cls._reference_image_parameters
    if device.vendor_id and device.device_id:
      params.vendor_id = device.vendor_id
      params.device_id = device.device_id
    elif device.vendor_string and device.device_string:
      params.vendor_string = device.vendor_string
      params.device_string = device.device_string
    elif page.gpu_process_disabled:
      # Match the vendor and device IDs that the browser advertises
      # when the software renderer is active.
      params.vendor_id = 65535
      params.device_id = 65535
    else:
      raise Exception('GPU device information was incomplete')
    # TODO(senorblanco): This should probably be checking
    # for the presence of the extensions in system_info.gpu_aux_attributes
    # in order to check for MSAA, rather than sniffing the blacklist.
    params.msaa = not (
        ('disable_chromium_framebuffer_multisample' in
          system_info.gpu.driver_bug_workarounds) or
        ('disable_multisample_render_to_texture' in
          system_info.gpu.driver_bug_workarounds))
    params.model_name = system_info.model_name

  @classmethod
  def _FormatGpuInfo(cls, tab, page):
    cls._ComputeGpuInfo(tab, page)
    params = cls._reference_image_parameters
    msaa_string = '_msaa' if params.msaa else '_non_msaa'
    if params.vendor_id:
      os_type = cls.GetParsedCommandLineOptions().os_type
      if str(cls.browser.platform.GetOSVersionName()).lower() == "win10":
        # Allow separate baselines for Windows 10 and Windows 7.
        os_type = "win10"
      return '%s_%04x_%04x%s' % (
        os_type, params.vendor_id, params.device_id, msaa_string)
    else:
      # This is the code path for Android devices. Disambiguate
      # chrome on Android and Android webview. Include the model
      # name (e.g. "Nexus 9") in the GPU string to disambiguate
      # multiple devices on the waterfall which might have the same
      # device string ("NVIDIA Tegra") but different screen
      # resolutions and device pixel ratios.
      os_type = cls.GetParsedCommandLineOptions().os_type
      if cls.browser.browser_type.startswith('android-webview'):
        os_type = os_type + "_webview"
      return '%s_%s_%s_%s%s' % (
        os_type, params.vendor_string, params.device_string,
        params.model_name, msaa_string)

  @classmethod
  def _FormatReferenceImageName(cls, img_name, page, tab):
    return '%s_v%s_%s.png' % (
      img_name,
      page.revision,
      cls._FormatGpuInfo(tab, page))

  @classmethod
  def _UploadBitmapToCloudStorage(cls, bucket, name, bitmap, public=False):
    # This sequence of steps works on all platforms to write a temporary
    # PNG to disk, following the pattern in bitmap_unittest.py. The key to
    # avoiding PermissionErrors seems to be to not actually try to write to
    # the temporary file object, but to re-open its name for all operations.
    temp_file = tempfile.NamedTemporaryFile(suffix='.png').name
    image_util.WritePngFile(bitmap, temp_file)
    cloud_storage.Insert(bucket, name, temp_file, publicly_readable=public)

  @classmethod
  def _ConditionallyUploadToCloudStorage(cls, img_name, page, tab, screenshot):
    """Uploads the screenshot to cloud storage as the reference image
    for this test, unless it already exists. Returns True if the
    upload was actually performed."""
    if not cls.GetParsedCommandLineOptions().refimg_cloud_storage_bucket:
      raise Exception('--refimg-cloud-storage-bucket argument is required')
    cloud_name = cls._FormatReferenceImageName(img_name, page, tab)
    if not cloud_storage.Exists(
        cls.GetParsedCommandLineOptions().refimg_cloud_storage_bucket,
        cloud_name):
      cls._UploadBitmapToCloudStorage(
        cls.GetParsedCommandLineOptions().refimg_cloud_storage_bucket,
        cloud_name,
        screenshot)
      return True
    return False

  @classmethod
  def _DownloadFromCloudStorage(cls, img_name, page, tab):
    """Downloads the reference image for the given test from cloud
    storage, returning it as a Telemetry Bitmap object."""
    # TODO(kbr): there's a race condition between the deletion of the
    # temporary file and gsutil's overwriting it.
    if not cls.GetParsedCommandLineOptions().refimg_cloud_storage_bucket:
      raise Exception('--refimg-cloud-storage-bucket argument is required')
    temp_file = tempfile.NamedTemporaryFile(suffix='.png').name
    cloud_storage.Get(
      cls.GetParsedCommandLineOptions().refimg_cloud_storage_bucket,
      cls._FormatReferenceImageName(img_name, page, tab),
      temp_file)
    return image_util.FromPngFile(temp_file)

  @classmethod
  def _UploadErrorImagesToCloudStorage(cls, image_name, screenshot, ref_img):
    """For a failing run, uploads the failing image, reference image (if
    supplied), and diff image (if reference image was supplied) to cloud
    storage. This subsumes the functionality of the
    archive_gpu_pixel_test_results.py script."""
    machine_name = re.sub(r'\W+', '_',
                          cls.GetParsedCommandLineOptions().test_machine_name)
    upload_dir = '%s_%s_telemetry' % (
      cls.GetParsedCommandLineOptions().build_revision, machine_name)
    base_bucket = '%s/runs/%s' % (error_image_cloud_storage_bucket, upload_dir)
    image_name_with_revision = '%s_%s.png' % (
      image_name, cls.GetParsedCommandLineOptions().build_revision)
    cls._UploadBitmapToCloudStorage(
      base_bucket + '/gen', image_name_with_revision, screenshot,
      public=True)
    if ref_img is not None:
      cls._UploadBitmapToCloudStorage(
        base_bucket + '/ref', image_name_with_revision, ref_img, public=True)
      diff_img = image_util.Diff(screenshot, ref_img)
      cls._UploadBitmapToCloudStorage(
        base_bucket + '/diff', image_name_with_revision, diff_img,
        public=True)
    print ('See http://%s.commondatastorage.googleapis.com/'
           'view_test_results.html?%s for this run\'s test results') % (
      error_image_cloud_storage_bucket, upload_dir)

  def _ValidateScreenshotSamples(self, tab, url, screenshot, expectations,
                                 tolerance, device_pixel_ratio):
    """Samples the given screenshot and verifies pixel color values.
       The sample locations and expected color values are given in expectations.
       In case any of the samples do not match the expected color, it raises
       a Failure and dumps the screenshot locally or cloud storage depending on
       what machine the test is being run."""
    try:
      self._CompareScreenshotSamples(
        tab, screenshot, expectations, tolerance, device_pixel_ratio,
        self.GetParsedCommandLineOptions().test_machine_name)
    except Exception:
      # An exception raised from self.fail() indicates a failure.
      image_name = self._UrlToImageName(url)
      if self.GetParsedCommandLineOptions().test_machine_name:
        self._UploadErrorImagesToCloudStorage(image_name, screenshot, None)
      else:
        self._WriteErrorImages(
          self.GetParsedCommandLineOptions().generated_dir, image_name,
          screenshot, None)
      raise

  def ToHex(self, num):
    return hex(int(num))

  def ToHexOrNone(self, num):
    return 'None' if num == None else self.ToHex(num)

  def _UploadTestResultToSkiaGold(self, image_name, screenshot,
                                  tab, page, build_id_args=None):
    if build_id_args is None:
      raise Exception('Requires build args to be specified, including --commit')
    if self._skia_gold_temp_dir is None:
      # TODO(kbr): this depends on Swarming to clean up the temporary
      # directory to avoid filling up the local disk.
      self._skia_gold_temp_dir = tempfile.mkdtemp()
    # Write screenshot to PNG file on local disk.
    png_temp_file = tempfile.NamedTemporaryFile(suffix='.png').name
    image_util.WritePngFile(screenshot, png_temp_file)
    ref_img_params = self.GetReferenceImageParameters(tab, page)
    # All values need to be strings, otherwise goldctl fails.
    gpu_keys = {
      'vendor_id': self.ToHexOrNone(ref_img_params.vendor_id),
      'device_id': self.ToHexOrNone(ref_img_params.device_id),
      'vendor_string': str(ref_img_params.vendor_string),
      'device_string': str(ref_img_params.device_string),
      'msaa': str(ref_img_params.msaa),
      'model_name': str(ref_img_params.model_name),
    }
    mode = ['--passfail']
    json_temp_file = tempfile.NamedTemporaryFile(suffix='.json').name
    failure_file = tempfile.NamedTemporaryFile(suffix='.txt').name
    with open(json_temp_file, 'w+') as f:
      json.dump(gpu_keys, f)
    try:
      if not self.GetParsedCommandLineOptions().no_luci_auth:
        subprocess.check_output([goldctl_bin, 'auth', '--luci',
                                 '--work-dir', self._skia_gold_temp_dir],
            stderr=subprocess.STDOUT)
      cmd = ([goldctl_bin, 'imgtest', 'add'] + mode +
                            ['--test-name', image_name,
                             '--instance', SKIA_GOLD_INSTANCE,
                             '--keys-file', json_temp_file,
                             '--png-file', png_temp_file,
                             '--work-dir', self._skia_gold_temp_dir,
                             '--failure-file', failure_file] +
                            build_id_args)
      subprocess.check_output(cmd, stderr=subprocess.STDOUT)
    except CalledProcessError as e:
      contents = ''
      try:
        with open(failure_file, 'r') as ff:
          contents = ff.read()
      except Exception:
        logging.error('Failed to read contents of goldctl failure file')
      logging.error('goldctl failed with output: %s', e.output)
      self._MaybeOutputSkiaGoldLink()
      if not self.GetParsedCommandLineOptions().no_skia_gold_failure:
        raise Exception('goldctl command failed: ' + contents)

  def _ValidateScreenshotSamplesWithSkiaGold(self, tab, page, screenshot,
                                             expectations, tolerance,
                                             device_pixel_ratio,
                                             build_id_args):
    """Samples the given screenshot and verifies pixel color values.
       The sample locations and expected color values are given in expectations.
       In case any of the samples do not match the expected color, it raises
       a Failure and dumps the screenshot locally or cloud storage depending on
       what machine the test is being run."""
    url = page.name
    try:
      self._CompareScreenshotSamples(
        tab, screenshot, expectations, tolerance, device_pixel_ratio,
        self.GetParsedCommandLineOptions().test_machine_name)
    except Exception:
      # An exception raised from self.fail() indicates a failure.
      image_name = self._UrlToImageName(url)
      if self.GetParsedCommandLineOptions().test_machine_name:
        self._UploadTestResultToSkiaGold(
          image_name, screenshot,
          tab, page,
          build_id_args=build_id_args)
      else:
        self._WriteErrorImages(
          self.GetParsedCommandLineOptions().generated_dir, image_name,
          screenshot, None)
      raise

  def _MaybeOutputSkiaGoldLink(self):
    # TODO(https://crbug.com/850107): Differentiate between an image mismatch
    # and an infra/other failure, and only output the link on image mismatch.
    skia_url = 'https://%s-gold.skia.org/search?' % SKIA_GOLD_INSTANCE
    patch_issue = self.GetParsedCommandLineOptions().review_patch_issue
    is_tryjob = patch_issue != None
    # These URL formats were just taken from links on the Gold instance pointing
    # to untriaged results.
    if is_tryjob:
      skia_url += 'issue=%s&unt=true&master=false' % patch_issue
    else:
      skia_url += 'blame=%s&unt=true&head=true&query=source_type%%3D%s' % (
          self.GetParsedCommandLineOptions().build_revision,
          SKIA_GOLD_INSTANCE)
    logging.error('View and triage untriaged images at %s', skia_url)

  @classmethod
  def GenerateGpuTests(cls, options):
    del options
    return []
