summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/SCons/scons-3.0.1/engine/SCons/EnvironmentTests.py')
-rw-r--r--3rdParty/SCons/scons-3.0.1/engine/SCons/EnvironmentTests.py3992
1 files changed, 3992 insertions, 0 deletions
diff --git a/3rdParty/SCons/scons-3.0.1/engine/SCons/EnvironmentTests.py b/3rdParty/SCons/scons-3.0.1/engine/SCons/EnvironmentTests.py
new file mode 100644
index 0000000..229858f
--- /dev/null
+++ b/3rdParty/SCons/scons-3.0.1/engine/SCons/EnvironmentTests.py
@@ -0,0 +1,3992 @@
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+from __future__ import print_function
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.compat
+
+import copy
+import io
+import os
+import sys
+import unittest
+from collections import UserDict as UD, UserList as UL
+
+import TestCmd
+import TestUnit
+
+from SCons.Environment import *
+import SCons.Warnings
+
+def diff_env(env1, env2):
+ s1 = "env1 = {\n"
+ s2 = "env2 = {\n"
+ d = {}
+ for k in list(env1._dict.keys()) + list(env2._dict.keys()):
+ 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 k in env2:
+ s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n"
+ s1 = s1 + "}\n"
+ s2 = s2 + "}\n"
+ return s1 + s2
+
+def diff_dict(d1, d2):
+ s1 = "d1 = {\n"
+ s2 = "d2 = {\n"
+ d = {}
+ for k in list(d1.keys()) + list(d2.keys()):
+ 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 k in env2:
+ s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n"
+ s1 = s1 + "}\n"
+ s2 = s2 + "}\n"
+ return s1 + s2
+
+called_it = {}
+built_it = {}
+
+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, 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):
+ global built_it
+ built_it[target] = 1
+
+
+
+scanned_it = {}
+
+class Scanner(object):
+ """A dummy Scanner class for testing purposes. "Scanning"
+ a target is simply setting a value in the dictionary.
+ """
+ def __init__(self, name, skeys=[]):
+ self.name = name
+ self.skeys = skeys
+
+ def __call__(self, filename):
+ global scanned_it
+ scanned_it[filename] = 1
+
+ def __eq__(self, other):
+ try:
+ return self.__dict__ == other.__dict__
+ except AttributeError:
+ return False
+
+ def get_skeys(self, env):
+ return self.skeys
+
+ def __str__(self):
+ return self.name
+
+
+
+class CLVar(UL):
+ def __init__(self, seq):
+ if isinstance(seq, str):
+ seq = seq.split()
+ UL.__init__(self, seq)
+ def __add__(self, other):
+ return UL.__add__(self, CLVar(other))
+ def __radd__(self, other):
+ return UL.__radd__(self, CLVar(other))
+ def __coerce__(self, other):
+ return (self, CLVar(other))
+
+
+
+class DummyNode(object):
+ def __init__(self, name):
+ self.name = name
+ def __str__(self):
+ return self.name
+ def rfile(self):
+ return self
+ def get_subst_proxy(self):
+ return self
+
+def test_tool( env ):
+ env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+
+class TestEnvironmentFixture(object):
+ 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
+
+ def test___cmp__(self):
+ """Test comparing SubstitutionEnvironments
+ """
+
+ env1 = SubstitutionEnvironment(XXX = 'x')
+ env2 = SubstitutionEnvironment(XXX = 'x')
+ env3 = SubstitutionEnvironment(XXX = 'xxx')
+ env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x')
+
+ assert env1 == env2
+ assert env1 != env3
+ assert env1 != env4
+
+ def test___delitem__(self):
+ """Test deleting a variable from a SubstitutionEnvironment
+ """
+ env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
+ env2 = SubstitutionEnvironment(XXX = 'x')
+ del env1['YYY']
+ assert env1 == env2
+
+ 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 SubstitutionEnvironment get() method
+ """
+ env = SubstitutionEnvironment(XXX = 'x')
+ assert env.get('XXX') == 'x', env.get('XXX')
+ assert env.get('YYY') is None, env.get('YYY')
+
+ 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
+ """
+ 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 = list(env.items())
+ assert len(items) == 2 and ('XXX','x') in items and ('YYY','y') in items, items
+ # Was. This fails under py3 as order changes
+ # assert items == [('XXX','x'), ('YYY','y')], items
+
+ def test_arg2nodes(self):
+ """Test the arg2nodes method
+ """
+ env = SubstitutionEnvironment()
+ dict = {}
+ class X(SCons.Node.Node):
+ pass
+ def Factory(name, directory = None, create = 1, dict=dict, X=X):
+ if name not in dict:
+ dict[name] = X()
+ dict[name].name = name
+ return dict[name]
+
+ nodes = env.arg2nodes("Util.py UtilTests.py", Factory)
+ assert len(nodes) == 1, nodes
+ assert isinstance(nodes[0], X)
+ assert nodes[0].name == "Util.py UtilTests.py"
+
+ nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
+ assert len(nodes) == 1, nodes
+ assert isinstance(nodes[0], X)
+ assert nodes[0].name == u"Util.py UtilTests.py"
+
+ nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
+ assert len(nodes) == 2, nodes
+ assert isinstance(nodes[0], X)
+ assert isinstance(nodes[1], X)
+ assert nodes[0].name == "Util.py"
+ assert nodes[1].name == "UtilTests.py"
+
+ n1 = Factory("Util.py")
+ nodes = env.arg2nodes([n1, "UtilTests.py"], Factory)
+ assert len(nodes) == 2, nodes
+ assert isinstance(nodes[0], X)
+ assert isinstance(nodes[1], X)
+ assert nodes[0].name == "Util.py"
+ assert nodes[1].name == "UtilTests.py"
+
+ class SConsNode(SCons.Node.Node):
+ pass
+ nodes = env.arg2nodes(SConsNode())
+ assert len(nodes) == 1, nodes
+ assert isinstance(nodes[0], SConsNode), node
+
+ class OtherNode(object):
+ pass
+ nodes = env.arg2nodes(OtherNode())
+ assert len(nodes) == 1, nodes
+ assert isinstance(nodes[0], OtherNode), node
+
+ def lookup_a(str, F=Factory):
+ if str[0] == 'a':
+ n = F(str)
+ n.a = 1
+ return n
+ else:
+ return None
+
+ def lookup_b(str, F=Factory):
+ if str[0] == 'b':
+ n = F(str)
+ n.b = 1
+ return n
+ else:
+ return None
+
+ env_ll = SubstitutionEnvironment()
+ env_ll.lookup_list = [lookup_a, lookup_b]
+
+ nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
+ assert len(nodes) == 3, nodes
+
+ assert nodes[0].name == 'aaa', nodes[0]
+ assert nodes[0].a == 1, nodes[0]
+ assert not hasattr(nodes[0], 'b'), nodes[0]
+
+ assert nodes[1].name == 'bbb'
+ assert not hasattr(nodes[1], 'a'), nodes[1]
+ assert nodes[1].b == 1, nodes[1]
+
+ assert nodes[2].name == 'ccc'
+ assert not hasattr(nodes[2], 'a'), nodes[1]
+ assert not hasattr(nodes[2], 'b'), nodes[1]
+
+ def lookup_bbbb(str, F=Factory):
+ if str == 'bbbb':
+ n = F(str)
+ n.bbbb = 1
+ return n
+ else:
+ return None
+
+ def lookup_c(str, F=Factory):
+ if str[0] == 'c':
+ n = F(str)
+ n.c = 1
+ return n
+ else:
+ return None
+
+ nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
+ [lookup_c, lookup_bbbb, lookup_b])
+ assert len(nodes) == 2, nodes
+
+ assert nodes[0].name == 'bbbb'
+ assert not hasattr(nodes[0], 'a'), nodes[1]
+ assert not hasattr(nodes[0], 'b'), nodes[1]
+ assert nodes[0].bbbb == 1, nodes[1]
+ assert not hasattr(nodes[0], 'c'), nodes[0]
+
+ assert nodes[1].name == 'ccc'
+ assert not hasattr(nodes[1], 'a'), nodes[1]
+ assert not hasattr(nodes[1], 'b'), nodes[1]
+ 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 = 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 = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
+ mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
+ assert mystr == "b bA bB b", mystr
+
+ 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 = 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
+
+ # 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 = 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 SubstitutionEnvironment
+ if 0:
+ # This will take some serious surgery to subst() and
+ # subst_list(), so just leave these tests out until we can
+ # do that.
+ def bar(arg):
+ pass
+
+ env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
+
+ subst = env.subst('$BAR', call=None)
+ assert subst is bar, subst
+
+ subst = env.subst('$FOO', call=None)
+ assert subst is bar, subst
+
+ def test_subst_kw(self):
+ """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']
+ assert kw['bbb'] == 'b', kw['bbb']
+
+ def test_subst_list(self):
+ """Test substituting construction variables in command lists
+ """
+ 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 = 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 = 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 = 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
+
+ t1 = DummyNode('t1')
+ t2 = DummyNode('t2')
+ s1 = DummyNode('s1')
+ s2 = DummyNode('s2')
+
+ 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
+
+ # 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 = 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 SubstitutionEnvironment
+ if 0:
+ # This will take some serious surgery to subst() and
+ # subst_list(), so just leave these tests out until we can
+ # do that.
+ def bar(arg):
+ pass
+
+ env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
+
+ subst = env.subst_list('$BAR', call=None)
+ assert subst is bar, subst
+
+ subst = env.subst_list('$FOO', call=None)
+ assert subst is bar, subst
+
+ def test_subst_path(self):
+ """Test substituting a path list
+ """
+ class MyProxy(object):
+ def __init__(self, val):
+ self.val = val
+ def get(self):
+ return self.val + '-proxy'
+
+ class MyNode(object):
+ def __init__(self, val):
+ self.val = val
+ def get_subst_proxy(self):
+ return self
+ def __str__(self):
+ return self.val
+
+ class MyObj(object):
+ def get(self):
+ return self
+
+ env = SubstitutionEnvironment(FOO='foo',
+ BAR='bar',
+ LIST=['one', 'two'],
+ PROXY=MyProxy('my1'))
+
+ r = env.subst_path('$FOO')
+ assert r == ['foo'], r
+
+ 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(object):
+ 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 = io.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 = io.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 = io.StringIO()
+ cmd = '%s %s' % (python, test.workpath('fail.py'))
+ try:
+ env.backtick(cmd)
+ except OSError as e:
+ assert str(e) == "'%s' exited 1" % cmd, str(e)
+ else:
+ self.fail("did not catch expected OSError")
+
+ sys.stderr = io.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' : [],
+ 'CXXFLAGS' : [],
+ '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 " + \
+ "-std=c++0x " + \
+ "-framework Carbon " + \
+ "-frameworkdir=fwd1 " + \
+ "-Ffwd2 " + \
+ "-F fwd3 " + \
+ "-dylib_file foo-dylib " + \
+ "-pthread " + \
+ "-fopenmp " + \
+ "-mno-cygwin -mwindows " + \
+ "-arch i386 -isysroot /tmp " + \
+ "-isystem /usr/include/foo " + \
+ "+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', '-fopenmp', '-mno-cygwin',
+ ('-arch', 'i386'), ('-isysroot', '/tmp'),
+ ('-isystem', '/usr/include/foo'),
+ '+DD64'], repr(d['CCFLAGS'])
+ assert d['CXXFLAGS'] == ['-std=c++0x'], repr(d['CXXFLAGS'])
+ 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',
+ '-dylib_file', 'foo-dylib',
+ '-pthread', '-fopenmp',
+ '-mno-cygwin', '-mwindows',
+ ('-arch', 'i386'),
+ ('-isysroot', '/tmp'),
+ '+DD64'], repr(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']
+
+
+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(object):
+ 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
+ """
+ global called_it
+
+ b1 = Builder()
+ b2 = Builder()
+
+ env = Environment()
+ env.Replace(BUILDERS = { 'builder1' : b1,
+ 'builder2' : b2 })
+ called_it = {}
+ env.builder1('in1')
+ assert called_it['target'] is None, called_it
+ assert called_it['source'] == ['in1'], called_it
+
+ 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
+
+ called_it = {}
+ env.builder1(foo = 'bar')
+ assert called_it['foo'] == 'bar', called_it
+ 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
+
+ self.assertRaises(AttributeError, getattr, bw, 'foobar')
+ bw.foobar = 42
+ assert bw.foobar is 42
+
+ # 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()
+
+ 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']
+
+ 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 = self.TestEnvironment(BUILDERS={ 'foo' : b1 })
+ env5['BUILDERS']['bar'] = b2
+ env5.foo.execute(target='out1')
+ env5.bar.execute(target='out2')
+ assert built_it['out1']
+ assert built_it['out2']
+
+ built_it = {}
+ env6 = Environment()
+ env6['BUILDERS'] = { 'foo' : b1,
+ 'bar' : b2 }
+ env6.foo.execute(target='out1')
+ env6.bar.execute(target='out2')
+ assert built_it['out1']
+ assert built_it['out2']
+
+
+
+ def test_Scanners(self):
+ """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"])
+ 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']
+#
+# scanned_it = {}
+# env2 = self.TestEnvironment(SCANNERS = [s1])
+# env1.scanner1(filename = 'out1')
+# assert scanned_it['out1']
+#
+# scanned_it = {}
+# env3 = Environment()
+# 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']
+
+ 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' in env.Dictionary()
+
+ env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' })
+ assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
+
+ def test_ReservedVariables(self):
+ """Test warning generation when reserved variable names are set"""
+
+ reserved_variables = [
+ 'CHANGED_SOURCES',
+ 'CHANGED_TARGETS',
+ 'SOURCE',
+ 'SOURCES',
+ 'TARGET',
+ 'TARGETS',
+ 'UNCHANGED_SOURCES',
+ 'UNCHANGED_TARGETS',
+ ]
+
+ warning = SCons.Warnings.ReservedVariableWarning
+ SCons.Warnings.enableWarningClass(warning)
+ old = SCons.Warnings.warningAsException(1)
+
+ try:
+ env4 = Environment()
+ for kw in self.reserved_variables:
+ exc_caught = None
+ try:
+ env4[kw] = 'xyzzy'
+ except warning:
+ exc_caught = 1
+ assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % 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)
+
+ def test_IllegalVariables(self):
+ """Test that use of illegal variables raises an exception"""
+ env = Environment()
+ def test_it(var, env=env):
+ exc_caught = None
+ try:
+ env[var] = 1
+ except SCons.Errors.UserError:
+ exc_caught = 1
+ assert exc_caught, "did not catch UserError for '%s'" % var
+ env['aaa'] = 1
+ assert env['aaa'] == 1, env['aaa']
+ test_it('foo/bar')
+ test_it('foo.bar')
+ test_it('foo-bar')
+
+ def test_autogenerate(dict):
+ """Test autogenerating variables in a dictionary."""
+
+ 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 = dict.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ],
+ LIBLINKPREFIX = 'foo',
+ 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 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]
+ 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]
+ 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 l == [[]], l
+ l = env.subst_list('$_F77INCFLAGS')
+ assert l == [[]], l
+ l = env.subst_list('$_LIBDIRFLAGS')
+ 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]
+ 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."""
+ class platform(object):
+ def __str__(self): return "TestPlatform"
+ def __call__(self, env): env['XYZZY'] = 777
+
+ def tool(env):
+ env['SET_TOOL'] = 'initialized'
+ assert env['PLATFORM'] == "TestPlatform"
+
+ env = self.TestEnvironment(platform = platform(), tools = [tool])
+ assert env['XYZZY'] == 777, env
+ assert env['PLATFORM'] == "TestPlatform"
+ assert env['SET_TOOL'] == "initialized"
+
+ def test_Default_PLATFORM(self):
+ """Test overriding the default PLATFORM variable"""
+ class platform(object):
+ def __str__(self): return "DefaultTestPlatform"
+ def __call__(self, env): env['XYZZY'] = 888
+
+ def tool(env):
+ env['SET_TOOL'] = 'abcde'
+ assert env['PLATFORM'] == "DefaultTestPlatform"
+
+ import SCons.Defaults
+ save = SCons.Defaults.ConstructionEnvironment.copy()
+ try:
+ import SCons.Defaults
+ SCons.Defaults.ConstructionEnvironment.update({
+ 'PLATFORM' : platform(),
+ })
+ env = self.TestEnvironment(tools = [tool])
+ assert env['XYZZY'] == 888, env
+ assert env['PLATFORM'] == "DefaultTestPlatform"
+ assert env['SET_TOOL'] == "abcde"
+ finally:
+ SCons.Defaults.ConstructionEnvironment = save
+
+ def test_tools(self):
+ """Test specifying a tool callable when instantiating."""
+ def t1(env):
+ env['TOOL1'] = 111
+ def t2(env):
+ env['TOOL2'] = 222
+ def t3(env):
+ env['AAA'] = env['XYZ']
+ def t4(env):
+ env['TOOL4'] = 444
+ 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):
+ env['TOOL5'] = 555
+ def t6(env):
+ env['TOOL6'] = 666
+ def t7(env):
+ env['BBB'] = env['XYZ']
+ def t8(env):
+ env['TOOL8'] = 888
+
+ import SCons.Defaults
+ save = SCons.Defaults.ConstructionEnvironment.copy()
+ try:
+ SCons.Defaults.ConstructionEnvironment.update({
+ 'TOOLS' : [t5, t6, t7],
+ })
+ env = Environment(XYZ = 'bbb')
+ assert env['TOOL5'] == 555, env['TOOL5']
+ assert env['TOOL6'] == 666, env
+ assert env['BBB'] == 'bbb', env
+ t8(env)
+ assert env['TOOL8'] == 888, env
+ 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 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
+ s = e1.subst
+ x = s("${_concat('', '', '', __env__)}")
+ assert x == '', x
+ x = s("${_concat('', [], '', __env__)}")
+ assert x == '', x
+ x = s("${_concat(PRE, '', SUF, __env__)}")
+ assert x == '', x
+ x = s("${_concat(PRE, STR, SUF, __env__)}")
+ assert x == 'prea bsuf', x
+ x = s("${_concat(PRE, LIST, SUF, __env__)}")
+ assert x == 'preasuf prebsuf', x
+
+ def test_concat_nested(self):
+ "Test _concat() on a nested substitution strings."
+ e = self.TestEnvironment(PRE='pre', SUF='suf',
+ L1=['a', 'b'],
+ L2=['c', 'd'],
+ L3=['$L2'])
+ x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)')
+ assert x == 'preasuf prebsuf', x
+ e.AppendUnique(L1 = ['$L2'])
+ x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)')
+ assert x == 'preasuf prebsuf precsuf predsuf', x
+ e.AppendUnique(L1 = ['$L3'])
+ x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)')
+ assert x == 'preasuf prebsuf precsuf predsuf precsuf predsuf', 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 = 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']
+ env._update({'X' : 'xxx',
+ 'TARGET' : 't',
+ 'TARGETS' : 'ttt',
+ 'SOURCE' : 's',
+ 'SOURCES' : 'sss',
+ 'Z' : 'zzz'})
+ assert env['X'] == 'xxx', env['X']
+ assert env['Y'] == 'y', env['Y']
+ assert env['Z'] == 'zzz', env['Z']
+ assert env['TARGET'] == 't', env['TARGET']
+ assert env['TARGETS'] == 'ttt', env['TARGETS']
+ assert env['SOURCE'] == 's', env['SOURCE']
+ assert env['SOURCES'] == 'sss', env['SOURCES']
+
+ def test_Append(self):
+ """Test appending to construction variables in an Environment
+ """
+
+ b1 = Environment()['BUILDERS']
+ b2 = Environment()['BUILDERS']
+ assert b1 == b2, diff_dict(b1, b2)
+
+ cases = [
+ 'a1', 'A1', 'a1A1',
+ 'a2', ['A2'], ['a2', 'A2'],
+ 'a3', UL(['A3']), UL(['a', '3', 'A3']),
+ 'a4', '', 'a4',
+ 'a5', [], ['a5'],
+ 'a6', UL([]), UL(['a', '6']),
+ 'a7', [''], ['a7', ''],
+ 'a8', UL(['']), UL(['a', '8', '']),
+
+ ['e1'], 'E1', ['e1', 'E1'],
+ ['e2'], ['E2'], ['e2', 'E2'],
+ ['e3'], UL(['E3']), UL(['e3', 'E3']),
+ ['e4'], '', ['e4'],
+ ['e5'], [], ['e5'],
+ ['e6'], UL([]), UL(['e6']),
+ ['e7'], [''], ['e7', ''],
+ ['e8'], UL(['']), UL(['e8', '']),
+
+ UL(['i1']), 'I1', UL(['i1', 'I', '1']),
+ UL(['i2']), ['I2'], UL(['i2', 'I2']),
+ UL(['i3']), UL(['I3']), UL(['i3', 'I3']),
+ UL(['i4']), '', UL(['i4']),
+ UL(['i5']), [], UL(['i5']),
+ UL(['i6']), UL([]), UL(['i6']),
+ 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']),
+ '', '', '',
+ '', [], [],
+ '', UL([]), UL([]),
+ '', [''], [''],
+ '', UL(['']), UL(['']),
+
+ [], 'N1', ['N1'],
+ [], ['N2'], ['N2'],
+ [], UL(['N3']), UL(['N3']),
+ [], '', [],
+ [], [], [],
+ [], UL([]), UL([]),
+ [], [''], [''],
+ [], UL(['']), UL(['']),
+
+ UL([]), 'O1', ['O', '1'],
+ UL([]), ['O2'], ['O2'],
+ UL([]), UL(['O3']), UL(['O3']),
+ UL([]), '', UL([]),
+ UL([]), [], UL([]),
+ UL([]), UL([]), UL([]),
+ UL([]), [''], UL(['']),
+ UL([]), UL(['']), UL(['']),
+
+ [''], 'P1', ['', 'P1'],
+ [''], ['P2'], ['', 'P2'],
+ [''], UL(['P3']), UL(['', 'P3']),
+ [''], '', [''],
+ [''], [], [''],
+ [''], UL([]), UL(['']),
+ [''], [''], ['', ''],
+ [''], UL(['']), UL(['', '']),
+
+ UL(['']), 'Q1', ['', 'Q', '1'],
+ UL(['']), ['Q2'], ['', 'Q2'],
+ UL(['']), UL(['Q3']), UL(['', 'Q3']),
+ UL(['']), '', UL(['']),
+ UL(['']), [], UL(['']),
+ UL(['']), UL([]), UL(['']),
+ UL(['']), [''], UL(['', '']),
+ UL(['']), UL(['']), UL(['', '']),
+ ]
+
+ env = Environment()
+ failed = 0
+ while cases:
+ input, append, expect = cases[:3]
+ env['XXX'] = copy.copy(input)
+ try:
+ env.Append(XXX = append)
+ except Exception as e:
+ if failed == 0: print()
+ 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
+
+ env['UL'] = UL(['foo'])
+ env.Append(UL = 'bar')
+ result = env['UL']
+ assert isinstance(result, UL), repr(result)
+ assert result == ['foo', 'b', 'a', 'r'], result
+
+ env['CLVar'] = CLVar(['foo'])
+ env.Append(CLVar = 'bar')
+ result = env['CLVar']
+ assert isinstance(result, CLVar), repr(result)
+ assert result == ['foo', 'bar'], result
+
+ class C(object):
+ def __init__(self, name):
+ self.name = name
+ def __str__(self):
+ return self.name
+ def __eq__(self, other):
+ raise Exception("should not compare")
+
+ ccc = C('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 = 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']
+
+ 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 = 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 = self.TestEnvironment(AAA1 = 'a1',
+ AAA2 = 'a2',
+ AAA3 = 'a3',
+ AAA4 = 'a4',
+ AAA5 = 'a5',
+ BBB1 = ['b1'],
+ BBB2 = ['b2'],
+ BBB3 = ['b3'],
+ BBB4 = ['b4'],
+ BBB5 = ['b5'],
+ CCC1 = '',
+ CCC2 = '',
+ DDD1 = ['a', 'b', 'c'])
+ env['LL1'] = [env.Literal('a literal'), env.Literal('b literal')]
+ env['LL2'] = [env.Literal('c literal'), env.Literal('b literal')]
+ env.AppendUnique(AAA1 = 'a1',
+ AAA2 = ['a2'],
+ AAA3 = ['a3', 'b', 'c', 'c', 'b', 'a3'], # ignore dups
+ AAA4 = 'a4.new',
+ AAA5 = ['a5.new'],
+ BBB1 = 'b1',
+ BBB2 = ['b2'],
+ BBB3 = ['b3', 'c', 'd', 'c', 'b3'],
+ BBB4 = 'b4.new',
+ BBB5 = ['b5.new'],
+ CCC1 = 'c1',
+ CCC2 = ['c2'],
+ DDD1 = 'b',
+ LL1 = env.Literal('a literal'),
+ LL2 = env.Literal('a literal'))
+
+ 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']
+ assert env['LL1'] == [env.Literal('a literal'), env.Literal('b literal')], env['LL1']
+ assert env['LL2'] == [env.Literal('c literal'), env.Literal('b literal'), env.Literal('a literal')], [str(x) for x in env['LL2']]
+
+ 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']
+ assert isinstance(result, CLVar), repr(result)
+ assert result == ['bar'], result
+
+ 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(object):
+ pass
+ env1 = self.TestEnvironment(XXX=TestA(), YYY = [ 1, 2, 3 ],
+ ZZZ = { 1:2, 3:4 })
+ 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 5 in env2.Dictionary('ZZZ')
+ assert 5 not in env1.Dictionary('ZZZ')
+
+ #
+ env1 = self.TestEnvironment(BUILDERS = {'b1' : Builder()})
+ assert hasattr(env1, 'b1'), "env1.b1 was not set"
+ 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.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.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 = 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
+ assert env1.get('BAZ') is None
+ assert env2.get('FOO') is 1
+ assert env2.get('BAR') is None
+ assert env2.get('BAZ') is None
+ assert env3.get('FOO') is 1
+ assert env3.get('BAR') is 2
+ assert env3.get('BAZ') is 3
+
+ # Ensure that recursive variable substitution when copying
+ # environments works properly.
+ 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
+ x = env2.get('XYZ')
+ assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x
+
+ # Ensure that special properties of a class don't get
+ # lost on copying.
+ env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2'))
+ x = env1.get('FLAGS')
+ assert x == ['flag1', 'flag2'], x
+ env2 = env1.Clone()
+ env2.Append(FLAGS = 'flag3 flag4')
+ x = env2.get('FLAGS')
+ assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
+ x = env1.get('FLAGS')
+ assert x == ['flag1', 'flag2'], x
+
+ # Ensure that appending directly to a copied CLVar
+ # doesn't modify the original.
+ env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2'))
+ x = env1.get('FLAGS')
+ assert x == ['flag1', 'flag2'], x
+ env2 = env1.Clone()
+ env2['FLAGS'] += ['flag3', 'flag4']
+ x = env2.get('FLAGS')
+ assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
+ x = env1.get('FLAGS')
+ assert x == ['flag1', 'flag2'], 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']
+
+ # test for pull request #150
+ env = self.TestEnvironment()
+ env._dict.pop('BUILDERS')
+ assert ('BUILDERS' in env) is False
+ env2 = env.Clone()
+
+ 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 = '')
+ test.subdir('sub1', 'sub2')
+ sub1 = test.workpath('sub1')
+ sub2 = test.workpath('sub2')
+
+ if sys.platform == 'win32':
+ test.write(['sub1', 'xxx'], "sub1/xxx\n")
+ test.write(['sub2', 'xxx'], "sub2/xxx\n")
+
+ 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 = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
+
+ x = env.Detect('xxx.exe')
+ assert x == 'xxx.exe', x
+
+ test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
+
+ x = env.Detect('xxx.exe')
+ assert x == 'xxx.exe', x
+
+ else:
+ test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
+ test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
+
+ env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
+
+ x = env.Detect('xxx.exe')
+ assert x is None, x
+
+ sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
+ os.chmod(sub2_xxx_exe, 0o755)
+
+ env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
+
+ x = env.Detect('xxx.exe')
+ assert x == 'xxx.exe', x
+
+ sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
+ os.chmod(sub1_xxx_exe, 0o755)
+
+ x = env.Detect('xxx.exe')
+ assert x == 'xxx.exe', x
+
+ 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 = 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 = self.TestEnvironment(LIBPREFIX='lib',
+ LIBSUFFIX='.a',
+ SHLIBPREFIX='lib',
+ SHLIBSUFFIX='.so',
+ PREFIX='pre',
+ SUFFIX='post')
+
+ paths = [os.path.join('dir', 'libfoo.a'),
+ os.path.join('dir', 'libfoo.so')]
+
+ assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+ assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+ assert None is env.FindIxes(paths, 'PREFIX', 'POST')
+
+ paths = ['libfoo.a', 'prefoopost']
+
+ assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+ assert None is env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+ assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
+
+ def test_ParseConfig(self):
+ """Test the ParseConfig() method"""
+ env = self.TestEnvironment(COMMAND='command',
+ ASFLAGS='assembler',
+ CCFLAGS=[''],
+ CPPDEFINES=[],
+ CPPFLAGS=[''],
+ CPPPATH='string',
+ FRAMEWORKPATH=[],
+ FRAMEWORKS=[],
+ LIBPATH=['list'],
+ LIBS='',
+ LINKFLAGS=[''],
+ RPATH=[])
+
+ orig_backtick = env.backtick
+ class my_backtick(object):
+ 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:
+ 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 " + \
+ "-isystem /usr/include/foo " + \
+ "+DD64 " + \
+ "-DFOO -DBAR=value")
+ env.ParseConfig("fake $COMMAND")
+ assert save_command == ['fake command'], save_command
+ assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS']
+ assert env['CCFLAGS'] == ['', '-X', '-Wa,-as',
+ '-pthread', '-mno-cygwin',
+ ('-arch', 'i386'), ('-isysroot', '/tmp'),
+ ('-isystem', '/usr/include/foo'),
+ '+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', '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:
+ 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 = self.TestEnvironment(WIN32='win32', NONE='no-such-platform')
+
+ exc_caught = None
+ try:
+ env.Platform('does_not_exist')
+ except SCons.Errors.UserError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
+
+ exc_caught = None
+ try:
+ env.Platform('$NONE')
+ except SCons.Errors.UserError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
+
+ env.Platform('posix')
+ assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
+
+ env.Platform('$WIN32')
+ assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
+
+ def test_Prepend(self):
+ """Test prepending to construction variables in an Environment
+ """
+ cases = [
+ 'a1', 'A1', 'A1a1',
+ 'a2', ['A2'], ['A2', 'a2'],
+ 'a3', UL(['A3']), UL(['A3', 'a', '3']),
+ 'a4', '', 'a4',
+ 'a5', [], ['a5'],
+ 'a6', UL([]), UL(['a', '6']),
+ 'a7', [''], ['', 'a7'],
+ 'a8', UL(['']), UL(['', 'a', '8']),
+
+ ['e1'], 'E1', ['E1', 'e1'],
+ ['e2'], ['E2'], ['E2', 'e2'],
+ ['e3'], UL(['E3']), UL(['E3', 'e3']),
+ ['e4'], '', ['e4'],
+ ['e5'], [], ['e5'],
+ ['e6'], UL([]), UL(['e6']),
+ ['e7'], [''], ['', 'e7'],
+ ['e8'], UL(['']), UL(['', 'e8']),
+
+ UL(['i1']), 'I1', UL(['I', '1', 'i1']),
+ UL(['i2']), ['I2'], UL(['I2', 'i2']),
+ UL(['i3']), UL(['I3']), UL(['I3', 'i3']),
+ UL(['i4']), '', UL(['i4']),
+ UL(['i5']), [], UL(['i5']),
+ UL(['i6']), UL([]), UL(['i6']),
+ 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']),
+ '', '', '',
+ '', [], [],
+ '', UL([]), UL([]),
+ '', [''], [''],
+ '', UL(['']), UL(['']),
+
+ [], 'N1', ['N1'],
+ [], ['N2'], ['N2'],
+ [], UL(['N3']), UL(['N3']),
+ [], '', [],
+ [], [], [],
+ [], UL([]), UL([]),
+ [], [''], [''],
+ [], UL(['']), UL(['']),
+
+ UL([]), 'O1', UL(['O', '1']),
+ UL([]), ['O2'], UL(['O2']),
+ UL([]), UL(['O3']), UL(['O3']),
+ UL([]), '', UL([]),
+ UL([]), [], UL([]),
+ UL([]), UL([]), UL([]),
+ UL([]), [''], UL(['']),
+ UL([]), UL(['']), UL(['']),
+
+ [''], 'P1', ['P1', ''],
+ [''], ['P2'], ['P2', ''],
+ [''], UL(['P3']), UL(['P3', '']),
+ [''], '', [''],
+ [''], [], [''],
+ [''], UL([]), UL(['']),
+ [''], [''], ['', ''],
+ [''], UL(['']), UL(['', '']),
+
+ UL(['']), 'Q1', UL(['Q', '1', '']),
+ UL(['']), ['Q2'], UL(['Q2', '']),
+ UL(['']), UL(['Q3']), UL(['Q3', '']),
+ UL(['']), '', UL(['']),
+ UL(['']), [], UL(['']),
+ UL(['']), UL([]), UL(['']),
+ UL(['']), [''], UL(['', '']),
+ UL(['']), UL(['']), UL(['', '']),
+ ]
+
+ env = Environment()
+ failed = 0
+ while cases:
+ input, prepend, expect = cases[:3]
+ env['XXX'] = copy.copy(input)
+ try:
+ env.Prepend(XXX = prepend)
+ except Exception as e:
+ if failed == 0: print()
+ 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
+
+ env['UL'] = UL(['foo'])
+ env.Prepend(UL = 'bar')
+ result = env['UL']
+ assert isinstance(result, UL), repr(result)
+ assert result == ['b', 'a', 'r', 'foo'], result
+
+ env['CLVar'] = CLVar(['foo'])
+ env.Prepend(CLVar = 'bar')
+ result = env['CLVar']
+ assert isinstance(result, CLVar), repr(result)
+ assert result == ['bar', 'foo'], result
+
+ 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']
+
+ 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 = 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')
+
+ 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 = self.TestEnvironment(AAA1 = 'a1',
+ AAA2 = 'a2',
+ AAA3 = 'a3',
+ AAA4 = 'a4',
+ AAA5 = 'a5',
+ BBB1 = ['b1'],
+ BBB2 = ['b2'],
+ BBB3 = ['b3'],
+ BBB4 = ['b4'],
+ BBB5 = ['b5'],
+ CCC1 = '',
+ CCC2 = '',
+ DDD1 = ['a', 'b', 'c'])
+ env.PrependUnique(AAA1 = 'a1',
+ AAA2 = ['a2'],
+ AAA3 = ['a3', 'b', 'c', 'b', 'a3'], # ignore dups
+ AAA4 = 'a4.new',
+ AAA5 = ['a5.new'],
+ BBB1 = 'b1',
+ BBB2 = ['b2'],
+ 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'] == ['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']
+ 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 = self.TestEnvironment(AAA = 'a', BBB = 'b')
+ env1.Replace(BBB = 'bbb', CCC = 'ccc')
+
+ env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
+ assert env1 == env2, diff_env(env1, env2)
+
+ b1 = Builder()
+ b2 = Builder()
+ env3 = self.TestEnvironment(BUILDERS = {'b1' : b1})
+ assert hasattr(env3, 'b1'), "b1 was not set"
+ 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 = self.TestEnvironment(LIBPREFIX='lib',
+ LIBSUFFIX='.a',
+ SHLIBPREFIX='lib',
+ SHLIBSUFFIX='.so',
+ PREFIX='pre',
+ SUFFIX='post')
+
+ assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
+ 'SHLIBPREFIX', 'SHLIBSUFFIX',
+ 'LIBPREFIX', 'LIBSUFFIX')
+
+ assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
+ 'SHLIBPREFIX', 'SHLIBSUFFIX',
+ 'LIBPREFIX', 'LIBSUFFIX')
+
+ assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
+ '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 = self.TestEnvironment(LINK='link', NONE='no-such-tool')
+
+ exc_caught = None
+ try:
+ env.Tool('does_not_exist')
+ except SCons.Errors.EnvironmentError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected EnvironmentError"
+
+ exc_caught = None
+ try:
+ env.Tool('$NONE')
+ except SCons.Errors.EnvironmentError:
+ exc_caught = 1
+ 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.
+ env.Tool('cc', toolpath=['/no/such/directory'])
+ assert env['CC'] == 'cc', env['CC']
+
+ 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 = '')
+
+ sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
+ sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
+ sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
+ sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
+
+ test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
+
+ if sys.platform != 'win32':
+ test.write(sub1_xxx_exe, "\n")
+
+ os.mkdir(sub2_xxx_exe)
+
+ test.write(sub3_xxx_exe, "\n")
+ os.chmod(sub3_xxx_exe, 0o777)
+
+ test.write(sub4_xxx_exe, "\n")
+ os.chmod(sub4_xxx_exe, 0o777)
+
+ env_path = os.environ['PATH']
+
+ pathdirs_1234 = [ test.workpath('sub1'),
+ test.workpath('sub2'),
+ test.workpath('sub3'),
+ test.workpath('sub4'),
+ ] + env_path.split(os.pathsep)
+
+ pathdirs_1243 = [ test.workpath('sub1'),
+ test.workpath('sub2'),
+ test.workpath('sub4'),
+ test.workpath('sub3'),
+ ] + env_path.split(os.pathsep)
+
+ 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', 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 = 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', os.pathsep.join(pathdirs_1234))
+ assert wi == test.workpath(sub3_xxx_exe), wi
+
+ if sys.platform == 'win32':
+ wi = env.WhereIs('xxx', pathext = '')
+ assert wi is None, wi
+
+ wi = env.WhereIs('xxx', pathext = '.exe')
+ assert wi == test.workpath(sub4_xxx_exe), wi
+
+ wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
+ 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 wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi
+
+
+
+ def test_Action(self):
+ """Test the Action() method"""
+ import SCons.Action
+
+ env = self.TestEnvironment(FOO = 'xyzzy')
+
+ a = env.Action('foo')
+ assert a, a
+ assert a.__class__ is SCons.Action.CommandAction, a.__class__
+
+ a = env.Action('$FOO')
+ assert a, 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.__class__
+
+ def func(arg):
+ pass
+ a = env.Action(func)
+ assert a, a
+ assert a.__class__ is SCons.Action.FunctionAction, a.__class__
+
+ def test_AddPostAction(self):
+ """Test the AddPostAction() method"""
+ env = self.TestEnvironment(FOO='fff', BAR='bbb')
+
+ n = env.AddPostAction('$FOO', lambda x: x)
+ assert str(n[0]) == 'fff', n[0]
+
+ n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
+ assert str(n[0]) == 'ggg', n[0]
+ assert str(n[1]) == 'bbb', n[1]
+
+ def test_AddPreAction(self):
+ """Test the AddPreAction() method"""
+ env = self.TestEnvironment(FOO='fff', BAR='bbb')
+
+ n = env.AddPreAction('$FOO', lambda x: x)
+ assert str(n[0]) == 'fff', n[0]
+
+ n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
+ assert str(n[0]) == 'ggg', n[0]
+ assert str(n[1]) == 'bbb', n[1]
+
+ def test_Alias(self):
+ """Test the Alias() method"""
+ env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_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)[0]
+ assert str(tgt) == 'None_alias', tgt
+ assert tgt.sources == [], tgt.sources
+
+ tgt = env.Alias('empty_list', [])[0]
+ assert str(tgt) == 'empty_list', tgt
+ assert tgt.sources == [], tgt.sources
+
+ tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0]
+ assert str(tgt) == 'export_alias', tgt
+ 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'])[0]
+ assert n is tgt, n
+ 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')[0]
+ assert n is tgt, n
+ 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, 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 = 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].get_internal_path() == 'a'
+ assert t[0].always_build
+ assert t[1].__class__.__name__ == 'Entry'
+ assert t[1].get_internal_path() == 'bfff'
+ assert t[1].always_build
+ assert t[2].__class__.__name__ == 'Entry'
+ assert t[2].get_internal_path() == 'c'
+ assert t[2].always_build
+ assert t[3].__class__.__name__ == 'Entry'
+ assert t[3].get_internal_path() == 'd'
+ assert t[3].always_build
+ assert t[4].__class__.__name__ == 'Entry'
+ assert t[4].get_internal_path() == 'bbb'
+ assert t[4].always_build
+ assert t[5].__class__.__name__ == 'Dir'
+ assert t[5].get_internal_path() == 'dir'
+ assert t[5].always_build
+ assert t[6].__class__.__name__ == 'File'
+ assert t[6].get_internal_path() == 'file'
+ assert t[6].always_build
+
+ def test_VariantDir(self):
+ """Test the VariantDir() method"""
+ class MyFS(object):
+ def Dir(self, name):
+ return name
+ def VariantDir(self, variant_dir, src_dir, duplicate):
+ self.variant_dir = variant_dir
+ self.src_dir = src_dir
+ self.duplicate = duplicate
+
+ env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
+ env.fs = MyFS()
+
+ 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.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 = self.TestEnvironment(FOO = 'xyzzy')
+
+ b = env.Builder(action = 'foo')
+ assert b is not None, b
+
+ b = env.Builder(action = '$FOO')
+ assert b is not None, b
+
+ b = env.Builder(action = ['$FOO', 'foo'])
+ assert b is not None, b
+
+ def func(arg):
+ pass
+ b = env.Builder(action = func)
+ assert b is not None, b
+ b = env.Builder(generator = func)
+ assert b is not None, b
+
+ def test_CacheDir(self):
+ """Test the CacheDir() method"""
+ env = self.TestEnvironment(CD = 'CacheDir')
+
+ env.CacheDir('foo')
+ assert env._CacheDir_path == 'foo', env._CacheDir_path
+
+ env.CacheDir('$CD')
+ assert env._CacheDir_path == 'CacheDir', env._CacheDir_path
+
+ def test_Clean(self):
+ """Test the Clean() method"""
+ env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
+
+ CT = SCons.Environment.CleanTargets
+
+ foo = env.arg2nodes('foo')[0]
+ fff = env.arg2nodes('fff')[0]
+
+ t = env.Clean('foo', 'aaa')
+ l = list(map(str, CT[foo]))
+ assert l == ['aaa'], l
+
+ t = env.Clean(foo, ['$BAR', 'ccc'])
+ l = list(map(str, CT[foo]))
+ assert l == ['aaa', 'bbb', 'ccc'], l
+
+ eee = env.arg2nodes('eee')[0]
+
+ t = env.Clean('$FOO', 'ddd')
+ l = list(map(str, CT[fff]))
+ assert l == ['ddd'], l
+ t = env.Clean(fff, [eee, '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')[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 [x.get_internal_path() for x in t.sources]
+ assert 'foo2.in' in [x.get_internal_path() for x in t.sources]
+
+ sub = env.fs.Dir('sub')
+ t = env.Command(target='bar.out', source='sub',
+ action='buildbar $target $source')[0]
+ assert 'sub' in [x.get_internal_path() for x in t.sources]
+
+ def testFunc(env, target, source):
+ assert str(target[0]) == 'foo.out'
+ 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)[0]
+ assert t.builder is not None
+ assert t.builder.action.__class__.__name__ == 'FunctionAction'
+ t.build()
+ assert 'foo1.in' in [x.get_internal_path() for x in t.sources]
+ assert 'foo2.in' in [x.get_internal_path() for x in t.sources]
+
+ x = []
+ def test2(baz, x=x):
+ x.append(baz)
+ env = self.TestEnvironment(TEST2 = test2)
+ t = env.Command(target='baz.out', source='baz.in',
+ action='${TEST2(XYZ)}',
+ 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.get_internal_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()
+
+ try:
+ os.chdir(test.workpath())
+
+ env = self.TestEnvironment(FOO = 'xyzzy')
+
+ def func(arg):
+ pass
+
+ c = env.Configure()
+ assert c is not None, c
+ c.Finish()
+
+ c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
+ assert c is not None, c
+ assert hasattr(c, 'foo')
+ assert hasattr(c, 'xyzzy')
+ c.Finish()
+ finally:
+ os.chdir(save)
+
+ def test_Depends(self):
+ """Test the explicit Depends method."""
+ 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')[0]
+ assert t.__class__.__name__ == 'Entry', t.__class__.__name__
+ assert t.get_internal_path() == 'EnvironmentTest.py'
+ assert len(t.depends) == 1
+ d = t.depends[0]
+ assert d.__class__.__name__ == 'Entry', d.__class__.__name__
+ assert d.get_internal_path() == 'Environment.py'
+
+ t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0]
+ assert t.__class__.__name__ == 'File', t.__class__.__name__
+ assert t.get_internal_path() == 'xxx.py'
+ assert len(t.depends) == 1
+ d = t.depends[0]
+ assert d.__class__.__name__ == 'File', d.__class__.__name__
+ assert d.get_internal_path() == 'yyy.py'
+
+ t = env.Depends(target='dir1', dependency='dir2')[0]
+ assert t.__class__.__name__ == 'Dir', t.__class__.__name__
+ assert t.get_internal_path() == 'dir1'
+ assert len(t.depends) == 1
+ d = t.depends[0]
+ assert d.__class__.__name__ == 'Dir', d.__class__.__name__
+ assert d.get_internal_path() == 'dir2'
+
+ def test_Dir(self):
+ """Test the Dir() method"""
+ class MyFS(object):
+ def Dir(self, name):
+ return 'Dir(%s)' % name
+
+ env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir')
+ env.fs = MyFS()
+
+ d = env.Dir('d')
+ assert d == 'Dir(d)', d
+
+ d = env.Dir('$FOO')
+ assert d == 'Dir(foodir)', d
+
+ 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].get_internal_path() == 'p_a'
+ assert t[0].noclean
+ assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
+ assert t[1].get_internal_path() == 'p_hhhb'
+ assert t[1].noclean
+ assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
+ assert t[2].get_internal_path() == 'p_c'
+ assert t[2].noclean
+ assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
+ assert t[3].get_internal_path() == 'p_d'
+ assert t[3].noclean
+ assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
+ assert t[4].get_internal_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 = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy')
+
+ e2 = env.Environment(X = '$FOO', Y = '$BAR')
+ assert e2['X'] == 'xxx', e2['X']
+ assert e2['Y'] == 'yyy', e2['Y']
+
+ def test_Execute(self):
+ """Test the Execute() method"""
+
+ class MyAction(object):
+ def __init__(self, *args, **kw):
+ self.args = args
+ def __call__(self, target, source, env):
+ return "%s executed" % self.args
+
+ env = Environment()
+ env.Action = MyAction
+
+ result = env.Execute("foo")
+ assert result == "foo executed", result
+
+ def test_Entry(self):
+ """Test the Entry() method"""
+ class MyFS(object):
+ 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(object):
+ def File(self, name):
+ return 'File(%s)' % name
+
+ env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile')
+ env.fs = MyFS()
+
+ f = env.File('f')
+ assert f == 'File(f)', f
+
+ f = env.File('$FOO')
+ assert f == 'File(foofile)', f
+
+ 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 = 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 = self.TestEnvironment(MAGIC = 'xyzzy')
+
+ p = env.GetBuildPath('foo')
+ assert p == 'foo', p
+
+ p = env.GetBuildPath('$MAGIC')
+ assert p == 'xyzzy', p
+
+ def test_Ignore(self):
+ """Test the explicit Ignore method."""
+ 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')[0]
+ assert t.__class__.__name__ == 'Entry', t.__class__.__name__
+ assert t.get_internal_path() == 'targ.py'
+ assert len(t.ignore) == 1
+ i = t.ignore[0]
+ assert i.__class__.__name__ == 'Entry', i.__class__.__name__
+ assert i.get_internal_path() == 'dep.py'
+
+ t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0]
+ assert t.__class__.__name__ == 'File', t.__class__.__name__
+ assert t.get_internal_path() == 'yyyzzz'
+ assert len(t.ignore) == 1
+ i = t.ignore[0]
+ assert i.__class__.__name__ == 'File', i.__class__.__name__
+ assert i.get_internal_path() == 'zzzyyy'
+
+ t = env.Ignore(target='dir1', dependency='dir2')[0]
+ assert t.__class__.__name__ == 'Dir', t.__class__.__name__
+ assert t.get_internal_path() == 'dir1'
+ assert len(t.ignore) == 1
+ i = t.ignore[0]
+ assert i.__class__.__name__ == 'Dir', i.__class__.__name__
+ assert i.get_internal_path() == 'dir2'
+
+ def test_Literal(self):
+ """Test the Literal() method"""
+ 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]
+ assert list == ['fff', '$BAR'], list
+
+ def test_Local(self):
+ """Test the Local() method."""
+ env = self.TestEnvironment(FOO='lll')
+
+ l = env.Local(env.fs.File('fff'))
+ assert str(l[0]) == 'fff', l[0]
+
+ l = env.Local('ggg', '$FOO')
+ assert str(l[0]) == 'ggg', l[0]
+ assert str(l[1]) == 'lll', l[1]
+
+ def test_Precious(self):
+ """Test the Precious() method"""
+ 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')
+
+ assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
+ assert t[0].get_internal_path() == 'p_a'
+ assert t[0].precious
+ assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
+ assert t[1].get_internal_path() == 'p_hhhb'
+ assert t[1].precious
+ assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
+ assert t[2].get_internal_path() == 'p_c'
+ assert t[2].precious
+ assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
+ assert t[3].get_internal_path() == 'p_d'
+ assert t[3].precious
+ assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
+ assert t[4].get_internal_path() == 'p_ggg'
+ assert t[4].precious
+
+ def test_Pseudo(self):
+ """Test the Pseudo() method"""
+ env = self.TestEnvironment(FOO='ggg', BAR='hhh')
+ env.Dir('p_hhhb')
+ env.File('p_d')
+ t = env.Pseudo('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
+
+ assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
+ assert t[0].get_internal_path() == 'p_a'
+ assert t[0].pseudo
+ assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
+ assert t[1].get_internal_path() == 'p_hhhb'
+ assert t[1].pseudo
+ assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
+ assert t[2].get_internal_path() == 'p_c'
+ assert t[2].pseudo
+ assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
+ assert t[3].get_internal_path() == 'p_d'
+ assert t[3].pseudo
+ assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
+ assert t[4].get_internal_path() == 'p_ggg'
+ assert t[4].pseudo
+
+ def test_Repository(self):
+ """Test the Repository() method."""
+ class MyFS(object):
+ def __init__(self):
+ self.list = []
+ def Repository(self, *dirs):
+ self.list.extend(list(dirs))
+ def Dir(self, name):
+ return name
+ env = self.TestEnvironment(FOO='rrr', BAR='sss')
+ env.fs = MyFS()
+ env.Repository('/tmp/foo')
+ env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
+ expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
+ assert env.fs.list == expect, env.fs.list
+
+ def test_Scanner(self):
+ """Test the Scanner() method"""
+ def scan(node, env, target, arg):
+ pass
+
+ env = self.TestEnvironment(FOO = scan)
+
+ s = env.Scanner('foo')
+ assert s is not None, s
+
+ s = env.Scanner(function = 'foo')
+ assert s is not None, s
+
+ if 0:
+ s = env.Scanner('$FOO')
+ assert s is not None, s
+
+ s = env.Scanner(function = '$FOO')
+ assert s is not None, s
+
+ def test_SConsignFile(self):
+ """Test the SConsignFile() method"""
+ import SCons.SConsign
+
+ class MyFS(object):
+ SConstruct_dir = os.sep + 'dir'
+
+ env = self.TestEnvironment(FOO = 'SConsign',
+ BAR = os.path.join(os.sep, 'File'))
+ env.fs = MyFS()
+ env.Execute = lambda action: None
+
+ try:
+ fnames = []
+ dbms = []
+ def capture(name, dbm_module, fnames=fnames, dbms=dbms):
+ fnames.append(name)
+ dbms.append(dbm_module)
+
+ save_SConsign_File = SCons.SConsign.File
+ SCons.SConsign.File = capture
+
+ env.SConsignFile('foo')
+ 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] is None, dbms
+
+ env.SConsignFile('/$FOO')
+ 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[-1] == os.path.join(os.sep, 'File'), fnames
+ assert dbms[-1] == 'x', dbms
+
+ env.SConsignFile('__$BAR', 7)
+ 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.SConsign.File = save_SConsign_File
+
+ def test_SideEffect(self):
+ """Test the SideEffect() method"""
+ env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb')
+ env.File('mylll.pdb')
+ env.Dir('mymmm.pdb')
+
+ 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.get_internal_path() == 'mylib.pdb'
+ assert s.side_effect
+ assert foo.side_effects == [s]
+ assert bar.side_effects == [s]
+
+ 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.get_internal_path() == 'mylll.pdb'
+ assert s.side_effect
+ assert fff.side_effects == [s], fff.side_effects
+ assert bbb.side_effects == [s], bbb.side_effects
+
+ 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.get_internal_path() == 'mymmm.pdb'
+ assert s.side_effect
+ assert ggg.side_effects == [s], ggg.side_effects
+ assert ccc.side_effects == [s], ccc.side_effects
+
+ def test_SourceCode(self):
+ """Test the SourceCode() method."""
+ env = self.TestEnvironment(FOO='mmm', BAR='nnn')
+ e = env.SourceCode('foo', None)[0]
+ assert e.get_internal_path() == 'foo'
+ s = e.src_builder()
+ assert s is None, s
+
+ b = Builder()
+ e = env.SourceCode(e, b)[0]
+ assert e.get_internal_path() == 'foo'
+ s = e.src_builder()
+ assert s is b, s
+
+ e = env.SourceCode('$BAR$FOO', None)[0]
+ assert e.get_internal_path() == 'nnnmmm'
+ s = e.src_builder()
+ assert s is None, s
+
+ def test_SourceSignatures(type):
+ """Test the SourceSignatures() method"""
+ import SCons.Errors
+
+ env = type.TestEnvironment(M = 'MD5', T = 'timestamp')
+
+ exc_caught = None
+ try:
+ env.SourceSignatures('invalid_type')
+ except SCons.Errors.UserError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
+
+ env.SourceSignatures('MD5')
+ assert env.src_sig_type == 'MD5', env.src_sig_type
+
+ env.SourceSignatures('$M')
+ assert env.src_sig_type == 'MD5', env.src_sig_type
+
+ env.SourceSignatures('timestamp')
+ assert env.src_sig_type == 'timestamp', env.src_sig_type
+
+ env.SourceSignatures('$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 = self.TestEnvironment(FOO='fff', BAR='bbb')
+ s = env.Split("foo bar")
+ assert s == ["foo", "bar"], s
+ s = env.Split("$FOO bar")
+ assert s == ["fff", "bar"], s
+ s = env.Split(["foo", "bar"])
+ assert s == ["foo", "bar"], s
+ s = env.Split(["foo", "${BAR}-bbb"])
+ assert s == ["foo", "bbb-bbb"], s
+ s = env.Split("foo")
+ assert s == ["foo"], s
+ s = env.Split("$FOO$BAR")
+ assert s == ["fffbbb"], s
+
+ def test_TargetSignatures(type):
+ """Test the TargetSignatures() method"""
+ import SCons.Errors
+
+ env = type.TestEnvironment(B = 'build', C = 'content')
+
+ exc_caught = None
+ try:
+ env.TargetSignatures('invalid_type')
+ except SCons.Errors.UserError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
+ assert not hasattr(env, '_build_signature')
+
+ env.TargetSignatures('build')
+ assert env.tgt_sig_type == 'build', env.tgt_sig_type
+
+ env.TargetSignatures('$B')
+ 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.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
+ """
+ env = Environment()
+ v1 = env.Value('a')
+ assert v1.value == 'a', v1.value
+
+ value2 = 'a'
+ v2 = env.Value(value2)
+ assert v2.value == value2, v2.value
+ assert v2.value is value2, v2.value
+
+ 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):
+ """Test setting Environment variable to an Environment.Base subclass"""
+ class MyEnv(SCons.Environment.Base):
+ def xxx(self, string):
+ return self.subst(string)
+
+ SCons.Environment.Environment = MyEnv
+
+ env = SCons.Environment.Environment(FOO = 'foo')
+
+ f = env.subst('$FOO')
+ assert f == 'foo', f
+
+ 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?"
+
+ 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"""
+ 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 = self.TestEnvironment(XXX = 'x', YYY = 'y')
+ assert env['XXX'] == 'x', env['XXX']
+ assert env['YYY'] == 'y', env['YYY']
+
+ proxy = NoSubstitutionProxy(env)
+ assert proxy['XXX'] == 'x', proxy['XXX']
+ assert proxy['YYY'] == 'y', proxy['YYY']
+
+ def test_attributes(self):
+ """Test getting and setting NoSubstitutionProxy attributes"""
+ env = Environment()
+ setattr(env, 'env_attr', 'value1')
+
+ proxy = NoSubstitutionProxy(env)
+ setattr(proxy, 'proxy_attr', 'value2')
+
+ x = getattr(env, 'env_attr')
+ assert x == 'value1', x
+ x = getattr(proxy, 'env_attr')
+ assert x == 'value1', x
+
+ x = getattr(env, 'proxy_attr')
+ assert x == 'value2', x
+ x = getattr(proxy, 'proxy_attr')
+ assert x == 'value2', x
+
+ def test_subst(self):
+ """Test the NoSubstitutionProxy.subst() method"""
+ env = self.TestEnvironment(XXX = 'x', YYY = 'y')
+ assert env['XXX'] == 'x', env['XXX']
+ assert env['YYY'] == 'y', env['YYY']
+
+ proxy = NoSubstitutionProxy(env)
+ assert proxy['XXX'] == 'x', proxy['XXX']
+ assert proxy['YYY'] == 'y', proxy['YYY']
+
+ x = env.subst('$XXX')
+ assert x == 'x', x
+ x = proxy.subst('$XXX')
+ assert x == '$XXX', x
+
+ x = proxy.subst('$YYY', raw=7, target=None, source=None,
+ conv=None,
+ extra_meaningless_keyword_argument=None)
+ assert x == '$YYY', x
+
+ def test_subst_kw(self):
+ """Test the NoSubstitutionProxy.subst_kw() method"""
+ env = self.TestEnvironment(XXX = 'x', YYY = 'y')
+ assert env['XXX'] == 'x', env['XXX']
+ assert env['YYY'] == 'y', env['YYY']
+
+ proxy = NoSubstitutionProxy(env)
+ assert proxy['XXX'] == 'x', proxy['XXX']
+ assert proxy['YYY'] == 'y', proxy['YYY']
+
+ x = env.subst_kw({'$XXX':'$YYY'})
+ assert x == {'x':'y'}, x
+ x = proxy.subst_kw({'$XXX':'$YYY'})
+ assert x == {'$XXX':'$YYY'}, x
+
+ def test_subst_list(self):
+ """Test the NoSubstitutionProxy.subst_list() method"""
+ env = self.TestEnvironment(XXX = 'x', YYY = 'y')
+ assert env['XXX'] == 'x', env['XXX']
+ assert env['YYY'] == 'y', env['YYY']
+
+ proxy = NoSubstitutionProxy(env)
+ assert proxy['XXX'] == 'x', proxy['XXX']
+ assert proxy['YYY'] == 'y', proxy['YYY']
+
+ x = env.subst_list('$XXX')
+ assert x == [['x']], x
+ x = proxy.subst_list('$XXX')
+ assert x == [[]], x
+
+ 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 = self.TestEnvironment(XXX = 'x', YYY = 'y')
+ assert env['XXX'] == 'x', env['XXX']
+ assert env['YYY'] == 'y', env['YYY']
+
+ proxy = NoSubstitutionProxy(env)
+ assert proxy['XXX'] == 'x', proxy['XXX']
+ assert proxy['YYY'] == 'y', proxy['YYY']
+
+ args = ('$XXX $TARGET $SOURCE $YYY',)
+ kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')}
+ x = env.subst_target_source(*args, **kw)
+ assert x == 'x ttt sss y', x
+ 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 = [ SubstitutionTestCase,
+ BaseTestCase,
+ OverrideEnvironmentTestCase,
+ NoSubstitutionProxyTestCase,
+ EnvironmentVariableTestCase ]
+ for tclass in tclasses:
+ names = unittest.getTestCaseNames(tclass, 'test_')
+ suite.addTests(list(map(tclass, names)))
+ TestUnit.run(suite)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: