From 37838329a1b4a4a336dfb19c4710fccec404ad8b Mon Sep 17 00:00:00 2001 From: Kp Date: Sat, 22 Aug 2015 20:43:04 +0000 Subject: [PATCH] Add SConf hook to check result against expected value --- SConstruct | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/SConstruct b/SConstruct index edf4ad05a..f397e677c 100644 --- a/SConstruct +++ b/SConstruct @@ -188,6 +188,8 @@ class ConfigureTests: sconf_force_success = 'force-success' # Force test to report success, do not modify flags sconf_assume_success = 'assume-success' + expect_sconf_success = 'success' + expect_sconf_failure = 'failure' _implicit_test = Collector() _custom_test = Collector() implicit_tests = _implicit_test.tests @@ -257,6 +259,7 @@ struct %(N)s_derived : %(N)s_base { self.__automatic_compiler_tests = { '.cpp': self.check_cxx_works, } + self._sconf_results = [] def message(self,msg): print "%s: %s" % (self.msgprefix, msg) @classmethod @@ -271,8 +274,9 @@ struct %(N)s_derived : %(N)s_base { def _quote_macro_value(v): return v.strip().replace('\n', ' \\\n') def _check_sconf_forced(self,calling_function): - if calling_function is not None: - return self._check_forced(calling_function) + return self._check_forced(calling_function), self._check_expected(calling_function) + @staticmethod + def _find_calling_sconf_function(): try: 1//0 except ZeroDivisionError: @@ -280,11 +284,19 @@ struct %(N)s_derived : %(N)s_base { while frame is not None: co_name = frame.f_code.co_name if co_name[:6] == 'check_': - return self._check_forced(co_name[6:]) + return co_name[6:] frame = frame.f_back assert False def _check_forced(self,name): return getattr(self.user_settings, 'sconf_%s' % name) + def _check_expected(self,name): + r = getattr(self.user_settings, 'expect_sconf_%s' % name) + if r is not None: + if r == self.expect_sconf_success: + return 1 + if r == self.expect_sconf_failure: + return 0 + return r def _check_macro(self,context,macro_name,macro_value,test,**kwargs): macro_value = self._quote_macro_value(macro_value) r = self.Compile(context, text=""" @@ -310,13 +322,17 @@ struct %(N)s_derived : %(N)s_base { return self._Test(context,action=context.TryLink, **kwargs) def _Test(self,context,text,msg,action,main='',ext='.cpp',testflags={},successflags={},skipped=None,successmsg=None,failuremsg=None,expect_failure=False,calling_function=None): self._check_compiler_works(context,ext) + if calling_function is None: + calling_function = self._find_calling_sconf_function() context.Message('%s: checking %s...' % (self.msgprefix, msg)) if skipped is not None: context.Result('(skipped){skipped}'.format(skipped=skipped)) + if self.user_settings.record_sconf_results: + self._sconf_results.append((calling_function, 'skipped')) return env_flags = self.PreservedEnvironment(context.env, successflags.keys() + testflags.keys() + self.__flags_Werror.keys() + ['CPPDEFINES']) context.env.MergeFlags(successflags) - forced = self._check_sconf_forced(calling_function) + forced, expected = self._check_sconf_forced(calling_function) caller_modified_env_flags = self.PreservedEnvironment(context.env, self.__flags_Werror.keys() + testflags.keys()) # Always pass -Werror context.env.Append(**self.__flags_Werror) @@ -329,6 +345,8 @@ struct %(N)s_derived : %(N)s_base { r = not r cc_env_strings.restore(context.env) context.Result((successmsg if r else failuremsg) or r) + if expected is not None and r != expected: + raise SCons.Errors.StopError('Expected and actual results differ. Test should ' + ('succeed' if expected else 'fail') + ', but it did not.') else: choices = (self.sconf_force_failure, self.sconf_force_success, self.sconf_assume_success) if forced not in choices: @@ -368,6 +386,7 @@ struct %(N)s_derived : %(N)s_base { self._extend_successflags(k, v) else: env_flags.restore(context.env) + self._sconf_results.append((calling_function, r)) return r def _soft_check_system_library(self,context,header,main,lib,successflags={}): include = '\n'.join(['#include <%s>' % h for h in header]) @@ -1368,16 +1387,24 @@ class DXXCommon(LazyObjectConstructor): def _enum_variable(key,help,default,allowed_values): return EnumVariable(key, help, default, allowed_values) def _options(self): + tests = ConfigureTests.implicit_tests + ConfigureTests.custom_tests return ( { 'variable': self._enum_variable, 'arguments': [ - ('sconf_%s' % name[6:], None, ConfigureTests.describe(name) or ('assume result of %s' % name), {'allowed_values' : ['0', '1', '2', ConfigureTests.sconf_force_failure, ConfigureTests.sconf_force_success, ConfigureTests.sconf_assume_success]}) for name in ConfigureTests.implicit_tests + ConfigureTests.custom_tests if name[0] != '_' + ('expect_sconf_%s' % name[6:], None, None, {'allowed_values' : ['0', '1', ConfigureTests.expect_sconf_success, ConfigureTests.expect_sconf_failure]}) for name in tests + ], + }, + { + 'variable': self._enum_variable, + 'arguments': [ + ('sconf_%s' % name[6:], None, ConfigureTests.describe(name) or ('assume result of %s' % name), {'allowed_values' : ['0', '1', '2', ConfigureTests.sconf_force_failure, ConfigureTests.sconf_force_success, ConfigureTests.sconf_assume_success]}) for name in tests if name[0] != '_' ], }, { 'variable': BoolVariable, 'arguments': ( + ('record_sconf_results', False, 'write sconf results to dxxsconf.h'), ('raspberrypi', False, 'build for Raspberry Pi (automatically sets opengles and opengles_lib)'), ('git_describe_version', os.path.exists(os.environ.get('GIT_DIR', '.git')), 'include git --describe in extra_version'), ('git_status', True, 'include git status'), @@ -2010,6 +2037,8 @@ class DXXArchive(DXXCommon): getattr(conf, k)() except SCons.Errors.StopError as e: raise SCons.Errors.StopError(e.args[0] + ' See {log_file} for details.'.format(log_file=log_file), *e.args[1:]) + if self.user_settings.record_sconf_results: + conf.config_h_text += '/*\n' + '\n'.join(['check_%s=%s' % (n,v) for (n,v) in tests._sconf_results]) + '\n*/\n' self.env = conf.Finish() self.configure_pch_flags = tests.pch_flags