#!/usr/bin/env vpython3
# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

#pylint: disable=protected-access

import os
import sys
import unittest

if sys.version_info[0] == 2:
  import mock
else:
  import unittest.mock as mock

from skia_gold_common import skia_gold_properties
from skia_gold_common import unittest_utils

createSkiaGoldArgs = unittest_utils.createSkiaGoldArgs


class SkiaGoldPropertiesInitializationTest(unittest.TestCase):
  """Tests that SkiaGoldProperties initializes (or doesn't) when expected."""

  def verifySkiaGoldProperties(
      self, instance: skia_gold_properties.SkiaGoldProperties,
      expected: dict) -> None:
    self.assertEqual(instance._local_pixel_tests,
                     expected.get('local_pixel_tests'))
    self.assertEqual(instance._no_luci_auth, expected.get('no_luci_auth'))
    self.assertEqual(instance._code_review_system,
                     expected.get('code_review_system'))
    self.assertEqual(instance._continuous_integration_system,
                     expected.get('continuous_integration_system'))
    self.assertEqual(instance._git_revision, expected.get('git_revision'))
    self.assertEqual(instance._issue, expected.get('gerrit_issue'))
    self.assertEqual(instance._patchset, expected.get('gerrit_patchset'))
    self.assertEqual(instance._job_id, expected.get('buildbucket_id'))
    self.assertEqual(instance._bypass_skia_gold_functionality,
                     expected.get('bypass_skia_gold_functionality'))

  def test_initializeSkiaGoldAttributes_unsetLocal(self) -> None:
    args = createSkiaGoldArgs()
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {})

  def test_initializeSkiaGoldAttributes_explicitLocal(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'local_pixel_tests': True})

  def test_initializeSkiaGoldAttributes_explicitNonLocal(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=False)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'local_pixel_tests': False})

  def test_initializeSkiaGoldAttributes_explicitNoLuciAuth(self) -> None:
    args = createSkiaGoldArgs(no_luci_auth=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'no_luci_auth': True})

  def test_initializeSkiaGoldAttributes_explicitServiceAccount(self) -> None:
    args = createSkiaGoldArgs(service_account='a')
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {
        'service_account': 'a',
        'no_luci_auth': True
    })

  def test_initializeSkiaGoldAttributes_explicitCrs(self) -> None:
    args = createSkiaGoldArgs(code_review_system='foo')
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'code_review_system': 'foo'})

  def test_initializeSkiaGoldAttributes_explicitCis(self) -> None:
    args = createSkiaGoldArgs(continuous_integration_system='foo')
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'continuous_integration_system': 'foo'})

  def test_initializeSkiaGoldAttributes_bypassExplicitTrue(self) -> None:
    args = createSkiaGoldArgs(bypass_skia_gold_functionality=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'bypass_skia_gold_functionality': True})

  def test_initializeSkiaGoldAttributes_explicitGitRevision(self) -> None:
    args = createSkiaGoldArgs(git_revision='a')
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {'git_revision': 'a'})

  def test_initializeSkiaGoldAttributes_tryjobArgsIgnoredWithoutRevision(
      self) -> None:
    args = createSkiaGoldArgs(gerrit_issue=1,
                              gerrit_patchset=2,
                              buildbucket_id=3)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(sgp, {})

  def test_initializeSkiaGoldAttributes_tryjobArgs(self) -> None:
    args = createSkiaGoldArgs(git_revision='a',
                              gerrit_issue=1,
                              gerrit_patchset=2,
                              buildbucket_id=3)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.verifySkiaGoldProperties(
        sgp, {
            'git_revision': 'a',
            'gerrit_issue': 1,
            'gerrit_patchset': 2,
            'buildbucket_id': 3
        })

  def test_initializeSkiaGoldAttributes_tryjobMissingPatchset(self) -> None:
    args = createSkiaGoldArgs(git_revision='a',
                              gerrit_issue=1,
                              buildbucket_id=3)
    with self.assertRaises(RuntimeError):
      skia_gold_properties.SkiaGoldProperties(args)

  def test_initializeSkiaGoldAttributes_tryjobMissingBuildbucket(self) -> None:
    args = createSkiaGoldArgs(git_revision='a',
                              gerrit_issue=1,
                              gerrit_patchset=2)
    with self.assertRaises(RuntimeError):
      skia_gold_properties.SkiaGoldProperties(args)


class SkiaGoldPropertiesCalculationTest(unittest.TestCase):
  """Tests that SkiaGoldProperties properly calculates certain properties."""

  def testLocalPixelTests_determineTrue(self) -> None:
    args = createSkiaGoldArgs()
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with mock.patch.dict(os.environ, {}, clear=True):
      self.assertTrue(sgp.local_pixel_tests)
    with mock.patch.dict(os.environ, {'RUNNING_IN_SKYLAB': '0'}, clear=True):
      self.assertTrue(sgp.local_pixel_tests)

  def testLocalPixelTests_determineFalse(self) -> None:
    args = createSkiaGoldArgs()
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with mock.patch.dict(os.environ, {'SWARMING_SERVER': ''}, clear=True):
      self.assertFalse(sgp.local_pixel_tests)
    with mock.patch.dict(os.environ, {'RUNNING_IN_SKYLAB': '1'}, clear=True):
      self.assertFalse(sgp.local_pixel_tests)

  def testIsTryjobRun_noIssue(self) -> None:
    args = createSkiaGoldArgs()
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.assertFalse(sgp.IsTryjobRun())

  def testIsTryjobRun_issue(self) -> None:
    args = createSkiaGoldArgs(git_revision='a',
                              gerrit_issue=1,
                              gerrit_patchset=2,
                              buildbucket_id=3)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.assertTrue(sgp.IsTryjobRun())

  def testGetGitRevision_revisionSet(self) -> None:
    args = createSkiaGoldArgs(git_revision='a')
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    self.assertEqual(sgp.git_revision, 'a')

  def testGetGitRevision_findValidRevision(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with mock.patch.object(skia_gold_properties.SkiaGoldProperties,
                           '_GetGitOriginMainHeadSha1') as patched_head:
      expected = 'a' * 40
      patched_head.return_value = expected
      self.assertEqual(sgp.git_revision, expected)
      # Should be cached.
      self.assertEqual(sgp._git_revision, expected)

  def testGetGitRevision_noExplicitOnBot(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=False)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with self.assertRaises(RuntimeError):
      _ = sgp.git_revision

  def testGetGitRevision_findEmptyRevision(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with mock.patch.object(skia_gold_properties.SkiaGoldProperties,
                           '_GetGitOriginMainHeadSha1') as patched_head:
      patched_head.return_value = ''
      with self.assertRaises(RuntimeError):
        _ = sgp.git_revision

  def testGetGitRevision_findMalformedRevision(self) -> None:
    args = createSkiaGoldArgs(local_pixel_tests=True)
    sgp = skia_gold_properties.SkiaGoldProperties(args)
    with mock.patch.object(skia_gold_properties.SkiaGoldProperties,
                           '_GetGitOriginMainHeadSha1') as patched_head:
      patched_head.return_value = 'a' * 39
      with self.assertRaises(RuntimeError):
        _ = sgp.git_revision


if __name__ == '__main__':
  unittest.main(verbosity=2)
