tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

version_test.py (8984B)


      1 # Copyright 2019 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import os
      6 import tempfile
      7 import time
      8 import unittest
      9 
     10 import mock
     11 import version
     12 
     13 
     14 def _ReplaceArgs(args, *replacements):
     15  new_args = args[:]
     16  for flag, val in replacements:
     17    flag_index = args.index(flag)
     18    new_args[flag_index + 1] = val
     19  return new_args
     20 
     21 
     22 class _VersionTest(unittest.TestCase):
     23  """Unittests for the version module.
     24  """
     25 
     26  _CHROME_VERSION_FILE = os.path.join(
     27      os.path.dirname(__file__), os.pardir, os.pardir, 'chrome', 'VERSION')
     28 
     29  _SCRIPT = os.path.join(os.path.dirname(__file__), 'version.py')
     30 
     31  _EXAMPLE_VERSION = {
     32      'MAJOR': '74',
     33      'MINOR': '0',
     34      'BUILD': '3720',
     35      'PATCH': '0',
     36  }
     37 
     38  _EXAMPLE_TEMPLATE = (
     39      'full = "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" '
     40      'major = "@MAJOR@" minor = "@MINOR@" '
     41      'build = "@BUILD@" patch = "@PATCH@" version_id = @VERSION_ID@ ')
     42 
     43  _ANDROID_CHROME_VARS = [
     44      'chrome_version_code',
     45      'monochrome_version_code',
     46      'trichrome_version_code',
     47      'webview_stable_version_code',
     48      'webview_beta_version_code',
     49      'webview_dev_version_code',
     50  ]
     51 
     52  _EXAMPLE_ANDROID_TEMPLATE = (
     53      _EXAMPLE_TEMPLATE + ''.join(
     54          ['%s = "@%s@" ' % (el, el.upper()) for el in _ANDROID_CHROME_VARS]))
     55 
     56  _EXAMPLE_ARGS = [
     57      '-f',
     58      _CHROME_VERSION_FILE,
     59      '-t',
     60      _EXAMPLE_TEMPLATE,
     61  ]
     62 
     63  _EXAMPLE_ANDROID_ARGS = _ReplaceArgs(_EXAMPLE_ARGS,
     64                                       ['-t', _EXAMPLE_ANDROID_TEMPLATE]) + [
     65                                           '-a',
     66                                           'arm',
     67                                           '--os',
     68                                           'android',
     69                                       ]
     70 
     71  @staticmethod
     72  def _RunBuildOutput(new_version_values={},
     73                      get_new_args=lambda old_args: old_args):
     74    """Parameterized helper method for running the main testable method in
     75    version.py.
     76 
     77    Keyword arguments:
     78    new_version_values -- dict used to update _EXAMPLE_VERSION
     79    get_new_args -- lambda for updating _EXAMPLE_ANDROID_ARGS
     80    """
     81 
     82    with mock.patch('version.FetchValuesFromFile') as \
     83        fetch_values_from_file_mock:
     84 
     85      fetch_values_from_file_mock.side_effect = (lambda values, file :
     86          values.update(
     87              dict(_VersionTest._EXAMPLE_VERSION, **new_version_values)))
     88 
     89      new_args = get_new_args(_VersionTest._EXAMPLE_ARGS)
     90      return version.BuildOutput(new_args)
     91 
     92  def testFetchValuesFromFile(self):
     93    """It returns a dict in correct format - { <str>: <str> }, to verify
     94    assumption of other tests that mock this function
     95    """
     96    result = {}
     97    version.FetchValuesFromFile(result, self._CHROME_VERSION_FILE)
     98 
     99    for key, val in result.items():
    100      self.assertIsInstance(key, str)
    101      self.assertIsInstance(val, str)
    102 
    103  def testBuildOutputAndroid(self):
    104    """Assert it gives includes assignments of expected variables"""
    105    output = self._RunBuildOutput(
    106        get_new_args=lambda args: self._EXAMPLE_ANDROID_ARGS)
    107    contents = output['contents']
    108 
    109    self.assertRegex(contents, r'\bchrome_version_code = "\d+"\s')
    110    self.assertRegex(contents, r'\bmonochrome_version_code = "\d+"\s')
    111    self.assertRegex(contents, r'\btrichrome_version_code = "\d+"\s')
    112    self.assertRegex(contents, r'\bwebview_stable_version_code = "\d+"\s')
    113    self.assertRegex(contents, r'\bwebview_beta_version_code = "\d+"\s')
    114    self.assertRegex(contents, r'\bwebview_dev_version_code = "\d+"\s')
    115 
    116  def testBuildOutputAndroidArchVariantsArm64(self):
    117    """Assert 64-bit-specific version codes"""
    118    new_template = (
    119        self._EXAMPLE_ANDROID_TEMPLATE +
    120        "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" "
    121        "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" "
    122        "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" "
    123        "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ")
    124    args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS,
    125                                      ['-t', new_template])
    126    new_args = _ReplaceArgs(args_with_template, ['-a', 'arm64'])
    127    output = self._RunBuildOutput(get_new_args=lambda args: new_args)
    128    contents = output['contents']
    129 
    130    self.assertRegex(contents, r'\bmonochrome_64_32_version_code = "\d+"\s')
    131    self.assertRegex(contents, r'\bmonochrome_64_version_code = "\d+"\s')
    132    self.assertRegex(contents, r'\btrichrome_64_32_version_code = "\d+"\s')
    133    self.assertRegex(contents, r'\btrichrome_64_version_code = "\d+"\s')
    134 
    135  def testBuildOutputAndroidArchVariantsX64(self):
    136    """Assert 64-bit-specific version codes"""
    137    new_template = (
    138        self._EXAMPLE_ANDROID_TEMPLATE +
    139        "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" "
    140        "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" "
    141        "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" "
    142        "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ")
    143    args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS,
    144                                      ['-t', new_template])
    145    new_args = _ReplaceArgs(args_with_template, ['-a', 'x64'])
    146    output = self._RunBuildOutput(get_new_args=lambda args: new_args)
    147    contents = output['contents']
    148 
    149    self.assertRegex(contents, r'\bmonochrome_64_32_version_code = "\d+"\s')
    150    self.assertRegex(contents, r'\bmonochrome_64_version_code = "\d+"\s')
    151    self.assertRegex(contents, r'\btrichrome_64_32_version_code = "\d+"\s')
    152    self.assertRegex(contents, r'\btrichrome_64_version_code = "\d+"\s')
    153 
    154  def testBuildOutputAndroidChromeArchInput(self):
    155    """Assert it raises an exception when using an invalid architecture input"""
    156    new_args = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS, ['-a', 'foobar'])
    157    # Mock sys.stderr because argparse will print to stderr when we pass
    158    # the invalid '-a' value.
    159    with self.assertRaises(SystemExit) as cm, mock.patch('sys.stderr'):
    160      self._RunBuildOutput(get_new_args=lambda args: new_args)
    161 
    162    self.assertEqual(cm.exception.code, 2)
    163 
    164  def testSetExecutable(self):
    165    """Assert that -x sets executable on POSIX and is harmless on Windows."""
    166    with tempfile.TemporaryDirectory() as tmpdir:
    167      in_file = os.path.join(tmpdir, "in")
    168      out_file = os.path.join(tmpdir, "out")
    169      with open(in_file, "w") as f:
    170        f.write("")
    171      self.assertEqual(version.main(['-i', in_file, '-o', out_file, '-x']), 0)
    172 
    173      # Whether lstat(out_file).st_mode has the executable bits set is
    174      # platform-specific. Therefore, test that out_file has the same
    175      # permissions that in_file would have after chmod(in_file, 0o755).
    176      # On Windows: both files will have 0o666.
    177      # On POSIX: both files will have 0o755.
    178      os.chmod(in_file, 0o755)  # On Windows, this sets in_file to 0o666.
    179      self.assertEqual(os.lstat(in_file).st_mode, os.lstat(out_file).st_mode)
    180 
    181  def testWriteIfChangedUpdateWhenContentChanged(self):
    182    """Assert it updates mtime of file when content is changed."""
    183    with tempfile.TemporaryDirectory() as tmpdir:
    184      file_name = os.path.join(tmpdir, "version.h")
    185      old_contents = "old contents"
    186      with open(file_name, "w") as f:
    187        f.write(old_contents)
    188      os.chmod(file_name, 0o644)
    189      mtime = os.lstat(file_name).st_mtime
    190      time.sleep(0.1)
    191      contents = "new contents"
    192      version.WriteIfChanged(file_name, contents, 0o644)
    193      with open(file_name) as f:
    194        self.assertEqual(contents, f.read())
    195      self.assertNotEqual(mtime, os.lstat(file_name).st_mtime)
    196 
    197  def testWriteIfChangedUpdateWhenModeChanged(self):
    198    """Assert it updates mtime of file when mode is changed."""
    199    with tempfile.TemporaryDirectory() as tmpdir:
    200      file_name = os.path.join(tmpdir, "version.h")
    201      contents = "old contents"
    202      with open(file_name, "w") as f:
    203        f.write(contents)
    204      os.chmod(file_name, 0o644)
    205      mtime = os.lstat(file_name).st_mtime
    206      time.sleep(0.1)
    207      version.WriteIfChanged(file_name, contents, 0o755)
    208      with open(file_name) as f:
    209        self.assertEqual(contents, f.read())
    210      self.assertNotEqual(mtime, os.lstat(file_name).st_mtime)
    211 
    212  def testWriteIfChangedNoUpdate(self):
    213    """Assert it does not update mtime of file when nothing is changed."""
    214    with tempfile.TemporaryDirectory() as tmpdir:
    215      file_name = os.path.join(tmpdir, "version.h")
    216      contents = "old contents"
    217      with open(file_name, "w") as f:
    218        f.write(contents)
    219      os.chmod(file_name, 0o644)
    220      mtime = os.lstat(file_name).st_mtime
    221      time.sleep(0.1)
    222      version.WriteIfChanged(file_name, contents, 0o644)
    223      with open(file_name) as f:
    224        self.assertEqual(contents, f.read())
    225      self.assertEqual(mtime, os.lstat(file_name).st_mtime)
    226 
    227 if __name__ == '__main__':
    228  unittest.main()