aboutsummaryrefslogtreecommitdiff
path: root/run_unittests.py
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-06-11 14:49:52 +0300
committerGitHub <noreply@github.com>2017-06-11 14:49:52 +0300
commitb8f02047bec9fd2d1a36db82df5fed14ef386cd6 (patch)
treeb4f2e99205f3b3846a086610802ad023227a35ae /run_unittests.py
parent22cfd44221ada3219d9096e15dc8b00d32e0f9f6 (diff)
parent868d85d2e567b0f5cfb49858eb0f2ac96f7d5749 (diff)
downloadmeson-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-xrun_unittests.py156
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