X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=src%2Fengine%2FSCons%2FEnvironmentTests.py;h=25404082a0b6311cf122018ae845e419ca39952e;hb=704f6e2480ef60718f1aa42c266f04afc9c79580;hp=b2b17e146343336cfeb7db6e518a2d0733994631;hpb=b9d72fa11125849ef6b5f690802c90f0177ba255;p=scons.git diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index b2b17e14..25404082 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -23,8 +23,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import SCons.compat + +import copy import os -import string +import StringIO import sys import TestCmd import unittest @@ -38,18 +41,16 @@ def diff_env(env1, env2): s2 = "env2 = {\n" d = {} for k in env1._dict.keys() + env2._dict.keys(): - d[k] = None - keys = d.keys() - keys.sort() - for k in keys: - if env1.has_key(k): - if env2.has_key(k): + d[k] = None + for k in sorted(d.keys()): + if k in env1: + if k in env2: if env1[k] != env2[k]: s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n" s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n" else: s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n" - elif env2.has_key(k): + elif k in env2: s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n" s1 = s1 + "}\n" s2 = s2 + "}\n" @@ -60,18 +61,16 @@ def diff_dict(d1, d2): s2 = "d2 = {\n" d = {} for k in d1.keys() + d2.keys(): - d[k] = None - keys = d.keys() - keys.sort() - for k in keys: - if d1.has_key(k): - if d2.has_key(k): + d[k] = None + for k in sorted(d.keys()): + if k in d1: + if k in d2: if d1[k] != d2[k]: s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n" s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n" else: s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n" - elif env2.has_key(k): + elif k in env2: s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n" s1 = s1 + "}\n" s2 = s2 + "}\n" @@ -80,15 +79,17 @@ def diff_dict(d1, d2): called_it = {} built_it = {} -class Builder: +class Builder(SCons.Builder.BuilderBase): """A dummy Builder class for testing purposes. "Building" a target is simply setting a value in the dictionary. """ def __init__(self, name = None): self.name = name - def __call__(self, env, **kw): + def __call__(self, env, target=None, source=None, **kw): global called_it + called_it['target'] = target + called_it['source'] = source called_it.update(kw) def execute(self, target = None, **kw): @@ -108,18 +109,32 @@ class Scanner: self.skeys = skeys def __call__(self, filename): + global scanned_it scanned_it[filename] = 1 def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) + try: + return cmp(self.__dict__, other.__dict__) + except AttributeError: + return 1 + + def get_skeys(self, env): + return self.skeys + + def __str__(self): + return self.name class CLVar(UserList.UserList): def __init__(self, seq): - if type(seq) == type(''): - seq = string.split(seq) + if isinstance(seq, str): + seq = seq.split() UserList.UserList.__init__(self, seq) + def __add__(self, other): + return UserList.UserList.__add__(self, CLVar(other)) + def __radd__(self, other): + return UserList.UserList.__radd__(self, CLVar(other)) def __coerce__(self, other): return (self, CLVar(other)) @@ -135,45 +150,118 @@ class DummyNode: def get_subst_proxy(self): return self +def test_tool( env ): + env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + +class TestEnvironmentFixture: + def TestEnvironment(self, *args, **kw): + if not kw or 'tools' not in kw: + kw['tools'] = [test_tool] + default_keys = { 'CC' : 'cc', + 'CCFLAGS' : '-DNDEBUG', + 'ENV' : { 'TMP' : '/tmp' } } + for key, value in default_keys.items(): + if key not in kw: + kw[key] = value + if 'BUILDERS' not in kw: + static_obj = SCons.Builder.Builder(action = {}, + emitter = {}, + suffix = '.o', + single_source = 1) + kw['BUILDERS'] = {'Object' : static_obj} + static_obj.add_action('.cpp', 'fake action') + + env = Environment(*args, **kw) + return env + +class SubstitutionTestCase(unittest.TestCase): + def test___init__(self): + """Test initializing a SubstitutionEnvironment + """ + env = SubstitutionEnvironment() + assert '__env__' not in env -class EnvironmentTestCase(unittest.TestCase): + def test___cmp__(self): + """Test comparing SubstitutionEnvironments + """ - def test___init__(self): - """Test construction Environment creation + env1 = SubstitutionEnvironment(XXX = 'x') + env2 = SubstitutionEnvironment(XXX = 'x') + env3 = SubstitutionEnvironment(XXX = 'xxx') + env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x') - Create two with identical arguments and check that - they compare the same. + assert env1 == env2 + assert env1 != env3 + assert env1 != env4 + + def test___delitem__(self): + """Test deleting a variable from a SubstitutionEnvironment """ - env1 = Environment(XXX = 'x', YYY = 'y') - env2 = Environment(XXX = 'x', YYY = 'y') - assert env1 == env2, diff_env(env1, env2) + env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y') + env2 = SubstitutionEnvironment(XXX = 'x') + del env1['YYY'] + assert env1 == env2 - assert env1['__env__'] is env1, env1['__env__'] - assert env2['__env__'] is env2, env2['__env__'] + def test___getitem__(self): + """Test fetching a variable from a SubstitutionEnvironment + """ + env = SubstitutionEnvironment(XXX = 'x') + assert env['XXX'] == 'x', env['XXX'] + + def test___setitem__(self): + """Test setting a variable in a SubstitutionEnvironment + """ + env1 = SubstitutionEnvironment(XXX = 'x') + env2 = SubstitutionEnvironment(XXX = 'x', YYY = 'y') + env1['YYY'] = 'y' + assert env1 == env2 def test_get(self): - """Test the get() method.""" - env = Environment(aaa = 'AAA') + """Test the SubstitutionEnvironment get() method + """ + env = SubstitutionEnvironment(XXX = 'x') + assert env.get('XXX') == 'x', env.get('XXX') + assert env.get('YYY') is None, env.get('YYY') - x = env.get('aaa') - assert x == 'AAA', x - x = env.get('aaa', 'XXX') - assert x == 'AAA', x - x = env.get('bbb') - assert x is None, x - x = env.get('bbb', 'XXX') - assert x == 'XXX', x + def test_has_key(self): + """Test the SubstitutionEnvironment has_key() method + """ + env = SubstitutionEnvironment(XXX = 'x') + assert 'XXX' in env + assert 'YYY' not in env + + def test_contains(self): + """Test the SubstitutionEnvironment __contains__() method + """ + try: + 'x' in {'x':1} + except TypeError: + # TODO(1.5) + # An early version of Python that doesn't support "in" + # on dictionaries. Just pass the test. + pass + else: + env = SubstitutionEnvironment(XXX = 'x') + assert 'XXX' in env + assert not 'YYY' in env + + def test_items(self): + """Test the SubstitutionEnvironment items() method + """ + env = SubstitutionEnvironment(XXX = 'x', YYY = 'y') + items = env.items() + assert items == [('XXX','x'), ('YYY','y')], items def test_arg2nodes(self): """Test the arg2nodes method """ - env = Environment() + env = SubstitutionEnvironment() dict = {} class X(SCons.Node.Node): pass def Factory(name, directory = None, create = 1, dict=dict, X=X): - if not dict.has_key(name): + if name not in dict: dict[name] = X() dict[name].name = name return dict[name] @@ -183,8 +271,9 @@ class EnvironmentTestCase(unittest.TestCase): assert isinstance(nodes[0], X) assert nodes[0].name == "Util.py UtilTests.py" - import types - if hasattr(types, 'UnicodeType'): + try: unicode + except NameError: pass + else: code = """if 1: nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory) assert len(nodes) == 1, nodes @@ -236,7 +325,7 @@ class EnvironmentTestCase(unittest.TestCase): else: return None - env_ll = env.Copy() + env_ll = SubstitutionEnvironment() env_ll.lookup_list = [lookup_a, lookup_b] nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory) @@ -286,53 +375,89 @@ class EnvironmentTestCase(unittest.TestCase): assert not hasattr(nodes[1], 'bbbb'), nodes[0] assert nodes[1].c == 1, nodes[1] + def test_arg2nodes_target_source(self): + """Test the arg2nodes method with target= and source= keywords + """ + targets = [DummyNode('t1'), DummyNode('t2')] + sources = [DummyNode('s1'), DummyNode('s2')] + env = SubstitutionEnvironment() + nodes = env.arg2nodes(['${TARGET}-a', + '${SOURCE}-b', + '${TARGETS[1]}-c', + '${SOURCES[1]}-d'], + DummyNode, + target=targets, + source=sources) + names = [n.name for n in nodes] + assert names == ['t1-a', 's1-b', 't2-c', 's2-d'], names + + def test_gvars(self): + """Test the base class gvars() method""" + env = SubstitutionEnvironment() + gvars = env.gvars() + assert gvars == {}, gvars + + def test_lvars(self): + """Test the base class lvars() method""" + env = SubstitutionEnvironment() + lvars = env.lvars() + assert lvars == {}, lvars + def test_subst(self): """Test substituting construction variables within strings Check various combinations, including recursive expansion of variables into other variables. """ - env = Environment(AAA = 'a', BBB = 'b') + env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') mystr = env.subst("$AAA ${AAA}A $BBBB $BBB") assert mystr == "a aA b", mystr # Changed the tests below to reflect a bug fix in # subst() - env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') + env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB") assert mystr == "b bA bB b", mystr - env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') + env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB") assert mystr == "c cA cB c", mystr + # Lists: + env = SubstitutionEnvironment(AAA = ['a', 'aa', 'aaa']) + mystr = env.subst("$AAA") + assert mystr == "a aa aaa", mystr + + # Tuples: + env = SubstitutionEnvironment(AAA = ('a', 'aa', 'aaa')) + mystr = env.subst("$AAA") + assert mystr == "a aa aaa", mystr + t1 = DummyNode('t1') t2 = DummyNode('t2') s1 = DummyNode('s1') s2 = DummyNode('s2') - env = Environment(AAA = 'aaa') + env = SubstitutionEnvironment(AAA = 'aaa') s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2]) assert s == "aaa t1 s1 s2", s s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2]) assert s == "aaa t1 t2 s1", s - s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2], dict={}) - assert s == "aaa", s - # Test callables in the Environment + # Test callables in the SubstitutionEnvironment def foo(target, source, env, for_signature): assert str(target) == 't', target assert str(source) == 's', source return env["FOO"] - env = Environment(BAR=foo, FOO='baz') + env = SubstitutionEnvironment(BAR=foo, FOO='baz') t = DummyNode('t') s = DummyNode('s') subst = env.subst('test $BAR', target=t, source=s) assert subst == 'test baz', subst - # Test not calling callables in the Environment + # Test not calling callables in the SubstitutionEnvironment if 0: # This will take some serious surgery to subst() and # subst_list(), so just leave these tests out until we can @@ -340,7 +465,7 @@ class EnvironmentTestCase(unittest.TestCase): def bar(arg): pass - env = Environment(BAR=bar, FOO='$BAR') + env = SubstitutionEnvironment(BAR=bar, FOO='$BAR') subst = env.subst('$BAR', call=None) assert subst is bar, subst @@ -349,8 +474,8 @@ class EnvironmentTestCase(unittest.TestCase): assert subst is bar, subst def test_subst_kw(self): - """Test substituting construction variables within dictionaries""" - env = Environment(AAA = 'a', BBB = 'b') + """Test substituting construction variables within dictionaries""" + env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'}) assert len(kw) == 2, kw assert kw['a'] == 'aaa', kw['a'] @@ -359,21 +484,21 @@ class EnvironmentTestCase(unittest.TestCase): def test_subst_list(self): """Test substituting construction variables in command lists """ - env = Environment(AAA = 'a', BBB = 'b') + env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') l = env.subst_list("$AAA ${AAA}A $BBBB $BBB") assert l == [["a", "aA", "b"]], l # Changed the tests below to reflect a bug fix in # subst() - env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') + env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB") assert l == [["b", "bA", "bB", "b"]], l - env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') + env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB") assert l == [["c", "cA", "cB", "c"]], mystr - env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ]) + env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ]) lst = env.subst_list([ "$AAA", "B $CCC" ]) assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst @@ -382,28 +507,26 @@ class EnvironmentTestCase(unittest.TestCase): s1 = DummyNode('s1') s2 = DummyNode('s2') - env = Environment(AAA = 'aaa') + env = SubstitutionEnvironment(AAA = 'aaa') s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2]) assert s == [["aaa", "t1", "s1", "s2"]], s s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2]) assert s == [["aaa", "t1", "t2", "s1"]], s - s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2], dict={}) - assert s == [["aaa"]], s - # Test callables in the Environment + # Test callables in the SubstitutionEnvironment def foo(target, source, env, for_signature): assert str(target) == 't', target assert str(source) == 's', source return env["FOO"] - env = Environment(BAR=foo, FOO='baz') + env = SubstitutionEnvironment(BAR=foo, FOO='baz') t = DummyNode('t') s = DummyNode('s') lst = env.subst_list('test $BAR', target=t, source=s) assert lst == [['test', 'baz']], lst - # Test not calling callables in the Environment + # Test not calling callables in the SubstitutionEnvironment if 0: # This will take some serious surgery to subst() and # subst_list(), so just leave these tests out until we can @@ -411,7 +534,7 @@ class EnvironmentTestCase(unittest.TestCase): def bar(arg): pass - env = Environment(BAR=bar, FOO='$BAR') + env = SubstitutionEnvironment(BAR=bar, FOO='$BAR') subst = env.subst_list('$BAR', call=None) assert subst is bar, subst @@ -428,10 +551,22 @@ class EnvironmentTestCase(unittest.TestCase): def get(self): return self.val + '-proxy' + class MyNode: + def __init__(self, val): + self.val = val + def get_subst_proxy(self): + return self + def __str__(self): + return self.val + class MyObj: - pass + def get(self): + return self - env = Environment(FOO='foo', BAR='bar', PROXY=MyProxy('my1')) + env = SubstitutionEnvironment(FOO='foo', + BAR='bar', + LIST=['one', 'two'], + PROXY=MyProxy('my1')) r = env.subst_path('$FOO') assert r == ['foo'], r @@ -439,11 +574,373 @@ class EnvironmentTestCase(unittest.TestCase): r = env.subst_path(['$FOO', 'xxx', '$BAR']) assert r == ['foo', 'xxx', 'bar'], r + r = env.subst_path(['$FOO', '$LIST', '$BAR']) + assert list(map(str, r)) == ['foo', 'one two', 'bar'], r + + r = env.subst_path(['$FOO', '$TARGET', '$SOURCE', '$BAR']) + assert r == ['foo', '', '', 'bar'], r + + r = env.subst_path(['$FOO', '$TARGET', '$BAR'], target=MyNode('ttt')) + assert list(map(str, r)) == ['foo', 'ttt', 'bar'], r + + r = env.subst_path(['$FOO', '$SOURCE', '$BAR'], source=MyNode('sss')) + assert list(map(str, r)) == ['foo', 'sss', 'bar'], r + n = MyObj() r = env.subst_path(['$PROXY', MyProxy('my2'), n]) assert r == ['my1-proxy', 'my2-proxy', n], r + class StringableObj: + def __init__(self, s): + self.s = s + def __str__(self): + return self.s + + env = SubstitutionEnvironment(FOO=StringableObj("foo"), + BAR=StringableObj("bar")) + + r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ]) + assert r == [ "foo/bar", "bar/baz" ], r + + r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ]) + assert r == [ "bar/foo", "baz/bar" ], r + + r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ]) + assert r == [ "bar/foo/bar", "baz/bar/baz" ], r + + def test_subst_target_source(self): + """Test the base environment subst_target_source() method""" + env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') + mystr = env.subst_target_source("$AAA ${AAA}A $BBBB $BBB") + assert mystr == "a aA b", mystr + + def test_backtick(self): + """Test the backtick() method for capturing command output""" + env = SubstitutionEnvironment() + + test = TestCmd.TestCmd(workdir = '') + test.write('stdout.py', """\ +import sys +sys.stdout.write('this came from stdout.py\\n') +sys.exit(0) +""") + test.write('stderr.py', """\ +import sys +sys.stderr.write('this came from stderr.py\\n') +sys.exit(0) +""") + test.write('fail.py', """\ +import sys +sys.exit(1) +""") + test.write('echo.py', """\ +import os, sys +sys.stdout.write(os.environ['ECHO'] + '\\n') +sys.exit(0) +""") + + save_stderr = sys.stderr + + python = '"' + sys.executable + '"' + + try: + sys.stderr = StringIO.StringIO() + cmd = '%s %s' % (python, test.workpath('stdout.py')) + output = env.backtick(cmd) + errout = sys.stderr.getvalue() + assert output == 'this came from stdout.py\n', output + assert errout == '', errout + + sys.stderr = StringIO.StringIO() + cmd = '%s %s' % (python, test.workpath('stderr.py')) + output = env.backtick(cmd) + errout = sys.stderr.getvalue() + assert output == '', output + assert errout == 'this came from stderr.py\n', errout + + sys.stderr = StringIO.StringIO() + cmd = '%s %s' % (python, test.workpath('fail.py')) + try: + env.backtick(cmd) + except OSError, e: + assert str(e) == "'%s' exited 1" % cmd, str(e) + else: + self.fail("did not catch expected OSError") + + sys.stderr = StringIO.StringIO() + cmd = '%s %s' % (python, test.workpath('echo.py')) + env['ENV'] = os.environ.copy() + env['ENV']['ECHO'] = 'this came from ECHO' + output = env.backtick(cmd) + errout = sys.stderr.getvalue() + assert output == 'this came from ECHO\n', output + assert errout == '', errout + + finally: + sys.stderr = save_stderr + + def test_AddMethod(self): + """Test the AddMethod() method""" + env = SubstitutionEnvironment(FOO = 'foo') + + def func(self): + return 'func-' + self['FOO'] + + assert not hasattr(env, 'func') + env.AddMethod(func) + r = env.func() + assert r == 'func-foo', r + + assert not hasattr(env, 'bar') + env.AddMethod(func, 'bar') + r = env.bar() + assert r == 'func-foo', r + + def func2(self, arg=''): + return 'func2-' + self['FOO'] + arg + + env.AddMethod(func2) + r = env.func2() + assert r == 'func2-foo', r + r = env.func2('-xxx') + assert r == 'func2-foo-xxx', r + + env.AddMethod(func2, 'func') + r = env.func() + assert r == 'func2-foo', r + r = env.func('-yyy') + assert r == 'func2-foo-yyy', r + + # Test that clones of clones correctly re-bind added methods. + env1 = Environment(FOO = '1') + env1.AddMethod(func2) + env2 = env1.Clone(FOO = '2') + env3 = env2.Clone(FOO = '3') + env4 = env3.Clone(FOO = '4') + r = env1.func2() + assert r == 'func2-1', r + r = env2.func2() + assert r == 'func2-2', r + r = env3.func2() + assert r == 'func2-3', r + r = env4.func2() + assert r == 'func2-4', r + + # Test that clones don't re-bind an attribute that the user + env1 = Environment(FOO = '1') + env1.AddMethod(func2) + def replace_func2(): + return 'replace_func2' + env1.func2 = replace_func2 + env2 = env1.Clone(FOO = '2') + r = env2.func2() + assert r == 'replace_func2', r + + def test_Override(self): + "Test overriding construction variables" + env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4) + assert env['ONE'] == 1, env['ONE'] + assert env['TWO'] == 2, env['TWO'] + assert env['THREE'] == 3, env['THREE'] + assert env['FOUR'] == 4, env['FOUR'] + + env2 = env.Override({'TWO' : '10', + 'THREE' :'x $THREE y', + 'FOUR' : ['x', '$FOUR', 'y']}) + assert env2['ONE'] == 1, env2['ONE'] + assert env2['TWO'] == '10', env2['TWO'] + assert env2['THREE'] == 'x 3 y', env2['THREE'] + assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR'] + + assert env['ONE'] == 1, env['ONE'] + assert env['TWO'] == 2, env['TWO'] + assert env['THREE'] == 3, env['THREE'] + assert env['FOUR'] == 4, env['FOUR'] + + env2.Replace(ONE = "won") + assert env2['ONE'] == "won", env2['ONE'] + assert env['ONE'] == 1, env['ONE'] + + def test_ParseFlags(self): + """Test the ParseFlags() method + """ + env = SubstitutionEnvironment() + + empty = { + 'ASFLAGS' : [], + 'CFLAGS' : [], + 'CCFLAGS' : [], + 'CPPDEFINES' : [], + 'CPPFLAGS' : [], + 'CPPPATH' : [], + 'FRAMEWORKPATH' : [], + 'FRAMEWORKS' : [], + 'LIBPATH' : [], + 'LIBS' : [], + 'LINKFLAGS' : [], + 'RPATH' : [], + } + + d = env.ParseFlags(None) + assert d == empty, d + + d = env.ParseFlags('') + assert d == empty, d + + d = env.ParseFlags([]) + assert d == empty, d + + s = "-I/usr/include/fum -I bar -X\n" + \ + '-I"C:\\Program Files\\ASCEND\\include" ' + \ + "-L/usr/fax -L foo -lxxx -l yyy " + \ + '-L"C:\\Program Files\\ASCEND" -lascend ' + \ + "-Wa,-as -Wl,-link " + \ + "-Wl,-rpath=rpath1 " + \ + "-Wl,-R,rpath2 " + \ + "-Wl,-Rrpath3 " + \ + "-Wp,-cpp " + \ + "-std=c99 " + \ + "-framework Carbon " + \ + "-frameworkdir=fwd1 " + \ + "-Ffwd2 " + \ + "-F fwd3 " + \ + "-pthread " + \ + "-mno-cygwin -mwindows " + \ + "-arch i386 -isysroot /tmp +DD64 " + \ + "-DFOO -DBAR=value -D BAZ " + + d = env.ParseFlags(s) + + assert d['ASFLAGS'] == ['-as'], d['ASFLAGS'] + assert d['CFLAGS'] == ['-std=c99'] + assert d['CCFLAGS'] == ['-X', '-Wa,-as', + '-pthread', '-mno-cygwin', + ('-arch', 'i386'), ('-isysroot', '/tmp'), + '+DD64'], d['CCFLAGS'] + assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES'] + assert d['CPPFLAGS'] == ['-Wp,-cpp'], d['CPPFLAGS'] + assert d['CPPPATH'] == ['/usr/include/fum', + 'bar', + 'C:\\Program Files\\ASCEND\\include'], d['CPPPATH'] + assert d['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], d['FRAMEWORKPATH'] + assert d['FRAMEWORKS'] == ['Carbon'], d['FRAMEWORKS'] + assert d['LIBPATH'] == ['/usr/fax', + 'foo', + 'C:\\Program Files\\ASCEND'], d['LIBPATH'] + LIBS = list(map(str, d['LIBS'])) + assert LIBS == ['xxx', 'yyy', 'ascend'], (d['LIBS'], LIBS) + assert d['LINKFLAGS'] == ['-Wl,-link', '-pthread', + '-mno-cygwin', '-mwindows', + ('-arch', 'i386'), + ('-isysroot', '/tmp'), + '+DD64'], d['LINKFLAGS'] + assert d['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], d['RPATH'] + + + def test_MergeFlags(self): + """Test the MergeFlags() method + """ + env = SubstitutionEnvironment() + env.MergeFlags('') + assert 'CCFLAGS' not in env, env['CCFLAGS'] + env.MergeFlags('-X') + assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] + env.MergeFlags('-X') + assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] + + env = SubstitutionEnvironment(CCFLAGS=None) + env.MergeFlags('-Y') + assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS'] + + env = SubstitutionEnvironment() + env.MergeFlags({'A':['aaa'], 'B':['bbb']}) + assert env['A'] == ['aaa'], env['A'] + assert env['B'] == ['bbb'], env['B'] + +# def test_MergeShellPaths(self): +# """Test the MergeShellPaths() method +# """ +# env = Environment() +# env.MergeShellPaths({}) +# assert not env['ENV'].has_key('INCLUDE'), env['INCLUDE'] +# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}) +# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] +# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}) +# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] +# env.MergeShellPaths({'INCLUDE': r'xyz'}) +# assert env['ENV']['INCLUDE'] == r'xyz%sc:\Program Files\Stuff'%os.pathsep, env['ENV']['INCLUDE'] + +# env = Environment() +# env['ENV']['INCLUDE'] = 'xyz' +# env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']} ) +# assert env['ENV']['INCLUDE'] == r'c:/inc1%sc:/inc2%sxyz'%(os.pathsep, os.pathsep), env['ENV']['INCLUDE'] + +# # test prepend=0 +# env = Environment() +# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}, prepend=0) +# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] +# env.MergeShellPaths({'INCLUDE': r'xyz'}, prepend=0) +# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff%sxyz'%os.pathsep, env['ENV']['INCLUDE'] + + +class BaseTestCase(unittest.TestCase,TestEnvironmentFixture): + + reserved_variables = [ + 'CHANGED_SOURCES', + 'CHANGED_TARGETS', + 'SOURCE', + 'SOURCES', + 'TARGET', + 'TARGETS', + 'UNCHANGED_SOURCES', + 'UNCHANGED_TARGETS', + ] + + def test___init__(self): + """Test construction Environment creation + + Create two with identical arguments and check that + they compare the same. + """ + env1 = self.TestEnvironment(XXX = 'x', YYY = 'y') + env2 = self.TestEnvironment(XXX = 'x', YYY = 'y') + assert env1 == env2, diff_env(env1, env2) + + assert '__env__' not in env1 + assert '__env__' not in env2 + + def test_variables(self): + """Test that variables only get applied once.""" + class FakeOptions: + def __init__(self, key, val): + self.calls = 0 + self.key = key + self.val = val + def keys(self): + return [self.key] + def Update(self, env): + env[self.key] = self.val + self.calls = self.calls + 1 + + o = FakeOptions('AAA', 'fake_opt') + env = Environment(variables=o, AAA='keyword_arg') + assert o.calls == 1, o.calls + assert env['AAA'] == 'fake_opt', env['AAA'] + + def test_get(self): + """Test the get() method.""" + env = self.TestEnvironment(aaa = 'AAA') + + x = env.get('aaa') + assert x == 'AAA', x + x = env.get('aaa', 'XXX') + assert x == 'AAA', x + x = env.get('bbb') + assert x is None, x + x = env.get('bbb', 'XXX') + assert x == 'XXX', x + def test_Builder_calls(self): """Test Builder calls through different environments """ @@ -456,54 +953,81 @@ class EnvironmentTestCase(unittest.TestCase): env.Replace(BUILDERS = { 'builder1' : b1, 'builder2' : b2 }) called_it = {} - env.builder1(target = 'out1') - assert called_it['target'] == 'out1', called_it - assert not called_it.has_key('source') + env.builder1('in1') + assert called_it['target'] is None, called_it + assert called_it['source'] == ['in1'], called_it called_it = {} - env.builder2(target = 'out2', xyzzy = 1) - assert called_it['target'] == 'out2', called_it + env.builder2(source = 'in2', xyzzy = 1) + assert called_it['target'] is None, called_it + assert called_it['source'] == ['in2'], called_it assert called_it['xyzzy'] == 1, called_it - assert not called_it.has_key('source') called_it = {} env.builder1(foo = 'bar') assert called_it['foo'] == 'bar', called_it - assert not called_it.has_key('target') - assert not called_it.has_key('source') + assert called_it['target'] is None, called_it + assert called_it['source'] is None, called_it + def test_BuilderWrapper_attributes(self): + """Test getting and setting of BuilderWrapper attributes + """ + b1 = Builder() + b2 = Builder() + e1 = Environment() + e2 = Environment() + + e1.Replace(BUILDERS = {'b' : b1}) + bw = e1.b + + assert bw.env is e1 + bw.env = e2 + assert bw.env is e2 + assert bw.builder is b1 + bw.builder = b2 + assert bw.builder is b2 - def test_Builder_execs(self): - """Test Builder execution through different environments + self.assertRaises(AttributeError, getattr, bw, 'foobar') + bw.foobar = 42 + assert bw.foobar is 42 - One environment is initialized with a single - Builder object, one with a list of a single Builder - object, and one with a list of two Builder objects. - """ - global built_it + # This unit test is currently disabled because we don't think the + # underlying method it tests (Environment.BuilderWrapper.execute()) + # is necessary, but we're leaving the code here for now in case + # that's mistaken. + def _DO_NOT_test_Builder_execs(self): + """Test Builder execution through different environments + + One environment is initialized with a single + Builder object, one with a list of a single Builder + object, and one with a list of two Builder objects. + """ + global built_it - b1 = Builder() - b2 = Builder() + b1 = Builder() + b2 = Builder() - built_it = {} + built_it = {} env3 = Environment() env3.Replace(BUILDERS = { 'builder1' : b1, 'builder2' : b2 }) - env3.builder1.execute(target = 'out1') - env3.builder2.execute(target = 'out2') - env3.builder1.execute(target = 'out3') - assert built_it['out1'] - assert built_it['out2'] - assert built_it['out3'] + env3.builder1.execute(target = 'out1') + env3.builder2.execute(target = 'out2') + env3.builder1.execute(target = 'out3') + assert built_it['out1'] + assert built_it['out2'] + assert built_it['out3'] - env4 = env3.Copy() - assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (env4.builder1.env, env3) - assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (env4.builder1.env, env3) + env4 = env3.Clone() + assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % ( +env4.builder1.env, env3) + assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % ( +env4.builder1.env, env3) # Now test BUILDERS as a dictionary. built_it = {} - env5 = Environment(BUILDERS={ 'foo' : b1 }) + env5 = self.TestEnvironment(BUILDERS={ 'foo' : b1 }) env5['BUILDERS']['bar'] = b2 env5.foo.execute(target='out1') env5.bar.execute(target='out2') @@ -519,71 +1043,166 @@ class EnvironmentTestCase(unittest.TestCase): assert built_it['out1'] assert built_it['out2'] + + def test_Scanners(self): - """Test Scanner execution through different environments + """Test setting SCANNERS in various ways One environment is initialized with a single Scanner object, one with a list of a single Scanner object, and one with a list of two Scanner objects. """ -# global scanned_it -# -# s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"]) -# s2 = Scanner(name = 'scanner2', skeys = [".m4"]) -# -# scanned_it = {} -# env1 = Environment(SCANNERS = s1) + global scanned_it + + s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"]) + s2 = Scanner(name = 'scanner2', skeys = [".m4"]) + s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"]) + s4 = Scanner(name = 'scanner4', skeys = [None]) + +# XXX Tests for scanner execution through different environments, +# XXX if we ever want to do that some day +# scanned_it = {} +# env1 = self.TestEnvironment(SCANNERS = s1) # env1.scanner1(filename = 'out1') -# assert scanned_it['out1'] +# assert scanned_it['out1'] # -# scanned_it = {} -# env2 = Environment(SCANNERS = [s1]) +# scanned_it = {} +# env2 = self.TestEnvironment(SCANNERS = [s1]) # env1.scanner1(filename = 'out1') -# assert scanned_it['out1'] +# assert scanned_it['out1'] # -# scanned_it = {} +# scanned_it = {} # env3 = Environment() -# env3.Replace(SCANNERS = [s1, s2]) +# env3.Replace(SCANNERS = [s1]) # env3.scanner1(filename = 'out1') # env3.scanner2(filename = 'out2') # env3.scanner1(filename = 'out3') -# assert scanned_it['out1'] -# assert scanned_it['out2'] -# assert scanned_it['out3'] -# -# s = env3.get_scanner(".c") -# assert s == s1, s -# s = env3.get_scanner(skey=".m4") -# assert s == s2, s -# s = env3.get_scanner(".cxx") -# assert s == None, s +# assert scanned_it['out1'] +# assert scanned_it['out2'] +# assert scanned_it['out3'] + + suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"] + + env = Environment() + try: del env['SCANNERS'] + except KeyError: pass + s = list(map(env.get_scanner, suffixes)) + assert s == [None, None, None, None, None], s + + env = self.TestEnvironment(SCANNERS = []) + s = list(map(env.get_scanner, suffixes)) + assert s == [None, None, None, None, None], s + + env.Replace(SCANNERS = [s1]) + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, None, None], s + + env.Append(SCANNERS = [s2]) + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, s2, None], s + + env.AppendUnique(SCANNERS = [s3]) + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, s2, s3], s + + env = env.Clone(SCANNERS = [s2]) + s = list(map(env.get_scanner, suffixes)) + assert s == [None, None, None, s2, None], s + + env['SCANNERS'] = [s1] + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, None, None], s + + env.PrependUnique(SCANNERS = [s2, s1]) + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, s2, None], s + + env.Prepend(SCANNERS = [s3]) + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, s3, s3], s + + # Verify behavior of case-insensitive suffix matches on Windows. + uc_suffixes = [_.upper() for _ in suffixes] + + env = Environment(SCANNERS = [s1, s2, s3], + PLATFORM = 'linux') + + s = list(map(env.get_scanner, suffixes)) + assert s == [s1, s1, None, s2, s3], s + + s = list(map(env.get_scanner, uc_suffixes)) + assert s == [None, None, None, None, None], s + + env['PLATFORM'] = 'win32' + + s = list(map(env.get_scanner, uc_suffixes)) + assert s == [s1, s1, None, s2, s3], s + + # Verify behavior for a scanner returning None (on Windows + # where we might try to perform case manipulation on None). + env.Replace(SCANNERS = [s4]) + s = list(map(env.get_scanner, suffixes)) + assert s == [None, None, None, None, None], s def test_ENV(self): - """Test setting the external ENV in Environments - """ - env = Environment() - assert env.Dictionary().has_key('ENV') + """Test setting the external ENV in Environments + """ + env = Environment() + assert 'ENV' in env.Dictionary() - env = Environment(ENV = { 'PATH' : '/foo:/bar' }) - assert env.Dictionary('ENV')['PATH'] == '/foo:/bar' + env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' }) + assert env.Dictionary('ENV')['PATH'] == '/foo:/bar' def test_ReservedVariables(self): - """Test generation of warnings when reserved variable names - are set in an environment.""" + """Test warning generation when reserved variable names are set""" + + reserved_variables = [ + 'CHANGED_SOURCES', + 'CHANGED_TARGETS', + 'SOURCE', + 'SOURCES', + 'TARGET', + 'TARGETS', + 'UNCHANGED_SOURCES', + 'UNCHANGED_TARGETS', + ] - SCons.Warnings.enableWarningClass(SCons.Warnings.ReservedVariableWarning) + warning = SCons.Warnings.ReservedVariableWarning + SCons.Warnings.enableWarningClass(warning) old = SCons.Warnings.warningAsException(1) try: env4 = Environment() - for kw in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']: + for kw in self.reserved_variables: exc_caught = None try: env4[kw] = 'xyzzy' - except SCons.Warnings.ReservedVariableWarning: + except warning: exc_caught = 1 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw - assert not env4.has_key(kw), "`%s' variable was incorrectly set" % kw + assert kw not in env4, "`%s' variable was incorrectly set" % kw + finally: + SCons.Warnings.warningAsException(old) + + def test_FutureReservedVariables(self): + """Test warning generation when future reserved variable names are set""" + + future_reserved_variables = [] + + warning = SCons.Warnings.FutureReservedVariableWarning + SCons.Warnings.enableWarningClass(warning) + old = SCons.Warnings.warningAsException(1) + + try: + env4 = Environment() + for kw in future_reserved_variables: + exc_caught = None + try: + env4[kw] = 'xyzzy' + except warning: + exc_caught = 1 + assert exc_caught, "Did not catch FutureReservedVariableWarning for `%s'" % kw + assert kw in env4, "`%s' variable was not set" % kw finally: SCons.Warnings.warningAsException(old) @@ -606,128 +1225,91 @@ class EnvironmentTestCase(unittest.TestCase): def test_autogenerate(dict): """Test autogenerating variables in a dictionary.""" - def RDirs(pathlist): - return SCons.Node.FS.default_fs.Rsearchall(pathlist, - clazz=SCons.Node.FS.Dir, - must_exist=0, - cwd=SCons.Node.FS.default_fs.Dir('xx')) + drive, p = os.path.splitdrive(os.getcwd()) + def normalize_path(path, drive=drive): + if path[0] in '\\/': + path = drive + path + path = os.path.normpath(path) + drive, path = os.path.splitdrive(path) + return drive.lower() + path - env = Environment(LIBS = [ 'foo', 'bar', 'baz' ], + env = dict.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ], LIBLINKPREFIX = 'foo', - LIBLINKSUFFIX = 'bar', - RDirs=RDirs) + LIBLINKSUFFIX = 'bar') + + def RDirs(pathlist, fs=env.fs): + return fs.Dir('xx').Rfindalldirs(pathlist) + + env['RDirs'] = RDirs flags = env.subst_list('$_LIBFLAGS', 1)[0] - assert len(flags) == 3, flags - assert flags[0] == 'foobar', \ - flags[0] - assert flags[1] == 'foobar', \ - flags[1] - assert flags[2] == 'foobazbar', \ - flags[2] - - blat = SCons.Node.FS.default_fs.Dir('blat') - - env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz', - RDirs=RDirs) + assert flags == ['foobar', 'foobar', 'foobazbar'], flags + + blat = env.fs.Dir('blat') + + env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ], + INCPREFIX = 'foo ', + INCSUFFIX = 'bar', + FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - assert len(flags) == 8, flags - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == os.path.normpath('foo'), \ - flags[1] - assert flags[2] == os.path.normpath('xx/foobar'), \ - flags[2] - assert flags[3] == os.path.normpath('foo'), \ - flags[3] - assert flags[4] == os.path.normpath('xx/baz/bar'), \ - flags[4] - assert flags[5] == os.path.normpath('foo'), \ - flags[5] - assert flags[6] == os.path.normpath('blatbar'), \ - flags[6] - assert flags[7] == '$)', \ - flags[7] - - env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz', - RDirs=RDirs) + expect = [ '$(', + normalize_path('foo'), + normalize_path('xx/foobar'), + normalize_path('foo'), + normalize_path('xx/baz/bar'), + normalize_path('foo'), + normalize_path('blatbar'), + '$)', + ] + assert flags == expect, flags + + env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ], + INCPREFIX = 'foo ', + INCSUFFIX = 'bar', + FOO = 'baz') flags = env.subst_list('$_F77INCFLAGS', 1)[0] - assert len(flags) == 8, flags - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == os.path.normpath('foo'), \ - flags[1] - assert flags[2] == os.path.normpath('xx/foobar'), \ - flags[2] - assert flags[3] == os.path.normpath('foo'), \ - flags[3] - assert flags[4] == os.path.normpath('xx/baz/bar'), \ - flags[4] - assert flags[5] == os.path.normpath('foo'), \ - flags[5] - assert flags[6] == os.path.normpath('blatbar'), \ - flags[6] - assert flags[7] == '$)', \ - flags[7] - - env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '', - RDirs=RDirs) + expect = [ '$(', + normalize_path('foo'), + normalize_path('xx/foobar'), + normalize_path('foo'), + normalize_path('xx/baz/bar'), + normalize_path('foo'), + normalize_path('blatbar'), + '$)', + ] + assert flags == expect, flags + + env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '') l = env.subst_list('$_CPPINCFLAGS') - assert len(l[0]) == 0, l[0] + assert l == [[]], l l = env.subst_list('$_F77INCFLAGS') - assert len(l[0]) == 0, l[0] + assert l == [[]], l l = env.subst_list('$_LIBDIRFLAGS') - assert len(l[0]) == 0, l[0] - - SCons.Node.FS.default_fs.Repository('/rep1') - SCons.Node.FS.default_fs.Repository('/rep2') - env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat], - INCPREFIX = '-I ', - INCSUFFIX = 'XXX', - FOO = 'baz', - RDirs=RDirs) + assert l == [[]], l + + env.fs.Repository('/rep1') + env.fs.Repository('/rep2') + env.Replace(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat], + INCPREFIX = '-I ', + INCSUFFIX = 'XXX', + FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == '-I', \ - flags[1] - assert flags[2] == os.path.normpath('xx/fooXXX'), \ - flags[2] - assert flags[3] == '-I', \ - flags[3] - assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \ - flags[4] - assert flags[5] == '-I', \ - flags[5] - assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \ - flags[6] - assert flags[7] == '-I', \ - flags[7] - assert flags[8] == os.path.normpath('/a/bXXX'), \ - flags[8] - assert flags[9] == '-I', \ - flags[9] - assert flags[10] == os.path.normpath('xx/baz/barXXX'), \ - flags[10] - assert flags[11] == '-I', \ - flags[11] - assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \ - flags[12] - assert flags[13] == '-I', \ - flags[13] - assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \ - flags[14] - assert flags[15] == '-I', \ - flags[15] - assert flags[16] == os.path.normpath('blatXXX'), \ - flags[16] - assert flags[17] == '$)', \ - flags[17] + expect = [ '$(', + '-I', normalize_path('xx/fooXXX'), + '-I', normalize_path('/rep1/xx/fooXXX'), + '-I', normalize_path('/rep2/xx/fooXXX'), + '-I', normalize_path('/a/bXXX'), + '-I', normalize_path('xx/baz/barXXX'), + '-I', normalize_path('/rep1/xx/baz/barXXX'), + '-I', normalize_path('/rep2/xx/baz/barXXX'), + '-I', normalize_path('blatXXX'), + '$)' + ] + def normalize_if_path(arg, np=normalize_path): + if arg not in ('$(','$)','-I'): + return np(str(arg)) + return arg + flags = list(map(normalize_if_path, flags)) + assert flags == expect, flags def test_platform(self): """Test specifying a platform callable when instantiating.""" @@ -739,7 +1321,7 @@ class EnvironmentTestCase(unittest.TestCase): env['SET_TOOL'] = 'initialized' assert env['PLATFORM'] == "TestPlatform" - env = Environment(platform = platform(), tools = [tool]) + env = self.TestEnvironment(platform = platform(), tools = [tool]) assert env['XYZZY'] == 777, env assert env['PLATFORM'] == "TestPlatform" assert env['SET_TOOL'] == "initialized" @@ -761,7 +1343,7 @@ class EnvironmentTestCase(unittest.TestCase): SCons.Defaults.ConstructionEnvironment.update({ 'PLATFORM' : platform(), }) - env = Environment(tools = [tool]) + env = self.TestEnvironment(tools = [tool]) assert env['XYZZY'] == 888, env assert env['PLATFORM'] == "DefaultTestPlatform" assert env['SET_TOOL'] == "abcde" @@ -778,13 +1360,29 @@ class EnvironmentTestCase(unittest.TestCase): env['AAA'] = env['XYZ'] def t4(env): env['TOOL4'] = 444 - env = Environment(tools = [t1, t2, t3], XYZ = 'aaa') + env = self.TestEnvironment(tools = [t1, t2, t3], XYZ = 'aaa') assert env['TOOL1'] == 111, env['TOOL1'] assert env['TOOL2'] == 222, env assert env['AAA'] == 'aaa', env t4(env) assert env['TOOL4'] == 444, env + test = TestCmd.TestCmd(workdir = '') + test.write('faketool.py', """\ +def generate(env, **kw): + for k, v in kw.items(): + env[k] = v + +def exists(env): + return 1 +""") + + env = self.TestEnvironment(tools = [('faketool', {'a':1, 'b':2, 'c':3})], + toolpath = [test.workpath('')]) + assert env['a'] == 1, env['a'] + assert env['b'] == 2, env['b'] + assert env['c'] == 3, env['c'] + def test_Default_TOOLS(self): """Test overriding the default TOOLS variable""" def t5(env): @@ -811,9 +1409,26 @@ class EnvironmentTestCase(unittest.TestCase): finally: SCons.Defaults.ConstructionEnvironment = save + def test_null_tools(self): + """Test specifying a tool of None is OK.""" + def t1(env): + env['TOOL1'] = 111 + def t2(env): + env['TOOL2'] = 222 + env = self.TestEnvironment(tools = [t1, None, t2], XYZ = 'aaa') + assert env['TOOL1'] == 111, env['TOOL1'] + assert env['TOOL2'] == 222, env + assert env['XYZ'] == 'aaa', env + env = self.TestEnvironment(tools = [None], XYZ = 'xyz') + assert env['XYZ'] == 'xyz', env + env = self.TestEnvironment(tools = [t1, '', t2], XYZ = 'ddd') + assert env['TOOL1'] == 111, env['TOOL1'] + assert env['TOOL2'] == 222, env + assert env['XYZ'] == 'ddd', env + def test_concat(self): "Test _concat()" - e1 = Environment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b']) + e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b']) s = e1.subst x = s("${_concat('', '', '', __env__)}") assert x == '', x @@ -826,9 +1441,17 @@ class EnvironmentTestCase(unittest.TestCase): x = s("${_concat(PRE, LIST, SUF, __env__)}") assert x == 'preasuf prebsuf', x + def test_gvars(self): + """Test the Environment gvars() method""" + env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z') + gvars = env.gvars() + assert gvars['XXX'] == 'x', gvars['XXX'] + assert gvars['YYY'] == 'y', gvars['YYY'] + assert gvars['ZZZ'] == 'z', gvars['ZZZ'] + def test__update(self): """Test the _update() method""" - env = Environment(X = 'x', Y = 'y', Z = 'z') + env = self.TestEnvironment(X = 'x', Y = 'y', Z = 'z') assert env['X'] == 'x', env['X'] assert env['Y'] == 'y', env['Y'] assert env['Z'] == 'z', env['Z'] @@ -856,6 +1479,8 @@ class EnvironmentTestCase(unittest.TestCase): b2 = Environment()['BUILDERS'] assert b1 == b2, diff_dict(b1, b2) + import UserDict + UD = UserDict.UserDict import UserList UL = UserList.UserList @@ -887,6 +1512,18 @@ class EnvironmentTestCase(unittest.TestCase): UL(['i7']), [''], UL(['i7', '']), UL(['i8']), UL(['']), UL(['i8', '']), + {'d1':1}, 'D1', {'d1':1, 'D1':None}, + {'d2':1}, ['D2'], {'d2':1, 'D2':None}, + {'d3':1}, UL(['D3']), {'d3':1, 'D3':None}, + {'d4':1}, {'D4':1}, {'d4':1, 'D4':1}, + {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}), + + UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}), + UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}), + UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}), + UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}), + UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}), + '', 'M1', 'M1', '', ['M2'], ['M2'], '', UL(['M3']), UL(['M3']), @@ -937,14 +1574,21 @@ class EnvironmentTestCase(unittest.TestCase): failed = 0 while cases: input, append, expect = cases[:3] - env['XXX'] = input - env.Append(XXX = append) - result = env['XXX'] - if result != expect: + env['XXX'] = copy.copy(input) + try: + env.Append(XXX = append) + except Exception, e: if failed == 0: print - print " %s Append %s => %s did not match %s" % \ - (repr(input), repr(append), repr(result), repr(expect)) + print " %s Append %s exception: %s" % \ + (repr(input), repr(append), e) failed = failed + 1 + else: + result = env['XXX'] + if result != expect: + if failed == 0: print + print " %s Append %s => %s did not match %s" % \ + (repr(input), repr(append), repr(result), repr(expect)) + failed = failed + 1 del cases[:3] assert failed == 0, "%d Append() cases failed" % failed @@ -970,121 +1614,190 @@ class EnvironmentTestCase(unittest.TestCase): ccc = C('ccc') - env2 = Environment(CCC1 = ['c1'], CCC2 = ccc) + env2 = self.TestEnvironment(CCC1 = ['c1'], CCC2 = ccc) env2.Append(CCC1 = ccc, CCC2 = ['c2']) assert env2['CCC1'][0] == 'c1', env2['CCC1'] assert env2['CCC1'][1] is ccc, env2['CCC1'] assert env2['CCC2'][0] is ccc, env2['CCC2'] assert env2['CCC2'][1] == 'c2', env2['CCC2'] - env3 = Environment(X = {'x1' : 7}) + env3 = self.TestEnvironment(X = {'x1' : 7}) env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10}) assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X'] assert env3['Y'] == {'y1': 10}, env3['Y'] - env4 = Environment(BUILDERS = {'z1' : 11}) - env4.Append(BUILDERS = {'z2' : 12}) - assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS'] + z1 = Builder() + z2 = Builder() + env4 = self.TestEnvironment(BUILDERS = {'z1' : z1}) + env4.Append(BUILDERS = {'z2' : z2}) + assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS'] assert hasattr(env4, 'z1') assert hasattr(env4, 'z2') def test_AppendENVPath(self): """Test appending to an ENV path.""" - env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, + env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}) # have to include the pathsep here so that the test will work on UNIX too. env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';') env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';') env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';') env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';') + # this should do nothing since delete_existing is 0 + env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0) assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one') + test = TestCmd.TestCmd(workdir = '') + test.subdir('sub1', 'sub2') + p=env1['ENV']['PATH'] + env1.AppendENVPath('PATH','#sub1', sep = ';') + env1.AppendENVPath('PATH',env1.fs.Dir('sub2'), sep = ';') + assert env1['ENV']['PATH'] == p + ';sub1;sub2', env1['ENV']['PATH'] + def test_AppendUnique(self): """Test appending to unique values to construction variables This strips values that are already present when lists are involved.""" - env = Environment(AAA1 = 'a1', + env = self.TestEnvironment(AAA1 = 'a1', AAA2 = 'a2', AAA3 = 'a3', + AAA4 = 'a4', + AAA5 = 'a5', BBB1 = ['b1'], BBB2 = ['b2'], - BBB3 = ['b3']) + BBB3 = ['b3'], + BBB4 = ['b4'], + BBB5 = ['b5'], + CCC1 = '', + CCC2 = '', + DDD1 = ['a', 'b', 'c']) env.AppendUnique(AAA1 = 'a1', AAA2 = ['a2'], - AAA3 = ['a3', 'b', 'c', 'a3'], + AAA3 = ['a3', 'b', 'c', 'c', 'b', 'a3'], # ignore dups + AAA4 = 'a4.new', + AAA5 = ['a5.new'], BBB1 = 'b1', BBB2 = ['b2'], - BBB3 = ['b3', 'c', 'd', 'b3']) + BBB3 = ['b3', 'c', 'd', 'c', 'b3'], + BBB4 = 'b4.new', + BBB5 = ['b5.new'], + CCC1 = 'c1', + CCC2 = ['c2'], + DDD1 = 'b') + assert env['AAA1'] == 'a1a1', env['AAA1'] assert env['AAA2'] == ['a2'], env['AAA2'] assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3'] + assert env['AAA4'] == 'a4a4.new', env['AAA4'] + assert env['AAA5'] == ['a5', 'a5.new'], env['AAA5'] assert env['BBB1'] == ['b1'], env['BBB1'] assert env['BBB2'] == ['b2'], env['BBB2'] assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3'] + assert env['BBB4'] == ['b4', 'b4.new'], env['BBB4'] + assert env['BBB5'] == ['b5', 'b5.new'], env['BBB5'] + assert env['CCC1'] == 'c1', env['CCC1'] + assert env['CCC2'] == ['c2'], env['CCC2'] + assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1'] + + env.AppendUnique(DDD1 = 'b', delete_existing=1) + assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # b moves to end + env.AppendUnique(DDD1 = ['a','b'], delete_existing=1) + assert env['DDD1'] == ['c', 'a', 'b'], env['DDD1'] # a & b move to end + env.AppendUnique(DDD1 = ['e','f', 'e'], delete_existing=1) + assert env['DDD1'] == ['c', 'a', 'b', 'f', 'e'], env['DDD1'] # add last + + env['CLVar'] = CLVar([]) + env.AppendUnique(CLVar = 'bar') + result = env['CLVar'] + if sys.version[0] == '1' or sys.version[:3] == '2.0': + # Python 2.0 and before have a quirky behavior where CLVar([]) + # actually matches '' and [] due to different __coerce__() + # semantics in the UserList implementation. It isn't worth a + # lot of effort to get this corner case to work identically + # (support for Python 1.5 support will die soon anyway), + # so just treat it separately for now. + assert result == 'bar', result + else: + assert isinstance(result, CLVar), repr(result) + assert result == ['bar'], result - def test_Copy(self): - """Test construction Environment copying - - Update the copy independently afterwards and check that - the original remains intact (that is, no dangling - references point to objects in the copied environment). - Copy the original with some construction variable - updates and check that the original remains intact - and the copy has the updated values. - """ - env1 = Environment(XXX = 'x', YYY = 'y') - env2 = env1.Copy() - env1copy = env1.Copy() - env2.Replace(YYY = 'yyy') - assert env1 != env2 - assert env1 == env1copy - - env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3') - assert env3.Dictionary('XXX') == 'x3' - assert env3.Dictionary('YYY') == 'y' - assert env3.Dictionary('ZZZ') == 'z3' - assert env1 == env1copy - - assert env1['__env__'] is env1, env1['__env__'] - assert env2['__env__'] is env2, env2['__env__'] - assert env3['__env__'] is env3, env3['__env__'] + env['CLVar'] = CLVar(['abc']) + env.AppendUnique(CLVar = 'bar') + result = env['CLVar'] + assert isinstance(result, CLVar), repr(result) + assert result == ['abc', 'bar'], result + + env['CLVar'] = CLVar(['bar']) + env.AppendUnique(CLVar = 'bar') + result = env['CLVar'] + assert isinstance(result, CLVar), repr(result) + assert result == ['bar'], result + + def test_Clone(self): + """Test construction environment copying + + Update the copy independently afterwards and check that + the original remains intact (that is, no dangling + references point to objects in the copied environment). + Clone the original with some construction variable + updates and check that the original remains intact + and the copy has the updated values. + """ + env1 = self.TestEnvironment(XXX = 'x', YYY = 'y') + env2 = env1.Clone() + env1copy = env1.Clone() + assert env1copy == env1copy + assert env2 == env2 + env2.Replace(YYY = 'yyy') + assert env2 == env2 + assert env1 != env2 + assert env1 == env1copy + + env3 = env1.Clone(XXX = 'x3', ZZZ = 'z3') + assert env3 == env3 + assert env3.Dictionary('XXX') == 'x3' + assert env3.Dictionary('YYY') == 'y' + assert env3.Dictionary('ZZZ') == 'z3' + assert env1 == env1copy # Ensure that lists and dictionaries are # deep copied, but not instances. class TestA: pass - env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ], + env1 = self.TestEnvironment(XXX=TestA(), YYY = [ 1, 2, 3 ], ZZZ = { 1:2, 3:4 }) - env2=env1.Copy() + env2=env1.Clone() env2.Dictionary('YYY').append(4) env2.Dictionary('ZZZ')[5] = 6 assert env1.Dictionary('XXX') is env2.Dictionary('XXX') assert 4 in env2.Dictionary('YYY') assert not 4 in env1.Dictionary('YYY') - assert env2.Dictionary('ZZZ').has_key(5) - assert not env1.Dictionary('ZZZ').has_key(5) + assert 5 in env2.Dictionary('ZZZ') + assert 5 not in env1.Dictionary('ZZZ') # - env1 = Environment(BUILDERS = {'b1' : 1}) + env1 = self.TestEnvironment(BUILDERS = {'b1' : Builder()}) assert hasattr(env1, 'b1'), "env1.b1 was not set" - assert env1.b1.env == env1, "b1.env doesn't point to env1" - env2 = env1.Copy(BUILDERS = {'b2' : 2}) + assert env1.b1.object == env1, "b1.object doesn't point to env1" + env2 = env1.Clone(BUILDERS = {'b2' : Builder()}) + assert env2 is env2 + assert env2 == env2 assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1" - assert env1.b1.env == env1, "b1.env was changed" + assert env1.b1.object == env1, "b1.object was changed" assert not hasattr(env2, 'b1'), "b1 was not cleared from env2" assert hasattr(env2, 'b2'), "env2.b2 was not set" - assert env2.b2.env == env2, "b2.env doesn't point to env2" + assert env2.b2.object == env2, "b2.object doesn't point to env2" # Ensure that specifying new tools in a copied environment # works. def foo(env): env['FOO'] = 1 def bar(env): env['BAR'] = 2 def baz(env): env['BAZ'] = 3 - env1 = Environment(tools=[foo]) - env2 = env1.Copy() - env3 = env1.Copy(tools=[bar, baz]) + env1 = self.TestEnvironment(tools=[foo]) + env2 = env1.Clone() + env3 = env1.Clone(tools=[bar, baz]) assert env1.get('FOO') is 1 assert env1.get('BAR') is None @@ -1098,8 +1811,8 @@ class EnvironmentTestCase(unittest.TestCase): # Ensure that recursive variable substitution when copying # environments works properly. - env1 = Environment(CCFLAGS = '-DFOO', XYZ = '-DXYZ') - env2 = env1.Copy(CCFLAGS = '$CCFLAGS -DBAR', + env1 = self.TestEnvironment(CCFLAGS = '-DFOO', XYZ = '-DXYZ') + env2 = env1.Clone(CCFLAGS = '$CCFLAGS -DBAR', XYZ = ['-DABC', 'x $XYZ y', '-DDEF']) x = env2.get('CCFLAGS') assert x == '-DFOO -DBAR', x @@ -1108,14 +1821,68 @@ class EnvironmentTestCase(unittest.TestCase): # Ensure that special properties of a class don't get # lost on copying. - env1 = Environment(FLAGS = CLVar('flag1 flag2')) + env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2')) x = env1.get('FLAGS') assert x == ['flag1', 'flag2'], x - env2 = env1.Copy() + env2 = env1.Clone() env2.Append(FLAGS = 'flag3 flag4') x = env2.get('FLAGS') assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x + # Test that the environment stores the toolpath and + # re-uses it for copies. + test = TestCmd.TestCmd(workdir = '') + + test.write('xxx.py', """\ +def exists(env): + 1 +def generate(env): + env['XXX'] = 'one' +""") + + test.write('yyy.py', """\ +def exists(env): + 1 +def generate(env): + env['YYY'] = 'two' +""") + + env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')]) + assert env['XXX'] == 'one', env['XXX'] + env = env.Clone(tools=['yyy']) + assert env['YYY'] == 'two', env['YYY'] + + + # Test that + real_value = [4] + + def my_tool(env, rv=real_value): + assert env['KEY_THAT_I_WANT'] == rv[0] + env['KEY_THAT_I_WANT'] = rv[0] + 1 + + env = self.TestEnvironment() + + real_value[0] = 5 + env = env.Clone(KEY_THAT_I_WANT=5, tools=[my_tool]) + assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT'] + + real_value[0] = 6 + env = env.Clone(KEY_THAT_I_WANT=6, tools=[my_tool]) + assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT'] + + + def test_Copy(self): + """Test copying using the old env.Copy() method""" + env1 = self.TestEnvironment(XXX = 'x', YYY = 'y') + env2 = env1.Copy() + env1copy = env1.Copy() + assert env1copy == env1copy + assert env2 == env2 + env2.Replace(YYY = 'yyy') + assert env2 == env2 + assert env1 != env2 + assert env1 == env1copy + def test_Detect(self): """Test Detect()ing tools""" test = TestCmd.TestCmd(workdir = '') @@ -1127,14 +1894,14 @@ class EnvironmentTestCase(unittest.TestCase): test.write(['sub1', 'xxx'], "sub1/xxx\n") test.write(['sub2', 'xxx'], "sub2/xxx\n") - env = Environment(ENV = { 'PATH' : [sub1, sub2] }) + env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) x = env.Detect('xxx.exe') assert x is None, x test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n") - env = Environment(ENV = { 'PATH' : [sub1, sub2] }) + env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) x = env.Detect('xxx.exe') assert x == 'xxx.exe', x @@ -1148,7 +1915,7 @@ class EnvironmentTestCase(unittest.TestCase): test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n") test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n") - env = Environment(ENV = { 'PATH' : [sub1, sub2] }) + env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) x = env.Detect('xxx.exe') assert x is None, x @@ -1156,7 +1923,7 @@ class EnvironmentTestCase(unittest.TestCase): sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') os.chmod(sub2_xxx_exe, 0755) - env = Environment(ENV = { 'PATH' : [sub1, sub2] }) + env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) x = env.Detect('xxx.exe') assert x == 'xxx.exe', x @@ -1167,37 +1934,37 @@ class EnvironmentTestCase(unittest.TestCase): x = env.Detect('xxx.exe') assert x == 'xxx.exe', x - env = Environment(ENV = { 'PATH' : [] }) + env = self.TestEnvironment(ENV = { 'PATH' : [] }) x = env.Detect('xxx.exe') assert x is None, x def test_Dictionary(self): - """Test retrieval of known construction variables - - Fetch them from the Dictionary and check for well-known - defaults that get inserted. - """ - env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z') - assert env.Dictionary('XXX') == 'x' - assert env.Dictionary('YYY') == 'y' - assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z'] - xxx, zzz = env.Dictionary('XXX', 'ZZZ') - assert xxx == 'x' - assert zzz == 'z' - assert env.Dictionary().has_key('BUILDERS') - assert env.Dictionary().has_key('CC') - assert env.Dictionary().has_key('CCFLAGS') - assert env.Dictionary().has_key('ENV') - - assert env['XXX'] == 'x' - env['XXX'] = 'foo' - assert env.Dictionary('XXX') == 'foo' - del env['XXX'] - assert not env.Dictionary().has_key('XXX') + """Test retrieval of known construction variables + + Fetch them from the Dictionary and check for well-known + defaults that get inserted. + """ + env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z') + assert env.Dictionary('XXX') == 'x' + assert env.Dictionary('YYY') == 'y' + assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z'] + xxx, zzz = env.Dictionary('XXX', 'ZZZ') + assert xxx == 'x' + assert zzz == 'z' + assert 'BUILDERS' in env.Dictionary() + assert 'CC' in env.Dictionary() + assert 'CCFLAGS' in env.Dictionary() + assert 'ENV' in env.Dictionary() + + assert env['XXX'] == 'x' + env['XXX'] = 'foo' + assert env.Dictionary('XXX') == 'foo' + del env['XXX'] + assert 'XXX' not in env.Dictionary() def test_FindIxes(self): "Test FindIxes()" - env = Environment(LIBPREFIX='lib', + env = self.TestEnvironment(LIBPREFIX='lib', LIBSUFFIX='.a', SHLIBPREFIX='lib', SHLIBSUFFIX='.so', @@ -1209,73 +1976,157 @@ class EnvironmentTestCase(unittest.TestCase): assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX') assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX') - assert None == env.FindIxes(paths, 'PREFIX', 'POST') + assert None is env.FindIxes(paths, 'PREFIX', 'POST') paths = ['libfoo.a', 'prefoopost'] assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX') - assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX') + assert None is env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX') assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX') - def test_Override(self): - "Test overriding construction variables" - env = Environment(ONE=1, TWO=2, THREE=3, FOUR=4) - assert env['ONE'] == 1, env['ONE'] - assert env['TWO'] == 2, env['TWO'] - assert env['THREE'] == 3, env['THREE'] - assert env['FOUR'] == 4, env['FOUR'] - - env2 = env.Override({'TWO' : '10', - 'THREE' :'x $THREE y', - 'FOUR' : ['x', '$FOUR', 'y']}) - assert env2['ONE'] == 1, env2['ONE'] - assert env2['TWO'] == '10', env2['TWO'] - assert env2['THREE'] == 'x 3 y', env2['THREE'] - assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR'] - - assert env['ONE'] == 1, env['ONE'] - assert env['TWO'] == 2, env['TWO'] - assert env['THREE'] == 3, env['THREE'] - assert env['FOUR'] == 4, env['FOUR'] - - env2.Replace(ONE = "won") - assert env2['ONE'] == "won", env2['ONE'] - assert env['ONE'] == 1, env['ONE'] - - assert env['__env__'] is env, env['__env__'] - assert env2['__env__'] is env2, env2['__env__'] - def test_ParseConfig(self): """Test the ParseConfig() method""" - env = Environment(COMMAND='command', + env = self.TestEnvironment(COMMAND='command', + ASFLAGS='assembler', + CCFLAGS=[''], + CPPDEFINES=[], + CPPFLAGS=[''], CPPPATH='string', + FRAMEWORKPATH=[], + FRAMEWORKS=[], LIBPATH=['list'], LIBS='', - CCFLAGS=['']) - save_command = [] - orig_popen = os.popen - def my_popen(command, save_command=save_command): - save_command.append(command) - class fake_file: - def read(self): - return "-I/usr/include/fum -Ibar -X\n" + \ - "-L/usr/fax -Lfoo -lxxx abc" - return fake_file() + LINKFLAGS=[''], + RPATH=[]) + + orig_backtick = env.backtick + class my_backtick: + def __init__(self, save_command, output): + self.save_command = save_command + self.output = output + def __call__(self, command): + self.save_command.append(command) + return self.output + try: - os.popen = my_popen - libs = env.ParseConfig("fake $COMMAND") + save_command = [] + env.backtick = my_backtick(save_command, + "-I/usr/include/fum -I bar -X\n" + \ + "-L/usr/fax -L foo -lxxx -l yyy " + \ + "-Wa,-as -Wl,-link " + \ + "-Wl,-rpath=rpath1 " + \ + "-Wl,-R,rpath2 " + \ + "-Wl,-Rrpath3 " + \ + "-Wp,-cpp abc " + \ + "-framework Carbon " + \ + "-frameworkdir=fwd1 " + \ + "-Ffwd2 " + \ + "-F fwd3 " + \ + "-pthread " + \ + "-mno-cygwin -mwindows " + \ + "-arch i386 -isysroot /tmp +DD64 " + \ + "-DFOO -DBAR=value") + env.ParseConfig("fake $COMMAND") assert save_command == ['fake command'], save_command - assert libs == ['abc'], libs + assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS'] + assert env['CCFLAGS'] == ['', '-X', '-Wa,-as', + '-pthread', '-mno-cygwin', + ('-arch', 'i386'), ('-isysroot', '/tmp'), + '+DD64'], env['CCFLAGS'] + assert env['CPPDEFINES'] == ['FOO', ['BAR', 'value']], env['CPPDEFINES'] + assert env['CPPFLAGS'] == ['', '-Wp,-cpp'], env['CPPFLAGS'] assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH'] + assert env['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], env['FRAMEWORKPATH'] + assert env['FRAMEWORKS'] == ['Carbon'], env['FRAMEWORKS'] assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH'] - assert env['LIBS'] == ['xxx'], env['LIBS'] - assert env['CCFLAGS'] == ['', '-X'], env['CCFLAGS'] + assert env['LIBS'] == ['xxx', 'yyy', env.File('abc')], env['LIBS'] + assert env['LINKFLAGS'] == ['', '-Wl,-link', '-pthread', + '-mno-cygwin', '-mwindows', + ('-arch', 'i386'), + ('-isysroot', '/tmp'), + '+DD64'], env['LINKFLAGS'] + assert env['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], env['RPATH'] + + env.backtick = my_backtick([], "-Ibar") + env.ParseConfig("fake2") + assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH'] + env.ParseConfig("fake2", unique=0) + assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar', 'bar'], env['CPPPATH'] finally: - os.popen = orig_popen + env.backtick = orig_backtick + + def test_ParseDepends(self): + """Test the ParseDepends() method""" + test = TestCmd.TestCmd(workdir = '') + + test.write('single', """ +#file: dependency + +f0: \ + d1 \ + d2 \ + d3 \ + +""") + + test.write('multiple', """ +f1: foo +f2 f3: bar +f4: abc def +#file: dependency +f5: \ + ghi \ + jkl \ + mno \ +""") + + env = self.TestEnvironment(SINGLE = test.workpath('single')) + + tlist = [] + dlist = [] + def my_depends(target, dependency, tlist=tlist, dlist=dlist): + tlist.extend(target) + dlist.extend(dependency) + + env.Depends = my_depends + + env.ParseDepends(test.workpath('does_not_exist')) + + exc_caught = None + try: + env.ParseDepends(test.workpath('does_not_exist'), must_exist=1) + except IOError: + exc_caught = 1 + assert exc_caught, "did not catch expected IOError" + + del tlist[:] + del dlist[:] + + env.ParseDepends('$SINGLE', only_one=1) + t = list(map(str, tlist)) + d = list(map(str, dlist)) + assert t == ['f0'], t + assert d == ['d1', 'd2', 'd3'], d + + del tlist[:] + del dlist[:] + + env.ParseDepends(test.workpath('multiple')) + t = list(map(str, tlist)) + d = list(map(str, dlist)) + assert t == ['f1', 'f2', 'f3', 'f4', 'f5'], t + assert d == ['foo', 'bar', 'abc', 'def', 'ghi', 'jkl', 'mno'], d + + exc_caught = None + try: + env.ParseDepends(test.workpath('multiple'), only_one=1) + except SCons.Errors.UserError: + exc_caught = 1 + assert exc_caught, "did not catch expected UserError" def test_Platform(self): """Test the Platform() method""" - env = Environment(WIN32='win32', NONE='no-such-platform') + env = self.TestEnvironment(WIN32='win32', NONE='no-such-platform') exc_caught = None try: @@ -1300,6 +2151,8 @@ class EnvironmentTestCase(unittest.TestCase): def test_Prepend(self): """Test prepending to construction variables in an Environment """ + import UserDict + UD = UserDict.UserDict import UserList UL = UserList.UserList @@ -1331,6 +2184,18 @@ class EnvironmentTestCase(unittest.TestCase): UL(['i7']), [''], UL(['', 'i7']), UL(['i8']), UL(['']), UL(['', 'i8']), + {'d1':1}, 'D1', {'d1':1, 'D1':None}, + {'d2':1}, ['D2'], {'d2':1, 'D2':None}, + {'d3':1}, UL(['D3']), {'d3':1, 'D3':None}, + {'d4':1}, {'D4':1}, {'d4':1, 'D4':1}, + {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}), + + UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}), + UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}), + UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}), + UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}), + UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}), + '', 'M1', 'M1', '', ['M2'], ['M2'], '', UL(['M3']), UL(['M3']), @@ -1381,14 +2246,21 @@ class EnvironmentTestCase(unittest.TestCase): failed = 0 while cases: input, prepend, expect = cases[:3] - env['XXX'] = input - env.Prepend(XXX = prepend) - result = env['XXX'] - if result != expect: + env['XXX'] = copy.copy(input) + try: + env.Prepend(XXX = prepend) + except Exception, e: if failed == 0: print - print " %s Prepend %s => %s did not match %s" % \ - (repr(input), repr(prepend), repr(result), repr(expect)) + print " %s Prepend %s exception: %s" % \ + (repr(input), repr(prepend), e) failed = failed + 1 + else: + result = env['XXX'] + if result != expect: + if failed == 0: print + print " %s Prepend %s => %s did not match %s" % \ + (repr(input), repr(prepend), repr(result), repr(expect)) + failed = failed + 1 del cases[:3] assert failed == 0, "%d Prepend() cases failed" % failed @@ -1404,85 +2276,142 @@ class EnvironmentTestCase(unittest.TestCase): assert isinstance(result, CLVar), repr(result) assert result == ['bar', 'foo'], result - env3 = Environment(X = {'x1' : 7}) + env3 = self.TestEnvironment(X = {'x1' : 7}) env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10}) assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X'] assert env3['Y'] == {'y1': 10}, env3['Y'] - env4 = Environment(BUILDERS = {'z1' : 11}) - env4.Prepend(BUILDERS = {'z2' : 12}) - assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS'] + z1 = Builder() + z2 = Builder() + env4 = self.TestEnvironment(BUILDERS = {'z1' : z1}) + env4.Prepend(BUILDERS = {'z2' : z2}) + assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS'] assert hasattr(env4, 'z1') assert hasattr(env4, 'z2') def test_PrependENVPath(self): """Test prepending to an ENV path.""" - env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, + env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}) # have to include the pathsep here so that the test will work on UNIX too. env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';') env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';') env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';') env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';') + # this should do nothing since delete_existing is 0 + env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0) assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') - def test_PrependENVPath(self): - """Test prepending to an ENV path.""" - env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, - MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}) - # have to include the pathsep here so that the test will work on UNIX too. - env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';') - env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';') - env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';') - env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';') - assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') - assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') + test = TestCmd.TestCmd(workdir = '') + test.subdir('sub1', 'sub2') + p=env1['ENV']['PATH'] + env1.PrependENVPath('PATH','#sub1', sep = ';') + env1.PrependENVPath('PATH',env1.fs.Dir('sub2'), sep = ';') + assert env1['ENV']['PATH'] == 'sub2;sub1;' + p, env1['ENV']['PATH'] def test_PrependUnique(self): """Test prepending unique values to construction variables This strips values that are already present when lists are involved.""" - env = Environment(AAA1 = 'a1', + env = self.TestEnvironment(AAA1 = 'a1', AAA2 = 'a2', AAA3 = 'a3', + AAA4 = 'a4', + AAA5 = 'a5', BBB1 = ['b1'], BBB2 = ['b2'], - BBB3 = ['b3']) + BBB3 = ['b3'], + BBB4 = ['b4'], + BBB5 = ['b5'], + CCC1 = '', + CCC2 = '', + DDD1 = ['a', 'b', 'c']) env.PrependUnique(AAA1 = 'a1', AAA2 = ['a2'], - AAA3 = ['a3', 'b', 'c', 'a3'], + AAA3 = ['a3', 'b', 'c', 'b', 'a3'], # ignore dups + AAA4 = 'a4.new', + AAA5 = ['a5.new'], BBB1 = 'b1', BBB2 = ['b2'], - BBB3 = ['b3', 'b', 'c', 'b3']) + BBB3 = ['b3', 'b', 'c', 'b3'], + BBB4 = 'b4.new', + BBB5 = ['b5.new'], + CCC1 = 'c1', + CCC2 = ['c2'], + DDD1 = 'b') assert env['AAA1'] == 'a1a1', env['AAA1'] assert env['AAA2'] == ['a2'], env['AAA2'] - assert env['AAA3'] == ['b', 'c', 'a3'], env['AAA3'] + assert env['AAA3'] == ['c', 'b', 'a3'], env['AAA3'] + assert env['AAA4'] == 'a4.newa4', env['AAA4'] + assert env['AAA5'] == ['a5.new', 'a5'], env['AAA5'] assert env['BBB1'] == ['b1'], env['BBB1'] assert env['BBB2'] == ['b2'], env['BBB2'] assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3'] + assert env['BBB4'] == ['b4.new', 'b4'], env['BBB4'] + assert env['BBB5'] == ['b5.new', 'b5'], env['BBB5'] + assert env['CCC1'] == 'c1', env['CCC1'] + assert env['CCC2'] == ['c2'], env['CCC2'] + assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1'] + + env.PrependUnique(DDD1 = 'b', delete_existing=1) + assert env['DDD1'] == ['b', 'a', 'c'], env['DDD1'] # b moves to front + env.PrependUnique(DDD1 = ['a','c'], delete_existing=1) + assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # a & c move to front + env.PrependUnique(DDD1 = ['d','e','d'], delete_existing=1) + assert env['DDD1'] == ['d', 'e', 'a', 'c', 'b'], env['DDD1'] + + + env['CLVar'] = CLVar([]) + env.PrependUnique(CLVar = 'bar') + result = env['CLVar'] + if sys.version[0] == '1' or sys.version[:3] == '2.0': + # Python 2.0 and before have a quirky behavior where CLVar([]) + # actually matches '' and [] due to different __coerce__() + # semantics in the UserList implementation. It isn't worth a + # lot of effort to get this corner case to work identically + # (support for Python 1.5 support will die soon anyway), + # so just treat it separately for now. + assert result == 'bar', result + else: + assert isinstance(result, CLVar), repr(result) + assert result == ['bar'], result + + env['CLVar'] = CLVar(['abc']) + env.PrependUnique(CLVar = 'bar') + result = env['CLVar'] + assert isinstance(result, CLVar), repr(result) + assert result == ['bar', 'abc'], result + + env['CLVar'] = CLVar(['bar']) + env.PrependUnique(CLVar = 'bar') + result = env['CLVar'] + assert isinstance(result, CLVar), repr(result) + assert result == ['bar'], result def test_Replace(self): """Test replacing construction variables in an Environment After creation of the Environment, of course. """ - env1 = Environment(AAA = 'a', BBB = 'b') + env1 = self.TestEnvironment(AAA = 'a', BBB = 'b') env1.Replace(BBB = 'bbb', CCC = 'ccc') - env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc') + env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc') assert env1 == env2, diff_env(env1, env2) - env3 = Environment(BUILDERS = {'b1' : 1}) + b1 = Builder() + b2 = Builder() + env3 = self.TestEnvironment(BUILDERS = {'b1' : b1}) assert hasattr(env3, 'b1'), "b1 was not set" - env3.Replace(BUILDERS = {'b2' : 2}) + env3.Replace(BUILDERS = {'b2' : b2}) assert not hasattr(env3, 'b1'), "b1 was not cleared" assert hasattr(env3, 'b2'), "b2 was not set" def test_ReplaceIxes(self): "Test ReplaceIxes()" - env = Environment(LIBPREFIX='lib', + env = self.TestEnvironment(LIBPREFIX='lib', LIBSUFFIX='.a', SHLIBPREFIX='lib', SHLIBSUFFIX='.so', @@ -1501,23 +2430,33 @@ class EnvironmentTestCase(unittest.TestCase): 'PREFIX', 'SUFFIX', 'LIBPREFIX', 'LIBSUFFIX') + def test_SetDefault(self): + """Test the SetDefault method""" + env = self.TestEnvironment(tools = []) + env.SetDefault(V1 = 1) + env.SetDefault(V1 = 2) + assert env['V1'] == 1 + env['V2'] = 2 + env.SetDefault(V2 = 1) + assert env['V2'] == 2 + def test_Tool(self): """Test the Tool() method""" - env = Environment(LINK='link', NONE='no-such-tool') + env = self.TestEnvironment(LINK='link', NONE='no-such-tool') exc_caught = None try: env.Tool('does_not_exist') - except SCons.Errors.UserError: + except SCons.Errors.EnvironmentError: exc_caught = 1 - assert exc_caught, "did not catch expected UserError" + assert exc_caught, "did not catch expected EnvironmentError" exc_caught = None try: env.Tool('$NONE') - except SCons.Errors.UserError: + except SCons.Errors.EnvironmentError: exc_caught = 1 - assert exc_caught, "did not catch expected UserError" + assert exc_caught, "did not catch expected EnvironmentError" # Use a non-existent toolpath directory just to make sure we # can call Tool() with the keyword argument. @@ -1527,6 +2466,29 @@ class EnvironmentTestCase(unittest.TestCase): env.Tool('$LINK') assert env['LINK'] == '$SMARTLINK', env['LINK'] + # Test that the environment stores the toolpath and + # re-uses it for later calls. + test = TestCmd.TestCmd(workdir = '') + + test.write('xxx.py', """\ +def exists(env): + 1 +def generate(env): + env['XXX'] = 'one' +""") + + test.write('yyy.py', """\ +def exists(env): + 1 +def generate(env): + env['YYY'] = 'two' +""") + + env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')]) + assert env['XXX'] == 'one', env['XXX'] + env.Tool('yyy') + assert env['YYY'] == 'two', env['YYY'] + def test_WhereIs(self): """Test the WhereIs() method""" test = TestCmd.TestCmd(workdir = '') @@ -1555,30 +2517,35 @@ class EnvironmentTestCase(unittest.TestCase): test.workpath('sub2'), test.workpath('sub3'), test.workpath('sub4'), - ] + string.split(env_path, os.pathsep) + ] + env_path.split(os.pathsep) pathdirs_1243 = [ test.workpath('sub1'), test.workpath('sub2'), test.workpath('sub4'), test.workpath('sub3'), - ] + string.split(env_path, os.pathsep) + ] + env_path.split(os.pathsep) - path = string.join(pathdirs_1234, os.pathsep) - env = Environment(ENV = {'PATH' : path}) + path = os.pathsep.join(pathdirs_1234) + env = self.TestEnvironment(ENV = {'PATH' : path}) wi = env.WhereIs('xxx.exe') assert wi == test.workpath(sub3_xxx_exe), wi wi = env.WhereIs('xxx.exe', pathdirs_1243) assert wi == test.workpath(sub4_xxx_exe), wi - wi = env.WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep)) + wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243)) + assert wi == test.workpath(sub4_xxx_exe), wi + + wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe) + assert wi == test.workpath(sub4_xxx_exe), wi + wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe) assert wi == test.workpath(sub4_xxx_exe), wi - path = string.join(pathdirs_1243, os.pathsep) - env = Environment(ENV = {'PATH' : path}) + path = os.pathsep.join(pathdirs_1243) + env = self.TestEnvironment(ENV = {'PATH' : path}) wi = env.WhereIs('xxx.exe') assert wi == test.workpath(sub4_xxx_exe), wi wi = env.WhereIs('xxx.exe', pathdirs_1234) assert wi == test.workpath(sub3_xxx_exe), wi - wi = env.WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep)) + wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1234)) assert wi == test.workpath(sub3_xxx_exe), wi if sys.platform == 'win32': @@ -1589,13 +2556,13 @@ class EnvironmentTestCase(unittest.TestCase): assert wi == test.workpath(sub4_xxx_exe), wi wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE') - assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi + assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi # Test that we return a normalized path even when # the path contains forward slashes. forward_slash = test.workpath('') + '/sub3' wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE') - assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi + assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi @@ -1603,29 +2570,33 @@ class EnvironmentTestCase(unittest.TestCase): """Test the Action() method""" import SCons.Action - env = Environment(FOO = 'xyzzy') + env = self.TestEnvironment(FOO = 'xyzzy') a = env.Action('foo') assert a, a - assert a.__class__ is SCons.Action.CommandAction, a + assert a.__class__ is SCons.Action.CommandAction, a.__class__ a = env.Action('$FOO') assert a, a - assert a.__class__ is SCons.Action.CommandGeneratorAction, a + assert a.__class__ is SCons.Action.CommandAction, a.__class__ + + a = env.Action('$$FOO') + assert a, a + assert a.__class__ is SCons.Action.LazyAction, a.__class__ a = env.Action(['$FOO', 'foo']) assert a, a - assert a.__class__ is SCons.Action.ListAction, a + assert a.__class__ is SCons.Action.ListAction, a.__class__ def func(arg): pass a = env.Action(func) assert a, a - assert a.__class__ is SCons.Action.FunctionAction, a + assert a.__class__ is SCons.Action.FunctionAction, a.__class__ def test_AddPostAction(self): """Test the AddPostAction() method""" - env = Environment(FOO='fff', BAR='bbb') + env = self.TestEnvironment(FOO='fff', BAR='bbb') n = env.AddPostAction('$FOO', lambda x: x) assert str(n[0]) == 'fff', n[0] @@ -1636,7 +2607,7 @@ class EnvironmentTestCase(unittest.TestCase): def test_AddPreAction(self): """Test the AddPreAction() method""" - env = Environment(FOO='fff', BAR='bbb') + env = self.TestEnvironment(FOO='fff', BAR='bbb') n = env.AddPreAction('$FOO', lambda x: x) assert str(n[0]) == 'fff', n[0] @@ -1647,128 +2618,149 @@ class EnvironmentTestCase(unittest.TestCase): def test_Alias(self): """Test the Alias() method""" - env = Environment(FOO='kkk', BAR='lll', EA='export_alias') + env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_alias') - tgt = env.Alias('new_alias') + tgt = env.Alias('new_alias')[0] assert str(tgt) == 'new_alias', tgt assert tgt.sources == [], tgt.sources + assert not hasattr(tgt, 'builder'), tgt.builder - tgt = env.Alias('None_alias', None) + tgt = env.Alias('None_alias', None)[0] assert str(tgt) == 'None_alias', tgt assert tgt.sources == [], tgt.sources - tgt = env.Alias('empty_list', []) + tgt = env.Alias('empty_list', [])[0] assert str(tgt) == 'empty_list', tgt assert tgt.sources == [], tgt.sources - tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ]) + tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0] assert str(tgt) == 'export_alias', tgt - assert len(tgt.sources) == 2, map(str, tgt.sources) - assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources) - assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources) + assert len(tgt.sources) == 2, list(map(str, tgt.sources)) + assert str(tgt.sources[0]) == 'asrc1', list(map(str, tgt.sources)) + assert str(tgt.sources[1]) == 'kkk', list(map(str, tgt.sources)) - n = env.Alias(tgt, source = ['$BAR', 'asrc4']) + n = env.Alias(tgt, source = ['$BAR', 'asrc4'])[0] assert n is tgt, n - assert len(tgt.sources) == 4, map(str, tgt.sources) - assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources) - assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources) + assert len(tgt.sources) == 4, list(map(str, tgt.sources)) + assert str(tgt.sources[2]) == 'lll', list(map(str, tgt.sources)) + assert str(tgt.sources[3]) == 'asrc4', list(map(str, tgt.sources)) - n = env.Alias('$EA', 'asrc5') + n = env.Alias('$EA', 'asrc5')[0] assert n is tgt, n - assert len(tgt.sources) == 5, map(str, tgt.sources) - assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources) + assert len(tgt.sources) == 5, list(map(str, tgt.sources)) + assert str(tgt.sources[4]) == 'asrc5', list(map(str, tgt.sources)) t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7']) assert str(t1) == 't1', t1 assert str(t2) == 't2', t2 - assert len(t1.sources) == 2, map(str, t1.sources) - assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources) - assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources) - assert len(t2.sources) == 2, map(str, t2.sources) - assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources) - assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources) + assert len(t1.sources) == 2, list(map(str, t1.sources)) + assert str(t1.sources[0]) == 'asrc6', list(map(str, t1.sources)) + assert str(t1.sources[1]) == 'asrc7', list(map(str, t1.sources)) + assert len(t2.sources) == 2, list(map(str, t2.sources)) + assert str(t2.sources[0]) == 'asrc6', list(map(str, t2.sources)) + assert str(t2.sources[1]) == 'asrc7', list(map(str, t2.sources)) + + tgt = env.Alias('add', 's1') + tgt = env.Alias('add', 's2')[0] + s = list(map(str, tgt.sources)) + assert s == ['s1', 's2'], s + tgt = env.Alias(tgt, 's3')[0] + s = list(map(str, tgt.sources)) + assert s == ['s1', 's2', 's3'], s + + tgt = env.Alias('act', None, "action1")[0] + s = str(tgt.builder.action) + assert s == "action1", s + tgt = env.Alias('act', None, "action2")[0] + s = str(tgt.builder.action) + assert s == "action1\naction2", s + tgt = env.Alias(tgt, None, "action3")[0] + s = str(tgt.builder.action) + assert s == "action1\naction2\naction3", s def test_AlwaysBuild(self): """Test the AlwaysBuild() method""" - env = Environment(FOO='fff', BAR='bbb') - t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR') - assert t[0].__class__.__name__ == 'File' + env = self.TestEnvironment(FOO='fff', BAR='bbb') + t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR', + env.fs.Dir('dir'), env.fs.File('file')) + assert t[0].__class__.__name__ == 'Entry' assert t[0].path == 'a' assert t[0].always_build - assert t[1].__class__.__name__ == 'File' + assert t[1].__class__.__name__ == 'Entry' assert t[1].path == 'bfff' assert t[1].always_build - assert t[2].__class__.__name__ == 'File' + assert t[2].__class__.__name__ == 'Entry' assert t[2].path == 'c' assert t[2].always_build - assert t[3].__class__.__name__ == 'File' + assert t[3].__class__.__name__ == 'Entry' assert t[3].path == 'd' assert t[3].always_build - assert t[4].__class__.__name__ == 'File' + assert t[4].__class__.__name__ == 'Entry' assert t[4].path == 'bbb' assert t[4].always_build - - def test_BuildDir(self): - """Test the BuildDir() method""" + assert t[5].__class__.__name__ == 'Dir' + assert t[5].path == 'dir' + assert t[5].always_build + assert t[6].__class__.__name__ == 'File' + assert t[6].path == 'file' + assert t[6].always_build + + def test_VariantDir(self): + """Test the VariantDir() method""" class MyFS: def Dir(self, name): return name - def BuildDir(self, build_dir, src_dir, duplicate): - self.build_dir = build_dir + def VariantDir(self, variant_dir, src_dir, duplicate): + self.variant_dir = variant_dir self.src_dir = src_dir self.duplicate = duplicate - env = Environment(FOO = 'fff', BAR = 'bbb') + env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') env.fs = MyFS() - env.BuildDir('build', 'src') - assert env.fs.build_dir == 'build', env.fs.build_dir + env.VariantDir('build', 'src') + assert env.fs.variant_dir == 'build', env.fs.variant_dir assert env.fs.src_dir == 'src', env.fs.src_dir assert env.fs.duplicate == 1, env.fs.duplicate - env.BuildDir('build${FOO}', '${BAR}src', 0) - assert env.fs.build_dir == 'buildfff', env.fs.build_dir + env.VariantDir('build${FOO}', '${BAR}src', 0) + assert env.fs.variant_dir == 'buildfff', env.fs.variant_dir assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir assert env.fs.duplicate == 0, env.fs.duplicate def test_Builder(self): """Test the Builder() method""" - env = Environment(FOO = 'xyzzy') + env = self.TestEnvironment(FOO = 'xyzzy') b = env.Builder(action = 'foo') - assert not b is None, b + assert b is not None, b b = env.Builder(action = '$FOO') - assert not b is None, b + assert b is not None, b b = env.Builder(action = ['$FOO', 'foo']) - assert not b is None, b + assert b is not None, b def func(arg): pass b = env.Builder(action = func) - assert not b is None, b + assert b is not None, b b = env.Builder(generator = func) - assert not b is None, b + assert b is not None, b def test_CacheDir(self): """Test the CacheDir() method""" - class MyFS: - def CacheDir(self, path): - self.CD = path - - env = Environment(CD = 'CacheDir') - env.fs = MyFS() + env = self.TestEnvironment(CD = 'CacheDir') env.CacheDir('foo') - assert env.fs.CD == 'foo', env.fs.CD + assert env._CacheDir_path == 'foo', env._CacheDir_path env.CacheDir('$CD') - assert env.fs.CD == 'CacheDir', env.fs.CD + assert env._CacheDir_path == 'CacheDir', env._CacheDir_path def test_Clean(self): """Test the Clean() method""" - env = Environment(FOO = 'fff', BAR = 'bbb') + env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') CT = SCons.Environment.CleanTargets @@ -1776,84 +2768,93 @@ class EnvironmentTestCase(unittest.TestCase): fff = env.arg2nodes('fff')[0] t = env.Clean('foo', 'aaa') - l = map(str, CT[foo]) + l = list(map(str, CT[foo])) assert l == ['aaa'], l t = env.Clean(foo, ['$BAR', 'ccc']) - l = map(str, CT[foo]) + l = list(map(str, CT[foo])) assert l == ['aaa', 'bbb', 'ccc'], l eee = env.arg2nodes('eee')[0] t = env.Clean('$FOO', 'ddd') - l = map(str, CT[fff]) + l = list(map(str, CT[fff])) assert l == ['ddd'], l t = env.Clean(fff, [eee, 'fff']) - l = map(str, CT[fff]) + l = list(map(str, CT[fff])) assert l == ['ddd', 'eee', 'fff'], l def test_Command(self): """Test the Command() method.""" env = Environment() t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'], - action='buildfoo $target $source') - assert not t.builder is None + action='buildfoo $target $source')[0] + assert t.builder is not None assert t.builder.action.__class__.__name__ == 'CommandAction' assert t.builder.action.cmd_list == 'buildfoo $target $source' - assert 'foo1.in' in map(lambda x: x.path, t.sources) - assert 'foo2.in' in map(lambda x: x.path, t.sources) + assert 'foo1.in' in [x.path for x in t.sources] + assert 'foo2.in' in [x.path for x in t.sources] - sub = SCons.Node.FS.default_fs.Dir('sub') + sub = env.fs.Dir('sub') t = env.Command(target='bar.out', source='sub', - action='buildbar $target $source') - assert 'sub' in map(lambda x: x.path, t.sources) + action='buildbar $target $source')[0] + assert 'sub' in [x.path for x in t.sources] def testFunc(env, target, source): assert str(target[0]) == 'foo.out' - assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source) + assert 'foo1.in' in list(map(str, source)) and 'foo2.in' in list(map(str, source)), list(map(str, source)) return 0 t = env.Command(target='foo.out', source=['foo1.in','foo2.in'], - action=testFunc) - assert not t.builder is None + action=testFunc)[0] + assert t.builder is not None assert t.builder.action.__class__.__name__ == 'FunctionAction' t.build() - assert 'foo1.in' in map(lambda x: x.path, t.sources) - assert 'foo2.in' in map(lambda x: x.path, t.sources) + assert 'foo1.in' in [x.path for x in t.sources] + assert 'foo2.in' in [x.path for x in t.sources] x = [] def test2(baz, x=x): x.append(baz) - env = Environment(TEST2 = test2) + env = self.TestEnvironment(TEST2 = test2) t = env.Command(target='baz.out', source='baz.in', action='${TEST2(XYZ)}', - XYZ='magic word') - assert not t.builder is None + XYZ='magic word')[0] + assert t.builder is not None t.build() assert x[0] == 'magic word', x + t = env.Command(target='${X}.out', source='${X}.in', + action = 'foo', + X = 'xxx')[0] + assert str(t) == 'xxx.out', str(t) + assert 'xxx.in' in [x.path for x in t.sources] + + env = self.TestEnvironment(source_scanner = 'should_not_find_this') + t = env.Command(target='file.out', source='file.in', + action = 'foo', + source_scanner = 'fake')[0] + assert t.builder.source_scanner == 'fake', t.builder.source_scanner + def test_Configure(self): """Test the Configure() method""" # Configure() will write to a local temporary file. test = TestCmd.TestCmd(workdir = '') save = os.getcwd() - # Configure() will test, if we are reading a SConscript file - import SCons.Script.SConscript - SCons.Script.SConscript.sconscript_reading = 1 try: os.chdir(test.workpath()) - env = Environment(FOO = 'xyzzy') + env = self.TestEnvironment(FOO = 'xyzzy') def func(arg): pass c = env.Configure() - assert not c is None, c + assert c is not None, c c.Finish() c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func}) - assert not c is None, c + assert c is not None, c assert hasattr(c, 'foo') assert hasattr(c, 'xyzzy') c.Finish() @@ -1862,12 +2863,13 @@ class EnvironmentTestCase(unittest.TestCase): def test_Depends(self): """Test the explicit Depends method.""" - env = Environment(FOO = 'xxx', BAR='yyy') + env = self.TestEnvironment(FOO = 'xxx', BAR='yyy') env.Dir('dir1') env.Dir('dir2') env.File('xxx.py') env.File('yyy.py') - t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py') + t = env.Depends(target='EnvironmentTest.py', + dependency='Environment.py')[0] assert t.__class__.__name__ == 'Entry', t.__class__.__name__ assert t.path == 'EnvironmentTest.py' assert len(t.depends) == 1 @@ -1875,7 +2877,7 @@ class EnvironmentTestCase(unittest.TestCase): assert d.__class__.__name__ == 'Entry', d.__class__.__name__ assert d.path == 'Environment.py' - t = env.Depends(target='${FOO}.py', dependency='${BAR}.py') + t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0] assert t.__class__.__name__ == 'File', t.__class__.__name__ assert t.path == 'xxx.py' assert len(t.depends) == 1 @@ -1883,7 +2885,7 @@ class EnvironmentTestCase(unittest.TestCase): assert d.__class__.__name__ == 'File', d.__class__.__name__ assert d.path == 'yyy.py' - t = env.Depends(target='dir1', dependency='dir2') + t = env.Depends(target='dir1', dependency='dir2')[0] assert t.__class__.__name__ == 'Dir', t.__class__.__name__ assert t.path == 'dir1' assert len(t.depends) == 1 @@ -1897,7 +2899,7 @@ class EnvironmentTestCase(unittest.TestCase): def Dir(self, name): return 'Dir(%s)' % name - env = Environment(FOO = 'foodir', BAR = 'bardir') + env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir') env.fs = MyFS() d = env.Dir('d') @@ -1909,9 +2911,45 @@ class EnvironmentTestCase(unittest.TestCase): d = env.Dir('${BAR}_$BAR') assert d == 'Dir(bardir_bardir)', d + d = env.Dir(['dir1']) + assert d == ['Dir(dir1)'], d + + d = env.Dir(['dir1', 'dir2']) + assert d == ['Dir(dir1)', 'Dir(dir2)'], d + + def test_NoClean(self): + """Test the NoClean() method""" + env = self.TestEnvironment(FOO='ggg', BAR='hhh') + env.Dir('p_hhhb') + env.File('p_d') + t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') + + assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ + assert t[0].path == 'p_a' + assert t[0].noclean + assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ + assert t[1].path == 'p_hhhb' + assert t[1].noclean + assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ + assert t[2].path == 'p_c' + assert t[2].noclean + assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ + assert t[3].path == 'p_d' + assert t[3].noclean + assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ + assert t[4].path == 'p_ggg' + assert t[4].noclean + + def test_Dump(self): + """Test the Dump() method""" + + env = self.TestEnvironment(FOO = 'foo') + assert env.Dump('FOO') == "'foo'", env.Dump('FOO') + assert len(env.Dump()) > 200, env.Dump() # no args version + def test_Environment(self): """Test the Environment() method""" - env = Environment(FOO = 'xxx', BAR = 'yyy') + env = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy') e2 = env.Environment(X = '$FOO', Y = '$BAR') assert e2['X'] == 'xxx', e2['X'] @@ -1932,13 +2970,37 @@ class EnvironmentTestCase(unittest.TestCase): result = env.Execute("foo") assert result == "foo executed", result + def test_Entry(self): + """Test the Entry() method""" + class MyFS: + def Entry(self, name): + return 'Entry(%s)' % name + + env = self.TestEnvironment(FOO = 'fooentry', BAR = 'barentry') + env.fs = MyFS() + + e = env.Entry('e') + assert e == 'Entry(e)', e + + e = env.Entry('$FOO') + assert e == 'Entry(fooentry)', e + + e = env.Entry('${BAR}_$BAR') + assert e == 'Entry(barentry_barentry)', e + + e = env.Entry(['entry1']) + assert e == ['Entry(entry1)'], e + + e = env.Entry(['entry1', 'entry2']) + assert e == ['Entry(entry1)', 'Entry(entry2)'], e + def test_File(self): """Test the File() method""" class MyFS: def File(self, name): return 'File(%s)' % name - env = Environment(FOO = 'foofile', BAR = 'barfile') + env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile') env.fs = MyFS() f = env.File('f') @@ -1950,18 +3012,32 @@ class EnvironmentTestCase(unittest.TestCase): f = env.File('${BAR}_$BAR') assert f == 'File(barfile_barfile)', f + f = env.File(['file1']) + assert f == ['File(file1)'], f + + f = env.File(['file1', 'file2']) + assert f == ['File(file1)', 'File(file2)'], f + def test_FindFile(self): """Test the FindFile() method""" - env = Environment(FOO = 'fff', BAR = 'bbb') + env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') r = env.FindFile('foo', ['no_such_directory']) assert r is None, r # XXX + def test_Flatten(self): + """Test the Flatten() method""" + env = Environment() + l = env.Flatten([1]) + assert l == [1] + l = env.Flatten([1, [2, [3, [4]]]]) + assert l == [1, 2, 3, 4], l + def test_GetBuildPath(self): """Test the GetBuildPath() method.""" - env = Environment(MAGIC = 'xyzzy') + env = self.TestEnvironment(MAGIC = 'xyzzy') p = env.GetBuildPath('foo') assert p == 'foo', p @@ -1971,13 +3047,13 @@ class EnvironmentTestCase(unittest.TestCase): def test_Ignore(self): """Test the explicit Ignore method.""" - env = Environment(FOO='yyy', BAR='zzz') + env = self.TestEnvironment(FOO='yyy', BAR='zzz') env.Dir('dir1') env.Dir('dir2') env.File('yyyzzz') env.File('zzzyyy') - t = env.Ignore(target='targ.py', dependency='dep.py') + t = env.Ignore(target='targ.py', dependency='dep.py')[0] assert t.__class__.__name__ == 'Entry', t.__class__.__name__ assert t.path == 'targ.py' assert len(t.ignore) == 1 @@ -1985,7 +3061,7 @@ class EnvironmentTestCase(unittest.TestCase): assert i.__class__.__name__ == 'Entry', i.__class__.__name__ assert i.path == 'dep.py' - t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO') + t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0] assert t.__class__.__name__ == 'File', t.__class__.__name__ assert t.path == 'yyyzzz' assert len(t.ignore) == 1 @@ -1993,7 +3069,7 @@ class EnvironmentTestCase(unittest.TestCase): assert i.__class__.__name__ == 'File', i.__class__.__name__ assert i.path == 'zzzyyy' - t = env.Ignore(target='dir1', dependency='dir2') + t = env.Ignore(target='dir1', dependency='dir2')[0] assert t.__class__.__name__ == 'Dir', t.__class__.__name__ assert t.path == 'dir1' assert len(t.ignore) == 1 @@ -2001,75 +3077,9 @@ class EnvironmentTestCase(unittest.TestCase): assert i.__class__.__name__ == 'Dir', i.__class__.__name__ assert i.path == 'dir2' - def test_Install(self): - """Test the Install method""" - env = Environment(FOO='iii', BAR='jjj') - - tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ]) - paths = map(str, tgt) - paths.sort() - expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ]) - assert paths == expect, paths - for tnode in tgt: - assert tnode.builder == InstallBuilder - - tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ]) - paths = map(str, tgt) - paths.sort() - expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ]) - assert paths == expect, paths - for tnode in tgt: - assert tnode.builder == InstallBuilder - - exc_caught = None - try: - tgt = env.Install('export', 'export') - except SCons.Errors.UserError, e: - exc_caught = 1 - assert exc_caught, "UserError should be thrown when Install() target is not a file." - match = str(e) == "Source `export' of Install() is not a file. Install() source must be one or more files." - assert match, e - - exc_caught = None - try: - tgt = env.Install('export', ['export', 'build/foo1']) - except SCons.Errors.UserError, e: - exc_caught = 1 - assert exc_caught, "UserError should be thrown when Install() target containins non-files." - match = str(e) == "Source `['export', 'build/foo1']' of Install() contains one or more non-files. Install() source must be one or more files." - assert match, e - - exc_caught = None - try: - tgt = env.Install('export/foo1', 'build/foo1') - except SCons.Errors.UserError, e: - exc_caught = 1 - assert exc_caught, "UserError should be thrown reversing the order of Install() targets." - match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" - assert match, e - - def test_InstallAs(self): - """Test the InstallAs method""" - env = Environment(FOO='iii', BAR='jjj') - - tgt = env.InstallAs(target=string.split('foo1 foo2'), - source=string.split('bar1 bar2')) - assert len(tgt) == 2, len(tgt) - paths = map(lambda x: str(x.sources[0]), tgt) - paths.sort() - expect = map(os.path.normpath, [ 'bar1', 'bar2' ]) - assert paths == expect, paths - for tnode in tgt: - assert tnode.builder == InstallBuilder - - tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s') - assert tgt.path == 'iii.t' - assert tgt.sources[0].path == 'jjj.s' - assert tgt.builder == InstallBuilder - def test_Literal(self): """Test the Literal() method""" - env = Environment(FOO='fff', BAR='bbb') + env = self.TestEnvironment(FOO='fff', BAR='bbb') list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0] assert list == ['$FOO', 'bbb'], list list = env.subst_list(['$FOO', env.Literal('$BAR')])[0] @@ -2077,7 +3087,7 @@ class EnvironmentTestCase(unittest.TestCase): def test_Local(self): """Test the Local() method.""" - env = Environment(FOO='lll') + env = self.TestEnvironment(FOO='lll') l = env.Local(env.fs.File('fff')) assert str(l[0]) == 'fff', l[0] @@ -2088,7 +3098,7 @@ class EnvironmentTestCase(unittest.TestCase): def test_Precious(self): """Test the Precious() method""" - env = Environment(FOO='ggg', BAR='hhh') + env = self.TestEnvironment(FOO='ggg', BAR='hhh') env.Dir('p_hhhb') env.File('p_d') t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') @@ -2118,7 +3128,7 @@ class EnvironmentTestCase(unittest.TestCase): self.list.extend(list(dirs)) def Dir(self, name): return name - env = Environment(FOO='rrr', BAR='sss') + env = self.TestEnvironment(FOO='rrr', BAR='sss') env.fs = MyFS() env.Repository('/tmp/foo') env.Repository('/tmp/$FOO', '/tmp/$BAR/foo') @@ -2130,31 +3140,32 @@ class EnvironmentTestCase(unittest.TestCase): def scan(node, env, target, arg): pass - env = Environment(FOO = scan) + env = self.TestEnvironment(FOO = scan) s = env.Scanner('foo') - assert not s is None, s + assert s is not None, s s = env.Scanner(function = 'foo') - assert not s is None, s + assert s is not None, s if 0: s = env.Scanner('$FOO') - assert not s is None, s + assert s is not None, s s = env.Scanner(function = '$FOO') - assert not s is None, s + assert s is not None, s def test_SConsignFile(self): """Test the SConsignFile() method""" - import SCons.Sig + import SCons.SConsign class MyFS: SConstruct_dir = os.sep + 'dir' - env = Environment(FOO = 'SConsign', + env = self.TestEnvironment(FOO = 'SConsign', BAR = os.path.join(os.sep, 'File')) env.fs = MyFS() + env.Execute = lambda action: None try: fnames = [] @@ -2163,92 +3174,100 @@ class EnvironmentTestCase(unittest.TestCase): fnames.append(name) dbms.append(dbm_module) - save_Sig_SConsignFile = SCons.Sig.SConsignFile - SCons.Sig.SConsignFile = capture + save_SConsign_File = SCons.SConsign.File + SCons.SConsign.File = capture env.SConsignFile('foo') - assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames - assert dbms[0] == None, dbms + assert fnames[-1] == os.path.join(os.sep, 'dir', 'foo'), fnames + assert dbms[-1] is None, dbms env.SConsignFile('$FOO') - assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames - assert dbms[1] == None, dbms + assert fnames[-1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames + assert dbms[-1] is None, dbms env.SConsignFile('/$FOO') - assert fnames[2] == '/SConsign', fnames - assert dbms[2] == None, dbms + assert fnames[-1] == os.sep + 'SConsign', fnames + assert dbms[-1] is None, dbms + + env.SConsignFile(os.sep + '$FOO') + assert fnames[-1] == os.sep + 'SConsign', fnames + assert dbms[-1] is None, dbms env.SConsignFile('$BAR', 'x') - assert fnames[3] == os.path.join(os.sep, 'File'), fnames - assert dbms[3] == 'x', dbms + assert fnames[-1] == os.path.join(os.sep, 'File'), fnames + assert dbms[-1] == 'x', dbms env.SConsignFile('__$BAR', 7) - assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames - assert dbms[4] == 7, dbms + assert fnames[-1] == os.path.join(os.sep, 'dir', '__', 'File'), fnames + assert dbms[-1] == 7, dbms + + env.SConsignFile() + assert fnames[-1] == os.path.join(os.sep, 'dir', '.sconsign'), fnames + assert dbms[-1] is None, dbms + + env.SConsignFile(None) + assert fnames[-1] is None, fnames + assert dbms[-1] is None, dbms finally: - SCons.Sig.SConsignFile = save_Sig_SConsignFile + SCons.SConsign.File = save_SConsign_File def test_SideEffect(self): """Test the SideEffect() method""" - env = Environment(LIB='lll', FOO='fff', BAR='bbb') + env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb') env.File('mylll.pdb') env.Dir('mymmm.pdb') - foo = env.Object('foo.obj', 'foo.cpp') - bar = env.Object('bar.obj', 'bar.cpp') - s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj']) + foo = env.Object('foo.obj', 'foo.cpp')[0] + bar = env.Object('bar.obj', 'bar.cpp')[0] + s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])[0] assert s.__class__.__name__ == 'Entry', s.__class__.__name__ assert s.path == 'mylib.pdb' assert s.side_effect assert foo.side_effects == [s] assert bar.side_effects == [s] - assert s.depends_on([bar]) - assert s.depends_on([foo]) - fff = env.Object('fff.obj', 'fff.cpp') - bbb = env.Object('bbb.obj', 'bbb.cpp') - s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj']) + fff = env.Object('fff.obj', 'fff.cpp')[0] + bbb = env.Object('bbb.obj', 'bbb.cpp')[0] + s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])[0] assert s.__class__.__name__ == 'File', s.__class__.__name__ assert s.path == 'mylll.pdb' assert s.side_effect assert fff.side_effects == [s], fff.side_effects assert bbb.side_effects == [s], bbb.side_effects - assert s.depends_on([bbb]) - assert s.depends_on([fff]) - ggg = env.Object('ggg.obj', 'ggg.cpp') - ccc = env.Object('ccc.obj', 'ccc.cpp') - s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj']) + ggg = env.Object('ggg.obj', 'ggg.cpp')[0] + ccc = env.Object('ccc.obj', 'ccc.cpp')[0] + s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])[0] assert s.__class__.__name__ == 'Dir', s.__class__.__name__ assert s.path == 'mymmm.pdb' assert s.side_effect assert ggg.side_effects == [s], ggg.side_effects assert ccc.side_effects == [s], ccc.side_effects - assert s.depends_on([ccc]) - assert s.depends_on([ggg]) def test_SourceCode(self): """Test the SourceCode() method.""" - env = Environment(FOO='mmm', BAR='nnn') - e = env.SourceCode('foo', None) + env = self.TestEnvironment(FOO='mmm', BAR='nnn') + e = env.SourceCode('foo', None)[0] assert e.path == 'foo' s = e.src_builder() assert s is None, s b = Builder() - e = env.SourceCode(e, b) + e = env.SourceCode(e, b)[0] assert e.path == 'foo' s = e.src_builder() assert s is b, s - e = env.SourceCode('$BAR$FOO', None) + e = env.SourceCode('$BAR$FOO', None)[0] assert e.path == 'nnnmmm' s = e.src_builder() assert s is None, s def test_SourceSignatures(type): """Test the SourceSignatures() method""" - env = Environment(M = 'MD5', T = 'timestamp') + import SCons.Errors + + env = type.TestEnvironment(M = 'MD5', T = 'timestamp') exc_caught = None try: @@ -2256,23 +3275,35 @@ class EnvironmentTestCase(unittest.TestCase): except SCons.Errors.UserError: exc_caught = 1 assert exc_caught, "did not catch expected UserError" - assert not hasattr(env, '_calc_module') env.SourceSignatures('MD5') - m = env._calc_module + assert env.src_sig_type == 'MD5', env.src_sig_type env.SourceSignatures('$M') - assert env._calc_module is m + assert env.src_sig_type == 'MD5', env.src_sig_type env.SourceSignatures('timestamp') - t = env._calc_module + assert env.src_sig_type == 'timestamp', env.src_sig_type env.SourceSignatures('$T') - assert env._calc_module is t + assert env.src_sig_type == 'timestamp', env.src_sig_type + + try: + import SCons.Util + save_md5 = SCons.Util.md5 + SCons.Util.md5 = None + try: + env.SourceSignatures('MD5') + except SCons.Errors.UserError: + pass + else: + self.fail('Did not catch expected UserError') + finally: + SCons.Util.md5 = save_md5 def test_Split(self): """Test the Split() method""" - env = Environment(FOO='fff', BAR='bbb') + env = self.TestEnvironment(FOO='fff', BAR='bbb') s = env.Split("foo bar") assert s == ["foo", "bar"], s s = env.Split("$FOO bar") @@ -2288,7 +3319,9 @@ class EnvironmentTestCase(unittest.TestCase): def test_TargetSignatures(type): """Test the TargetSignatures() method""" - env = Environment(B = 'build', C = 'content') + import SCons.Errors + + env = type.TestEnvironment(B = 'build', C = 'content') exc_caught = None try: @@ -2299,16 +3332,41 @@ class EnvironmentTestCase(unittest.TestCase): assert not hasattr(env, '_build_signature') env.TargetSignatures('build') - assert env._build_signature == 1, env._build_signature - - env.TargetSignatures('content') - assert env._build_signature == 0, env._build_signature + assert env.tgt_sig_type == 'build', env.tgt_sig_type env.TargetSignatures('$B') - assert env._build_signature == 1, env._build_signature + assert env.tgt_sig_type == 'build', env.tgt_sig_type + + env.TargetSignatures('content') + assert env.tgt_sig_type == 'content', env.tgt_sig_type env.TargetSignatures('$C') - assert env._build_signature == 0, env._build_signature + assert env.tgt_sig_type == 'content', env.tgt_sig_type + + env.TargetSignatures('MD5') + assert env.tgt_sig_type == 'MD5', env.tgt_sig_type + + env.TargetSignatures('timestamp') + assert env.tgt_sig_type == 'timestamp', env.tgt_sig_type + + try: + import SCons.Util + save_md5 = SCons.Util.md5 + SCons.Util.md5 = None + try: + env.TargetSignatures('MD5') + except SCons.Errors.UserError: + pass + else: + self.fail('Did not catch expected UserError') + try: + env.TargetSignatures('content') + except SCons.Errors.UserError: + pass + else: + self.fail('Did not catch expected UserError') + finally: + SCons.Util.md5 = save_md5 def test_Value(self): """Test creating a Value() object @@ -2325,6 +3383,9 @@ class EnvironmentTestCase(unittest.TestCase): assert not v1 is v2 assert v1.value == v2.value + v3 = env.Value('c', 'build-c') + assert v3.value == 'c', v3.value + def test_Environment_global_variable(type): @@ -2343,13 +3404,440 @@ class EnvironmentTestCase(unittest.TestCase): f = env.xxx('$FOO') assert f == 'foo', f + def test_bad_keywords(self): + """Test trying to use reserved keywords in an Environment""" + added = [] + + env = self.TestEnvironment(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + INIT = 'init') + bad_msg = '%s is not reserved, but got omitted; see Environment.construction_var_name_ok' + added.append('INIT') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + env.Append(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + APPEND = 'append') + added.append('APPEND') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + env.AppendUnique(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + APPENDUNIQUE = 'appendunique') + added.append('APPENDUNIQUE') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + env.Prepend(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + PREPEND = 'prepend') + added.append('PREPEND') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + env.Prepend(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + PREPENDUNIQUE = 'prependunique') + added.append('PREPENDUNIQUE') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + env.Replace(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + REPLACE = 'replace') + added.append('REPLACE') + for x in self.reserved_variables: + assert x not in env, env[x] + for x in added: + assert x in env, bad_msg % x + + copy = env.Clone(TARGETS = 'targets', + SOURCES = 'sources', + SOURCE = 'source', + TARGET = 'target', + CHANGED_SOURCES = 'changed_sources', + CHANGED_TARGETS = 'changed_targets', + UNCHANGED_SOURCES = 'unchanged_sources', + UNCHANGED_TARGETS = 'unchanged_targets', + COPY = 'copy') + for x in self.reserved_variables: + assert x not in copy, env[x] + for x in added + ['COPY']: + assert x in copy, bad_msg % x + + over = env.Override({'TARGETS' : 'targets', + 'SOURCES' : 'sources', + 'SOURCE' : 'source', + 'TARGET' : 'target', + 'CHANGED_SOURCES' : 'changed_sources', + 'CHANGED_TARGETS' : 'changed_targets', + 'UNCHANGED_SOURCES' : 'unchanged_sources', + 'UNCHANGED_TARGETS' : 'unchanged_targets', + 'OVERRIDE' : 'override'}) + for x in self.reserved_variables: + assert x not in over, over[x] + for x in added + ['OVERRIDE']: + assert x in over, bad_msg % x + + def test_parse_flags(self): + '''Test the Base class parse_flags argument''' + # all we have to show is that it gets to MergeFlags internally + env = Environment(tools=[], parse_flags = '-X') + assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] + + env = Environment(tools=[], CCFLAGS=None, parse_flags = '-Y') + assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS'] + + env = Environment(tools=[], CPPDEFINES = 'FOO', parse_flags = '-std=c99 -X -DBAR') + assert env['CFLAGS'] == ['-std=c99'], env['CFLAGS'] + assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] + assert env['CPPDEFINES'] == ['FOO', 'BAR'], env['CPPDEFINES'] + + def test_clone_parse_flags(self): + '''Test the env.Clone() parse_flags argument''' + # all we have to show is that it gets to MergeFlags internally + env = Environment(tools = []) + env2 = env.Clone(parse_flags = '-X') + assert 'CCFLAGS' not in env + assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] + + env = Environment(tools = [], CCFLAGS=None) + env2 = env.Clone(parse_flags = '-Y') + assert env['CCFLAGS'] is None, env['CCFLAGS'] + assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS'] + + env = Environment(tools = [], CPPDEFINES = 'FOO') + env2 = env.Clone(parse_flags = '-std=c99 -X -DBAR') + assert 'CFLAGS' not in env + assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS'] + assert 'CCFLAGS' not in env + assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] + assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES'] + assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES'] + + + +class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): + + def setUp(self): + env = Environment() + env._dict = {'XXX' : 'x', 'YYY' : 'y'} + env2 = OverrideEnvironment(env, {'XXX' : 'x2'}) + env3 = OverrideEnvironment(env2, {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}) + self.envs = [ env, env2, env3 ] + + def checkpath(self, node, expect): + return str(node) == os.path.normpath(expect) + + def test___init__(self): + """Test OverrideEnvironment initialization""" + env, env2, env3 = self.envs + assert env['XXX'] == 'x', env['XXX'] + assert env2['XXX'] == 'x2', env2['XXX'] + assert env3['XXX'] == 'x3', env3['XXX'] + assert env['YYY'] == 'y', env['YYY'] + assert env2['YYY'] == 'y', env2['YYY'] + assert env3['YYY'] == 'y3', env3['YYY'] + + def test___delitem__(self): + """Test deleting variables from an OverrideEnvironment""" + env, env2, env3 = self.envs + del env3['XXX'] + assert 'XXX' not in env, "env has XXX?" + assert 'XXX' not in env2, "env2 has XXX?" + assert 'XXX' not in env3, "env3 has XXX?" -class NoSubstitutionProxyTestCase(unittest.TestCase): + del env3['YYY'] + assert 'YYY' not in env, "env has YYY?" + assert 'YYY' not in env2, "env2 has YYY?" + assert 'YYY' not in env3, "env3 has YYY?" + + del env3['ZZZ'] + assert 'ZZZ' not in env, "env has ZZZ?" + assert 'ZZZ' not in env2, "env2 has ZZZ?" + assert 'ZZZ' not in env3, "env3 has ZZZ?" + + def test_get(self): + """Test the OverrideEnvironment get() method""" + env, env2, env3 = self.envs + assert env.get('XXX') == 'x', env.get('XXX') + assert env2.get('XXX') == 'x2', env2.get('XXX') + assert env3.get('XXX') == 'x3', env3.get('XXX') + assert env.get('YYY') == 'y', env.get('YYY') + assert env2.get('YYY') == 'y', env2.get('YYY') + assert env3.get('YYY') == 'y3', env3.get('YYY') + assert env.get('ZZZ') is None, env.get('ZZZ') + assert env2.get('ZZZ') is None, env2.get('ZZZ') + assert env3.get('ZZZ') == 'z3', env3.get('ZZZ') + + def test_has_key(self): + """Test the OverrideEnvironment has_key() method""" + env, env2, env3 = self.envs + assert 'XXX' in env, 'XXX' in env + assert 'XXX' in env2, 'XXX' in env2 + assert 'XXX' in env3, 'XXX' in env3 + assert 'YYY' in env, 'YYY' in env + assert 'YYY' in env2, 'YYY' in env2 + assert 'YYY' in env3, 'YYY' in env3 + assert 'ZZZ' not in env, 'ZZZ' in env + assert 'ZZZ' not in env2, 'ZZZ' in env2 + assert 'ZZZ' in env3, 'ZZZ' in env3 + + def test_contains(self): + """Test the OverrideEnvironment __contains__() method""" + try: + 'x' in {'x':1} + except TypeError: + # TODO(1.5) + # An early version of Python that doesn't support "in" + # on dictionaries. Just pass the test. + pass + else: + env, env2, env3 = self.envs + assert 'XXX' in env + assert 'XXX' in env2 + assert 'XXX' in env3 + assert 'YYY' in env + assert 'YYY' in env2 + assert 'YYY' in env3 + assert not 'ZZZ' in env + assert not 'ZZZ' in env2 + assert 'ZZZ' in env3 + + def test_items(self): + """Test the OverrideEnvironment Dictionary() method""" + env, env2, env3 = self.envs + items = env.Dictionary() + assert items == {'XXX' : 'x', 'YYY' : 'y'}, items + items = env2.Dictionary() + assert items == {'XXX' : 'x2', 'YYY' : 'y'}, items + items = env3.Dictionary() + assert items == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, items + + def test_items(self): + """Test the OverrideEnvironment items() method""" + env, env2, env3 = self.envs + items = sorted(env.items()) + assert items == [('XXX', 'x'), ('YYY', 'y')], items + items = sorted(env2.items()) + assert items == [('XXX', 'x2'), ('YYY', 'y')], items + items = sorted(env3.items()) + assert items == [('XXX', 'x3'), ('YYY', 'y3'), ('ZZZ', 'z3')], items + + def test_gvars(self): + """Test the OverrideEnvironment gvars() method""" + env, env2, env3 = self.envs + gvars = env.gvars() + assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars + gvars = env2.gvars() + assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars + gvars = env3.gvars() + assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars + + def test_lvars(self): + """Test the OverrideEnvironment lvars() method""" + env, env2, env3 = self.envs + lvars = env.lvars() + assert lvars == {}, lvars + lvars = env2.lvars() + assert lvars == {'XXX' : 'x2'}, lvars + lvars = env3.lvars() + assert lvars == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, lvars + + def test_Replace(self): + """Test the OverrideEnvironment Replace() method""" + env, env2, env3 = self.envs + assert env['XXX'] == 'x', env['XXX'] + assert env2['XXX'] == 'x2', env2['XXX'] + assert env3['XXX'] == 'x3', env3['XXX'] + assert env['YYY'] == 'y', env['YYY'] + assert env2['YYY'] == 'y', env2['YYY'] + assert env3['YYY'] == 'y3', env3['YYY'] + + env.Replace(YYY = 'y4') + + assert env['XXX'] == 'x', env['XXX'] + assert env2['XXX'] == 'x2', env2['XXX'] + assert env3['XXX'] == 'x3', env3['XXX'] + assert env['YYY'] == 'y4', env['YYY'] + assert env2['YYY'] == 'y4', env2['YYY'] + assert env3['YYY'] == 'y3', env3['YYY'] + + # Tests a number of Base methods through an OverrideEnvironment to + # make sure they handle overridden constructionv variables properly. + # + # The following Base methods also call self.subst(), and so could + # theoretically be subject to problems with evaluating overridden + # variables, but they're never really called that way in the rest + # of our code, so we won't worry about them (at least for now): + # + # ParseConfig() + # ParseDepends() + # Platform() + # Tool() + # + # Action() + # Alias() + # Builder() + # CacheDir() + # Configure() + # Environment() + # FindFile() + # Scanner() + # SourceSignatures() + # TargetSignatures() + + # It's unlikely Clone() will ever be called this way, so let the + # other methods test that handling overridden values works. + #def test_Clone(self): + # """Test the OverrideEnvironment Clone() method""" + # pass + + def test_FindIxes(self): + """Test the OverrideEnvironment FindIxes() method""" + env, env2, env3 = self.envs + x = env.FindIxes(['xaaay'], 'XXX', 'YYY') + assert x == 'xaaay', x + x = env2.FindIxes(['x2aaay'], 'XXX', 'YYY') + assert x == 'x2aaay', x + x = env3.FindIxes(['x3aaay3'], 'XXX', 'YYY') + assert x == 'x3aaay3', x + + def test_ReplaceIxes(self): + """Test the OverrideEnvironment ReplaceIxes() method""" + env, env2, env3 = self.envs + x = env.ReplaceIxes('xaaay', 'XXX', 'YYY', 'YYY', 'XXX') + assert x == 'yaaax', x + x = env2.ReplaceIxes('x2aaay', 'XXX', 'YYY', 'YYY', 'XXX') + assert x == 'yaaax2', x + x = env3.ReplaceIxes('x3aaay3', 'XXX', 'YYY', 'YYY', 'XXX') + assert x == 'y3aaax3', x + + # It's unlikely WhereIs() will ever be called this way, so let the + # other methods test that handling overridden values works. + #def test_WhereIs(self): + # """Test the OverrideEnvironment WhereIs() method""" + # pass + + def test_Dir(self): + """Test the OverrideEnvironment Dir() method""" + env, env2, env3 = self.envs + x = env.Dir('ddir/$XXX') + assert self.checkpath(x, 'ddir/x'), str(x) + x = env2.Dir('ddir/$XXX') + assert self.checkpath(x, 'ddir/x2'), str(x) + x = env3.Dir('ddir/$XXX') + assert self.checkpath(x, 'ddir/x3'), str(x) + + def test_Entry(self): + """Test the OverrideEnvironment Entry() method""" + env, env2, env3 = self.envs + x = env.Entry('edir/$XXX') + assert self.checkpath(x, 'edir/x'), str(x) + x = env2.Entry('edir/$XXX') + assert self.checkpath(x, 'edir/x2'), str(x) + x = env3.Entry('edir/$XXX') + assert self.checkpath(x, 'edir/x3'), str(x) + + def test_File(self): + """Test the OverrideEnvironment File() method""" + env, env2, env3 = self.envs + x = env.File('fdir/$XXX') + assert self.checkpath(x, 'fdir/x'), str(x) + x = env2.File('fdir/$XXX') + assert self.checkpath(x, 'fdir/x2'), str(x) + x = env3.File('fdir/$XXX') + assert self.checkpath(x, 'fdir/x3'), str(x) + + def test_Split(self): + """Test the OverrideEnvironment Split() method""" + env, env2, env3 = self.envs + env['AAA'] = '$XXX $YYY $ZZZ' + x = env.Split('$AAA') + assert x == ['x', 'y'], x + x = env2.Split('$AAA') + assert x == ['x2', 'y'], x + x = env3.Split('$AAA') + assert x == ['x3', 'y3', 'z3'], x + + def test_parse_flags(self): + '''Test the OverrideEnvironment parse_flags argument''' + # all we have to show is that it gets to MergeFlags internally + env = SubstitutionEnvironment() + env2 = env.Override({'parse_flags' : '-X'}) + assert 'CCFLAGS' not in env + assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] + + env = SubstitutionEnvironment(CCFLAGS=None) + env2 = env.Override({'parse_flags' : '-Y'}) + assert env['CCFLAGS'] is None, env['CCFLAGS'] + assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS'] + + env = SubstitutionEnvironment(CPPDEFINES = 'FOO') + env2 = env.Override({'parse_flags' : '-std=c99 -X -DBAR'}) + assert 'CFLAGS' not in env + assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS'] + assert 'CCFLAGS' not in env + assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] + assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES'] + assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES'] + + + +class NoSubstitutionProxyTestCase(unittest.TestCase,TestEnvironmentFixture): def test___init__(self): """Test NoSubstitutionProxy initialization""" - env = Environment(XXX = 'x', YYY = 'y') + env = self.TestEnvironment(XXX = 'x', YYY = 'y') assert env['XXX'] == 'x', env['XXX'] assert env['YYY'] == 'y', env['YYY'] @@ -2377,7 +3865,7 @@ class NoSubstitutionProxyTestCase(unittest.TestCase): def test_subst(self): """Test the NoSubstitutionProxy.subst() method""" - env = Environment(XXX = 'x', YYY = 'y') + env = self.TestEnvironment(XXX = 'x', YYY = 'y') assert env['XXX'] == 'x', env['XXX'] assert env['YYY'] == 'y', env['YYY'] @@ -2391,13 +3879,13 @@ class NoSubstitutionProxyTestCase(unittest.TestCase): assert x == '$XXX', x x = proxy.subst('$YYY', raw=7, target=None, source=None, - dict=None, conv=None, + conv=None, extra_meaningless_keyword_argument=None) assert x == '$YYY', x def test_subst_kw(self): """Test the NoSubstitutionProxy.subst_kw() method""" - env = Environment(XXX = 'x', YYY = 'y') + env = self.TestEnvironment(XXX = 'x', YYY = 'y') assert env['XXX'] == 'x', env['XXX'] assert env['YYY'] == 'y', env['YYY'] @@ -2412,7 +3900,7 @@ class NoSubstitutionProxyTestCase(unittest.TestCase): def test_subst_list(self): """Test the NoSubstitutionProxy.subst_list() method""" - env = Environment(XXX = 'x', YYY = 'y') + env = self.TestEnvironment(XXX = 'x', YYY = 'y') assert env['XXX'] == 'x', env['XXX'] assert env['YYY'] == 'y', env['YYY'] @@ -2425,13 +3913,12 @@ class NoSubstitutionProxyTestCase(unittest.TestCase): x = proxy.subst_list('$XXX') assert x == [[]], x - x = proxy.subst_list('$YYY', raw=0, target=None, source=None, - dict=None, conv=None) + x = proxy.subst_list('$YYY', raw=0, target=None, source=None, conv=None) assert x == [[]], x def test_subst_target_source(self): """Test the NoSubstitutionProxy.subst_target_source() method""" - env = Environment(XXX = 'x', YYY = 'y') + env = self.TestEnvironment(XXX = 'x', YYY = 'y') assert env['XXX'] == 'x', env['XXX'] assert env['YYY'] == 'y', env['YYY'] @@ -2441,19 +3928,61 @@ class NoSubstitutionProxyTestCase(unittest.TestCase): args = ('$XXX $TARGET $SOURCE $YYY',) kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')} - x = apply(env.subst_target_source, args, kw) + x = env.subst_target_source(*args, **kw) assert x == 'x ttt sss y', x - x = apply(proxy.subst_target_source, args, kw) + x = proxy.subst_target_source(*args, **kw) assert x == ' ttt sss ', x +class EnvironmentVariableTestCase(unittest.TestCase): + + def test_is_valid_construction_var(self): + """Testing is_valid_construction_var()""" + r = is_valid_construction_var("_a") + assert r is not None, r + r = is_valid_construction_var("z_") + assert r is not None, r + r = is_valid_construction_var("X_") + assert r is not None, r + r = is_valid_construction_var("2a") + assert r is None, r + r = is_valid_construction_var("a2_") + assert r is not None, r + r = is_valid_construction_var("/") + assert r is None, r + r = is_valid_construction_var("_/") + assert r is None, r + r = is_valid_construction_var("a/") + assert r is None, r + r = is_valid_construction_var(".b") + assert r is None, r + r = is_valid_construction_var("_.b") + assert r is None, r + r = is_valid_construction_var("b1._") + assert r is None, r + r = is_valid_construction_var("-b") + assert r is None, r + r = is_valid_construction_var("_-b") + assert r is None, r + r = is_valid_construction_var("b1-_") + assert r is None, r + if __name__ == "__main__": suite = unittest.TestSuite() - tclasses = [ EnvironmentTestCase, - NoSubstitutionProxyTestCase ] + tclasses = [ SubstitutionTestCase, + BaseTestCase, + OverrideEnvironmentTestCase, + NoSubstitutionProxyTestCase, + EnvironmentVariableTestCase ] for tclass in tclasses: names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(map(tclass, names)) + suite.addTests(list(map(tclass, names))) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: