# Copyright 2019 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 unittest

import mock
import version


def _ReplaceArgs(args, *replacements):
  new_args = args[:]
  for flag, val in replacements:
    flag_index = args.index(flag)
    new_args[flag_index + 1] = val
  return new_args


class _VersionTest(unittest.TestCase):
  """Unittests for the version module.
  """

  _CHROME_VERSION_FILE = os.path.join(
      os.path.dirname(__file__), os.pardir, os.pardir, 'chrome', 'VERSION')

  _SCRIPT = os.path.join(os.path.dirname(__file__), 'version.py')

  _EXAMPLE_VERSION = {
      'MAJOR': '74',
      'MINOR': '0',
      'BUILD': '3720',
      'PATCH': '0',
  }

  _EXAMPLE_TEMPLATE = (
      'full = "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" '
      'major = "@MAJOR@" minor = "@MINOR@" '
      'build = "@BUILD@" patch = "@PATCH@" version_id = @VERSION_ID@ ')

  _ANDROID_CHROME_VARS = [
      'chrome_version_code',
      'monochrome_version_code',
      'trichrome_version_code',
      'webview_stable_version_code',
      'webview_beta_version_code',
      'webview_dev_version_code',
  ]

  _EXAMPLE_ANDROID_TEMPLATE = (
      _EXAMPLE_TEMPLATE + ''.join(
          ['%s = "@%s@" ' % (el, el.upper()) for el in _ANDROID_CHROME_VARS]))

  _EXAMPLE_ARGS = [
      '-f',
      _CHROME_VERSION_FILE,
      '-t',
      _EXAMPLE_TEMPLATE,
  ]

  _EXAMPLE_ANDROID_ARGS = _ReplaceArgs(_EXAMPLE_ARGS,
                                       ['-t', _EXAMPLE_ANDROID_TEMPLATE]) + [
                                           '-a',
                                           'arm',
                                           '--os',
                                           'android',
                                       ]

  @staticmethod
  def _RunBuildOutput(new_version_values={},
                      get_new_args=lambda old_args: old_args):
    """Parameterized helper method for running the main testable method in
    version.py.

    Keyword arguments:
    new_version_values -- dict used to update _EXAMPLE_VERSION
    get_new_args -- lambda for updating _EXAMPLE_ANDROID_ARGS
    """

    with mock.patch('version.FetchValuesFromFile') as \
        fetch_values_from_file_mock:

      fetch_values_from_file_mock.side_effect = (lambda values, file :
          values.update(
              dict(_VersionTest._EXAMPLE_VERSION, **new_version_values)))

      new_args = get_new_args(_VersionTest._EXAMPLE_ARGS)
      return version.BuildOutput(new_args)

  def testFetchValuesFromFile(self):
    """It returns a dict in correct format - { <str>: <str> }, to verify
    assumption of other tests that mock this function
    """
    result = {}
    version.FetchValuesFromFile(result, self._CHROME_VERSION_FILE)

    for key, val in result.items():
      self.assertIsInstance(key, str)
      self.assertIsInstance(val, str)

  def testBuildOutputAndroid(self):
    """Assert it gives includes assignments of expected variables"""
    output = self._RunBuildOutput(
        get_new_args=lambda args: self._EXAMPLE_ANDROID_ARGS)
    contents = output['contents']

    self.assertRegex(contents, r'\bchrome_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bmonochrome_version_code = "\d+"\s')
    self.assertRegex(contents, r'\btrichrome_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bwebview_stable_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bwebview_beta_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bwebview_dev_version_code = "\d+"\s')

  def testBuildOutputAndroidArchVariantsArm64(self):
    """Assert 64-bit-specific version codes"""
    new_template = (
        self._EXAMPLE_ANDROID_TEMPLATE +
        "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" "
        "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" "
        "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" "
        "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ")
    args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS,
                                      ['-t', new_template])
    new_args = _ReplaceArgs(args_with_template, ['-a', 'arm64'])
    output = self._RunBuildOutput(get_new_args=lambda args: new_args)
    contents = output['contents']

    self.assertRegex(contents, r'\bmonochrome_64_32_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bmonochrome_64_version_code = "\d+"\s')
    self.assertRegex(contents, r'\btrichrome_64_32_version_code = "\d+"\s')
    self.assertRegex(contents, r'\btrichrome_64_version_code = "\d+"\s')

  def testBuildOutputAndroidArchVariantsX64(self):
    """Assert 64-bit-specific version codes"""
    new_template = (
        self._EXAMPLE_ANDROID_TEMPLATE +
        "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" "
        "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" "
        "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" "
        "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ")
    args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS,
                                      ['-t', new_template])
    new_args = _ReplaceArgs(args_with_template, ['-a', 'x64'])
    output = self._RunBuildOutput(get_new_args=lambda args: new_args)
    contents = output['contents']

    self.assertRegex(contents, r'\bmonochrome_64_32_version_code = "\d+"\s')
    self.assertRegex(contents, r'\bmonochrome_64_version_code = "\d+"\s')
    self.assertRegex(contents, r'\btrichrome_64_32_version_code = "\d+"\s')
    self.assertRegex(contents, r'\btrichrome_64_version_code = "\d+"\s')

  def testBuildOutputAndroidChromeArchInput(self):
    """Assert it raises an exception when using an invalid architecture input"""
    new_args = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS, ['-a', 'foobar'])
    # Mock sys.stderr because argparse will print to stderr when we pass
    # the invalid '-a' value.
    with self.assertRaises(SystemExit) as cm, mock.patch('sys.stderr'):
      self._RunBuildOutput(get_new_args=lambda args: new_args)

    self.assertEqual(cm.exception.code, 2)


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