diff options
Diffstat (limited to 'run_unittests.py')
-rwxr-xr-x | run_unittests.py | 202 |
1 files changed, 111 insertions, 91 deletions
diff --git a/run_unittests.py b/run_unittests.py index 4b14a87..1ff54eb 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -30,8 +30,6 @@ import functools import io import operator import threading -import urllib.error -import urllib.request import zipfile import hashlib from itertools import chain @@ -61,7 +59,7 @@ from mesonbuild.mesonlib import ( quote_arg, relpath, is_linux, git, GIT ) from mesonbuild.environment import detect_ninja -from mesonbuild.mesonlib import MesonException, EnvironmentException +from mesonbuild.mesonlib import MesonException, EnvironmentException, OptionKey from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram import mesonbuild.dependencies.base from mesonbuild.build import Target, ConfigurationData @@ -265,7 +263,8 @@ def skip_if_not_base_option(feature): def wrapped(*args, **kwargs): env = get_fake_env() cc = env.detect_c_compiler(MachineChoice.HOST) - if feature not in cc.base_options: + key = OptionKey(feature) + if key not in cc.base_options: raise unittest.SkipTest( '{} not available with {}'.format(feature, cc.id)) return f(*args, **kwargs) @@ -874,7 +873,7 @@ class InternalTests(unittest.TestCase): env = get_fake_env() compiler = env.detect_c_compiler(MachineChoice.HOST) env.coredata.compilers.host = {'c': compiler} - env.coredata.compiler_options.host['c']['link_args'] = FakeCompilerOptions() + env.coredata.options[OptionKey('link_args', lang='c')] = FakeCompilerOptions() p1 = Path(tmpdir) / '1' p2 = Path(tmpdir) / '2' p1.mkdir() @@ -1336,10 +1335,10 @@ class DataTests(unittest.TestCase): cc = env.detect_c_compiler(MachineChoice.HOST) cpp = env.detect_cpp_compiler(MachineChoice.HOST) for comp in (cc, cpp): - for opt in comp.get_options().keys(): - self.assertIn(opt, md) + for opt in comp.get_options(): + self.assertIn(str(opt), md) for opt in comp.base_options: - self.assertIn(opt, md) + self.assertIn(str(opt), md) self.assertNotIn('b_unknown', md) @staticmethod @@ -1392,8 +1391,8 @@ class DataTests(unittest.TestCase): found_entries |= options self.assertEqual(found_entries, set([ - *mesonbuild.coredata.BUILTIN_OPTIONS.keys(), - *mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE.keys() + *[str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS], + *[str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE], ])) # Check that `buildtype` table inside `Core options` matches how @@ -1414,10 +1413,10 @@ class DataTests(unittest.TestCase): debug = False else: raise RuntimeError('Invalid debug value {!r} in row:\n{}'.format(debug, m.group())) - env.coredata.set_builtin_option('buildtype', buildtype) - self.assertEqual(env.coredata.builtins['buildtype'].value, buildtype) - self.assertEqual(env.coredata.builtins['optimization'].value, opt) - self.assertEqual(env.coredata.builtins['debug'].value, debug) + env.coredata.set_option(OptionKey('buildtype'), buildtype) + self.assertEqual(env.coredata.options[OptionKey('buildtype')].value, buildtype) + self.assertEqual(env.coredata.options[OptionKey('optimization')].value, opt) + self.assertEqual(env.coredata.options[OptionKey('debug')].value, debug) def test_cpu_families_documented(self): with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f: @@ -1905,11 +1904,14 @@ class AllPlatformTests(BasePlatformTests): https://github.com/mesonbuild/meson/issues/1349 ''' testdir = os.path.join(self.common_test_dir, '88 default options') - self.init(testdir, default_args=False) + self.init(testdir, default_args=False, inprocess=True) opts = self.introspect('--buildoptions') for opt in opts: if opt['name'] == 'prefix': prefix = opt['value'] + break + else: + raise self.fail('Did not find option "prefix"') self.assertEqual(prefix, '/absoluteprefix') def test_do_conf_file_preserve_newlines(self): @@ -3632,10 +3634,10 @@ class AllPlatformTests(BasePlatformTests): def test_conflicting_d_dash_option(self): testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') - with self.assertRaises(subprocess.CalledProcessError) as e: + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as e: self.init(testdir, extra_args=['-Dbindir=foo', '--bindir=bar']) # Just to ensure that we caught the correct error - self.assertIn('passed as both', e.stderr) + self.assertIn('as both', e.stderr) def _test_same_option_twice(self, arg, args): testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') @@ -3684,57 +3686,63 @@ class AllPlatformTests(BasePlatformTests): # Verify default values when passing no args that affect the # configuration, and as a bonus, test that --profile-self works. - self.init(testdir, extra_args=['--profile-self']) + self.init(testdir, extra_args=['--profile-self', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'static') - self.assertEqual(obj.builtins['warning_level'].value, '1') - self.assertEqual(obj.user_options['set_sub_opt'].value, True) - self.assertEqual(obj.user_options['subp:subp_opt'].value, 'default3') + self.assertEqual(obj.options[OptionKey('default_library')].value, 'static') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.assertEqual(obj.options[OptionKey('set_sub_opt')].value, True) + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'default3') self.wipe() # warning_level is special, it's --warnlevel instead of --warning-level # for historical reasons - self.init(testdir, extra_args=['--warnlevel=2']) + self.init(testdir, extra_args=['--warnlevel=2', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '2') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') self.setconf('--warnlevel=3') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '3') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') self.wipe() # But when using -D syntax, it should be 'warning_level' - self.init(testdir, extra_args=['-Dwarning_level=2']) + self.init(testdir, extra_args=['-Dwarning_level=2', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '2') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') self.setconf('-Dwarning_level=3') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '3') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') self.wipe() # Mixing --option and -Doption is forbidden - with self.assertRaises(subprocess.CalledProcessError) as cm: + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: self.init(testdir, extra_args=['--warnlevel=1', '-Dwarning_level=3']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('as both', cm.exception.output) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) self.init(testdir) - with self.assertRaises(subprocess.CalledProcessError) as cm: + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: self.setconf(['--warnlevel=1', '-Dwarning_level=3']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('as both', cm.exception.output) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) self.wipe() # --default-library should override default value from project() - self.init(testdir, extra_args=['--default-library=both']) + self.init(testdir, extra_args=['--default-library=both', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'both') + self.assertEqual(obj.options[OptionKey('default_library')].value, 'both') self.setconf('--default-library=shared') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'shared') + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') if self.backend is Backend.ninja: # reconfigure target works only with ninja backend self.build('reconfigure') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'shared') + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') self.wipe() # Should warn on unknown options @@ -3743,15 +3751,22 @@ class AllPlatformTests(BasePlatformTests): self.wipe() # Should fail on malformed option - with self.assertRaises(subprocess.CalledProcessError) as cm: + msg = "Option 'foo' must have a value separated by equals sign." + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: self.init(testdir, extra_args=['-Dfoo']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('Option \'foo\' must have a value separated by equals sign.', cm.exception.output) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) self.init(testdir) - with self.assertRaises(subprocess.CalledProcessError) as cm: + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: self.setconf('-Dfoo') - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('Option \'foo\' must have a value separated by equals sign.', cm.exception.output) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) self.wipe() # It is not an error to set wrong option for unknown subprojects or @@ -3760,24 +3775,24 @@ class AllPlatformTests(BasePlatformTests): self.wipe() # Test we can set subproject option - self.init(testdir, extra_args=['-Dsubp:subp_opt=foo']) + self.init(testdir, extra_args=['-Dsubp:subp_opt=foo', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.user_options['subp:subp_opt'].value, 'foo') + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'foo') self.wipe() # c_args value should be parsed with split_args - self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"']) + self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dfoo', '-Dbar', '-Dthird=one two']) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo', '-Dbar', '-Dthird=one two']) self.setconf('-Dc_args="foo bar" one two') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.compiler_options.host['c']['args'].value, ['foo bar', 'one', 'two']) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['foo bar', 'one', 'two']) self.wipe() - self.init(testdir, extra_args=['-Dset_percent_opt=myoption%']) + self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.user_options['set_percent_opt'].value, 'myoption%') + self.assertEqual(obj.options[OptionKey('set_percent_opt')].value, 'myoption%') self.wipe() # Setting a 2nd time the same option should override the first value @@ -3785,21 +3800,22 @@ class AllPlatformTests(BasePlatformTests): self.init(testdir, extra_args=['--bindir=foo', '--bindir=bar', '-Dbuildtype=plain', '-Dbuildtype=release', '-Db_sanitize=address', '-Db_sanitize=thread', - '-Dc_args=-Dfoo', '-Dc_args=-Dbar']) + '-Dc_args=-Dfoo', '-Dc_args=-Dbar', + '-Db_lundef=false', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['bindir'].value, 'bar') - self.assertEqual(obj.builtins['buildtype'].value, 'release') - self.assertEqual(obj.base_options['b_sanitize'].value, 'thread') - self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dbar']) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'bar') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'release') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'thread') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dbar']) self.setconf(['--bindir=bar', '--bindir=foo', '-Dbuildtype=release', '-Dbuildtype=plain', '-Db_sanitize=thread', '-Db_sanitize=address', '-Dc_args=-Dbar', '-Dc_args=-Dfoo']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['bindir'].value, 'foo') - self.assertEqual(obj.builtins['buildtype'].value, 'plain') - self.assertEqual(obj.base_options['b_sanitize'].value, 'address') - self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dfoo']) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'foo') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'plain') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'address') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo']) self.wipe() except KeyError: # Ignore KeyError, it happens on CI for compilers that does not @@ -3813,25 +3829,25 @@ class AllPlatformTests(BasePlatformTests): # Verify default values when passing no args self.init(testdir) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') self.wipe() # verify we can override w/ --warnlevel self.init(testdir, extra_args=['--warnlevel=1']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '1') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') self.setconf('--warnlevel=0') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') self.wipe() # verify we can override w/ -Dwarning_level self.init(testdir, extra_args=['-Dwarning_level=1']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '1') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') self.setconf('-Dwarning_level=0') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') self.wipe() def test_feature_check_usage_subprojects(self): @@ -4238,7 +4254,8 @@ class AllPlatformTests(BasePlatformTests): self.init(testdir, default_args=False) res_wb = self.introspect('--buildoptions') self.maxDiff = None - self.assertListEqual(res_nb, res_wb) + # XXX: These now generate in a different order, is that okay? + self.assertListEqual(sorted(res_nb, key=lambda x: x['name']), sorted(res_wb, key=lambda x: x['name'])) def test_meson_configure_from_source_does_not_crash(self): testdir = os.path.join(self.unit_test_dir, '59 introspect buildoptions') @@ -4489,20 +4506,20 @@ class AllPlatformTests(BasePlatformTests): with open(introfile, 'r') as fp: res1 = json.load(fp) - self.setconf('-Dcpp_std=c++14') - self.setconf('-Dbuildtype=release') - - for idx, i in enumerate(res1): + for i in res1: if i['name'] == 'cpp_std': - res1[idx]['value'] = 'c++14' + i['value'] = 'c++14' if i['name'] == 'build.cpp_std': - res1[idx]['value'] = 'c++14' + i['value'] = 'c++14' if i['name'] == 'buildtype': - res1[idx]['value'] = 'release' + i['value'] = 'release' if i['name'] == 'optimization': - res1[idx]['value'] = '3' + i['value'] = '3' if i['name'] == 'debug': - res1[idx]['value'] = False + i['value'] = False + + self.setconf('-Dcpp_std=c++14') + self.setconf('-Dbuildtype=release') with open(introfile, 'r') as fp: res2 = json.load(fp) @@ -5758,7 +5775,7 @@ class WindowsTests(BasePlatformTests): # Verify that the `b_vscrt` option is available env = get_fake_env() cc = env.detect_c_compiler(MachineChoice.HOST) - if 'b_vscrt' not in cc.base_options: + if OptionKey('b_vscrt') not in cc.base_options: raise unittest.SkipTest('Compiler does not support setting the VS CRT') # Verify that qmake is for Qt5 if not shutil.which('qmake-qt5'): @@ -5784,7 +5801,7 @@ class WindowsTests(BasePlatformTests): # Verify that the `b_vscrt` option is available env = get_fake_env() cc = env.detect_c_compiler(MachineChoice.HOST) - if 'b_vscrt' not in cc.base_options: + if OptionKey('b_vscrt') not in cc.base_options: raise unittest.SkipTest('Compiler does not support setting the VS CRT') def sanitycheck_vscrt(vscrt): @@ -6285,7 +6302,7 @@ class LinuxlikeTests(BasePlatformTests): Oargs = [arg for arg in cmd if arg.startswith('-O')] self.assertEqual(Oargs, [Oflag, '-O0']) - def _test_stds_impl(self, testdir, compiler: 'Compiler', p: str) -> None: + def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0')) @@ -6301,8 +6318,8 @@ class LinuxlikeTests(BasePlatformTests): # Check that all the listed -std=xxx options for this compiler work just fine when used # https://en.wikipedia.org/wiki/Xcode#Latest_versions # https://www.gnu.org/software/gcc/projects/cxx-status.html - for v in compiler.get_options()['std'].choices: - lang_std = p + '_std' + key = OptionKey('std', lang=compiler.language) + for v in compiler.get_options()[key].choices: # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly # thus, C++ first if '++17' in v and not has_cpp17: @@ -6316,8 +6333,7 @@ class LinuxlikeTests(BasePlatformTests): continue elif '18' in v and not has_c18: continue - std_opt = '{}={}'.format(lang_std, v) - self.init(testdir, extra_args=['-D' + std_opt]) + self.init(testdir, extra_args=[f'-D{key!s}={v}']) cmd = self.get_compdb()[0]['command'] # c++03 and gnu++03 are not understood by ICC, don't try to look for them skiplist = frozenset([ @@ -6329,15 +6345,15 @@ class LinuxlikeTests(BasePlatformTests): try: self.build() except Exception: - print('{} was {!r}'.format(lang_std, v)) + print(f'{key!s} was {v!r}') raise self.wipe() # Check that an invalid std option in CFLAGS/CPPFLAGS fails # Needed because by default ICC ignores invalid options cmd_std = '-std=FAIL' - if p == 'c': + if compiler.language == 'c': env_flag_name = 'CFLAGS' - elif p == 'cpp': + elif compiler.language == 'cpp': env_flag_name = 'CXXFLAGS' else: raise NotImplementedError('Language {} not defined.'.format(p)) @@ -6358,7 +6374,7 @@ class LinuxlikeTests(BasePlatformTests): testdir = os.path.join(self.common_test_dir, '1 trivial') env = get_fake_env(testdir, self.builddir, self.prefix) cc = env.detect_c_compiler(MachineChoice.HOST) - self._test_stds_impl(testdir, cc, 'c') + self._test_stds_impl(testdir, cc) def test_compiler_cpp_stds(self): ''' @@ -6368,7 +6384,7 @@ class LinuxlikeTests(BasePlatformTests): testdir = os.path.join(self.common_test_dir, '2 cpp') env = get_fake_env(testdir, self.builddir, self.prefix) cpp = env.detect_cpp_compiler(MachineChoice.HOST) - self._test_stds_impl(testdir, cpp, 'cpp') + self._test_stds_impl(testdir, cpp) def test_unity_subproj(self): testdir = os.path.join(self.common_test_dir, '43 subproject') @@ -6890,7 +6906,7 @@ class LinuxlikeTests(BasePlatformTests): self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc'))) env = get_fake_env(testdir, self.builddir, self.prefix) - env.coredata.set_options({'pkg_config_path': pkg_dir}, subproject='') + env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') kwargs = {'required': True, 'silent': True} relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) self.assertTrue(relative_path_dep.found()) @@ -8442,9 +8458,13 @@ class NativeFileTests(BasePlatformTests): testcase = os.path.join(self.common_test_dir, '224 persubproject options') config = self.helper_create_native_file({'sub2:built-in options': {'default_library': 'shared'}}) - with self.assertRaises(subprocess.CalledProcessError) as cm: + with self.assertRaises((RuntimeError, subprocess.CalledProcessError)) as cm: self.init(testcase, extra_args=['--native-file', config]) - self.assertIn(cm.exception.stdout, 'Parent should override default_library') + if isinstance(cm, RuntimeError): + check = str(cm.exception) + else: + check = cm.exception.stdout + self.assertIn(check, 'Parent should override default_library') def test_builtin_options_subprojects_dont_inherits_parent_override(self): # If the buildfile says subproject(... default_library: shared), ensure that's overwritten @@ -9299,7 +9319,7 @@ class SubprojectsCommandTests(BasePlatformTests): out = self._subprojects_cmd(['foreach', '--types', 'git'] + dummy_cmd) self.assertEqual(ran_in(out), ['subprojects/sub_git']) -def _clang_at_least(compiler, minver: str, apple_minver: T.Optional[str]) -> bool: +def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool: """ check that Clang compiler is at least a specified version, whether AppleClang or regular Clang |