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