aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-03-14 05:47:38 -0400
committerGitHub <noreply@github.com>2017-03-14 05:47:38 -0400
commit02da0a02a60fd72a9e7cb28f5efc4ee3bd64c64b (patch)
tree9cdb586f7a16bee0e2a9f3e88b3e4a0fb38cbb6e
parent1612dbd719cafc88db2da098a035c82456e4c638 (diff)
parentf427603aa26e6db9dfeaff06eb6a4bb9967f25cc (diff)
downloadmeson-02da0a02a60fd72a9e7cb28f5efc4ee3bd64c64b.zip
meson-02da0a02a60fd72a9e7cb28f5efc4ee3bd64c64b.tar.gz
meson-02da0a02a60fd72a9e7cb28f5efc4ee3bd64c64b.tar.bz2
Merge pull request #1463 from centricular/test-has-include-fallback
tests/37 has header: Also test the fallback include check
-rwxr-xr-xrun_project_tests.py50
-rwxr-xr-xrun_unittests.py37
-rw-r--r--test cases/common/37 has header/meson.build73
3 files changed, 101 insertions, 59 deletions
diff --git a/run_project_tests.py b/run_project_tests.py
index 1457432..3684de5 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -18,6 +18,7 @@ from glob import glob
import os, subprocess, shutil, sys, signal
from io import StringIO
from ast import literal_eval
+from enum import Enum
import tempfile
import mesontest
from mesonbuild import environment
@@ -33,9 +34,17 @@ import concurrent.futures as conc
from mesonbuild.coredata import backendlist
+class BuildStep(Enum):
+ configure = 1
+ build = 2
+ test = 3
+ install = 4
+ clean = 5
+
class TestResult:
- def __init__(self, msg, stdo, stde, mlog, conftime=0, buildtime=0, testtime=0):
+ def __init__(self, msg, step, stdo, stde, mlog, conftime=0, buildtime=0, testtime=0):
self.msg = msg
+ self.step = step
self.stdo = stdo
self.stde = stde
self.mlog = mlog
@@ -74,6 +83,7 @@ class AutoDeletedDir:
failing_logs = []
print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ
do_debug = not {'MESON_PRINT_TEST_OUTPUT', 'TRAVIS', 'APPVEYOR'}.isdisjoint(os.environ)
+no_meson_log_msg = 'No meson-log.txt found.'
meson_command = os.path.join(os.getcwd(), 'meson')
if not os.path.exists(meson_command):
@@ -270,14 +280,14 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
with open(logfile, errors='ignore') as f:
mesonlog = f.read()
except Exception:
- mesonlog = 'No meson-log.txt found.'
+ mesonlog = no_meson_log_msg
gen_time = time.time() - gen_start
if should_fail == 'meson':
if returncode != 0:
- return TestResult('', stdo, stde, mesonlog, gen_time)
- return TestResult('Test that should have failed succeeded', stdo, stde, mesonlog, gen_time)
+ return TestResult('', BuildStep.configure, stdo, stde, mesonlog, gen_time)
+ return TestResult('Test that should have failed succeeded', BuildStep.configure, stdo, stde, mesonlog, gen_time)
if returncode != 0:
- return TestResult('Generating the build system failed.', stdo, stde, mesonlog, gen_time)
+ return TestResult('Generating the build system failed.', BuildStep.configure, stdo, stde, mesonlog, gen_time)
# Build with subprocess
comp = get_compile_commands_for_dir(compile_commands, test_build_dir)
build_start = time.time()
@@ -287,10 +297,10 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
stde += e
if should_fail == 'build':
if pc.returncode != 0:
- return TestResult('', stdo, stde, mesonlog, gen_time)
- return TestResult('Test that should have failed to build succeeded', stdo, stde, mesonlog, gen_time)
+ return TestResult('', BuildStep.build, stdo, stde, mesonlog, gen_time)
+ return TestResult('Test that should have failed to build succeeded', BuildStep.build, stdo, stde, mesonlog, gen_time)
if pc.returncode != 0:
- return TestResult('Compiling source code failed.', stdo, stde, mesonlog, gen_time, build_time)
+ return TestResult('Compiling source code failed.', BuildStep.build, stdo, stde, mesonlog, gen_time, build_time)
# Touch the meson.build file to force a regenerate so we can test that
# regeneration works. We need to sleep for 0.2s because Ninja tracks mtimes
# at a low resolution: https://github.com/ninja-build/ninja/issues/371
@@ -304,12 +314,12 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
stde += tstde
if should_fail == 'test':
if returncode != 0:
- return TestResult('', stdo, stde, mesonlog, gen_time)
- return TestResult('Test that should have failed to run unit tests succeeded', stdo, stde, mesonlog, gen_time)
+ return TestResult('', BuildStep.test, stdo, stde, mesonlog, gen_time)
+ return TestResult('Test that should have failed to run unit tests succeeded', BuildStep.test, stdo, stde, mesonlog, gen_time)
if returncode != 0:
- return TestResult('Running unit tests failed.', stdo, stde, mesonlog, gen_time, build_time, test_time)
+ return TestResult('Running unit tests failed.', BuildStep.test, stdo, stde, mesonlog, gen_time, build_time, test_time)
if len(install_commands) == 0:
- return TestResult('', '', '', gen_time, build_time, test_time)
+ return TestResult('', BuildStep.install, '', '', mesonlog, gen_time, build_time, test_time)
env = os.environ.copy()
env['DESTDIR'] = install_dir
# Install with subprocess
@@ -317,7 +327,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
stdo += o
stde += e
if pi.returncode != 0:
- return TestResult('Running install failed.', stdo, stde, mesonlog, gen_time, build_time, test_time)
+ return TestResult('Running install failed.', BuildStep.install, stdo, stde, mesonlog, gen_time, build_time, test_time)
if len(clean_commands) != 0:
env = os.environ.copy()
# Clean with subprocess
@@ -325,8 +335,8 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
stdo += o
stde += e
if pi.returncode != 0:
- return TestResult('Running clean failed.', stdo, stde, mesonlog, gen_time, build_time, test_time)
- return TestResult(validate_install(testdir, install_dir), stdo, stde, mesonlog, gen_time, build_time, test_time)
+ return TestResult('Running clean failed.', BuildStep.clean, stdo, stde, mesonlog, gen_time, build_time, test_time)
+ return TestResult(validate_install(testdir, install_dir), BuildStep.clean, stdo, stde, mesonlog, gen_time, build_time, test_time)
def gather_tests(testdir):
tests = [t.replace('\\', '/').split('/', 2)[2] for t in glob(os.path.join(testdir, '*'))]
@@ -441,10 +451,16 @@ def run_tests(all_tests, log_name_base, extra_args):
else:
without_install = "" if len(install_commands) > 0 else " (without install)"
if result.msg != '':
- print('Failed test%s: %s' % (without_install, t))
+ print('Failed test{} during {}: {!r}'.format(without_install, result.step.name, t))
print('Reason:', result.msg)
failing_tests += 1
- failing_logs.append(result.stdo)
+ if result.step == BuildStep.configure and result.mlog != no_meson_log_msg:
+ # For configure failures, instead of printing stdout,
+ # print the meson log if available since it's a superset
+ # of stdout and often has very useful information.
+ failing_logs.append(result.mlog)
+ else:
+ failing_logs.append(result.stdo)
failing_logs.append(result.stde)
else:
print('Succeeded test%s: %s' % (without_install, t))
diff --git a/run_unittests.py b/run_unittests.py
index 82c1b80..9945057 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -356,16 +356,31 @@ class BasePlatformTests(unittest.TestCase):
self.unit_test_dir = os.path.join(src_root, 'test cases/unit')
self.orig_env = os.environ.copy()
+ def _print_meson_log(self):
+ log = os.path.join(self.logdir, 'meson-log.txt')
+ if not os.path.isfile(log):
+ print("{!r} doesn't exist".format(log))
+ return
+ with open(log, 'r', encoding='utf-8') as f:
+ print(f.read())
+
def tearDown(self):
shutil.rmtree(self.builddir)
os.environ = self.orig_env
super().tearDown()
def _run(self, command):
- output = subprocess.check_output(command, stderr=subprocess.STDOUT,
- env=os.environ.copy(),
- universal_newlines=True)
+ '''
+ Run a command while printing the stdout and stderr to stdout,
+ and also return a copy of it
+ '''
+ p = subprocess.Popen(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, env=os.environ.copy(),
+ universal_newlines=True)
+ output = p.communicate()[0]
print(output)
+ if p.returncode != 0:
+ raise subprocess.CalledProcessError(p.returncode, command)
return output
def init(self, srcdir, extra_args=None, default_args=True):
@@ -375,7 +390,11 @@ class BasePlatformTests(unittest.TestCase):
if default_args:
args += ['--prefix', self.prefix,
'--libdir', self.libdir]
- self._run(self.meson_command + args + extra_args)
+ try:
+ self._run(self.meson_command + args + extra_args)
+ except:
+ self._print_meson_log()
+ raise
self.privatedir = os.path.join(self.builddir, 'meson-private')
def build(self, extra_args=None):
@@ -394,11 +413,11 @@ class BasePlatformTests(unittest.TestCase):
self._run(self.ninja_command + ['uninstall'])
def run_target(self, target):
- output = subprocess.check_output(self.ninja_command + [target],
- stderr=subprocess.STDOUT,
- universal_newlines=True)
- print(output)
- return output
+ '''
+ Run a Ninja target while printing the stdout and stderr to stdout,
+ and also return a copy of it
+ '''
+ return self._run(self.ninja_command + [target])
def setconf(self, arg, will_build=True):
# This is needed to increase the difference between build.ninja's
diff --git a/test cases/common/37 has header/meson.build b/test cases/common/37 has header/meson.build
index 9709183..4299ce5 100644
--- a/test cases/common/37 has header/meson.build
+++ b/test cases/common/37 has header/meson.build
@@ -9,39 +9,46 @@ configure_file(input : non_existant_header,
output : non_existant_header,
configuration : configuration_data())
-foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')]
- if not comp.has_header('stdio.h')
- error('Stdio missing.')
- endif
-
- # stdio.h doesn't actually need stdlib.h, but just test that setting the
- # prefix does not result in an error.
- if not comp.has_header('stdio.h', prefix : '#include <stdlib.h>')
- error('Stdio missing.')
- endif
-
- # XInput.h should not require type definitions from windows.h, but it does
- # require macro definitions. Specifically, it requires an arch setting for
- # VS2015 at least.
- # We only do this check on MSVC because MinGW often defines its own wrappers
- # that pre-include windows.h
- if comp.get_id() == 'msvc'
- if not comp.has_header('XInput.h', prefix : '#include <windows.h>')
- error('XInput.h should not be missing on Windows')
+# Test that the fallback to __has_include also works on all compilers
+if host_system != 'darwin'
+ args = [[], ['-U__has_include']]
+else
+ # On Darwin's clang you can't redefine builtin macros so the above doesn't work
+ args = [[]]
+endif
+
+foreach arg : args
+ foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')]
+ assert(comp.has_header('stdio.h', args : arg), 'Stdio missing.')
+
+ # stdio.h doesn't actually need stdlib.h, but just test that setting the
+ # prefix does not result in an error.
+ assert(comp.has_header('stdio.h', prefix : '#include <stdlib.h>', args : arg),
+ 'Stdio missing.')
+
+ # XInput.h should not require type definitions from windows.h, but it does
+ # require macro definitions. Specifically, it requires an arch setting for
+ # VS2015 at least.
+ # We only do this check on MSVC because MinGW often defines its own wrappers
+ # that pre-include windows.h
+ if comp.get_id() == 'msvc'
+ assert(comp.has_header('XInput.h', prefix : '#include <windows.h>', args : arg),
+ 'XInput.h should not be missing on Windows')
+ assert(comp.has_header('XInput.h', prefix : '#define _X86_', args : arg),
+ 'XInput.h should not need windows.h')
endif
- if not comp.has_header('XInput.h', prefix : '#define _X86_')
- error('XInput.h should not need windows.h')
+
+ # Test that the following GCC bug doesn't happen:
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005
+ # https://github.com/mesonbuild/meson/issues/1458
+ if host_system == 'linux'
+ assert(comp.has_header('linux/if.h', args : arg),
+ 'Could not find <linux/if.h>')
endif
- endif
-
- # Test that the following GCC bug doesn't happen:
- # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005
- # https://github.com/mesonbuild/meson/issues/1458
- if host_system == 'linux'
- assert(comp.has_header('linux/if.h'), 'Could not find <linux/if.h>')
- endif
-
- # This header exists in the source and the builddir, but we still must not
- # find it since we are looking in the system directories.
- assert(not comp.has_header(non_existant_header), 'Found non-existant header.')
+
+ # This header exists in the source and the builddir, but we still must not
+ # find it since we are looking in the system directories.
+ assert(not comp.has_header(non_existant_header, args : arg),
+ 'Found non-existant header.')
+ endforeach
endforeach