http://scons.tigris.org/issues/show_bug.cgi?id=2329
[scons.git] / src / engine / SCons / SConfTests.py
index bf003b4d3fd6ba49e35a2729cad46a2a5532db2d..26f21f398b00b5e5ba82a01fb6ff12cdfa53547a 100644 (file)
@@ -25,7 +25,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import os
 import re
-import string
 import StringIO
 import sys
 from types import *
@@ -44,20 +43,25 @@ class SConfTestCase(unittest.TestCase):
 
     def setUp(self):
         # we always want to start with a clean directory
+        self.save_cwd = os.getcwd()
         self.test = TestCmd.TestCmd(workdir = '') 
+        os.chdir(self.test.workpath(''))
 
     def tearDown(self):
         self.test.cleanup()
+        import SCons.SConsign
+        SCons.SConsign.Reset()
+        os.chdir(self.save_cwd)
 
     def _resetSConfState(self):
         # Ok, this is tricky, and i do not know, if everything is sane.
         # We try to reset scons' state (including all global variables)
-        import SCons.Sig
-        SCons.Sig.write() # simulate normal scons-finish
+        import SCons.SConsign
+        SCons.SConsign.write() # simulate normal scons-finish
         for n in sys.modules.keys():
-            if string.split(n, '.')[0] == 'SCons':
+            if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat':
                 m = sys.modules[n]
-                if type(m) is ModuleType:
+                if isinstance(m, ModuleType):
                     # if this is really a scons module, clear its namespace
                     del sys.modules[n]
                     m.__dict__.clear()
@@ -69,37 +73,45 @@ class SConfTestCase(unittest.TestCase):
         # and we need a new environment, cause references may point to
         # old modules (well, at least this is safe ...)
         self.scons_env = self.Environment.Environment()
-        self.scons_env['ENV']['PATH'] = os.environ['PATH']
+        self.scons_env.AppendENVPath('PATH', os.environ['PATH'])
 
         # we want to do some autodetection here
         # this stuff works with
-        #    - cygwin on win32 (using cmd.exe, not bash)
+        #    - cygwin on Windows (using cmd.exe, not bash)
         #    - posix
-        #    - msvc on win32 (hopefully)
-        if self.scons_env.subst('$CXX') == 'c++':
-            # better use g++ (which is normally no symbolic link
-            # --> the c++ call fails on cygwin
-            self.scons_env['CXX'] = 'g++'
-        if self.scons_env.subst('$LINK') == 'c++':
-            self.scons_env['LINK'] = 'g++'
+        #    - msvc on Windows (hopefully)
         if (not self.scons_env.Detect( self.scons_env.subst('$CXX') ) or
             not self.scons_env.Detect( self.scons_env.subst('$CC') ) or
             not self.scons_env.Detect( self.scons_env.subst('$LINK') )):
             raise Exception, "This test needs an installed compiler!"
-        if self.scons_env['LINK'] == 'g++':
+        if self.scons_env['CXX'] == 'g++':
             global existing_lib
             existing_lib = 'm'
-        
+
+        if sys.platform in ['cygwin', 'win32']:
+             # On Windows, SCons.Platform.win32 redefines the builtin
+             # file() and open() functions to close the file handles.
+             # This interferes with the unittest.py infrastructure in
+             # some way.  Just sidestep the issue by restoring the
+             # original builtin functions whenever we have to reset
+             # all of our global state.
+
+             import __builtin__
+             import SCons.Platform.win32
+
+             __builtin__.file = SCons.Platform.win32._builtin_file
+             __builtin__.open = SCons.Platform.win32._builtin_open
+
     def _baseTryXXX(self, TryFunc):
         # TryCompile and TryLink are much the same, so we can test them
         # in one method, we pass the function as a string ('TryCompile',
         # 'TryLink'), so we are aware of reloading modules.
         
         def checks(self, sconf, TryFuncString):
-            TryFunc = self.SConf.SConf.__dict__[TryFuncString]
-            res1 = TryFunc( sconf, "int main() { return 0; }", ".c" )
+            TryFunc = self.SConf.SConfBase.__dict__[TryFuncString]
+            res1 = TryFunc( sconf, "int main() { return 0; }\n", ".c" )
             res2 = TryFunc( sconf,
-                            '#include "no_std_header.h"\nint main() {return 0; }',
+                            '#include "no_std_header.h"\nint main() {return 0; }\n',
                             '.c' )
             return (res1,res2)
 
@@ -110,7 +122,7 @@ class SConfTestCase(unittest.TestCase):
                                  log_file=self.test.workpath('config.log'))
         try:
             res = checks( self, sconf, TryFunc )
-            assert res[0] and not res[1] 
+            assert res[0] and not res[1], res
         finally:
             sconf.Finish()
             
@@ -121,28 +133,29 @@ class SConfTestCase(unittest.TestCase):
                                  log_file=self.test.workpath('config.log'))
         try:
             res = checks( self, sconf, TryFunc )
-            assert res[0] and not res[1] 
+            assert res[0] and not res[1], res
         finally:
             sconf.Finish()
         # we should have exactly one one error cached 
         log = self.test.read( self.test.workpath('config.log') )
-        expr = re.compile( ".*(\(cached\))", re.DOTALL ) 
+        expr = re.compile( ".*failed in a previous run and all", re.DOTALL ) 
         firstOcc = expr.match( log )
-        assert firstOcc != None 
+        assert firstOcc is not None, log
         secondOcc = expr.match( log, firstOcc.end(0) )
-        assert secondOcc == None
+        assert secondOcc is None, log
 
         # 2.2 test the error caching mechanism (dependencies have changed)
         self._resetSConfState()
         sconf = self.SConf.SConf(self.scons_env,
                                  conf_dir=self.test.workpath('config.tests'),
                                  log_file=self.test.workpath('config.log'))
-        test_h = self.test.write( self.test.workpath('config.tests', 'no_std_header.h'),
-                                  "/* we are changing a dependency now */" );
+        no_std_header_h = self.test.workpath('config.tests', 'no_std_header.h')
+        test_h = self.test.write( no_std_header_h,
+                                  "/* we are changing a dependency now */\n" );
         try:
             res = checks( self, sconf, TryFunc )
             log = self.test.read( self.test.workpath('config.log') )
-            assert res[0] and res[1] 
+            assert res[0] and res[1], res
         finally:
             sconf.Finish()
 
@@ -154,7 +167,8 @@ class SConfTestCase(unittest.TestCase):
         sconf = self.SConf.SConf(self.scons_env,
                                  conf_dir=self.test.workpath('config.tests'),
                                  log_file=self.test.workpath('config.log'))
-        class MyBuilder:
+        import SCons.Builder
+        class MyBuilder(SCons.Builder.BuilderBase):
             def __init__(self):
                 self.prefix = ''
                 self.suffix = ''
@@ -163,7 +177,12 @@ class SConfTestCase(unittest.TestCase):
                     def __init__(self, name):
                         self.name = name
                         self.state = None
+                        self.waiting_parents = set()
                         self.side_effects = []
+                        self.builder = None
+                        self.prerequisites = []
+                    def disambiguate(self):
+                        return self
                     def has_builder(self):
                         return 1
                     def add_pre_action(self, *actions):
@@ -180,9 +199,39 @@ class SConfTestCase(unittest.TestCase):
                         return [], None
                     def depends_on(self, nodes):
                         return None
+                    def postprocess(self):
+                        pass
+                    def clear(self):
+                        pass
+                    def is_up_to_date(self):
+                        return None
+                    def prepare(self):
+                        pass
+                    def push_to_cache(self):
+                        pass
+                    def retrieve_from_cache(self):
+                        return 0
+                    def build(self, **kw):
+                        return
+                    def built(self):
+                        pass
+                    def get_stored_info(self):
+                        pass
+                    def do_not_store_info(self):
+                        pass
+                    def get_executor(self):
+                        class Executor:
+                            def __init__(self, targets):
+                                self.targets = targets
+                            def get_all_targets(self):
+                                return self.targets
+                        return Executor([self])
                 return [MyNode('n1'), MyNode('n2')]
-        self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
-        sconf.TryBuild(self.scons_env.SConfActionBuilder)
+        try:
+            self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
+            sconf.TryBuild(self.scons_env.SConfActionBuilder)
+        finally:
+            sconf.Finish()
 
     def test_TryCompile(self):
         """Test SConf.TryCompile
@@ -206,7 +255,7 @@ int main() {
 }
 """
             res1 = sconf.TryRun( prog, ".c" ) 
-            res2 = sconf.TryRun( "not a c program", ".c" )
+            res2 = sconf.TryRun( "not a c program\n", ".c" )
             return (res1, res2)
         
         self._resetSConfState()
@@ -215,10 +264,11 @@ int main() {
                                  log_file=self.test.workpath('config.log'))
         try:
             res = checks(sconf)
-            assert res[0][0] and res[0][1] == "Hello" 
-            assert not res[1][0] and res[1][1] == ""
+            assert res[0][0] and res[0][1] == "Hello", res
+            assert not res[1][0] and res[1][1] == "", res
         finally:
             sconf.Finish()
+        log = self.test.read( self.test.workpath('config.log') )
 
         # test the caching mechanism
         self._resetSConfState()
@@ -227,24 +277,24 @@ int main() {
                                  log_file=self.test.workpath('config.log'))
         try:
             res = checks(sconf)
-            assert res[0][0] and res[0][1] == "Hello" 
-            assert not res[1][0] and res[1][1] == ""
+            assert res[0][0] and res[0][1] == "Hello", res
+            assert not res[1][0] and res[1][1] == "", res
         finally:
             sconf.Finish()
-        # we should have exactly one one error cached 
+        # we should have exactly one error cached 
         log = self.test.read( self.test.workpath('config.log') )
-        expr = re.compile( ".*(\(cached\))", re.DOTALL )
+        expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
         firstOcc = expr.match( log )
-        assert firstOcc != None 
+        assert firstOcc is not None, log
         secondOcc = expr.match( log, firstOcc.end(0) )
-        assert secondOcc == None 
+        assert secondOcc is None, log
 
 
     def test_TryAction(self):
         """Test SConf.TryAction
         """
         def actionOK(target, source, env):
-            open(str(target[0]), "w").write( "RUN OK" )
+            open(str(target[0]), "w").write( "RUN OK\n" )
             return None
         def actionFAIL(target, source, env):
             return 1
@@ -254,102 +304,414 @@ int main() {
                                   log_file=self.test.workpath('config.log'))
         try:
             (ret, output) = sconf.TryAction(action=actionOK)
-            assert ret and output == "RUN OK"
+            assert ret and output == "RUN OK" + os.linesep, (ret, output)
             (ret, output) = sconf.TryAction(action=actionFAIL)
-            assert not ret and output == ""
+            assert not ret and output == "", (ret, output)
         finally:
             sconf.Finish()
-            
-        
 
-    def test_StandardTests(self):
-        """Test standard checks
+    def _test_check_compilers(self, comp, func, name):
+        """This is the implementation for CheckCC and CheckCXX tests."""
+        from copy import deepcopy
+
+        # Check that Check* works
+        r = func()
+        assert r, "could not find %s ?" % comp
+
+        # Check that Check* does fail if comp is not available in env
+        oldcomp = deepcopy(self.scons_env[comp])
+        del self.scons_env[comp]
+        r = func()
+        assert not r, "%s worked wo comp ?" % name
+
+        # Check that Check* does fail if comp is set but empty
+        self.scons_env[comp] = ''
+        r = func()
+        assert not r, "%s worked with comp = '' ?" % name
+
+        # Check that Check* does fail if comp is set to buggy executable
+        self.scons_env[comp] = 'thiscccompilerdoesnotexist'
+        r = func()
+        assert not r, "%s worked with comp = thiscompilerdoesnotexist ?" % name
+
+        # Check that Check* does fail if CFLAGS is buggy
+        self.scons_env[comp] = oldcomp
+        self.scons_env['%sFLAGS' % comp] = '/WX qwertyuiop.c'
+        r = func()
+        assert not r, "%s worked with %sFLAGS = qwertyuiop ?" % (name, comp)
+
+    def test_CheckCC(self):
+        """Test SConf.CheckCC()
         """
-        def CHeaderChecks( sconf ):
-            res1 = sconf.CheckCHeader( "stdio.h", include_quotes="<>" )
-            res2 = sconf.CheckCHeader( "HopefullyNotCHeader.noh" )
-            return (res1,res2)
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            try:
+                self._test_check_compilers('CC', sconf.CheckCC, 'CheckCC')
+            except AssertionError:
+                sys.stderr.write(self.test.read('config.log'))
+                raise
+        finally:
+            sconf.Finish()
 
-        def CXXHeaderChecks(sconf):
-            res1 = sconf.CheckCXXHeader( "vector", include_quotes="<>" )
-            res2 = sconf.CheckCXXHeader( "HopefullyNotCXXHeader.noh" )
-            return (res1,res2)
+    def test_CheckSHCC(self):
+        """Test SConf.CheckSHCC()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            try:
+                self._test_check_compilers('SHCC', sconf.CheckSHCC, 'CheckSHCC')
+            except AssertionError:
+                sys.stderr.write(self.test.read('config.log'))
+                raise
+        finally:
+            sconf.Finish()
 
-        def LibChecks(sconf):
-            res1 = sconf.CheckLib( existing_lib, "main", autoadd=0 )
-            res2 = sconf.CheckLib( "hopefullynolib", "main", autoadd=0 )
-            return (res1, res2)
-        
-        def LibChecksAutoAdd(sconf):
+    def test_CheckCXX(self):
+        """Test SConf.CheckCXX()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            try:
+                self._test_check_compilers('CXX', sconf.CheckCXX, 'CheckCXX')
+            except AssertionError:
+                sys.stderr.write(self.test.read('config.log'))
+                raise
+        finally:
+            sconf.Finish()
+
+    def test_CheckSHCXX(self):
+        """Test SConf.CheckSHCXX()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            try:
+                self._test_check_compilers('SHCXX', sconf.CheckSHCXX, 'CheckSHCXX')
+            except AssertionError:
+                sys.stderr.write(self.test.read('config.log'))
+                raise
+        finally:
+            sconf.Finish()
+
+
+    def test_CheckHeader(self):
+        """Test SConf.CheckHeader()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            # CheckHeader()
+            r = sconf.CheckHeader( "stdio.h", include_quotes="<>", language="C" )
+            assert r, "did not find stdio.h"
+            r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C" )
+            assert not r, "unexpectedly found HopefullyNoHeader.noh"
+            r = sconf.CheckHeader( "vector", include_quotes="<>", language="C++" )
+            assert r, "did not find vector"
+            r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C++" )
+            assert not r, "unexpectedly found HopefullyNoHeader.noh"
+
+        finally:
+            sconf.Finish()
+
+    def test_CheckCHeader(self):
+        """Test SConf.CheckCHeader()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+
+        try:
+            # CheckCHeader()
+            r = sconf.CheckCHeader( "stdio.h", include_quotes="<>" )
+            assert r, "did not find stdio.h"
+            r = sconf.CheckCHeader( ["math.h", "stdio.h"], include_quotes="<>" )
+            assert r, "did not find stdio.h, #include math.h first"
+            r = sconf.CheckCHeader( "HopefullyNoCHeader.noh" )
+            assert not r, "unexpectedly found HopefullyNoCHeader.noh"
+
+        finally:
+            sconf.Finish()
+
+    def test_CheckCXXHeader(self):
+        """Test SConf.CheckCXXHeader()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+
+        try:
+            # CheckCXXHeader()
+            r = sconf.CheckCXXHeader( "vector", include_quotes="<>" )
+            assert r, "did not find vector"
+            r = sconf.CheckCXXHeader( ["stdio.h", "vector"], include_quotes="<>" )
+            assert r, "did not find vector, #include stdio.h first"
+            r = sconf.CheckCXXHeader( "HopefullyNoCXXHeader.noh" )
+            assert not r, "unexpectedly found HopefullyNoCXXHeader.noh"
+
+        finally:
+            sconf.Finish()
+
+    def test_CheckLib(self):
+        """Test SConf.CheckLib()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+
+        try:
+            # CheckLib()
+            r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
+            assert r, "did not find %s" % existing_lib
+            r = sconf.CheckLib( "hopefullynolib", "main", autoadd=0 )
+            assert not r, "unexpectedly found hopefullynolib"
+
+            # CheckLib() with list of libs
+            r = sconf.CheckLib( [existing_lib], "main", autoadd=0 )
+            assert r, "did not find %s" % existing_lib
+            r = sconf.CheckLib( ["hopefullynolib"], "main", autoadd=0 )
+            assert not r, "unexpectedly found hopefullynolib"
+            # This is a check that a null list doesn't find functions
+            # that are in libraries that must be explicitly named.
+            # This works on POSIX systems where you have to -lm to
+            # get the math functions, but it fails on Visual Studio
+            # where you apparently get all those functions for free.
+            # Comment out this check until someone who understands
+            # Visual Studio better can come up with a corresponding
+            # test (if that ever really becomes necessary).
+            #r = sconf.CheckLib( [], "sin", autoadd=0 )
+            #assert not r, "unexpectedly found nonexistent library"
+            r = sconf.CheckLib( [existing_lib,"hopefullynolib"], "main", autoadd=0 )
+            assert r, "did not find %s,%s " % (existing_lib,r)
+            r = sconf.CheckLib( ["hopefullynolib",existing_lib], "main", autoadd=0 )
+            assert r, "did not find %s " % existing_lib
+
+            # CheckLib() with autoadd
             def libs(env):
-                if env.has_key( "LIBS" ):
-                    return env['LIBS']
-                else:
-                    return []
-            env = sconf.env.Copy()
-            res1 = sconf.CheckLib( existing_lib, "main", autoadd=1 )
-            libs1 = (libs(env), libs(sconf.env) )
-            sconf.env = env.Copy()
-            res2 = sconf.CheckLib( existing_lib, "main", autoadd=0 )
-            libs2 = (libs(env), libs(sconf.env) )
-            sconf.env = env.Copy()
-            return ((res1, libs1), (res2, libs2))
-
-        def LibWithHeaderChecks(sconf):
-            res1 = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
-            res2 = sconf.CheckLibWithHeader( "hopefullynolib", "math.h", "C", autoadd=0 )
-            return (res1, res2)
+                return env.get('LIBS', [])
+
+            env = sconf.env.Clone()
+
+            try:
+                r = sconf.CheckLib( existing_lib, "main", autoadd=1 )
+                assert r, "did not find main in %s" % existing_lib
+                expect = libs(env) + [existing_lib]
+                got = libs(sconf.env)
+                assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
+
+                sconf.env = env.Clone()
+                r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
+                assert r, "did not find main in %s" % existing_lib
+                expect = libs(env)
+                got = libs(sconf.env)
+                assert got == expect, "before and after LIBS were not the same"
+            finally:
+                sconf.env = env
+        finally:
+            sconf.Finish()
 
-        def LibWithHeaderChecksAutoAdd(sconf):
+    def test_CheckLibWithHeader(self):
+        """Test SConf.CheckLibWithHeader()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+
+        try:
+            # CheckLibWithHeader()
+            r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
+            assert r, "did not find %s" % existing_lib
+            r = sconf.CheckLibWithHeader( existing_lib, ["stdio.h", "math.h"], "C", autoadd=0 )
+            assert r, "did not find %s, #include stdio.h first" % existing_lib
+            r = sconf.CheckLibWithHeader( "hopefullynolib", "math.h", "C", autoadd=0 )
+            assert not r, "unexpectedly found hopefullynolib"
+
+            # CheckLibWithHeader() with lists of libs
+            r = sconf.CheckLibWithHeader( [existing_lib], "math.h", "C", autoadd=0 )
+            assert r, "did not find %s" % existing_lib
+            r = sconf.CheckLibWithHeader( [existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
+            assert r, "did not find %s, #include stdio.h first" % existing_lib
+            # This is a check that a null list doesn't find functions
+            # that are in libraries that must be explicitly named.
+            # This works on POSIX systems where you have to -lm to
+            # get the math functions, but it fails on Visual Studio
+            # where you apparently get all those functions for free.
+            # Comment out this check until someone who understands
+            # Visual Studio better can come up with a corresponding
+            # test (if that ever really becomes necessary).
+            #r = sconf.CheckLibWithHeader( [], "math.h", "C", call="sin(3);", autoadd=0 )
+            #assert not r, "unexpectedly found non-existent library"
+            r = sconf.CheckLibWithHeader( ["hopefullynolib"], "math.h", "C", autoadd=0 )
+            assert not r, "unexpectedly found hopefullynolib"
+            r = sconf.CheckLibWithHeader( ["hopefullynolib",existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
+            assert r, "did not find %s, #include stdio.h first" % existing_lib
+            r = sconf.CheckLibWithHeader( [existing_lib,"hopefullynolib"], ["stdio.h", "math.h"], "C", autoadd=0 )
+            assert r, "did not find %s, #include stdio.h first" % existing_lib
+
+            # CheckLibWithHeader with autoadd
             def libs(env):
-                if env.has_key( "LIBS" ):
-                    return env['LIBS']
-                else:
-                    return []
-            env = sconf.env.Copy()
-            res1 = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
-            libs1 = (libs(env), libs(sconf.env) )
-            sconf.env = env.Copy()
-            res2 = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
-            libs2 = (libs(env), libs(sconf.env) )
-            sconf.env = env.Copy()
-            return ((res1, libs1), (res2, libs2))
-
-        def FuncChecks(sconf):
-            res1 = sconf.CheckFunc('strcpy')
-            res2 = sconf.CheckFunc('hopefullynofunction')
-            return (res1, res2)
+                return env.get('LIBS', [])
 
-        def TypeChecks(sconf):
-            res1 = sconf.CheckType('u_int', '#include <sys/types.h>\n')
-            res2 = sconf.CheckType('hopefullynotypedef_not')
-            return (res1, res2)
+            env = sconf.env.Clone()
+
+            try:
+                r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
+                assert r, "did not find math.h with %s" % existing_lib
+                expect = libs(env) + [existing_lib]
+                got = libs(sconf.env)
+                assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
+
+                sconf.env = env.Clone()
+                r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
+                assert r, "did not find math.h with %s" % existing_lib
+                expect = libs(env)
+                got = libs(sconf.env)
+                assert got == expect, "before and after LIBS were not the same"
+            finally:
+                sconf.env = env
+
+        finally:
+            sconf.Finish()
 
+    def test_CheckFunc(self):
+        """Test SConf.CheckFunc()
+        """
         self._resetSConfState()
         sconf = self.SConf.SConf(self.scons_env,
                                  conf_dir=self.test.workpath('config.tests'),
                                  log_file=self.test.workpath('config.log'))
+
         try:
-            (res1, res2) = CHeaderChecks(sconf)
-            assert res1 and not res2 
-            (res1, res2) = CXXHeaderChecks(sconf)
-            assert res1 and not res2 
-            (res1, res2) = LibChecks(sconf)
-            assert res1 and not res2 
-            ((res1, libs1), (res2, libs2)) = LibChecksAutoAdd(sconf)
-            assert res1 and res2 
-            assert len(libs1[1]) - 1 == len(libs1[0]) and libs1[1][-1] == existing_lib
-            assert len(libs2[1]) == len(libs2[0]) 
-            (res1, res2) = LibWithHeaderChecks(sconf)
-            assert res1 and not res2 
-            ((res1, libs1), (res2, libs2)) = LibWithHeaderChecksAutoAdd(sconf)
-            assert res1 and res2 
-            assert len(libs1[1]) - 1 == len(libs1[0]) and libs1[1][-1] == existing_lib
-            assert len(libs2[1]) == len(libs2[0]) 
-            (res1, res2) = FuncChecks(sconf)
-            assert res1 and not res2 
-            (res1, res2) = TypeChecks(sconf)
-            assert res1 and not res2 
+            # CheckFunc()
+            r = sconf.CheckFunc('strcpy')
+            assert r, "did not find strcpy"
+            r = sconf.CheckFunc('strcpy', '/* header */ char strcpy();')
+            assert r, "did not find strcpy"
+            r = sconf.CheckFunc('hopefullynofunction')
+            assert not r, "unexpectedly found hopefullynofunction"
+
+        finally:
+            sconf.Finish()
+
+    def test_Define(self):
+        """Test SConf.Define()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'),
+                                 config_h = self.test.workpath('config.h'))
+        try:
+            # XXX: we test the generated config.h string. This is not so good,
+            # ideally, we would like to test if the generated file included in
+            # a test program does what we want.
+
+            # Test defining one symbol wo value
+            sconf.config_h_text = ''
+            sconf.Define('YOP')
+            assert sconf.config_h_text == '#define YOP\n'
+
+            # Test defining one symbol with integer value
+            sconf.config_h_text = ''
+            sconf.Define('YOP', 1)
+            assert sconf.config_h_text == '#define YOP 1\n'
+
+            # Test defining one symbol with string value
+            sconf.config_h_text = ''
+            sconf.Define('YOP', '"YIP"')
+            assert sconf.config_h_text == '#define YOP "YIP"\n'
+
+            # Test defining one symbol with string value
+            sconf.config_h_text = ''
+            sconf.Define('YOP', "YIP")
+            assert sconf.config_h_text == '#define YOP YIP\n'
+
+        finally:
+            sconf.Finish()
+
+    def test_CheckTypeSize(self):
+        """Test SConf.CheckTypeSize()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            # CheckTypeSize()
+
+            # In ANSI C, sizeof(char) == 1.
+            r = sconf.CheckTypeSize('char', expect = 1)
+            assert r == 1, "sizeof(char) != 1 ??"
+            r = sconf.CheckTypeSize('char', expect = 0)
+            assert r == 0, "sizeof(char) == 0 ??"
+            r = sconf.CheckTypeSize('char', expect = 2)
+            assert r == 0, "sizeof(char) == 2 ??"
+            r = sconf.CheckTypeSize('char')
+            assert r == 1, "sizeof(char) != 1 ??"
+            r = sconf.CheckTypeSize('const unsigned char')
+            assert r == 1, "sizeof(const unsigned char) != 1 ??"
+
+            # Checking C++
+            r = sconf.CheckTypeSize('const unsigned char', language = 'C++')
+            assert r == 1, "sizeof(const unsigned char) != 1 ??"
+
+            # Checking Non-existing type
+            r = sconf.CheckTypeSize('thistypedefhasnotchancetosexist_scons')
+            assert r == 0, \
+                   "Checking size of thistypedefhasnotchancetosexist_scons succeeded ?"
+
+        finally:
+            sconf.Finish()
+
+    def test_CheckDeclaration(self):
+        """Test SConf.CheckDeclaration()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            # In ANSI C, malloc should be available in stdlib
+            r = sconf.CheckDeclaration('malloc', includes = "#include <stdlib.h>")
+            assert r, "malloc not declared ??"
+            # For C++, __cplusplus should be declared 
+            r = sconf.CheckDeclaration('__cplusplus', language = 'C++')
+            assert r, "__cplusplus not declared in C++ ??"
+            r = sconf.CheckDeclaration('__cplusplus', language = 'C')
+            assert not r, "__cplusplus declared  in C ??"
+        finally:
+            sconf.Finish()
+
+    def test_(self):
+        """Test SConf.CheckType()
+        """
+        self._resetSConfState()
+        sconf = self.SConf.SConf(self.scons_env,
+                                 conf_dir=self.test.workpath('config.tests'),
+                                 log_file=self.test.workpath('config.log'))
+        try:
+            # CheckType()
+            r = sconf.CheckType('off_t', '#include <sys/types.h>\n')
+            assert r, "did not find off_t"
+            r = sconf.CheckType('hopefullynotypedef_not')
+            assert not r, "unexpectedly found hopefullynotypedef_not"
+
         finally:
             sconf.Finish()
 
@@ -368,7 +730,7 @@ int main() {
 """
             (ret, output) = test.TryRun( prog, ".c" )
             test.Result( ret )
-            assert ret and output == "Hello" 
+            assert ret and output == "Hello", (ret, output)
             return ret
         
 
@@ -379,7 +741,7 @@ int main() {
                                  log_file=self.test.workpath('config.log'))
         try:
             ret = sconf.CheckCustom()
-            assert ret 
+            assert ret, ret
         finally:
             sconf.Finish()
             
@@ -390,3 +752,8 @@ if __name__ == "__main__":
     if not res.wasSuccessful():
         sys.exit(1)
 
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: