diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2017-03-14 05:47:38 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-14 05:47:38 -0400 |
commit | 02da0a02a60fd72a9e7cb28f5efc4ee3bd64c64b (patch) | |
tree | 9cdb586f7a16bee0e2a9f3e88b3e4a0fb38cbb6e | |
parent | 1612dbd719cafc88db2da098a035c82456e4c638 (diff) | |
parent | f427603aa26e6db9dfeaff06eb6a4bb9967f25cc (diff) | |
download | meson-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-x | run_project_tests.py | 50 | ||||
-rwxr-xr-x | run_unittests.py | 37 | ||||
-rw-r--r-- | test cases/common/37 has header/meson.build | 73 |
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 |