diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2017-06-11 14:49:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-11 14:49:52 +0300 |
commit | b8f02047bec9fd2d1a36db82df5fed14ef386cd6 (patch) | |
tree | b4f2e99205f3b3846a086610802ad023227a35ae /run_unittests.py | |
parent | 22cfd44221ada3219d9096e15dc8b00d32e0f9f6 (diff) | |
parent | 868d85d2e567b0f5cfb49858eb0f2ac96f7d5749 (diff) | |
download | meson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.zip meson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.tar.gz meson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.tar.bz2 |
Merge pull request #1900 from centricular/abstract-extdeps
dependencies: Add a new class ExternalDependency
Diffstat (limited to 'run_unittests.py')
-rwxr-xr-x | run_unittests.py | 156 |
1 files changed, 145 insertions, 11 deletions
diff --git a/run_unittests.py b/run_unittests.py index 8a9ac0a..dbfd638 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -25,16 +25,19 @@ import unittest from configparser import ConfigParser from glob import glob from pathlib import PurePath + +import mesonbuild.mlog import mesonbuild.compilers import mesonbuild.environment import mesonbuild.mesonlib from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin from mesonbuild.environment import Environment +from mesonbuild.dependencies import DependencyException from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram from run_tests import exe_suffix, get_fake_options, FakeEnvironment from run_tests import get_builddir_target_args, get_backend_commands, Backend -from run_tests import ensure_backend_detects_changes +from run_tests import ensure_backend_detects_changes, run_configure_inprocess def get_dynamic_section_entry(fname, entry): @@ -401,8 +404,8 @@ class BasePlatformTests(unittest.TestCase): # Get the backend # FIXME: Extract this from argv? self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja')) - self.meson_command = [sys.executable, os.path.join(src_root, 'meson.py'), - '--backend=' + self.backend.name] + self.meson_args = [os.path.join(src_root, 'meson.py'), '--backend=' + self.backend.name] + self.meson_command = [sys.executable] + self.meson_args self.mconf_command = [sys.executable, os.path.join(src_root, 'mesonconf.py')] self.mintro_command = [sys.executable, os.path.join(src_root, 'mesonintrospect.py')] self.mtest_command = [sys.executable, os.path.join(src_root, 'mesontest.py'), '-C', self.builddir] @@ -452,7 +455,7 @@ class BasePlatformTests(unittest.TestCase): raise subprocess.CalledProcessError(p.returncode, command) return output - def init(self, srcdir, extra_args=None, default_args=True): + def init(self, srcdir, extra_args=None, default_args=True, inprocess=False): self.assertTrue(os.path.exists(srcdir)) if extra_args is None: extra_args = [] @@ -462,14 +465,27 @@ class BasePlatformTests(unittest.TestCase): if default_args: args += ['--prefix', self.prefix, '--libdir', self.libdir] - try: - self._run(self.meson_command + args + extra_args) - except unittest.SkipTest: - raise unittest.SkipTest('Project requested skipping: ' + srcdir) - except: - self._print_meson_log() - raise self.privatedir = os.path.join(self.builddir, 'meson-private') + if inprocess: + try: + out = run_configure_inprocess(self.meson_args + args + extra_args)[1] + except: + self._print_meson_log() + raise + finally: + # Close log file to satisfy Windows file locking + mesonbuild.mlog.shutdown() + mesonbuild.mlog.log_dir = None + mesonbuild.mlog.log_file = None + else: + try: + out = self._run(self.meson_command + args + extra_args) + except unittest.SkipTest: + raise unittest.SkipTest('Project requested skipping: ' + srcdir) + except: + self._print_meson_log() + raise + return out def build(self, target=None, extra_args=None): if extra_args is None: @@ -1196,6 +1212,124 @@ int main(int argc, char **argv) { self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) +class FailureTests(BasePlatformTests): + ''' + Tests that test failure conditions. Build files here should be dynamically + generated and static tests should go into `test cases/failing*`. + This is useful because there can be many ways in which a particular + function can fail, and creating failing tests for all of them is tedious + and slows down testing. + ''' + dnf = "[Dd]ependency.*not found" + + def setUp(self): + super().setUp() + self.srcdir = os.path.realpath(tempfile.mkdtemp()) + self.mbuild = os.path.join(self.srcdir, 'meson.build') + + def tearDown(self): + super().tearDown() + shutil.rmtree(self.srcdir) + + def assertMesonRaises(self, contents, match, extra_args=None, langs=None): + ''' + Assert that running meson configure on the specified @contents raises + a error message matching regex @match. + ''' + if langs is None: + langs = [] + with open(self.mbuild, 'w') as f: + f.write("project('failure test', 'c', 'cpp')\n") + for lang in langs: + f.write("add_languages('{}', required : false)\n".format(lang)) + f.write(contents) + # Force tracebacks so we can detect them properly + os.environ['MESON_FORCE_BACKTRACE'] = '1' + with self.assertRaisesRegex(DependencyException, match, msg=contents): + # Must run in-process or we'll get a generic CalledProcessError + self.init(self.srcdir, extra_args=extra_args, inprocess=True) + + def assertMesonOutputs(self, contents, match, extra_args=None, langs=None): + ''' + Assert that running meson configure on the specified @contents outputs + something that matches regex @match. + ''' + if langs is None: + langs = [] + with open(self.mbuild, 'w') as f: + f.write("project('output test', 'c', 'cpp')\n") + for lang in langs: + f.write("add_languages('{}', required : false)\n".format(lang)) + f.write(contents) + # Run in-process for speed and consistency with assertMesonRaises + out = self.init(self.srcdir, extra_args=extra_args, inprocess=True) + self.assertRegex(out, match) + + def test_dependency(self): + if not shutil.which('pkg-config'): + raise unittest.SkipTest('pkg-config not found') + a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"), + ("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"), + ("dependency('zlib', version : 1)", "[Vv]ersion.*string or list"), + ("dependency('zlib', required : 1)", "[Rr]equired.*boolean"), + ("dependency('zlib', method : 1)", "[Mm]ethod.*string"), + ("dependency('zlibfail')", self.dnf),) + for contents, match in a: + self.assertMesonRaises(contents, match) + + def test_apple_frameworks_dependency(self): + if not is_osx(): + raise unittest.SkipTest('only run on macOS') + self.assertMesonRaises("dependency('appleframeworks')", + "requires at least one module") + + def test_sdl2_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('sdl2-config'): + raise unittest.SkipTest('sdl2-config found') + self.assertMesonRaises("dependency('sdl2', method : 'sdlconfig')", self.dnf) + self.assertMesonRaises("dependency('sdl2', method : 'pkg-config')", self.dnf) + + def test_gnustep_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('gnustep-config'): + raise unittest.SkipTest('gnustep-config found') + self.assertMesonRaises("dependency('gnustep')", + "(requires a Objc compiler|{})".format(self.dnf), + langs = ['objc']) + + def test_wx_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('wx-config-3.0') or shutil.which('wx-config'): + raise unittest.SkipTest('wx-config or wx-config-3.0 found') + self.assertMesonRaises("dependency('wxwidgets')", self.dnf) + self.assertMesonOutputs("dependency('wxwidgets', required : false)", + "nor wx-config found") + + def test_wx_dependency(self): + if not shutil.which('wx-config-3.0') and not shutil.which('wx-config'): + raise unittest.SkipTest('Neither wx-config nor wx-config-3.0 found') + self.assertMesonRaises("dependency('wxwidgets', modules : 1)", + "module argument is not a string") + + def test_llvm_dependency(self): + self.assertMesonRaises("dependency('llvm', modules : 'fail')", + "(required.*fail|{})".format(self.dnf)) + + def test_boost_notfound_dependency(self): + # Can be run even if Boost is found or not + self.assertMesonRaises("dependency('boost', modules : 1)", + "module.*not a string") + self.assertMesonRaises("dependency('boost', modules : 'fail')", + "(fail.*not found|{})".format(self.dnf)) + + def test_boost_BOOST_ROOT_dependency(self): + # Test BOOST_ROOT; can be run even if Boost is found or not + os.environ['BOOST_ROOT'] = 'relative/path' + self.assertMesonRaises("dependency('boost')", + "(BOOST_ROOT.*absolute|{})".format(self.dnf)) + + class WindowsTests(BasePlatformTests): ''' Tests that should run on Cygwin, MinGW, and MSVC |