123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- #!/usr/bin/env vpython3
- # Copyright 2021 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.
- """Unittests for xcode_util.py."""
- import logging
- import mock
- import os
- import unittest
- import test_runner_errors
- import test_runner_test
- import xcode_util
- _XCODEBUILD_VERSION_OUTPUT_12 = b"""Xcode 12.4
- Build version 12D4e
- """
- _XCODEBUILD_VERSION_OUTPUT_13 = b"""Xcode 13.0
- Build version 13A5155e
- """
- class XcodeUtilTest(test_runner_test.TestCase):
- """Test class for xcode_util functions."""
- def setUp(self):
- super(XcodeUtilTest, self).setUp()
- @mock.patch(
- 'subprocess.check_output', return_value=_XCODEBUILD_VERSION_OUTPUT_13)
- def test_version(self, _):
- """Tests xcode_util.version()"""
- version, build_version = xcode_util.version()
- self.assertEqual(version, '13.0')
- self.assertEqual(build_version, '13a5155e')
- @mock.patch(
- 'subprocess.check_output', return_value=_XCODEBUILD_VERSION_OUTPUT_12)
- def test_using_xcode_12(self, _):
- """Tests xcode_util.using_xcode_11_or_higher"""
- self.assertTrue(xcode_util.using_xcode_11_or_higher())
- self.assertFalse(xcode_util.using_xcode_13_or_higher())
- @mock.patch(
- 'subprocess.check_output', return_value=_XCODEBUILD_VERSION_OUTPUT_13)
- def test_using_xcode_13(self, _):
- """Tests xcode_util.using_xcode_13_or_higher"""
- self.assertTrue(xcode_util.using_xcode_11_or_higher())
- self.assertTrue(xcode_util.using_xcode_13_or_higher())
- class InstallTest(XcodeUtilTest):
- """Test class for xcode_util.install function."""
- def setUp(self):
- super(InstallTest, self).setUp()
- self.mac_toolchain = 'mac_toolchain'
- self.xcode_build_version = 'TestXcodeVersion'
- self.xcode_app_path = 'test/path/Xcode.app'
- self.runtime_cache_folder = 'test/path/Runtime'
- self.ios_version = '14.4'
- @mock.patch('xcode_util.move_runtime', autospec=True)
- @mock.patch('xcode_util._install_runtime', autospec=True)
- @mock.patch('xcode_util._install_xcode', autospec=True)
- def test_legacy_mactoolchain_new_xcode(self, mock_install_xcode,
- mock_install_runtime,
- mock_move_runtime):
- self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: False)
- self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
- with self.assertRaises(test_runner_errors.XcodeMacToolchainMismatchError):
- is_legacy_xcode = xcode_util.install(self.mac_toolchain,
- self.xcode_build_version,
- self.xcode_app_path)
- self.assertTrue(is_legacy_xcode, 'install should return true')
- mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
- 'test/path/Xcode.app', False)
- self.assertFalse(mock_install_runtime.called,
- '_install_runtime shouldn\'t be called')
- self.assertFalse(mock_move_runtime.called,
- 'move_runtime shouldn\'t be called')
- @mock.patch('xcode_util.move_runtime', autospec=True)
- @mock.patch('xcode_util._install_runtime', autospec=True)
- @mock.patch('xcode_util._install_xcode', autospec=True)
- def test_legacy_mactoolchain_legacy_xcode(self, mock_install_xcode,
- mock_install_runtime,
- mock_move_runtime):
- self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: False)
- self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: True)
- is_legacy_xcode = xcode_util.install(self.mac_toolchain,
- self.xcode_build_version,
- self.xcode_app_path)
- self.assertTrue(is_legacy_xcode, 'install_should return true')
- mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
- 'test/path/Xcode.app', False)
- self.assertFalse(mock_install_runtime.called,
- '_install_runtime shouldn\'t be called')
- self.assertFalse(mock_move_runtime.called,
- 'move_runtime shouldn\'t be called')
- @mock.patch('xcode_util.move_runtime', autospec=True)
- @mock.patch('xcode_util._install_runtime', autospec=True)
- @mock.patch('xcode_util._install_xcode', autospec=True)
- def test_new_mactoolchain_legacy_xcode(self, mock_install_xcode,
- mock_install_runtime,
- mock_move_runtime):
- self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
- self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: True)
- is_legacy_xcode = xcode_util.install(self.mac_toolchain,
- self.xcode_build_version,
- self.xcode_app_path)
- self.assertTrue(is_legacy_xcode, 'install should return true')
- mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
- 'test/path/Xcode.app', True)
- self.assertFalse(mock_install_runtime.called,
- '_install_runtime shouldn\'t be called')
- self.assertFalse(mock_move_runtime.called,
- 'move_runtime shouldn\'t be called')
- @mock.patch('xcode_util.move_runtime', autospec=True)
- @mock.patch('xcode_util._install_runtime')
- @mock.patch('xcode_util._install_xcode')
- def test_new_mactoolchain_new_xcode(self, mock_install_xcode,
- mock_install_runtime, mock_move_runtime):
- self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
- self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
- is_legacy_xcode = xcode_util.install(
- self.mac_toolchain,
- self.xcode_build_version,
- self.xcode_app_path,
- runtime_cache_folder=self.runtime_cache_folder,
- ios_version=self.ios_version)
- self.assertFalse(is_legacy_xcode, 'install should return False')
- mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
- 'test/path/Xcode.app', True)
- mock_install_runtime.assert_called_with('mac_toolchain',
- 'test/path/Runtime',
- 'TestXcodeVersion', '14.4')
- mock_move_runtime.assert_called_with('test/path/Runtime',
- 'test/path/Xcode.app', True)
- @mock.patch('xcode_util.move_runtime', autospec=True)
- @mock.patch('xcode_util._install_runtime')
- @mock.patch('xcode_util._install_xcode')
- def test_new_mactoolchain_new_xcode_no_runtime(self, mock_install_xcode,
- mock_install_runtime,
- mock_move_runtime):
- self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
- self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
- is_legacy_xcode = xcode_util.install(
- self.mac_toolchain,
- self.xcode_build_version,
- self.xcode_app_path,
- runtime_cache_folder=None,
- ios_version=None)
- self.assertFalse(is_legacy_xcode, 'install should return False')
- mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
- 'test/path/Xcode.app', True)
- self.assertFalse(mock_install_runtime.called)
- self.assertFalse(mock_move_runtime.called)
- class HelperFunctionTests(XcodeUtilTest):
- """Test class for xcode_util misc util functions."""
- def setUp(self):
- super(HelperFunctionTests, self).setUp()
- self.xcode_runtime_dir_rel_path = (
- 'Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes')
- self.xcode_runtime_rel_path = (
- 'Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime')
- @mock.patch('subprocess.check_output', autospec=True)
- def test_using_new_mac_toolchain(self, mock_check_output):
- mock_check_output.return_value = b"""
- Mac OS / iOS toolchain management
- Usage: mac_toolchain [command] [arguments]
- Commands:
- help prints help about a command
- install Installs Xcode.
- upload Uploads Xcode CIPD packages.
- package Create CIPD packages locally.
- install-runtime Installs Runtime.
- Use "mac_toolchain help [command]" for more information about a command."""
- self.assertTrue(xcode_util._using_new_mac_toolchain('mac_toolchain'))
- @mock.patch('subprocess.check_output', autospec=True)
- def test_using_new_legacy_toolchain(self, mock_check_output):
- mock_check_output.return_value = b"""
- Mac OS / iOS toolchain management
- Usage: mac_toolchain [command] [arguments]
- Commands:
- help prints help about a command
- install Installs Xcode.
- upload Uploads Xcode CIPD packages.
- package Create CIPD packages locally.
- Use "mac_toolchain help [command]" for more information about a command."""
- self.assertFalse(xcode_util._using_new_mac_toolchain('mac_toolchain'))
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_is_legacy_xcode_package_legacy(self, mock_glob, mock_rmtree):
- test_xcode_path = 'test/path/Xcode.app/'
- runtime_names = ['iOS.simruntime', 'iOS 12.4.simruntime']
- xcode_runtime_paths = [
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- runtime_name) for runtime_name in runtime_names
- ]
- mock_glob.return_value = xcode_runtime_paths
- self.assertTrue(xcode_util._is_legacy_xcode_package(test_xcode_path))
- mock_glob.assert_called_with(
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- '*.simruntime'))
- self.assertFalse(mock_rmtree.called)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_is_legacy_xcode_package_no_runtime(self, mock_glob, mock_rmtree):
- test_xcode_path = 'test/path/Xcode.app/'
- xcode_runtime_paths = []
- mock_glob.return_value = xcode_runtime_paths
- self.assertFalse(xcode_util._is_legacy_xcode_package(test_xcode_path))
- mock_glob.assert_called_with(
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- '*.simruntime'))
- self.assertFalse(mock_rmtree.called)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_is_legacy_xcode_package_single_runtime(self, mock_glob, mock_rmtree):
- test_xcode_path = 'test/path/Xcode.app/'
- runtime_names = ['iOS.simruntime']
- xcode_runtime_paths = [
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- runtime_name) for runtime_name in runtime_names
- ]
- mock_glob.return_value = xcode_runtime_paths
- self.assertFalse(xcode_util._is_legacy_xcode_package(test_xcode_path))
- mock_glob.assert_called_with(
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- '*.simruntime'))
- mock_rmtree.assert_called_with(
- os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
- 'iOS.simruntime'))
- class MoveRuntimeTests(XcodeUtilTest):
- """Test class for xcode_util.move_runtime function."""
- def setUp(self):
- super(MoveRuntimeTests, self).setUp()
- self.runtime_cache_folder = 'test/path/Runtime'
- self.xcode_app_path = 'test/path/Xcode.app'
- @mock.patch('shutil.move', autospec=True)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_move_runtime_into_xcode(self, mock_glob, mock_rmtree, mock_move):
- mock_glob.side_effect = [['test/path/Runtime/iOS.simruntime'], []]
- xcode_util.move_runtime(self.runtime_cache_folder, self.xcode_app_path,
- True)
- xcode_runtime_path = ('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime')
- calls = [
- mock.call('test/path/Runtime/*.simruntime'),
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/*.simruntime'))
- ]
- mock_glob.assert_has_calls(calls)
- self.assertFalse(mock_rmtree.called)
- mock_move.assert_called_with('test/path/Runtime/iOS.simruntime',
- xcode_runtime_path)
- @mock.patch('shutil.move', autospec=True)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_move_runtime_outside_xcode(self, mock_glob, mock_rmtree, mock_move):
- xcode_runtime_folder = ('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes')
- mock_glob.side_effect = [[xcode_runtime_folder + '/iOS.simruntime'], []]
- xcode_util.move_runtime(self.runtime_cache_folder, self.xcode_app_path,
- False)
- calls = [
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/*.simruntime')),
- mock.call('test/path/Runtime/*.simruntime')
- ]
- mock_glob.assert_has_calls(calls)
- self.assertFalse(mock_rmtree.called)
- mock_move.assert_called_with(xcode_runtime_folder + '/iOS.simruntime',
- 'test/path/Runtime/iOS.simruntime')
- @mock.patch('shutil.move', autospec=True)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_move_runtime_multiple_in_src(self, mock_glob, mock_rmtree,
- mock_move):
- mock_glob.side_effect = [[
- 'test/path/Runtime/iOS.simruntime',
- 'test/path/Runtime/iOS 13.4.simruntime'
- ], []]
- with self.assertRaises(test_runner_errors.IOSRuntimeHandlingError):
- xcode_util.move_runtime(self.runtime_cache_folder, self.xcode_app_path,
- True)
- mock_glob.assert_called_with('test/path/Runtime/*.simruntime')
- self.assertFalse(mock_rmtree.called)
- self.assertFalse(mock_move.called)
- @mock.patch('shutil.move', autospec=True)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_move_runtime_remove_from_dst(self, mock_glob, mock_rmtree,
- mock_move):
- mock_glob.side_effect = [['test/path/Runtime/iOS.simruntime'],
- [('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime')
- ]]
- xcode_util.move_runtime(self.runtime_cache_folder, self.xcode_app_path,
- True)
- xcode_runtime_path = ('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime')
- calls = [
- mock.call('test/path/Runtime/*.simruntime'),
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/*.simruntime'))
- ]
- mock_glob.assert_has_calls(calls)
- mock_rmtree.assert_called_with(xcode_runtime_path)
- mock_move.assert_called_with('test/path/Runtime/iOS.simruntime',
- xcode_runtime_path)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- def test_remove_runtimes(self, mock_glob, mock_rmtree):
- mock_glob.return_value = [
- ('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime'),
- ('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS 15.0.simruntime')
- ]
- xcode_util.remove_runtimes(self.xcode_app_path)
- calls = [
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/*.simruntime'))
- ]
- mock_glob.assert_has_calls(calls)
- calls = [
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS.simruntime')),
- mock.call(('test/path/Xcode.app/Contents/Developer/'
- 'Platforms/iPhoneOS.platform/Library/Developer/'
- 'CoreSimulator/Profiles/Runtimes/iOS 15.0.simruntime'))
- ]
- mock_rmtree.assert_has_calls(calls)
- class MacToolchainInvocationTests(XcodeUtilTest):
- """Test class for xcode_util functions invoking mac_toolchain."""
- def setUp(self):
- super(MacToolchainInvocationTests, self).setUp()
- self.mac_toolchain = 'mac_toolchain'
- self.xcode_build_version = 'TestXcodeVersion'
- self.xcode_app_path = 'test/path/Xcode.app'
- self.runtime_cache_folder = 'test/path/Runtime'
- self.ios_version = '14.4'
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('os.path.exists', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- @mock.patch('subprocess.check_call', autospec=True)
- def test_install_runtime_no_cache(self, mock_check_output, mock_glob,
- mock_exists, mock_rmtree):
- mock_glob.return_value = []
- mock_exists.return_value = False
- xcode_util._install_runtime(self.mac_toolchain, self.runtime_cache_folder,
- self.xcode_build_version, self.ios_version)
- mock_glob.assert_called_with('test/path/Runtime/*.simruntime')
- calls = [
- mock.call('test/path/Runtime/.cipd'),
- mock.call('test/path/Runtime/.xcode_versions'),
- ]
- mock_exists.assert_has_calls(calls)
- self.assertFalse(mock_rmtree.called)
- mock_check_output.assert_called_with([
- 'mac_toolchain', 'install-runtime', '-xcode-version',
- 'testxcodeversion', '-runtime-version', 'ios-14-4', '-output-dir',
- 'test/path/Runtime'
- ],
- stderr=-2)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('os.path.exists', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- @mock.patch('subprocess.check_call', autospec=True)
- def test_install_runtime_has_cache(self, mock_check_output, mock_glob,
- mock_exists, mock_rmtree):
- mock_glob.return_value = ['test/path/Runtime/iOS.simruntime']
- xcode_util._install_runtime(self.mac_toolchain, self.runtime_cache_folder,
- self.xcode_build_version, self.ios_version)
- mock_glob.assert_called_with('test/path/Runtime/*.simruntime')
- self.assertFalse(mock_exists.called)
- self.assertFalse(mock_rmtree.called)
- mock_check_output.assert_called_with([
- 'mac_toolchain', 'install-runtime', '-xcode-version',
- 'testxcodeversion', '-runtime-version', 'ios-14-4', '-output-dir',
- 'test/path/Runtime'
- ],
- stderr=-2)
- @mock.patch('shutil.rmtree', autospec=True)
- @mock.patch('os.path.exists', autospec=True)
- @mock.patch('glob.glob', autospec=True)
- @mock.patch('subprocess.check_call', autospec=True)
- def test_install_runtime_incorrect_cache(self, mock_check_output, mock_glob,
- mock_exists, mock_rmtree):
- mock_glob.return_value = []
- mock_exists.return_value = True
- xcode_util._install_runtime(self.mac_toolchain, self.runtime_cache_folder,
- self.xcode_build_version, self.ios_version)
- mock_glob.assert_called_with('test/path/Runtime/*.simruntime')
- calls = [
- mock.call('test/path/Runtime/.cipd'),
- mock.call('test/path/Runtime/.xcode_versions'),
- ]
- mock_exists.assert_has_calls(calls)
- mock_rmtree.assert_has_calls(calls)
- mock_check_output.assert_called_with([
- 'mac_toolchain', 'install-runtime', '-xcode-version',
- 'testxcodeversion', '-runtime-version', 'ios-14-4', '-output-dir',
- 'test/path/Runtime'
- ],
- stderr=-2)
- @mock.patch('subprocess.check_call', autospec=True)
- def test_install_xcode_legacy_mac_toolchain(self, mock_check_output):
- using_new_mac_toolchain = False
- xcode_util._install_xcode(self.mac_toolchain, self.xcode_build_version,
- self.xcode_app_path, using_new_mac_toolchain)
- mock_check_output.assert_called_with([
- 'mac_toolchain', 'install', '-kind', 'ios', '-xcode-version',
- 'testxcodeversion', '-output-dir', 'test/path/Xcode.app'
- ],
- stderr=-2)
- @mock.patch('subprocess.check_call', autospec=True)
- def test_install_xcode_new_mac_toolchain(self, mock_check_output):
- using_new_mac_toolchain = True
- xcode_util._install_xcode(self.mac_toolchain, self.xcode_build_version,
- self.xcode_app_path, using_new_mac_toolchain)
- mock_check_output.assert_called_with([
- 'mac_toolchain', 'install', '-kind', 'ios', '-xcode-version',
- 'testxcodeversion', '-output-dir', 'test/path/Xcode.app',
- '-with-runtime=False'
- ],
- stderr=-2)
- if __name__ == '__main__':
- logging.basicConfig(
- format='[%(asctime)s:%(levelname)s] %(message)s',
- level=logging.DEBUG,
- datefmt='%I:%M:%S')
- unittest.main()
|