__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons.compat
+
+import io
import os
import re
-import string
-import StringIO
import sys
from types import *
import unittest
import TestCmd
-sys.stdout = StringIO.StringIO()
+sys.stdout = io.StringIO()
if sys.platform == 'win32':
existing_lib = "msvcrt"
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.
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()
# we only use SCons.Environment and SCons.SConf for these tests.
import SCons.Environment
import SCons.SConf
- import SCons.Script.SConscript
- SCons.Script.SConscript.sconscript_reading = 1
self.Environment = SCons.Environment
self.SConf = SCons.SConf
# and we need a new environment, cause references may point to
# 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)
+ # - 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!"
+ raise Exception("This test needs an installed compiler!")
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 builtins
+ import SCons.Platform.win32
+
+ builtins.file = SCons.Platform.win32._builtin_file
+ builtins.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)
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()
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()
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 = ''
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):
pass
def clear(self):
pass
- def current(self, calc=None):
+ 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')]
try:
self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
}
"""
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()
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()
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
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_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()
+ """
+ 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 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 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 libs(env):
return env.get('LIBS', [])
- env = sconf.env.Copy()
+ env = sconf.env.Clone()
try:
r = sconf.CheckLib( existing_lib, "main", autoadd=1 )
got = libs(sconf.env)
assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
- sconf.env = env.Copy()
+ 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)
assert got == expect, "before and after LIBS were not the same"
finally:
sconf.env = env
-
finally:
sconf.Finish()
def libs(env):
return env.get('LIBS', [])
- env = sconf.env.Copy()
+ env = sconf.env.Clone()
try:
r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
got = libs(sconf.env)
assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
- sconf.env = env.Copy()
+ 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)
# 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()
"""
"""
(ret, output) = test.TryRun( prog, ".c" )
test.Result( ret )
- assert ret and output == "Hello"
+ assert ret and output == "Hello", (ret, output)
return ret
log_file=self.test.workpath('config.log'))
try:
ret = sconf.CheckCustom()
- assert ret
+ assert ret, ret
finally:
sconf.Finish()
if not res.wasSuccessful():
sys.exit(1)
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: