Merge pull request #2863 from jon-turney/exit-status-on-exception
Verify that failing tests are failing with an error, not a python exception
This commit is contained in:
commit
55a7c265c1
|
@ -146,3 +146,9 @@ Meson has a standard command line help feature. It can be accessed
|
||||||
with the following command.
|
with the following command.
|
||||||
|
|
||||||
meson --help
|
meson --help
|
||||||
|
|
||||||
|
Exit status
|
||||||
|
==
|
||||||
|
|
||||||
|
Meson exits with status 0 if successful, 1 for problems with the command line or
|
||||||
|
meson.build file, and 2 for internal errors.
|
||||||
|
|
13
man/meson.1
13
man/meson.1
|
@ -202,6 +202,19 @@ show available versions of the specified project
|
||||||
\fBstatus\fR
|
\fBstatus\fR
|
||||||
show installed and available versions of currently used subprojects
|
show installed and available versions of currently used subprojects
|
||||||
|
|
||||||
|
.SH EXIT STATUS
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B 0
|
||||||
|
Successful.
|
||||||
|
.TP
|
||||||
|
.B 1
|
||||||
|
Usage error, or an error parsing or executing meson.build.
|
||||||
|
.TP
|
||||||
|
.B 2
|
||||||
|
Internal error.
|
||||||
|
.TP
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
|
||||||
http://mesonbuild.com/
|
http://mesonbuild.com/
|
||||||
|
|
|
@ -695,10 +695,11 @@ class Environment:
|
||||||
for compiler in compilers:
|
for compiler in compilers:
|
||||||
if isinstance(compiler, str):
|
if isinstance(compiler, str):
|
||||||
compiler = [compiler]
|
compiler = [compiler]
|
||||||
|
arg = ['--version']
|
||||||
try:
|
try:
|
||||||
p, out = Popen_safe(compiler + ['--version'])[0:2]
|
p, out = Popen_safe(compiler + arg)[0:2]
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
popen_exceptions[compiler] = e
|
popen_exceptions[' '.join(compiler + arg)] = e
|
||||||
continue
|
continue
|
||||||
|
|
||||||
version = search_version(out)
|
version = search_version(out)
|
||||||
|
|
|
@ -1504,6 +1504,8 @@ class Interpreter(InterpreterBase):
|
||||||
'test': self.func_test,
|
'test': self.func_test,
|
||||||
'vcs_tag': self.func_vcs_tag,
|
'vcs_tag': self.func_vcs_tag,
|
||||||
})
|
})
|
||||||
|
if 'MESON_UNIT_TEST' in os.environ:
|
||||||
|
self.funcs.update({'exception': self.func_exception})
|
||||||
|
|
||||||
def holderify(self, item):
|
def holderify(self, item):
|
||||||
if isinstance(item, list):
|
if isinstance(item, list):
|
||||||
|
@ -1984,6 +1986,11 @@ to directly access options of other subprojects.''')
|
||||||
self.validate_arguments(args, 1, [str])
|
self.validate_arguments(args, 1, [str])
|
||||||
raise InterpreterException('Problem encountered: ' + args[0])
|
raise InterpreterException('Problem encountered: ' + args[0])
|
||||||
|
|
||||||
|
@noKwargs
|
||||||
|
def func_exception(self, node, args, kwargs):
|
||||||
|
self.validate_arguments(args, 0, [])
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
def detect_compilers(self, lang, need_cross_compiler):
|
def detect_compilers(self, lang, need_cross_compiler):
|
||||||
cross_comp = None
|
cross_comp = None
|
||||||
if lang == 'c':
|
if lang == 'c':
|
||||||
|
|
|
@ -267,9 +267,8 @@ class InterpreterBase:
|
||||||
|
|
||||||
def validate_comparison_types(self, val1, val2):
|
def validate_comparison_types(self, val1, val2):
|
||||||
if type(val1) != type(val2):
|
if type(val1) != type(val2):
|
||||||
mlog.warning('''Trying to compare values of different types ({}, {}).
|
return False
|
||||||
The result of this is undefined and will become a hard error
|
return True
|
||||||
in a future Meson release.'''.format(type(val1).__name__, type(val2).__name__))
|
|
||||||
|
|
||||||
def evaluate_comparison(self, node):
|
def evaluate_comparison(self, node):
|
||||||
val1 = self.evaluate_statement(node.left)
|
val1 = self.evaluate_statement(node.left)
|
||||||
|
@ -278,11 +277,23 @@ in a future Meson release.'''.format(type(val1).__name__, type(val2).__name__))
|
||||||
val2 = self.evaluate_statement(node.right)
|
val2 = self.evaluate_statement(node.right)
|
||||||
if is_disabler(val2):
|
if is_disabler(val2):
|
||||||
return val2
|
return val2
|
||||||
self.validate_comparison_types(val1, val2)
|
valid = self.validate_comparison_types(val1, val2)
|
||||||
|
# Ordering comparisons of different types isn't allowed since PR #1810
|
||||||
|
# (0.41.0). Since PR #2884 we also warn about equality comparisons of
|
||||||
|
# different types, which will one day become an error.
|
||||||
|
if not valid and (node.ctype == '==' or node.ctype == '!='):
|
||||||
|
mlog.warning('''Trying to compare values of different types ({}, {}) using {}.
|
||||||
|
The result of this is undefined and will become a hard error in a future Meson release.'''
|
||||||
|
.format(type(val1).__name__, type(val2).__name__, node.ctype), location=node)
|
||||||
if node.ctype == '==':
|
if node.ctype == '==':
|
||||||
return val1 == val2
|
return val1 == val2
|
||||||
elif node.ctype == '!=':
|
elif node.ctype == '!=':
|
||||||
return val1 != val2
|
return val1 != val2
|
||||||
|
elif not valid:
|
||||||
|
raise InterpreterException(
|
||||||
|
'Values of different types ({}, {}) cannot be compared using {}.'.format(type(val1).__name__,
|
||||||
|
type(val2).__name__,
|
||||||
|
node.ctype))
|
||||||
elif not self.is_elementary_type(val1):
|
elif not self.is_elementary_type(val1):
|
||||||
raise InterpreterException('{} can only be compared for equality.'.format(node.left.value))
|
raise InterpreterException('{} can only be compared for equality.'.format(node.left.value))
|
||||||
elif not self.is_elementary_type(val2):
|
elif not self.is_elementary_type(val2):
|
||||||
|
|
|
@ -376,11 +376,12 @@ def run(original_args, mainfile=None):
|
||||||
mlog.log("\nA full log can be found at", mlog.bold(logfile))
|
mlog.log("\nA full log can be found at", mlog.bold(logfile))
|
||||||
if os.environ.get('MESON_FORCE_BACKTRACE'):
|
if os.environ.get('MESON_FORCE_BACKTRACE'):
|
||||||
raise
|
raise
|
||||||
|
return 1
|
||||||
else:
|
else:
|
||||||
if os.environ.get('MESON_FORCE_BACKTRACE'):
|
if os.environ.get('MESON_FORCE_BACKTRACE'):
|
||||||
raise
|
raise
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return 1
|
return 2
|
||||||
finally:
|
finally:
|
||||||
mlog.shutdown()
|
mlog.shutdown()
|
||||||
|
|
||||||
|
|
|
@ -321,9 +321,12 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
|
||||||
mesonlog = no_meson_log_msg
|
mesonlog = no_meson_log_msg
|
||||||
gen_time = time.time() - gen_start
|
gen_time = time.time() - gen_start
|
||||||
if should_fail == 'meson':
|
if should_fail == 'meson':
|
||||||
if returncode != 0:
|
if returncode == 1:
|
||||||
return TestResult('', BuildStep.configure, 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)
|
elif returncode != 0:
|
||||||
|
return TestResult('Test exited with unexpected status {}'.format(returncode), BuildStep.configure, stdo, stde, mesonlog, gen_time)
|
||||||
|
else:
|
||||||
|
return TestResult('Test that should have failed succeeded', BuildStep.configure, stdo, stde, mesonlog, gen_time)
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
return TestResult('Generating the build system failed.', BuildStep.configure, stdo, stde, mesonlog, gen_time)
|
return TestResult('Generating the build system failed.', BuildStep.configure, stdo, stde, mesonlog, gen_time)
|
||||||
# Touch the meson.build file to force a regenerate so we can test that
|
# Touch the meson.build file to force a regenerate so we can test that
|
||||||
|
|
|
@ -1933,6 +1933,17 @@ class FailureTests(BasePlatformTests):
|
||||||
self.assertRegex(out, r'Also couldn\'t find a fallback subproject in '
|
self.assertRegex(out, r'Also couldn\'t find a fallback subproject in '
|
||||||
'.*subprojects.*failingsubproj.*for the dependency.*somedep')
|
'.*subprojects.*failingsubproj.*for the dependency.*somedep')
|
||||||
|
|
||||||
|
def test_exception_exit_status(self):
|
||||||
|
'''
|
||||||
|
Test exit status on python exception
|
||||||
|
'''
|
||||||
|
tdir = os.path.join(self.unit_test_dir, '21 exit status')
|
||||||
|
os.environ['MESON_UNIT_TEST'] = '1'
|
||||||
|
with self.assertRaises(subprocess.CalledProcessError) as cm:
|
||||||
|
self.init(tdir, inprocess=False)
|
||||||
|
self.assertEqual(cm.exception.returncode, 2)
|
||||||
|
self.wipe()
|
||||||
|
|
||||||
|
|
||||||
class WindowsTests(BasePlatformTests):
|
class WindowsTests(BasePlatformTests):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -126,3 +126,14 @@ test('equalfalse', exe13)
|
||||||
test('equaltrue', exe14)
|
test('equaltrue', exe14)
|
||||||
test('nequaltrue', exe15)
|
test('nequaltrue', exe15)
|
||||||
test('nequalfalse', exe16)
|
test('nequalfalse', exe16)
|
||||||
|
|
||||||
|
# Equality comparisons of different elementary types
|
||||||
|
# (these all cause warnings currently, will become an error in future)
|
||||||
|
|
||||||
|
assert([] != 'st', 'not equal')
|
||||||
|
assert([] != 1, 'not equal')
|
||||||
|
assert(2 != 'st', 'not equal')
|
||||||
|
|
||||||
|
assert(not ([] == 'st'), 'not equal')
|
||||||
|
assert(not ([] == 1), 'not equal')
|
||||||
|
assert(not (2 == 'st'), 'not equal')
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
project('exit status')
|
||||||
|
exception()
|
Loading…
Reference in New Issue