# This source file is part of the Swift.org open source project # # Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors # Licensed under Apache License v2.0 with Runtime Library Exception # # See https://swift.org/LICENSE.txt for license information # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors from __future__ import unicode_literals import os from .utils import TestCase, UTILS_PATH, add_metaclass from .. import presets from ..presets import Preset, PresetParser try: # Python 2 import ConfigParser as configparser except ImportError: import configparser PRESET_FILES = [ os.path.join(UTILS_PATH, 'build-presets.ini'), ] PRESET_DEFAULTS = { 'darwin_toolchain_alias': 'Alias', 'darwin_toolchain_bundle_identifier': 'BundleIdentifier', 'darwin_toolchain_display_name': 'DisplayName', 'darwin_toolchain_display_name_short': 'DispalyNameShort', 'darwin_toolchain_version': '1.0', 'darwin_toolchain_xctoolchain_name': 'default', 'extra_swift_args': '', 'install_destdir': '/tmp/install', 'install_symroot': '/tmp/install/symroot', 'install_toolchain_dir': '/tmp/install/toolchain', 'installable_package': '/tmp/install/pkg', 'swift_install_destdir': '/tmp/install/swift', 'symbols_package': '/path/to/symbols/package', } SAMPLE_PRESET = """ [preset: sample] # This is a comment ios tvos watchos test validation-test lit-args=-v compiler-vendor=apple # The '--' argument is now unnecessary dash-dash verbose-build build-ninja # Default interpolation install-symroot=%(install_symroot)s """ IGNORED_SECTION = """ [section_name] random-options=1 """ MIXIN_ORDER_PRESETS = """ [preset: test_mixin] first-opt=0 second-opt=1 [preset: test] first-opt=1 mixin-preset=test_mixin second-opt=2 """ INTERPOLATED_PRESET = """ [preset: test] install-symroot=%(install_symroot)s """ DUPLICATE_PRESET_NAMES = """ [preset: test] ios [preset: test] tvos """ DUPLICATE_PRESET_OPTIONS = """ [preset: test] ios ios """ # ----------------------------------------------------------------------------- class TestPreset(TestCase): def test_format_args(self): preset = Preset('sample', [('--ios', None), ('--test', '1')]) self.assertEqual(preset.format_args(), ['--ios', '--test=1']) # ----------------------------------------------------------------------------- class TestPresetParserMeta(type): """Metaclass used to dynamically generate test methods to validate all of the available presets. """ def __new__(cls, name, bases, attrs): preset_parser = PresetParser() preset_parser.read(PRESET_FILES) # Generate tests for each preset for preset_name in preset_parser.preset_names(): test_name = 'test_get_preset_' + preset_name attrs[test_name] = cls.generate_get_preset_test( preset_parser, preset_name) return super(TestPresetParserMeta, cls).__new__( cls, name, bases, attrs) @classmethod def generate_get_preset_test(cls, preset_parser, preset_name): def test(self): preset_parser.get_preset(preset_name, vars=PRESET_DEFAULTS) return test @add_metaclass(TestPresetParserMeta) class TestPresetParser(TestCase): def test_read(self): parser = PresetParser() parser.read(PRESET_FILES) def test_read_invalid_files(self): parser = PresetParser() with self.assertRaises(presets.UnparsedFilesError) as cm: parser.read(['nonsense-presets.ini']) e = cm.exception self.assertListEqual(e.filenames, ['nonsense-presets.ini']) def test_read_file(self): parser = PresetParser() with self.assertNotRaises(): parser.read_file(PRESET_FILES[0]) def test_read_string(self): parser = PresetParser() parser.read_string(SAMPLE_PRESET) preset = parser.get_preset('sample', vars={'install_symroot': '/tmp'}) self.assertIsNotNone(preset) self.assertEqual(preset.name, 'sample') self.assertListEqual(preset.args, [ ('--ios', None), ('--tvos', None), ('--watchos', None), ('--test', None), ('--validation-test', None), ('--lit-args', '-v'), ('--compiler-vendor', 'apple'), ('--verbose-build', None), ('--build-ninja', None), ('--install-symroot', '/tmp') ]) def test_parser_ignores_non_preset_sections(self): parser = PresetParser() parser.read_string(IGNORED_SECTION) self.assertEqual(len(parser._presets), 0) def test_mixin_expansion_preserves_argument_order(self): """Mixins should be expanded in-place. """ parser = PresetParser() parser.read_string(MIXIN_ORDER_PRESETS) preset = parser.get_preset('test') self.assertListEqual(preset.format_args(), [ '--first-opt=1', # Mixin arguments '--first-opt=0', '--second-opt=1', '--second-opt=2', ]) def test_interpolation_error(self): parser = PresetParser() parser.read_string(INTERPOLATED_PRESET) with self.assertRaises(presets.InterpolationError) as cm: parser.get_preset('test') e = cm.exception self.assertEqual(e.preset_name, 'test') self.assertEqual(e.option, '--install-symroot') self.assertEqual(e.rawval, '%(install_symroot)s') self.assertEqual(e.reference, 'install_symroot') def test_duplicate_option_error(self): # Skip test if using the Python 2 ConfigParser module if not hasattr(configparser, 'DuplicateOptionError'): return parser = PresetParser() with self.assertRaises(presets.DuplicateOptionError) as cm: parser.read_string(DUPLICATE_PRESET_OPTIONS) e = cm.exception self.assertEqual(e.preset_name, 'test') self.assertEqual(e.option, 'ios') def test_duplicate_preset_error(self): # Skip test if using the Python 2 ConfigParser module if not hasattr(configparser, 'DuplicateOptionError'): return parser = PresetParser() with self.assertRaises(presets.DuplicatePresetError) as cm: parser.read_string(DUPLICATE_PRESET_NAMES) e = cm.exception self.assertEqual(e.preset_name, 'test') def test_get_preset_raw(self): parser = PresetParser() parser.read_string(INTERPOLATED_PRESET) preset = parser.get_preset('test', raw=True) self.assertEqual(preset.args, [ ('--install-symroot', '%(install_symroot)s') ]) def test_get_missing_preset(self): parser = PresetParser() with self.assertRaises(presets.PresetNotFoundError) as cm: parser.get_preset('test') e = cm.exception self.assertEqual(e.preset_name, 'test') def test_preset_names(self): parser = PresetParser() parser.read_string('[preset: foo]') parser.read_string('[preset: bar]') parser.read_string('[preset: baz]') self.assertEqual(set(parser.preset_names()), set(['foo', 'bar', 'baz']))