4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
34 from SCons.Environment import *
37 def diff_env(env1, env2):
41 for k in env1._dict.keys() + env2._dict.keys():
48 if env1[k] != env2[k]:
49 s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n"
50 s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n"
52 s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n"
54 s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n"
59 def diff_dict(d1, d2):
63 for k in d1.keys() + d2.keys():
71 s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n"
72 s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n"
74 s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n"
76 s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n"
84 class Builder(SCons.Builder.BuilderBase):
85 """A dummy Builder class for testing purposes. "Building"
86 a target is simply setting a value in the dictionary.
88 def __init__(self, name = None):
91 def __call__(self, env, target=None, source=None, **kw):
93 called_it['target'] = target
94 called_it['source'] = source
97 def execute(self, target = None, **kw):
106 """A dummy Scanner class for testing purposes. "Scanning"
107 a target is simply setting a value in the dictionary.
109 def __init__(self, name, skeys=[]):
113 def __call__(self, filename):
115 scanned_it[filename] = 1
117 def __cmp__(self, other):
119 return cmp(self.__dict__, other.__dict__)
120 except AttributeError:
123 def get_skeys(self, env):
131 class CLVar(UserList.UserList):
132 def __init__(self, seq):
133 if type(seq) == type(''):
135 UserList.UserList.__init__(self, seq)
136 def __add__(self, other):
137 return UserList.UserList.__add__(self, CLVar(other))
138 def __radd__(self, other):
139 return UserList.UserList.__radd__(self, CLVar(other))
140 def __coerce__(self, other):
141 return (self, CLVar(other))
146 def __init__(self, name):
152 def get_subst_proxy(self):
155 def test_tool( env ):
156 env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
158 class TestEnvironmentFixture:
159 def TestEnvironment(self, *args, **kw):
160 if not kw or 'tools' not in kw:
161 kw['tools'] = [test_tool]
162 default_keys = { 'CC' : 'cc',
163 'CCFLAGS' : '-DNDEBUG',
164 'ENV' : { 'TMP' : '/tmp' } }
165 for key, value in default_keys.items():
168 if 'BUILDERS' not in kw:
169 static_obj = SCons.Builder.Builder(action = {},
173 kw['BUILDERS'] = {'Object' : static_obj}
174 static_obj.add_action('.cpp', 'fake action')
176 env = Environment(*args, **kw)
179 class SubstitutionTestCase(unittest.TestCase):
181 def test___init__(self):
182 """Test initializing a SubstitutionEnvironment
184 env = SubstitutionEnvironment()
185 assert '__env__' not in env
187 def test___cmp__(self):
188 """Test comparing SubstitutionEnvironments
191 env1 = SubstitutionEnvironment(XXX = 'x')
192 env2 = SubstitutionEnvironment(XXX = 'x')
193 env3 = SubstitutionEnvironment(XXX = 'xxx')
194 env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x')
200 def test___delitem__(self):
201 """Test deleting a variable from a SubstitutionEnvironment
203 env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
204 env2 = SubstitutionEnvironment(XXX = 'x')
208 def test___getitem__(self):
209 """Test fetching a variable from a SubstitutionEnvironment
211 env = SubstitutionEnvironment(XXX = 'x')
212 assert env['XXX'] == 'x', env['XXX']
214 def test___setitem__(self):
215 """Test setting a variable in a SubstitutionEnvironment
217 env1 = SubstitutionEnvironment(XXX = 'x')
218 env2 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
223 """Test the SubstitutionEnvironment get() method
225 env = SubstitutionEnvironment(XXX = 'x')
226 assert env.get('XXX') == 'x', env.get('XXX')
227 assert env.get('YYY') is None, env.get('YYY')
229 def test_has_key(self):
230 """Test the SubstitutionEnvironment has_key() method
232 env = SubstitutionEnvironment(XXX = 'x')
234 assert 'YYY' not in env
236 def test_contains(self):
237 """Test the SubstitutionEnvironment __contains__() method
243 # An early version of Python that doesn't support "in"
244 # on dictionaries. Just pass the test.
247 env = SubstitutionEnvironment(XXX = 'x')
249 assert not 'YYY' in env
251 def test_items(self):
252 """Test the SubstitutionEnvironment items() method
254 env = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
256 assert items == [('XXX','x'), ('YYY','y')], items
258 def test_arg2nodes(self):
259 """Test the arg2nodes method
261 env = SubstitutionEnvironment()
263 class X(SCons.Node.Node):
265 def Factory(name, directory = None, create = 1, dict=dict, X=X):
268 dict[name].name = name
271 nodes = env.arg2nodes("Util.py UtilTests.py", Factory)
272 assert len(nodes) == 1, nodes
273 assert isinstance(nodes[0], X)
274 assert nodes[0].name == "Util.py UtilTests.py"
277 if hasattr(types, 'UnicodeType'):
279 nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
280 assert len(nodes) == 1, nodes
281 assert isinstance(nodes[0], X)
282 assert nodes[0].name == u"Util.py UtilTests.py"
284 exec code in globals(), locals()
286 nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
287 assert len(nodes) == 2, nodes
288 assert isinstance(nodes[0], X)
289 assert isinstance(nodes[1], X)
290 assert nodes[0].name == "Util.py"
291 assert nodes[1].name == "UtilTests.py"
293 n1 = Factory("Util.py")
294 nodes = env.arg2nodes([n1, "UtilTests.py"], Factory)
295 assert len(nodes) == 2, nodes
296 assert isinstance(nodes[0], X)
297 assert isinstance(nodes[1], X)
298 assert nodes[0].name == "Util.py"
299 assert nodes[1].name == "UtilTests.py"
301 class SConsNode(SCons.Node.Node):
303 nodes = env.arg2nodes(SConsNode())
304 assert len(nodes) == 1, nodes
305 assert isinstance(nodes[0], SConsNode), node
309 nodes = env.arg2nodes(OtherNode())
310 assert len(nodes) == 1, nodes
311 assert isinstance(nodes[0], OtherNode), node
313 def lookup_a(str, F=Factory):
321 def lookup_b(str, F=Factory):
329 env_ll = SubstitutionEnvironment()
330 env_ll.lookup_list = [lookup_a, lookup_b]
332 nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
333 assert len(nodes) == 3, nodes
335 assert nodes[0].name == 'aaa', nodes[0]
336 assert nodes[0].a == 1, nodes[0]
337 assert not hasattr(nodes[0], 'b'), nodes[0]
339 assert nodes[1].name == 'bbb'
340 assert not hasattr(nodes[1], 'a'), nodes[1]
341 assert nodes[1].b == 1, nodes[1]
343 assert nodes[2].name == 'ccc'
344 assert not hasattr(nodes[2], 'a'), nodes[1]
345 assert not hasattr(nodes[2], 'b'), nodes[1]
347 def lookup_bbbb(str, F=Factory):
355 def lookup_c(str, F=Factory):
363 nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
364 [lookup_c, lookup_bbbb, lookup_b])
365 assert len(nodes) == 2, nodes
367 assert nodes[0].name == 'bbbb'
368 assert not hasattr(nodes[0], 'a'), nodes[1]
369 assert not hasattr(nodes[0], 'b'), nodes[1]
370 assert nodes[0].bbbb == 1, nodes[1]
371 assert not hasattr(nodes[0], 'c'), nodes[0]
373 assert nodes[1].name == 'ccc'
374 assert not hasattr(nodes[1], 'a'), nodes[1]
375 assert not hasattr(nodes[1], 'b'), nodes[1]
376 assert not hasattr(nodes[1], 'bbbb'), nodes[0]
377 assert nodes[1].c == 1, nodes[1]
379 def test_arg2nodes_target_source(self):
380 """Test the arg2nodes method with target= and source= keywords
382 targets = [DummyNode('t1'), DummyNode('t2')]
383 sources = [DummyNode('s1'), DummyNode('s2')]
384 env = SubstitutionEnvironment()
385 nodes = env.arg2nodes(['${TARGET}-a',
392 names = [n.name for n in nodes]
393 assert names == ['t1-a', 's1-b', 't2-c', 's2-d'], names
395 def test_gvars(self):
396 """Test the base class gvars() method"""
397 env = SubstitutionEnvironment()
399 assert gvars == {}, gvars
401 def test_lvars(self):
402 """Test the base class lvars() method"""
403 env = SubstitutionEnvironment()
405 assert lvars == {}, lvars
407 def test_subst(self):
408 """Test substituting construction variables within strings
410 Check various combinations, including recursive expansion
411 of variables into other variables.
413 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
414 mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
415 assert mystr == "a aA b", mystr
417 # Changed the tests below to reflect a bug fix in
419 env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
420 mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
421 assert mystr == "b bA bB b", mystr
423 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
424 mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
425 assert mystr == "c cA cB c", mystr
428 env = SubstitutionEnvironment(AAA = ['a', 'aa', 'aaa'])
429 mystr = env.subst("$AAA")
430 assert mystr == "a aa aaa", mystr
433 env = SubstitutionEnvironment(AAA = ('a', 'aa', 'aaa'))
434 mystr = env.subst("$AAA")
435 assert mystr == "a aa aaa", mystr
442 env = SubstitutionEnvironment(AAA = 'aaa')
443 s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
444 assert s == "aaa t1 s1 s2", s
445 s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
446 assert s == "aaa t1 t2 s1", s
448 # Test callables in the SubstitutionEnvironment
449 def foo(target, source, env, for_signature):
450 assert str(target) == 't', target
451 assert str(source) == 's', source
454 env = SubstitutionEnvironment(BAR=foo, FOO='baz')
458 subst = env.subst('test $BAR', target=t, source=s)
459 assert subst == 'test baz', subst
461 # Test not calling callables in the SubstitutionEnvironment
463 # This will take some serious surgery to subst() and
464 # subst_list(), so just leave these tests out until we can
469 env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
471 subst = env.subst('$BAR', call=None)
472 assert subst is bar, subst
474 subst = env.subst('$FOO', call=None)
475 assert subst is bar, subst
477 def test_subst_kw(self):
478 """Test substituting construction variables within dictionaries"""
479 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
480 kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
481 assert len(kw) == 2, kw
482 assert kw['a'] == 'aaa', kw['a']
483 assert kw['bbb'] == 'b', kw['bbb']
485 def test_subst_list(self):
486 """Test substituting construction variables in command lists
488 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
489 l = env.subst_list("$AAA ${AAA}A $BBBB $BBB")
490 assert l == [["a", "aA", "b"]], l
492 # Changed the tests below to reflect a bug fix in
494 env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
495 l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
496 assert l == [["b", "bA", "bB", "b"]], l
498 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
499 l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
500 assert l == [["c", "cA", "cB", "c"]], mystr
502 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
503 lst = env.subst_list([ "$AAA", "B $CCC" ])
504 assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst
511 env = SubstitutionEnvironment(AAA = 'aaa')
512 s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
513 assert s == [["aaa", "t1", "s1", "s2"]], s
514 s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
515 assert s == [["aaa", "t1", "t2", "s1"]], s
517 # Test callables in the SubstitutionEnvironment
518 def foo(target, source, env, for_signature):
519 assert str(target) == 't', target
520 assert str(source) == 's', source
523 env = SubstitutionEnvironment(BAR=foo, FOO='baz')
527 lst = env.subst_list('test $BAR', target=t, source=s)
528 assert lst == [['test', 'baz']], lst
530 # Test not calling callables in the SubstitutionEnvironment
532 # This will take some serious surgery to subst() and
533 # subst_list(), so just leave these tests out until we can
538 env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
540 subst = env.subst_list('$BAR', call=None)
541 assert subst is bar, subst
543 subst = env.subst_list('$FOO', call=None)
544 assert subst is bar, subst
546 def test_subst_path(self):
547 """Test substituting a path list
550 def __init__(self, val):
553 return self.val + '-proxy'
556 def __init__(self, val):
558 def get_subst_proxy(self):
567 env = SubstitutionEnvironment(FOO='foo',
570 PROXY=MyProxy('my1'))
572 r = env.subst_path('$FOO')
573 assert r == ['foo'], r
575 r = env.subst_path(['$FOO', 'xxx', '$BAR'])
576 assert r == ['foo', 'xxx', 'bar'], r
578 r = env.subst_path(['$FOO', '$LIST', '$BAR'])
579 assert list(map(str, r)) == ['foo', 'one two', 'bar'], r
581 r = env.subst_path(['$FOO', '$TARGET', '$SOURCE', '$BAR'])
582 assert r == ['foo', '', '', 'bar'], r
584 r = env.subst_path(['$FOO', '$TARGET', '$BAR'], target=MyNode('ttt'))
585 assert list(map(str, r)) == ['foo', 'ttt', 'bar'], r
587 r = env.subst_path(['$FOO', '$SOURCE', '$BAR'], source=MyNode('sss'))
588 assert list(map(str, r)) == ['foo', 'sss', 'bar'], r
592 r = env.subst_path(['$PROXY', MyProxy('my2'), n])
593 assert r == ['my1-proxy', 'my2-proxy', n], r
596 def __init__(self, s):
601 env = SubstitutionEnvironment(FOO=StringableObj("foo"),
602 BAR=StringableObj("bar"))
604 r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ])
605 assert r == [ "foo/bar", "bar/baz" ], r
607 r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ])
608 assert r == [ "bar/foo", "baz/bar" ], r
610 r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ])
611 assert r == [ "bar/foo/bar", "baz/bar/baz" ], r
613 def test_subst_target_source(self):
614 """Test the base environment subst_target_source() method"""
615 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
616 mystr = env.subst_target_source("$AAA ${AAA}A $BBBB $BBB")
617 assert mystr == "a aA b", mystr
619 def test_backtick(self):
620 """Test the backtick() method for capturing command output"""
621 env = SubstitutionEnvironment()
623 test = TestCmd.TestCmd(workdir = '')
624 test.write('stdout.py', """\
626 sys.stdout.write('this came from stdout.py\\n')
629 test.write('stderr.py', """\
631 sys.stderr.write('this came from stderr.py\\n')
634 test.write('fail.py', """\
638 test.write('echo.py', """\
640 sys.stdout.write(os.environ['ECHO'] + '\\n')
644 save_stderr = sys.stderr
646 python = '"' + sys.executable + '"'
649 sys.stderr = StringIO.StringIO()
650 cmd = '%s %s' % (python, test.workpath('stdout.py'))
651 output = env.backtick(cmd)
652 errout = sys.stderr.getvalue()
653 assert output == 'this came from stdout.py\n', output
654 assert errout == '', errout
656 sys.stderr = StringIO.StringIO()
657 cmd = '%s %s' % (python, test.workpath('stderr.py'))
658 output = env.backtick(cmd)
659 errout = sys.stderr.getvalue()
660 assert output == '', output
661 assert errout == 'this came from stderr.py\n', errout
663 sys.stderr = StringIO.StringIO()
664 cmd = '%s %s' % (python, test.workpath('fail.py'))
668 assert str(e) == "'%s' exited 1" % cmd, str(e)
670 self.fail("did not catch expected OSError")
672 sys.stderr = StringIO.StringIO()
673 cmd = '%s %s' % (python, test.workpath('echo.py'))
674 env['ENV'] = os.environ.copy()
675 env['ENV']['ECHO'] = 'this came from ECHO'
676 output = env.backtick(cmd)
677 errout = sys.stderr.getvalue()
678 assert output == 'this came from ECHO\n', output
679 assert errout == '', errout
682 sys.stderr = save_stderr
684 def test_AddMethod(self):
685 """Test the AddMethod() method"""
686 env = SubstitutionEnvironment(FOO = 'foo')
689 return 'func-' + self['FOO']
691 assert not hasattr(env, 'func')
694 assert r == 'func-foo', r
696 assert not hasattr(env, 'bar')
697 env.AddMethod(func, 'bar')
699 assert r == 'func-foo', r
701 def func2(self, arg=''):
702 return 'func2-' + self['FOO'] + arg
706 assert r == 'func2-foo', r
707 r = env.func2('-xxx')
708 assert r == 'func2-foo-xxx', r
710 env.AddMethod(func2, 'func')
712 assert r == 'func2-foo', r
714 assert r == 'func2-foo-yyy', r
716 # Test that clones of clones correctly re-bind added methods.
717 env1 = Environment(FOO = '1')
718 env1.AddMethod(func2)
719 env2 = env1.Clone(FOO = '2')
720 env3 = env2.Clone(FOO = '3')
721 env4 = env3.Clone(FOO = '4')
723 assert r == 'func2-1', r
725 assert r == 'func2-2', r
727 assert r == 'func2-3', r
729 assert r == 'func2-4', r
731 # Test that clones don't re-bind an attribute that the user
732 env1 = Environment(FOO = '1')
733 env1.AddMethod(func2)
735 return 'replace_func2'
736 env1.func2 = replace_func2
737 env2 = env1.Clone(FOO = '2')
739 assert r == 'replace_func2', r
741 def test_Override(self):
742 "Test overriding construction variables"
743 env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4)
744 assert env['ONE'] == 1, env['ONE']
745 assert env['TWO'] == 2, env['TWO']
746 assert env['THREE'] == 3, env['THREE']
747 assert env['FOUR'] == 4, env['FOUR']
749 env2 = env.Override({'TWO' : '10',
750 'THREE' :'x $THREE y',
751 'FOUR' : ['x', '$FOUR', 'y']})
752 assert env2['ONE'] == 1, env2['ONE']
753 assert env2['TWO'] == '10', env2['TWO']
754 assert env2['THREE'] == 'x 3 y', env2['THREE']
755 assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR']
757 assert env['ONE'] == 1, env['ONE']
758 assert env['TWO'] == 2, env['TWO']
759 assert env['THREE'] == 3, env['THREE']
760 assert env['FOUR'] == 4, env['FOUR']
762 env2.Replace(ONE = "won")
763 assert env2['ONE'] == "won", env2['ONE']
764 assert env['ONE'] == 1, env['ONE']
766 def test_ParseFlags(self):
767 """Test the ParseFlags() method
769 env = SubstitutionEnvironment()
778 'FRAMEWORKPATH' : [],
786 d = env.ParseFlags(None)
789 d = env.ParseFlags('')
792 d = env.ParseFlags([])
795 s = "-I/usr/include/fum -I bar -X\n" + \
796 '-I"C:\\Program Files\\ASCEND\\include" ' + \
797 "-L/usr/fax -L foo -lxxx -l yyy " + \
798 '-L"C:\\Program Files\\ASCEND" -lascend ' + \
799 "-Wa,-as -Wl,-link " + \
800 "-Wl,-rpath=rpath1 " + \
805 "-framework Carbon " + \
806 "-frameworkdir=fwd1 " + \
810 "-mno-cygwin -mwindows " + \
811 "-arch i386 -isysroot /tmp +DD64 " + \
812 "-DFOO -DBAR=value -D BAZ "
814 d = env.ParseFlags(s)
816 assert d['ASFLAGS'] == ['-as'], d['ASFLAGS']
817 assert d['CFLAGS'] == ['-std=c99']
818 assert d['CCFLAGS'] == ['-X', '-Wa,-as',
819 '-pthread', '-mno-cygwin',
820 ('-arch', 'i386'), ('-isysroot', '/tmp'),
821 '+DD64'], d['CCFLAGS']
822 assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES']
823 assert d['CPPFLAGS'] == ['-Wp,-cpp'], d['CPPFLAGS']
824 assert d['CPPPATH'] == ['/usr/include/fum',
826 'C:\\Program Files\\ASCEND\\include'], d['CPPPATH']
827 assert d['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], d['FRAMEWORKPATH']
828 assert d['FRAMEWORKS'] == ['Carbon'], d['FRAMEWORKS']
829 assert d['LIBPATH'] == ['/usr/fax',
831 'C:\\Program Files\\ASCEND'], d['LIBPATH']
832 LIBS = list(map(str, d['LIBS']))
833 assert LIBS == ['xxx', 'yyy', 'ascend'], (d['LIBS'], LIBS)
834 assert d['LINKFLAGS'] == ['-Wl,-link', '-pthread',
835 '-mno-cygwin', '-mwindows',
837 ('-isysroot', '/tmp'),
838 '+DD64'], d['LINKFLAGS']
839 assert d['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], d['RPATH']
842 def test_MergeFlags(self):
843 """Test the MergeFlags() method
845 env = SubstitutionEnvironment()
847 assert 'CCFLAGS' not in env, env['CCFLAGS']
849 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
851 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
853 env = SubstitutionEnvironment(CCFLAGS=None)
855 assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS']
857 env = SubstitutionEnvironment()
858 env.MergeFlags({'A':['aaa'], 'B':['bbb']})
859 assert env['A'] == ['aaa'], env['A']
860 assert env['B'] == ['bbb'], env['B']
862 # def test_MergeShellPaths(self):
863 # """Test the MergeShellPaths() method
865 # env = Environment()
866 # env.MergeShellPaths({})
867 # assert not env['ENV'].has_key('INCLUDE'), env['INCLUDE']
868 # env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'})
869 # assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
870 # env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'})
871 # assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
872 # env.MergeShellPaths({'INCLUDE': r'xyz'})
873 # assert env['ENV']['INCLUDE'] == r'xyz%sc:\Program Files\Stuff'%os.pathsep, env['ENV']['INCLUDE']
875 # env = Environment()
876 # env['ENV']['INCLUDE'] = 'xyz'
877 # env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']} )
878 # assert env['ENV']['INCLUDE'] == r'c:/inc1%sc:/inc2%sxyz'%(os.pathsep, os.pathsep), env['ENV']['INCLUDE']
881 # env = Environment()
882 # env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}, prepend=0)
883 # assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
884 # env.MergeShellPaths({'INCLUDE': r'xyz'}, prepend=0)
885 # assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff%sxyz'%os.pathsep, env['ENV']['INCLUDE']
888 class BaseTestCase(unittest.TestCase,TestEnvironmentFixture):
890 reserved_variables = [
901 def test___init__(self):
902 """Test construction Environment creation
904 Create two with identical arguments and check that
905 they compare the same.
907 env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
908 env2 = self.TestEnvironment(XXX = 'x', YYY = 'y')
909 assert env1 == env2, diff_env(env1, env2)
911 assert '__env__' not in env1
912 assert '__env__' not in env2
914 def test_variables(self):
915 """Test that variables only get applied once."""
917 def __init__(self, key, val):
923 def Update(self, env):
924 env[self.key] = self.val
925 self.calls = self.calls + 1
927 o = FakeOptions('AAA', 'fake_opt')
928 env = Environment(variables=o, AAA='keyword_arg')
929 assert o.calls == 1, o.calls
930 assert env['AAA'] == 'fake_opt', env['AAA']
933 """Test the get() method."""
934 env = self.TestEnvironment(aaa = 'AAA')
938 x = env.get('aaa', 'XXX')
942 x = env.get('bbb', 'XXX')
945 def test_Builder_calls(self):
946 """Test Builder calls through different environments
954 env.Replace(BUILDERS = { 'builder1' : b1,
958 assert called_it['target'] is None, called_it
959 assert called_it['source'] == ['in1'], called_it
962 env.builder2(source = 'in2', xyzzy = 1)
963 assert called_it['target'] is None, called_it
964 assert called_it['source'] == ['in2'], called_it
965 assert called_it['xyzzy'] == 1, called_it
968 env.builder1(foo = 'bar')
969 assert called_it['foo'] == 'bar', called_it
970 assert called_it['target'] is None, called_it
971 assert called_it['source'] is None, called_it
973 def test_BuilderWrapper_attributes(self):
974 """Test getting and setting of BuilderWrapper attributes
981 e1.Replace(BUILDERS = {'b' : b1})
988 assert bw.builder is b1
990 assert bw.builder is b2
992 self.assertRaises(AttributeError, getattr, bw, 'foobar')
994 assert bw.foobar is 42
996 # This unit test is currently disabled because we don't think the
997 # underlying method it tests (Environment.BuilderWrapper.execute())
998 # is necessary, but we're leaving the code here for now in case
1000 def _DO_NOT_test_Builder_execs(self):
1001 """Test Builder execution through different environments
1003 One environment is initialized with a single
1004 Builder object, one with a list of a single Builder
1005 object, and one with a list of two Builder objects.
1013 env3 = Environment()
1014 env3.Replace(BUILDERS = { 'builder1' : b1,
1016 env3.builder1.execute(target = 'out1')
1017 env3.builder2.execute(target = 'out2')
1018 env3.builder1.execute(target = 'out3')
1019 assert built_it['out1']
1020 assert built_it['out2']
1021 assert built_it['out3']
1024 assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (
1025 env4.builder1.env, env3)
1026 assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (
1027 env4.builder1.env, env3)
1029 # Now test BUILDERS as a dictionary.
1031 env5 = self.TestEnvironment(BUILDERS={ 'foo' : b1 })
1032 env5['BUILDERS']['bar'] = b2
1033 env5.foo.execute(target='out1')
1034 env5.bar.execute(target='out2')
1035 assert built_it['out1']
1036 assert built_it['out2']
1039 env6 = Environment()
1040 env6['BUILDERS'] = { 'foo' : b1,
1042 env6.foo.execute(target='out1')
1043 env6.bar.execute(target='out2')
1044 assert built_it['out1']
1045 assert built_it['out2']
1049 def test_Scanners(self):
1050 """Test setting SCANNERS in various ways
1052 One environment is initialized with a single
1053 Scanner object, one with a list of a single Scanner
1054 object, and one with a list of two Scanner objects.
1058 s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
1059 s2 = Scanner(name = 'scanner2', skeys = [".m4"])
1060 s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"])
1061 s4 = Scanner(name = 'scanner4', skeys = [None])
1063 # XXX Tests for scanner execution through different environments,
1064 # XXX if we ever want to do that some day
1066 # env1 = self.TestEnvironment(SCANNERS = s1)
1067 # env1.scanner1(filename = 'out1')
1068 # assert scanned_it['out1']
1071 # env2 = self.TestEnvironment(SCANNERS = [s1])
1072 # env1.scanner1(filename = 'out1')
1073 # assert scanned_it['out1']
1076 # env3 = Environment()
1077 # env3.Replace(SCANNERS = [s1])
1078 # env3.scanner1(filename = 'out1')
1079 # env3.scanner2(filename = 'out2')
1080 # env3.scanner1(filename = 'out3')
1081 # assert scanned_it['out1']
1082 # assert scanned_it['out2']
1083 # assert scanned_it['out3']
1085 suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"]
1088 try: del env['SCANNERS']
1089 except KeyError: pass
1090 s = list(map(env.get_scanner, suffixes))
1091 assert s == [None, None, None, None, None], s
1093 env = self.TestEnvironment(SCANNERS = [])
1094 s = list(map(env.get_scanner, suffixes))
1095 assert s == [None, None, None, None, None], s
1097 env.Replace(SCANNERS = [s1])
1098 s = list(map(env.get_scanner, suffixes))
1099 assert s == [s1, s1, None, None, None], s
1101 env.Append(SCANNERS = [s2])
1102 s = list(map(env.get_scanner, suffixes))
1103 assert s == [s1, s1, None, s2, None], s
1105 env.AppendUnique(SCANNERS = [s3])
1106 s = list(map(env.get_scanner, suffixes))
1107 assert s == [s1, s1, None, s2, s3], s
1109 env = env.Clone(SCANNERS = [s2])
1110 s = list(map(env.get_scanner, suffixes))
1111 assert s == [None, None, None, s2, None], s
1113 env['SCANNERS'] = [s1]
1114 s = list(map(env.get_scanner, suffixes))
1115 assert s == [s1, s1, None, None, None], s
1117 env.PrependUnique(SCANNERS = [s2, s1])
1118 s = list(map(env.get_scanner, suffixes))
1119 assert s == [s1, s1, None, s2, None], s
1121 env.Prepend(SCANNERS = [s3])
1122 s = list(map(env.get_scanner, suffixes))
1123 assert s == [s1, s1, None, s3, s3], s
1125 # Verify behavior of case-insensitive suffix matches on Windows.
1126 uc_suffixes = [_.upper() for _ in suffixes]
1128 env = Environment(SCANNERS = [s1, s2, s3],
1131 s = list(map(env.get_scanner, suffixes))
1132 assert s == [s1, s1, None, s2, s3], s
1134 s = list(map(env.get_scanner, uc_suffixes))
1135 assert s == [None, None, None, None, None], s
1137 env['PLATFORM'] = 'win32'
1139 s = list(map(env.get_scanner, uc_suffixes))
1140 assert s == [s1, s1, None, s2, s3], s
1142 # Verify behavior for a scanner returning None (on Windows
1143 # where we might try to perform case manipulation on None).
1144 env.Replace(SCANNERS = [s4])
1145 s = list(map(env.get_scanner, suffixes))
1146 assert s == [None, None, None, None, None], s
1149 """Test setting the external ENV in Environments
1152 assert 'ENV' in env.Dictionary()
1154 env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' })
1155 assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
1157 def test_ReservedVariables(self):
1158 """Test warning generation when reserved variable names are set"""
1160 reserved_variables = [
1167 'UNCHANGED_SOURCES',
1168 'UNCHANGED_TARGETS',
1171 warning = SCons.Warnings.ReservedVariableWarning
1172 SCons.Warnings.enableWarningClass(warning)
1173 old = SCons.Warnings.warningAsException(1)
1176 env4 = Environment()
1177 for kw in self.reserved_variables:
1183 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw
1184 assert kw not in env4, "`%s' variable was incorrectly set" % kw
1186 SCons.Warnings.warningAsException(old)
1188 def test_FutureReservedVariables(self):
1189 """Test warning generation when future reserved variable names are set"""
1191 future_reserved_variables = []
1193 warning = SCons.Warnings.FutureReservedVariableWarning
1194 SCons.Warnings.enableWarningClass(warning)
1195 old = SCons.Warnings.warningAsException(1)
1198 env4 = Environment()
1199 for kw in future_reserved_variables:
1205 assert exc_caught, "Did not catch FutureReservedVariableWarning for `%s'" % kw
1206 assert kw in env4, "`%s' variable was not set" % kw
1208 SCons.Warnings.warningAsException(old)
1210 def test_IllegalVariables(self):
1211 """Test that use of illegal variables raises an exception"""
1213 def test_it(var, env=env):
1217 except SCons.Errors.UserError:
1219 assert exc_caught, "did not catch UserError for '%s'" % var
1221 assert env['aaa'] == 1, env['aaa']
1226 def test_autogenerate(dict):
1227 """Test autogenerating variables in a dictionary."""
1229 drive, p = os.path.splitdrive(os.getcwd())
1230 def normalize_path(path, drive=drive):
1231 if path[0] in '\\/':
1233 path = os.path.normpath(path)
1234 drive, path = os.path.splitdrive(path)
1235 return drive.lower() + path
1237 env = dict.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ],
1238 LIBLINKPREFIX = 'foo',
1239 LIBLINKSUFFIX = 'bar')
1241 def RDirs(pathlist, fs=env.fs):
1242 return fs.Dir('xx').Rfindalldirs(pathlist)
1244 env['RDirs'] = RDirs
1245 flags = env.subst_list('$_LIBFLAGS', 1)[0]
1246 assert flags == ['foobar', 'foobar', 'foobazbar'], flags
1248 blat = env.fs.Dir('blat')
1250 env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ],
1254 flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1256 normalize_path('foo'),
1257 normalize_path('xx/foobar'),
1258 normalize_path('foo'),
1259 normalize_path('xx/baz/bar'),
1260 normalize_path('foo'),
1261 normalize_path('blatbar'),
1264 assert flags == expect, flags
1266 env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ],
1270 flags = env.subst_list('$_F77INCFLAGS', 1)[0]
1272 normalize_path('foo'),
1273 normalize_path('xx/foobar'),
1274 normalize_path('foo'),
1275 normalize_path('xx/baz/bar'),
1276 normalize_path('foo'),
1277 normalize_path('blatbar'),
1280 assert flags == expect, flags
1282 env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '')
1283 l = env.subst_list('$_CPPINCFLAGS')
1285 l = env.subst_list('$_F77INCFLAGS')
1287 l = env.subst_list('$_LIBDIRFLAGS')
1290 env.fs.Repository('/rep1')
1291 env.fs.Repository('/rep2')
1292 env.Replace(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
1296 flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1298 '-I', normalize_path('xx/fooXXX'),
1299 '-I', normalize_path('/rep1/xx/fooXXX'),
1300 '-I', normalize_path('/rep2/xx/fooXXX'),
1301 '-I', normalize_path('/a/bXXX'),
1302 '-I', normalize_path('xx/baz/barXXX'),
1303 '-I', normalize_path('/rep1/xx/baz/barXXX'),
1304 '-I', normalize_path('/rep2/xx/baz/barXXX'),
1305 '-I', normalize_path('blatXXX'),
1308 def normalize_if_path(arg, np=normalize_path):
1309 if arg not in ('$(','$)','-I'):
1312 flags = list(map(normalize_if_path, flags))
1313 assert flags == expect, flags
1315 def test_platform(self):
1316 """Test specifying a platform callable when instantiating."""
1318 def __str__(self): return "TestPlatform"
1319 def __call__(self, env): env['XYZZY'] = 777
1322 env['SET_TOOL'] = 'initialized'
1323 assert env['PLATFORM'] == "TestPlatform"
1325 env = self.TestEnvironment(platform = platform(), tools = [tool])
1326 assert env['XYZZY'] == 777, env
1327 assert env['PLATFORM'] == "TestPlatform"
1328 assert env['SET_TOOL'] == "initialized"
1330 def test_Default_PLATFORM(self):
1331 """Test overriding the default PLATFORM variable"""
1333 def __str__(self): return "DefaultTestPlatform"
1334 def __call__(self, env): env['XYZZY'] = 888
1337 env['SET_TOOL'] = 'abcde'
1338 assert env['PLATFORM'] == "DefaultTestPlatform"
1340 import SCons.Defaults
1341 save = SCons.Defaults.ConstructionEnvironment.copy()
1343 import SCons.Defaults
1344 SCons.Defaults.ConstructionEnvironment.update({
1345 'PLATFORM' : platform(),
1347 env = self.TestEnvironment(tools = [tool])
1348 assert env['XYZZY'] == 888, env
1349 assert env['PLATFORM'] == "DefaultTestPlatform"
1350 assert env['SET_TOOL'] == "abcde"
1352 SCons.Defaults.ConstructionEnvironment = save
1354 def test_tools(self):
1355 """Test specifying a tool callable when instantiating."""
1361 env['AAA'] = env['XYZ']
1364 env = self.TestEnvironment(tools = [t1, t2, t3], XYZ = 'aaa')
1365 assert env['TOOL1'] == 111, env['TOOL1']
1366 assert env['TOOL2'] == 222, env
1367 assert env['AAA'] == 'aaa', env
1369 assert env['TOOL4'] == 444, env
1371 test = TestCmd.TestCmd(workdir = '')
1372 test.write('faketool.py', """\
1373 def generate(env, **kw):
1374 for k, v in kw.items():
1381 env = self.TestEnvironment(tools = [('faketool', {'a':1, 'b':2, 'c':3})],
1382 toolpath = [test.workpath('')])
1383 assert env['a'] == 1, env['a']
1384 assert env['b'] == 2, env['b']
1385 assert env['c'] == 3, env['c']
1387 def test_Default_TOOLS(self):
1388 """Test overriding the default TOOLS variable"""
1394 env['BBB'] = env['XYZ']
1398 import SCons.Defaults
1399 save = SCons.Defaults.ConstructionEnvironment.copy()
1401 SCons.Defaults.ConstructionEnvironment.update({
1402 'TOOLS' : [t5, t6, t7],
1404 env = Environment(XYZ = 'bbb')
1405 assert env['TOOL5'] == 555, env['TOOL5']
1406 assert env['TOOL6'] == 666, env
1407 assert env['BBB'] == 'bbb', env
1409 assert env['TOOL8'] == 888, env
1411 SCons.Defaults.ConstructionEnvironment = save
1413 def test_null_tools(self):
1414 """Test specifying a tool of None is OK."""
1419 env = self.TestEnvironment(tools = [t1, None, t2], XYZ = 'aaa')
1420 assert env['TOOL1'] == 111, env['TOOL1']
1421 assert env['TOOL2'] == 222, env
1422 assert env['XYZ'] == 'aaa', env
1423 env = self.TestEnvironment(tools = [None], XYZ = 'xyz')
1424 assert env['XYZ'] == 'xyz', env
1425 env = self.TestEnvironment(tools = [t1, '', t2], XYZ = 'ddd')
1426 assert env['TOOL1'] == 111, env['TOOL1']
1427 assert env['TOOL2'] == 222, env
1428 assert env['XYZ'] == 'ddd', env
1430 def test_concat(self):
1432 e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
1434 x = s("${_concat('', '', '', __env__)}")
1436 x = s("${_concat('', [], '', __env__)}")
1438 x = s("${_concat(PRE, '', SUF, __env__)}")
1440 x = s("${_concat(PRE, STR, SUF, __env__)}")
1441 assert x == 'prea bsuf', x
1442 x = s("${_concat(PRE, LIST, SUF, __env__)}")
1443 assert x == 'preasuf prebsuf', x
1445 def test_gvars(self):
1446 """Test the Environment gvars() method"""
1447 env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1449 assert gvars['XXX'] == 'x', gvars['XXX']
1450 assert gvars['YYY'] == 'y', gvars['YYY']
1451 assert gvars['ZZZ'] == 'z', gvars['ZZZ']
1453 def test__update(self):
1454 """Test the _update() method"""
1455 env = self.TestEnvironment(X = 'x', Y = 'y', Z = 'z')
1456 assert env['X'] == 'x', env['X']
1457 assert env['Y'] == 'y', env['Y']
1458 assert env['Z'] == 'z', env['Z']
1459 env._update({'X' : 'xxx',
1465 assert env['X'] == 'xxx', env['X']
1466 assert env['Y'] == 'y', env['Y']
1467 assert env['Z'] == 'zzz', env['Z']
1468 assert env['TARGET'] == 't', env['TARGET']
1469 assert env['TARGETS'] == 'ttt', env['TARGETS']
1470 assert env['SOURCE'] == 's', env['SOURCE']
1471 assert env['SOURCES'] == 'sss', env['SOURCES']
1475 def test_Append(self):
1476 """Test appending to construction variables in an Environment
1479 b1 = Environment()['BUILDERS']
1480 b2 = Environment()['BUILDERS']
1481 assert b1 == b2, diff_dict(b1, b2)
1484 UD = UserDict.UserDict
1486 UL = UserList.UserList
1490 'a2', ['A2'], ['a2', 'A2'],
1491 'a3', UL(['A3']), UL(['a', '3', 'A3']),
1494 'a6', UL([]), UL(['a', '6']),
1495 'a7', [''], ['a7', ''],
1496 'a8', UL(['']), UL(['a', '8', '']),
1498 ['e1'], 'E1', ['e1', 'E1'],
1499 ['e2'], ['E2'], ['e2', 'E2'],
1500 ['e3'], UL(['E3']), UL(['e3', 'E3']),
1503 ['e6'], UL([]), UL(['e6']),
1504 ['e7'], [''], ['e7', ''],
1505 ['e8'], UL(['']), UL(['e8', '']),
1507 UL(['i1']), 'I1', UL(['i1', 'I', '1']),
1508 UL(['i2']), ['I2'], UL(['i2', 'I2']),
1509 UL(['i3']), UL(['I3']), UL(['i3', 'I3']),
1510 UL(['i4']), '', UL(['i4']),
1511 UL(['i5']), [], UL(['i5']),
1512 UL(['i6']), UL([]), UL(['i6']),
1513 UL(['i7']), [''], UL(['i7', '']),
1514 UL(['i8']), UL(['']), UL(['i8', '']),
1516 {'d1':1}, 'D1', {'d1':1, 'D1':None},
1517 {'d2':1}, ['D2'], {'d2':1, 'D2':None},
1518 {'d3':1}, UL(['D3']), {'d3':1, 'D3':None},
1519 {'d4':1}, {'D4':1}, {'d4':1, 'D4':1},
1520 {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}),
1522 UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}),
1523 UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}),
1524 UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}),
1525 UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}),
1526 UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
1530 '', UL(['M3']), UL(['M3']),
1535 '', UL(['']), UL(['']),
1539 [], UL(['N3']), UL(['N3']),
1544 [], UL(['']), UL(['']),
1546 UL([]), 'O1', ['O', '1'],
1547 UL([]), ['O2'], ['O2'],
1548 UL([]), UL(['O3']), UL(['O3']),
1551 UL([]), UL([]), UL([]),
1552 UL([]), [''], UL(['']),
1553 UL([]), UL(['']), UL(['']),
1555 [''], 'P1', ['', 'P1'],
1556 [''], ['P2'], ['', 'P2'],
1557 [''], UL(['P3']), UL(['', 'P3']),
1560 [''], UL([]), UL(['']),
1561 [''], [''], ['', ''],
1562 [''], UL(['']), UL(['', '']),
1564 UL(['']), 'Q1', ['', 'Q', '1'],
1565 UL(['']), ['Q2'], ['', 'Q2'],
1566 UL(['']), UL(['Q3']), UL(['', 'Q3']),
1567 UL(['']), '', UL(['']),
1568 UL(['']), [], UL(['']),
1569 UL(['']), UL([]), UL(['']),
1570 UL(['']), [''], UL(['', '']),
1571 UL(['']), UL(['']), UL(['', '']),
1577 input, append, expect = cases[:3]
1578 env['XXX'] = copy.copy(input)
1580 env.Append(XXX = append)
1581 except Exception, e:
1582 if failed == 0: print
1583 print " %s Append %s exception: %s" % \
1584 (repr(input), repr(append), e)
1588 if result != expect:
1589 if failed == 0: print
1590 print " %s Append %s => %s did not match %s" % \
1591 (repr(input), repr(append), repr(result), repr(expect))
1594 assert failed == 0, "%d Append() cases failed" % failed
1596 env['UL'] = UL(['foo'])
1597 env.Append(UL = 'bar')
1599 assert isinstance(result, UL), repr(result)
1600 assert result == ['foo', 'b', 'a', 'r'], result
1602 env['CLVar'] = CLVar(['foo'])
1603 env.Append(CLVar = 'bar')
1604 result = env['CLVar']
1605 assert isinstance(result, CLVar), repr(result)
1606 assert result == ['foo', 'bar'], result
1609 def __init__(self, name):
1613 def __cmp__(self, other):
1614 raise "should not compare"
1618 env2 = self.TestEnvironment(CCC1 = ['c1'], CCC2 = ccc)
1619 env2.Append(CCC1 = ccc, CCC2 = ['c2'])
1620 assert env2['CCC1'][0] == 'c1', env2['CCC1']
1621 assert env2['CCC1'][1] is ccc, env2['CCC1']
1622 assert env2['CCC2'][0] is ccc, env2['CCC2']
1623 assert env2['CCC2'][1] == 'c2', env2['CCC2']
1625 env3 = self.TestEnvironment(X = {'x1' : 7})
1626 env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1627 assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X']
1628 assert env3['Y'] == {'y1': 10}, env3['Y']
1632 env4 = self.TestEnvironment(BUILDERS = {'z1' : z1})
1633 env4.Append(BUILDERS = {'z2' : z2})
1634 assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS']
1635 assert hasattr(env4, 'z1')
1636 assert hasattr(env4, 'z2')
1638 def test_AppendENVPath(self):
1639 """Test appending to an ENV path."""
1640 env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1641 MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1642 # have to include the pathsep here so that the test will work on UNIX too.
1643 env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
1644 env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
1645 env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
1646 env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
1647 # this should do nothing since delete_existing is 0
1648 env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0)
1649 assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
1650 assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
1652 test = TestCmd.TestCmd(workdir = '')
1653 test.subdir('sub1', 'sub2')
1654 p=env1['ENV']['PATH']
1655 env1.AppendENVPath('PATH','#sub1', sep = ';')
1656 env1.AppendENVPath('PATH',env1.fs.Dir('sub2'), sep = ';')
1657 assert env1['ENV']['PATH'] == p + ';sub1;sub2', env1['ENV']['PATH']
1659 def test_AppendUnique(self):
1660 """Test appending to unique values to construction variables
1662 This strips values that are already present when lists are
1664 env = self.TestEnvironment(AAA1 = 'a1',
1676 DDD1 = ['a', 'b', 'c'])
1677 env.AppendUnique(AAA1 = 'a1',
1679 AAA3 = ['a3', 'b', 'c', 'c', 'b', 'a3'], # ignore dups
1684 BBB3 = ['b3', 'c', 'd', 'c', 'b3'],
1691 assert env['AAA1'] == 'a1a1', env['AAA1']
1692 assert env['AAA2'] == ['a2'], env['AAA2']
1693 assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3']
1694 assert env['AAA4'] == 'a4a4.new', env['AAA4']
1695 assert env['AAA5'] == ['a5', 'a5.new'], env['AAA5']
1696 assert env['BBB1'] == ['b1'], env['BBB1']
1697 assert env['BBB2'] == ['b2'], env['BBB2']
1698 assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3']
1699 assert env['BBB4'] == ['b4', 'b4.new'], env['BBB4']
1700 assert env['BBB5'] == ['b5', 'b5.new'], env['BBB5']
1701 assert env['CCC1'] == 'c1', env['CCC1']
1702 assert env['CCC2'] == ['c2'], env['CCC2']
1703 assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1']
1705 env.AppendUnique(DDD1 = 'b', delete_existing=1)
1706 assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # b moves to end
1707 env.AppendUnique(DDD1 = ['a','b'], delete_existing=1)
1708 assert env['DDD1'] == ['c', 'a', 'b'], env['DDD1'] # a & b move to end
1709 env.AppendUnique(DDD1 = ['e','f', 'e'], delete_existing=1)
1710 assert env['DDD1'] == ['c', 'a', 'b', 'f', 'e'], env['DDD1'] # add last
1712 env['CLVar'] = CLVar([])
1713 env.AppendUnique(CLVar = 'bar')
1714 result = env['CLVar']
1715 if sys.version[0] == '1' or sys.version[:3] == '2.0':
1716 # Python 2.0 and before have a quirky behavior where CLVar([])
1717 # actually matches '' and [] due to different __coerce__()
1718 # semantics in the UserList implementation. It isn't worth a
1719 # lot of effort to get this corner case to work identically
1720 # (support for Python 1.5 support will die soon anyway),
1721 # so just treat it separately for now.
1722 assert result == 'bar', result
1724 assert isinstance(result, CLVar), repr(result)
1725 assert result == ['bar'], result
1727 env['CLVar'] = CLVar(['abc'])
1728 env.AppendUnique(CLVar = 'bar')
1729 result = env['CLVar']
1730 assert isinstance(result, CLVar), repr(result)
1731 assert result == ['abc', 'bar'], result
1733 env['CLVar'] = CLVar(['bar'])
1734 env.AppendUnique(CLVar = 'bar')
1735 result = env['CLVar']
1736 assert isinstance(result, CLVar), repr(result)
1737 assert result == ['bar'], result
1739 def test_Clone(self):
1740 """Test construction environment copying
1742 Update the copy independently afterwards and check that
1743 the original remains intact (that is, no dangling
1744 references point to objects in the copied environment).
1745 Clone the original with some construction variable
1746 updates and check that the original remains intact
1747 and the copy has the updated values.
1749 env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
1751 env1copy = env1.Clone()
1752 assert env1copy == env1copy
1754 env2.Replace(YYY = 'yyy')
1757 assert env1 == env1copy
1759 env3 = env1.Clone(XXX = 'x3', ZZZ = 'z3')
1761 assert env3.Dictionary('XXX') == 'x3'
1762 assert env3.Dictionary('YYY') == 'y'
1763 assert env3.Dictionary('ZZZ') == 'z3'
1764 assert env1 == env1copy
1766 # Ensure that lists and dictionaries are
1767 # deep copied, but not instances.
1770 env1 = self.TestEnvironment(XXX=TestA(), YYY = [ 1, 2, 3 ],
1773 env2.Dictionary('YYY').append(4)
1774 env2.Dictionary('ZZZ')[5] = 6
1775 assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
1776 assert 4 in env2.Dictionary('YYY')
1777 assert not 4 in env1.Dictionary('YYY')
1778 assert 5 in env2.Dictionary('ZZZ')
1779 assert 5 not in env1.Dictionary('ZZZ')
1782 env1 = self.TestEnvironment(BUILDERS = {'b1' : Builder()})
1783 assert hasattr(env1, 'b1'), "env1.b1 was not set"
1784 assert env1.b1.object == env1, "b1.object doesn't point to env1"
1785 env2 = env1.Clone(BUILDERS = {'b2' : Builder()})
1788 assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
1789 assert env1.b1.object == env1, "b1.object was changed"
1790 assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
1791 assert hasattr(env2, 'b2'), "env2.b2 was not set"
1792 assert env2.b2.object == env2, "b2.object doesn't point to env2"
1794 # Ensure that specifying new tools in a copied environment
1796 def foo(env): env['FOO'] = 1
1797 def bar(env): env['BAR'] = 2
1798 def baz(env): env['BAZ'] = 3
1799 env1 = self.TestEnvironment(tools=[foo])
1801 env3 = env1.Clone(tools=[bar, baz])
1803 assert env1.get('FOO') is 1
1804 assert env1.get('BAR') is None
1805 assert env1.get('BAZ') is None
1806 assert env2.get('FOO') is 1
1807 assert env2.get('BAR') is None
1808 assert env2.get('BAZ') is None
1809 assert env3.get('FOO') is 1
1810 assert env3.get('BAR') is 2
1811 assert env3.get('BAZ') is 3
1813 # Ensure that recursive variable substitution when copying
1814 # environments works properly.
1815 env1 = self.TestEnvironment(CCFLAGS = '-DFOO', XYZ = '-DXYZ')
1816 env2 = env1.Clone(CCFLAGS = '$CCFLAGS -DBAR',
1817 XYZ = ['-DABC', 'x $XYZ y', '-DDEF'])
1818 x = env2.get('CCFLAGS')
1819 assert x == '-DFOO -DBAR', x
1821 assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x
1823 # Ensure that special properties of a class don't get
1825 env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2'))
1826 x = env1.get('FLAGS')
1827 assert x == ['flag1', 'flag2'], x
1829 env2.Append(FLAGS = 'flag3 flag4')
1830 x = env2.get('FLAGS')
1831 assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
1833 # Test that the environment stores the toolpath and
1834 # re-uses it for copies.
1835 test = TestCmd.TestCmd(workdir = '')
1837 test.write('xxx.py', """\
1844 test.write('yyy.py', """\
1851 env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
1852 assert env['XXX'] == 'one', env['XXX']
1853 env = env.Clone(tools=['yyy'])
1854 assert env['YYY'] == 'two', env['YYY']
1860 def my_tool(env, rv=real_value):
1861 assert env['KEY_THAT_I_WANT'] == rv[0]
1862 env['KEY_THAT_I_WANT'] = rv[0] + 1
1864 env = self.TestEnvironment()
1867 env = env.Clone(KEY_THAT_I_WANT=5, tools=[my_tool])
1868 assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT']
1871 env = env.Clone(KEY_THAT_I_WANT=6, tools=[my_tool])
1872 assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT']
1875 def test_Copy(self):
1876 """Test copying using the old env.Copy() method"""
1877 env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
1879 env1copy = env1.Copy()
1880 assert env1copy == env1copy
1882 env2.Replace(YYY = 'yyy')
1885 assert env1 == env1copy
1887 def test_Detect(self):
1888 """Test Detect()ing tools"""
1889 test = TestCmd.TestCmd(workdir = '')
1890 test.subdir('sub1', 'sub2')
1891 sub1 = test.workpath('sub1')
1892 sub2 = test.workpath('sub2')
1894 if sys.platform == 'win32':
1895 test.write(['sub1', 'xxx'], "sub1/xxx\n")
1896 test.write(['sub2', 'xxx'], "sub2/xxx\n")
1898 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1900 x = env.Detect('xxx.exe')
1903 test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1905 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1907 x = env.Detect('xxx.exe')
1908 assert x == 'xxx.exe', x
1910 test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1912 x = env.Detect('xxx.exe')
1913 assert x == 'xxx.exe', x
1916 test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1917 test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1919 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1921 x = env.Detect('xxx.exe')
1924 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1925 os.chmod(sub2_xxx_exe, 0755)
1927 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1929 x = env.Detect('xxx.exe')
1930 assert x == 'xxx.exe', x
1932 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1933 os.chmod(sub1_xxx_exe, 0755)
1935 x = env.Detect('xxx.exe')
1936 assert x == 'xxx.exe', x
1938 env = self.TestEnvironment(ENV = { 'PATH' : [] })
1939 x = env.Detect('xxx.exe')
1942 def test_Dictionary(self):
1943 """Test retrieval of known construction variables
1945 Fetch them from the Dictionary and check for well-known
1946 defaults that get inserted.
1948 env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1949 assert env.Dictionary('XXX') == 'x'
1950 assert env.Dictionary('YYY') == 'y'
1951 assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
1952 xxx, zzz = env.Dictionary('XXX', 'ZZZ')
1955 assert 'BUILDERS' in env.Dictionary()
1956 assert 'CC' in env.Dictionary()
1957 assert 'CCFLAGS' in env.Dictionary()
1958 assert 'ENV' in env.Dictionary()
1960 assert env['XXX'] == 'x'
1962 assert env.Dictionary('XXX') == 'foo'
1964 assert 'XXX' not in env.Dictionary()
1966 def test_FindIxes(self):
1968 env = self.TestEnvironment(LIBPREFIX='lib',
1975 paths = [os.path.join('dir', 'libfoo.a'),
1976 os.path.join('dir', 'libfoo.so')]
1978 assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1979 assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1980 assert None is env.FindIxes(paths, 'PREFIX', 'POST')
1982 paths = ['libfoo.a', 'prefoopost']
1984 assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1985 assert None is env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1986 assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
1988 def test_ParseConfig(self):
1989 """Test the ParseConfig() method"""
1990 env = self.TestEnvironment(COMMAND='command',
1991 ASFLAGS='assembler',
2003 orig_backtick = env.backtick
2005 def __init__(self, save_command, output):
2006 self.save_command = save_command
2007 self.output = output
2008 def __call__(self, command):
2009 self.save_command.append(command)
2014 env.backtick = my_backtick(save_command,
2015 "-I/usr/include/fum -I bar -X\n" + \
2016 "-L/usr/fax -L foo -lxxx -l yyy " + \
2017 "-Wa,-as -Wl,-link " + \
2018 "-Wl,-rpath=rpath1 " + \
2019 "-Wl,-R,rpath2 " + \
2022 "-framework Carbon " + \
2023 "-frameworkdir=fwd1 " + \
2027 "-mno-cygwin -mwindows " + \
2028 "-arch i386 -isysroot /tmp +DD64 " + \
2029 "-DFOO -DBAR=value")
2030 env.ParseConfig("fake $COMMAND")
2031 assert save_command == ['fake command'], save_command
2032 assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS']
2033 assert env['CCFLAGS'] == ['', '-X', '-Wa,-as',
2034 '-pthread', '-mno-cygwin',
2035 ('-arch', 'i386'), ('-isysroot', '/tmp'),
2036 '+DD64'], env['CCFLAGS']
2037 assert env['CPPDEFINES'] == ['FOO', ['BAR', 'value']], env['CPPDEFINES']
2038 assert env['CPPFLAGS'] == ['', '-Wp,-cpp'], env['CPPFLAGS']
2039 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
2040 assert env['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], env['FRAMEWORKPATH']
2041 assert env['FRAMEWORKS'] == ['Carbon'], env['FRAMEWORKS']
2042 assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
2043 assert env['LIBS'] == ['xxx', 'yyy', env.File('abc')], env['LIBS']
2044 assert env['LINKFLAGS'] == ['', '-Wl,-link', '-pthread',
2045 '-mno-cygwin', '-mwindows',
2047 ('-isysroot', '/tmp'),
2048 '+DD64'], env['LINKFLAGS']
2049 assert env['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], env['RPATH']
2051 env.backtick = my_backtick([], "-Ibar")
2052 env.ParseConfig("fake2")
2053 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
2054 env.ParseConfig("fake2", unique=0)
2055 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar', 'bar'], env['CPPPATH']
2057 env.backtick = orig_backtick
2059 def test_ParseDepends(self):
2060 """Test the ParseDepends() method"""
2061 test = TestCmd.TestCmd(workdir = '')
2063 test.write('single', """
2073 test.write('multiple', """
2084 env = self.TestEnvironment(SINGLE = test.workpath('single'))
2088 def my_depends(target, dependency, tlist=tlist, dlist=dlist):
2089 tlist.extend(target)
2090 dlist.extend(dependency)
2092 env.Depends = my_depends
2094 env.ParseDepends(test.workpath('does_not_exist'))
2098 env.ParseDepends(test.workpath('does_not_exist'), must_exist=1)
2101 assert exc_caught, "did not catch expected IOError"
2106 env.ParseDepends('$SINGLE', only_one=1)
2107 t = list(map(str, tlist))
2108 d = list(map(str, dlist))
2109 assert t == ['f0'], t
2110 assert d == ['d1', 'd2', 'd3'], d
2115 env.ParseDepends(test.workpath('multiple'))
2116 t = list(map(str, tlist))
2117 d = list(map(str, dlist))
2118 assert t == ['f1', 'f2', 'f3', 'f4', 'f5'], t
2119 assert d == ['foo', 'bar', 'abc', 'def', 'ghi', 'jkl', 'mno'], d
2123 env.ParseDepends(test.workpath('multiple'), only_one=1)
2124 except SCons.Errors.UserError:
2126 assert exc_caught, "did not catch expected UserError"
2128 def test_Platform(self):
2129 """Test the Platform() method"""
2130 env = self.TestEnvironment(WIN32='win32', NONE='no-such-platform')
2134 env.Platform('does_not_exist')
2135 except SCons.Errors.UserError:
2137 assert exc_caught, "did not catch expected UserError"
2141 env.Platform('$NONE')
2142 except SCons.Errors.UserError:
2144 assert exc_caught, "did not catch expected UserError"
2146 env.Platform('posix')
2147 assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
2149 env.Platform('$WIN32')
2150 assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
2152 def test_Prepend(self):
2153 """Test prepending to construction variables in an Environment
2156 UD = UserDict.UserDict
2158 UL = UserList.UserList
2162 'a2', ['A2'], ['A2', 'a2'],
2163 'a3', UL(['A3']), UL(['A3', 'a', '3']),
2166 'a6', UL([]), UL(['a', '6']),
2167 'a7', [''], ['', 'a7'],
2168 'a8', UL(['']), UL(['', 'a', '8']),
2170 ['e1'], 'E1', ['E1', 'e1'],
2171 ['e2'], ['E2'], ['E2', 'e2'],
2172 ['e3'], UL(['E3']), UL(['E3', 'e3']),
2175 ['e6'], UL([]), UL(['e6']),
2176 ['e7'], [''], ['', 'e7'],
2177 ['e8'], UL(['']), UL(['', 'e8']),
2179 UL(['i1']), 'I1', UL(['I', '1', 'i1']),
2180 UL(['i2']), ['I2'], UL(['I2', 'i2']),
2181 UL(['i3']), UL(['I3']), UL(['I3', 'i3']),
2182 UL(['i4']), '', UL(['i4']),
2183 UL(['i5']), [], UL(['i5']),
2184 UL(['i6']), UL([]), UL(['i6']),
2185 UL(['i7']), [''], UL(['', 'i7']),
2186 UL(['i8']), UL(['']), UL(['', 'i8']),
2188 {'d1':1}, 'D1', {'d1':1, 'D1':None},
2189 {'d2':1}, ['D2'], {'d2':1, 'D2':None},
2190 {'d3':1}, UL(['D3']), {'d3':1, 'D3':None},
2191 {'d4':1}, {'D4':1}, {'d4':1, 'D4':1},
2192 {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}),
2194 UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}),
2195 UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}),
2196 UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}),
2197 UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}),
2198 UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
2202 '', UL(['M3']), UL(['M3']),
2207 '', UL(['']), UL(['']),
2211 [], UL(['N3']), UL(['N3']),
2216 [], UL(['']), UL(['']),
2218 UL([]), 'O1', UL(['O', '1']),
2219 UL([]), ['O2'], UL(['O2']),
2220 UL([]), UL(['O3']), UL(['O3']),
2223 UL([]), UL([]), UL([]),
2224 UL([]), [''], UL(['']),
2225 UL([]), UL(['']), UL(['']),
2227 [''], 'P1', ['P1', ''],
2228 [''], ['P2'], ['P2', ''],
2229 [''], UL(['P3']), UL(['P3', '']),
2232 [''], UL([]), UL(['']),
2233 [''], [''], ['', ''],
2234 [''], UL(['']), UL(['', '']),
2236 UL(['']), 'Q1', UL(['Q', '1', '']),
2237 UL(['']), ['Q2'], UL(['Q2', '']),
2238 UL(['']), UL(['Q3']), UL(['Q3', '']),
2239 UL(['']), '', UL(['']),
2240 UL(['']), [], UL(['']),
2241 UL(['']), UL([]), UL(['']),
2242 UL(['']), [''], UL(['', '']),
2243 UL(['']), UL(['']), UL(['', '']),
2249 input, prepend, expect = cases[:3]
2250 env['XXX'] = copy.copy(input)
2252 env.Prepend(XXX = prepend)
2253 except Exception, e:
2254 if failed == 0: print
2255 print " %s Prepend %s exception: %s" % \
2256 (repr(input), repr(prepend), e)
2260 if result != expect:
2261 if failed == 0: print
2262 print " %s Prepend %s => %s did not match %s" % \
2263 (repr(input), repr(prepend), repr(result), repr(expect))
2266 assert failed == 0, "%d Prepend() cases failed" % failed
2268 env['UL'] = UL(['foo'])
2269 env.Prepend(UL = 'bar')
2271 assert isinstance(result, UL), repr(result)
2272 assert result == ['b', 'a', 'r', 'foo'], result
2274 env['CLVar'] = CLVar(['foo'])
2275 env.Prepend(CLVar = 'bar')
2276 result = env['CLVar']
2277 assert isinstance(result, CLVar), repr(result)
2278 assert result == ['bar', 'foo'], result
2280 env3 = self.TestEnvironment(X = {'x1' : 7})
2281 env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
2282 assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
2283 assert env3['Y'] == {'y1': 10}, env3['Y']
2287 env4 = self.TestEnvironment(BUILDERS = {'z1' : z1})
2288 env4.Prepend(BUILDERS = {'z2' : z2})
2289 assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS']
2290 assert hasattr(env4, 'z1')
2291 assert hasattr(env4, 'z2')
2293 def test_PrependENVPath(self):
2294 """Test prepending to an ENV path."""
2295 env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
2296 MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
2297 # have to include the pathsep here so that the test will work on UNIX too.
2298 env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
2299 env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
2300 env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
2301 env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
2302 # this should do nothing since delete_existing is 0
2303 env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0)
2304 assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
2305 assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
2307 test = TestCmd.TestCmd(workdir = '')
2308 test.subdir('sub1', 'sub2')
2309 p=env1['ENV']['PATH']
2310 env1.PrependENVPath('PATH','#sub1', sep = ';')
2311 env1.PrependENVPath('PATH',env1.fs.Dir('sub2'), sep = ';')
2312 assert env1['ENV']['PATH'] == 'sub2;sub1;' + p, env1['ENV']['PATH']
2314 def test_PrependUnique(self):
2315 """Test prepending unique values to construction variables
2317 This strips values that are already present when lists are
2319 env = self.TestEnvironment(AAA1 = 'a1',
2331 DDD1 = ['a', 'b', 'c'])
2332 env.PrependUnique(AAA1 = 'a1',
2334 AAA3 = ['a3', 'b', 'c', 'b', 'a3'], # ignore dups
2339 BBB3 = ['b3', 'b', 'c', 'b3'],
2345 assert env['AAA1'] == 'a1a1', env['AAA1']
2346 assert env['AAA2'] == ['a2'], env['AAA2']
2347 assert env['AAA3'] == ['c', 'b', 'a3'], env['AAA3']
2348 assert env['AAA4'] == 'a4.newa4', env['AAA4']
2349 assert env['AAA5'] == ['a5.new', 'a5'], env['AAA5']
2350 assert env['BBB1'] == ['b1'], env['BBB1']
2351 assert env['BBB2'] == ['b2'], env['BBB2']
2352 assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3']
2353 assert env['BBB4'] == ['b4.new', 'b4'], env['BBB4']
2354 assert env['BBB5'] == ['b5.new', 'b5'], env['BBB5']
2355 assert env['CCC1'] == 'c1', env['CCC1']
2356 assert env['CCC2'] == ['c2'], env['CCC2']
2357 assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1']
2359 env.PrependUnique(DDD1 = 'b', delete_existing=1)
2360 assert env['DDD1'] == ['b', 'a', 'c'], env['DDD1'] # b moves to front
2361 env.PrependUnique(DDD1 = ['a','c'], delete_existing=1)
2362 assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # a & c move to front
2363 env.PrependUnique(DDD1 = ['d','e','d'], delete_existing=1)
2364 assert env['DDD1'] == ['d', 'e', 'a', 'c', 'b'], env['DDD1']
2367 env['CLVar'] = CLVar([])
2368 env.PrependUnique(CLVar = 'bar')
2369 result = env['CLVar']
2370 if sys.version[0] == '1' or sys.version[:3] == '2.0':
2371 # Python 2.0 and before have a quirky behavior where CLVar([])
2372 # actually matches '' and [] due to different __coerce__()
2373 # semantics in the UserList implementation. It isn't worth a
2374 # lot of effort to get this corner case to work identically
2375 # (support for Python 1.5 support will die soon anyway),
2376 # so just treat it separately for now.
2377 assert result == 'bar', result
2379 assert isinstance(result, CLVar), repr(result)
2380 assert result == ['bar'], result
2382 env['CLVar'] = CLVar(['abc'])
2383 env.PrependUnique(CLVar = 'bar')
2384 result = env['CLVar']
2385 assert isinstance(result, CLVar), repr(result)
2386 assert result == ['bar', 'abc'], result
2388 env['CLVar'] = CLVar(['bar'])
2389 env.PrependUnique(CLVar = 'bar')
2390 result = env['CLVar']
2391 assert isinstance(result, CLVar), repr(result)
2392 assert result == ['bar'], result
2394 def test_Replace(self):
2395 """Test replacing construction variables in an Environment
2397 After creation of the Environment, of course.
2399 env1 = self.TestEnvironment(AAA = 'a', BBB = 'b')
2400 env1.Replace(BBB = 'bbb', CCC = 'ccc')
2402 env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
2403 assert env1 == env2, diff_env(env1, env2)
2407 env3 = self.TestEnvironment(BUILDERS = {'b1' : b1})
2408 assert hasattr(env3, 'b1'), "b1 was not set"
2409 env3.Replace(BUILDERS = {'b2' : b2})
2410 assert not hasattr(env3, 'b1'), "b1 was not cleared"
2411 assert hasattr(env3, 'b2'), "b2 was not set"
2413 def test_ReplaceIxes(self):
2414 "Test ReplaceIxes()"
2415 env = self.TestEnvironment(LIBPREFIX='lib',
2422 assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
2423 'SHLIBPREFIX', 'SHLIBSUFFIX',
2424 'LIBPREFIX', 'LIBSUFFIX')
2426 assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
2427 'SHLIBPREFIX', 'SHLIBSUFFIX',
2428 'LIBPREFIX', 'LIBSUFFIX')
2430 assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
2432 'LIBPREFIX', 'LIBSUFFIX')
2434 def test_SetDefault(self):
2435 """Test the SetDefault method"""
2436 env = self.TestEnvironment(tools = [])
2437 env.SetDefault(V1 = 1)
2438 env.SetDefault(V1 = 2)
2439 assert env['V1'] == 1
2441 env.SetDefault(V2 = 1)
2442 assert env['V2'] == 2
2444 def test_Tool(self):
2445 """Test the Tool() method"""
2446 env = self.TestEnvironment(LINK='link', NONE='no-such-tool')
2450 env.Tool('does_not_exist')
2451 except SCons.Errors.EnvironmentError:
2453 assert exc_caught, "did not catch expected EnvironmentError"
2458 except SCons.Errors.EnvironmentError:
2460 assert exc_caught, "did not catch expected EnvironmentError"
2462 # Use a non-existent toolpath directory just to make sure we
2463 # can call Tool() with the keyword argument.
2464 env.Tool('cc', toolpath=['/no/such/directory'])
2465 assert env['CC'] == 'cc', env['CC']
2468 assert env['LINK'] == '$SMARTLINK', env['LINK']
2470 # Test that the environment stores the toolpath and
2471 # re-uses it for later calls.
2472 test = TestCmd.TestCmd(workdir = '')
2474 test.write('xxx.py', """\
2481 test.write('yyy.py', """\
2488 env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
2489 assert env['XXX'] == 'one', env['XXX']
2491 assert env['YYY'] == 'two', env['YYY']
2493 def test_WhereIs(self):
2494 """Test the WhereIs() method"""
2495 test = TestCmd.TestCmd(workdir = '')
2497 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
2498 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
2499 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
2500 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
2502 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
2504 if sys.platform != 'win32':
2505 test.write(sub1_xxx_exe, "\n")
2507 os.mkdir(sub2_xxx_exe)
2509 test.write(sub3_xxx_exe, "\n")
2510 os.chmod(sub3_xxx_exe, 0777)
2512 test.write(sub4_xxx_exe, "\n")
2513 os.chmod(sub4_xxx_exe, 0777)
2515 env_path = os.environ['PATH']
2517 pathdirs_1234 = [ test.workpath('sub1'),
2518 test.workpath('sub2'),
2519 test.workpath('sub3'),
2520 test.workpath('sub4'),
2521 ] + env_path.split(os.pathsep)
2523 pathdirs_1243 = [ test.workpath('sub1'),
2524 test.workpath('sub2'),
2525 test.workpath('sub4'),
2526 test.workpath('sub3'),
2527 ] + env_path.split(os.pathsep)
2529 path = os.pathsep.join(pathdirs_1234)
2530 env = self.TestEnvironment(ENV = {'PATH' : path})
2531 wi = env.WhereIs('xxx.exe')
2532 assert wi == test.workpath(sub3_xxx_exe), wi
2533 wi = env.WhereIs('xxx.exe', pathdirs_1243)
2534 assert wi == test.workpath(sub4_xxx_exe), wi
2535 wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243))
2536 assert wi == test.workpath(sub4_xxx_exe), wi
2538 wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe)
2539 assert wi == test.workpath(sub4_xxx_exe), wi
2540 wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
2541 assert wi == test.workpath(sub4_xxx_exe), wi
2543 path = os.pathsep.join(pathdirs_1243)
2544 env = self.TestEnvironment(ENV = {'PATH' : path})
2545 wi = env.WhereIs('xxx.exe')
2546 assert wi == test.workpath(sub4_xxx_exe), wi
2547 wi = env.WhereIs('xxx.exe', pathdirs_1234)
2548 assert wi == test.workpath(sub3_xxx_exe), wi
2549 wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1234))
2550 assert wi == test.workpath(sub3_xxx_exe), wi
2552 if sys.platform == 'win32':
2553 wi = env.WhereIs('xxx', pathext = '')
2554 assert wi is None, wi
2556 wi = env.WhereIs('xxx', pathext = '.exe')
2557 assert wi == test.workpath(sub4_xxx_exe), wi
2559 wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
2560 assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi
2562 # Test that we return a normalized path even when
2563 # the path contains forward slashes.
2564 forward_slash = test.workpath('') + '/sub3'
2565 wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE')
2566 assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi
2570 def test_Action(self):
2571 """Test the Action() method"""
2574 env = self.TestEnvironment(FOO = 'xyzzy')
2576 a = env.Action('foo')
2578 assert a.__class__ is SCons.Action.CommandAction, a.__class__
2580 a = env.Action('$FOO')
2582 assert a.__class__ is SCons.Action.CommandAction, a.__class__
2584 a = env.Action('$$FOO')
2586 assert a.__class__ is SCons.Action.LazyAction, a.__class__
2588 a = env.Action(['$FOO', 'foo'])
2590 assert a.__class__ is SCons.Action.ListAction, a.__class__
2594 a = env.Action(func)
2596 assert a.__class__ is SCons.Action.FunctionAction, a.__class__
2598 def test_AddPostAction(self):
2599 """Test the AddPostAction() method"""
2600 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2602 n = env.AddPostAction('$FOO', lambda x: x)
2603 assert str(n[0]) == 'fff', n[0]
2605 n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
2606 assert str(n[0]) == 'ggg', n[0]
2607 assert str(n[1]) == 'bbb', n[1]
2609 def test_AddPreAction(self):
2610 """Test the AddPreAction() method"""
2611 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2613 n = env.AddPreAction('$FOO', lambda x: x)
2614 assert str(n[0]) == 'fff', n[0]
2616 n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
2617 assert str(n[0]) == 'ggg', n[0]
2618 assert str(n[1]) == 'bbb', n[1]
2620 def test_Alias(self):
2621 """Test the Alias() method"""
2622 env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_alias')
2624 tgt = env.Alias('new_alias')[0]
2625 assert str(tgt) == 'new_alias', tgt
2626 assert tgt.sources == [], tgt.sources
2627 assert not hasattr(tgt, 'builder'), tgt.builder
2629 tgt = env.Alias('None_alias', None)[0]
2630 assert str(tgt) == 'None_alias', tgt
2631 assert tgt.sources == [], tgt.sources
2633 tgt = env.Alias('empty_list', [])[0]
2634 assert str(tgt) == 'empty_list', tgt
2635 assert tgt.sources == [], tgt.sources
2637 tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0]
2638 assert str(tgt) == 'export_alias', tgt
2639 assert len(tgt.sources) == 2, list(map(str, tgt.sources))
2640 assert str(tgt.sources[0]) == 'asrc1', list(map(str, tgt.sources))
2641 assert str(tgt.sources[1]) == 'kkk', list(map(str, tgt.sources))
2643 n = env.Alias(tgt, source = ['$BAR', 'asrc4'])[0]
2645 assert len(tgt.sources) == 4, list(map(str, tgt.sources))
2646 assert str(tgt.sources[2]) == 'lll', list(map(str, tgt.sources))
2647 assert str(tgt.sources[3]) == 'asrc4', list(map(str, tgt.sources))
2649 n = env.Alias('$EA', 'asrc5')[0]
2651 assert len(tgt.sources) == 5, list(map(str, tgt.sources))
2652 assert str(tgt.sources[4]) == 'asrc5', list(map(str, tgt.sources))
2654 t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
2655 assert str(t1) == 't1', t1
2656 assert str(t2) == 't2', t2
2657 assert len(t1.sources) == 2, list(map(str, t1.sources))
2658 assert str(t1.sources[0]) == 'asrc6', list(map(str, t1.sources))
2659 assert str(t1.sources[1]) == 'asrc7', list(map(str, t1.sources))
2660 assert len(t2.sources) == 2, list(map(str, t2.sources))
2661 assert str(t2.sources[0]) == 'asrc6', list(map(str, t2.sources))
2662 assert str(t2.sources[1]) == 'asrc7', list(map(str, t2.sources))
2664 tgt = env.Alias('add', 's1')
2665 tgt = env.Alias('add', 's2')[0]
2666 s = list(map(str, tgt.sources))
2667 assert s == ['s1', 's2'], s
2668 tgt = env.Alias(tgt, 's3')[0]
2669 s = list(map(str, tgt.sources))
2670 assert s == ['s1', 's2', 's3'], s
2672 tgt = env.Alias('act', None, "action1")[0]
2673 s = str(tgt.builder.action)
2674 assert s == "action1", s
2675 tgt = env.Alias('act', None, "action2")[0]
2676 s = str(tgt.builder.action)
2677 assert s == "action1\naction2", s
2678 tgt = env.Alias(tgt, None, "action3")[0]
2679 s = str(tgt.builder.action)
2680 assert s == "action1\naction2\naction3", s
2682 def test_AlwaysBuild(self):
2683 """Test the AlwaysBuild() method"""
2684 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2685 t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR',
2686 env.fs.Dir('dir'), env.fs.File('file'))
2687 assert t[0].__class__.__name__ == 'Entry'
2688 assert t[0].path == 'a'
2689 assert t[0].always_build
2690 assert t[1].__class__.__name__ == 'Entry'
2691 assert t[1].path == 'bfff'
2692 assert t[1].always_build
2693 assert t[2].__class__.__name__ == 'Entry'
2694 assert t[2].path == 'c'
2695 assert t[2].always_build
2696 assert t[3].__class__.__name__ == 'Entry'
2697 assert t[3].path == 'd'
2698 assert t[3].always_build
2699 assert t[4].__class__.__name__ == 'Entry'
2700 assert t[4].path == 'bbb'
2701 assert t[4].always_build
2702 assert t[5].__class__.__name__ == 'Dir'
2703 assert t[5].path == 'dir'
2704 assert t[5].always_build
2705 assert t[6].__class__.__name__ == 'File'
2706 assert t[6].path == 'file'
2707 assert t[6].always_build
2709 def test_VariantDir(self):
2710 """Test the VariantDir() method"""
2712 def Dir(self, name):
2714 def VariantDir(self, variant_dir, src_dir, duplicate):
2715 self.variant_dir = variant_dir
2716 self.src_dir = src_dir
2717 self.duplicate = duplicate
2719 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2722 env.VariantDir('build', 'src')
2723 assert env.fs.variant_dir == 'build', env.fs.variant_dir
2724 assert env.fs.src_dir == 'src', env.fs.src_dir
2725 assert env.fs.duplicate == 1, env.fs.duplicate
2727 env.VariantDir('build${FOO}', '${BAR}src', 0)
2728 assert env.fs.variant_dir == 'buildfff', env.fs.variant_dir
2729 assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir
2730 assert env.fs.duplicate == 0, env.fs.duplicate
2732 def test_Builder(self):
2733 """Test the Builder() method"""
2734 env = self.TestEnvironment(FOO = 'xyzzy')
2736 b = env.Builder(action = 'foo')
2737 assert b is not None, b
2739 b = env.Builder(action = '$FOO')
2740 assert b is not None, b
2742 b = env.Builder(action = ['$FOO', 'foo'])
2743 assert b is not None, b
2747 b = env.Builder(action = func)
2748 assert b is not None, b
2749 b = env.Builder(generator = func)
2750 assert b is not None, b
2752 def test_CacheDir(self):
2753 """Test the CacheDir() method"""
2754 env = self.TestEnvironment(CD = 'CacheDir')
2757 assert env._CacheDir_path == 'foo', env._CacheDir_path
2760 assert env._CacheDir_path == 'CacheDir', env._CacheDir_path
2762 def test_Clean(self):
2763 """Test the Clean() method"""
2764 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2766 CT = SCons.Environment.CleanTargets
2768 foo = env.arg2nodes('foo')[0]
2769 fff = env.arg2nodes('fff')[0]
2771 t = env.Clean('foo', 'aaa')
2772 l = list(map(str, CT[foo]))
2773 assert l == ['aaa'], l
2775 t = env.Clean(foo, ['$BAR', 'ccc'])
2776 l = list(map(str, CT[foo]))
2777 assert l == ['aaa', 'bbb', 'ccc'], l
2779 eee = env.arg2nodes('eee')[0]
2781 t = env.Clean('$FOO', 'ddd')
2782 l = list(map(str, CT[fff]))
2783 assert l == ['ddd'], l
2784 t = env.Clean(fff, [eee, 'fff'])
2785 l = list(map(str, CT[fff]))
2786 assert l == ['ddd', 'eee', 'fff'], l
2788 def test_Command(self):
2789 """Test the Command() method."""
2791 t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
2792 action='buildfoo $target $source')[0]
2793 assert t.builder is not None
2794 assert t.builder.action.__class__.__name__ == 'CommandAction'
2795 assert t.builder.action.cmd_list == 'buildfoo $target $source'
2796 assert 'foo1.in' in [x.path for x in t.sources]
2797 assert 'foo2.in' in [x.path for x in t.sources]
2799 sub = env.fs.Dir('sub')
2800 t = env.Command(target='bar.out', source='sub',
2801 action='buildbar $target $source')[0]
2802 assert 'sub' in [x.path for x in t.sources]
2804 def testFunc(env, target, source):
2805 assert str(target[0]) == 'foo.out'
2806 assert 'foo1.in' in list(map(str, source)) and 'foo2.in' in list(map(str, source)), list(map(str, source))
2808 t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
2810 assert t.builder is not None
2811 assert t.builder.action.__class__.__name__ == 'FunctionAction'
2813 assert 'foo1.in' in [x.path for x in t.sources]
2814 assert 'foo2.in' in [x.path for x in t.sources]
2817 def test2(baz, x=x):
2819 env = self.TestEnvironment(TEST2 = test2)
2820 t = env.Command(target='baz.out', source='baz.in',
2821 action='${TEST2(XYZ)}',
2822 XYZ='magic word')[0]
2823 assert t.builder is not None
2825 assert x[0] == 'magic word', x
2827 t = env.Command(target='${X}.out', source='${X}.in',
2830 assert str(t) == 'xxx.out', str(t)
2831 assert 'xxx.in' in [x.path for x in t.sources]
2833 env = self.TestEnvironment(source_scanner = 'should_not_find_this')
2834 t = env.Command(target='file.out', source='file.in',
2836 source_scanner = 'fake')[0]
2837 assert t.builder.source_scanner == 'fake', t.builder.source_scanner
2839 def test_Configure(self):
2840 """Test the Configure() method"""
2841 # Configure() will write to a local temporary file.
2842 test = TestCmd.TestCmd(workdir = '')
2846 os.chdir(test.workpath())
2848 env = self.TestEnvironment(FOO = 'xyzzy')
2854 assert c is not None, c
2857 c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
2858 assert c is not None, c
2859 assert hasattr(c, 'foo')
2860 assert hasattr(c, 'xyzzy')
2865 def test_Depends(self):
2866 """Test the explicit Depends method."""
2867 env = self.TestEnvironment(FOO = 'xxx', BAR='yyy')
2872 t = env.Depends(target='EnvironmentTest.py',
2873 dependency='Environment.py')[0]
2874 assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2875 assert t.path == 'EnvironmentTest.py'
2876 assert len(t.depends) == 1
2878 assert d.__class__.__name__ == 'Entry', d.__class__.__name__
2879 assert d.path == 'Environment.py'
2881 t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0]
2882 assert t.__class__.__name__ == 'File', t.__class__.__name__
2883 assert t.path == 'xxx.py'
2884 assert len(t.depends) == 1
2886 assert d.__class__.__name__ == 'File', d.__class__.__name__
2887 assert d.path == 'yyy.py'
2889 t = env.Depends(target='dir1', dependency='dir2')[0]
2890 assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2891 assert t.path == 'dir1'
2892 assert len(t.depends) == 1
2894 assert d.__class__.__name__ == 'Dir', d.__class__.__name__
2895 assert d.path == 'dir2'
2898 """Test the Dir() method"""
2900 def Dir(self, name):
2901 return 'Dir(%s)' % name
2903 env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir')
2907 assert d == 'Dir(d)', d
2910 assert d == 'Dir(foodir)', d
2912 d = env.Dir('${BAR}_$BAR')
2913 assert d == 'Dir(bardir_bardir)', d
2915 d = env.Dir(['dir1'])
2916 assert d == ['Dir(dir1)'], d
2918 d = env.Dir(['dir1', 'dir2'])
2919 assert d == ['Dir(dir1)', 'Dir(dir2)'], d
2921 def test_NoClean(self):
2922 """Test the NoClean() method"""
2923 env = self.TestEnvironment(FOO='ggg', BAR='hhh')
2926 t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2928 assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2929 assert t[0].path == 'p_a'
2931 assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2932 assert t[1].path == 'p_hhhb'
2934 assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2935 assert t[2].path == 'p_c'
2937 assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2938 assert t[3].path == 'p_d'
2940 assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2941 assert t[4].path == 'p_ggg'
2944 def test_Dump(self):
2945 """Test the Dump() method"""
2947 env = self.TestEnvironment(FOO = 'foo')
2948 assert env.Dump('FOO') == "'foo'", env.Dump('FOO')
2949 assert len(env.Dump()) > 200, env.Dump() # no args version
2951 def test_Environment(self):
2952 """Test the Environment() method"""
2953 env = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy')
2955 e2 = env.Environment(X = '$FOO', Y = '$BAR')
2956 assert e2['X'] == 'xxx', e2['X']
2957 assert e2['Y'] == 'yyy', e2['Y']
2959 def test_Execute(self):
2960 """Test the Execute() method"""
2963 def __init__(self, *args, **kw):
2965 def __call__(self, target, source, env):
2966 return "%s executed" % self.args
2969 env.Action = MyAction
2971 result = env.Execute("foo")
2972 assert result == "foo executed", result
2974 def test_Entry(self):
2975 """Test the Entry() method"""
2977 def Entry(self, name):
2978 return 'Entry(%s)' % name
2980 env = self.TestEnvironment(FOO = 'fooentry', BAR = 'barentry')
2984 assert e == 'Entry(e)', e
2986 e = env.Entry('$FOO')
2987 assert e == 'Entry(fooentry)', e
2989 e = env.Entry('${BAR}_$BAR')
2990 assert e == 'Entry(barentry_barentry)', e
2992 e = env.Entry(['entry1'])
2993 assert e == ['Entry(entry1)'], e
2995 e = env.Entry(['entry1', 'entry2'])
2996 assert e == ['Entry(entry1)', 'Entry(entry2)'], e
2998 def test_File(self):
2999 """Test the File() method"""
3001 def File(self, name):
3002 return 'File(%s)' % name
3004 env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile')
3008 assert f == 'File(f)', f
3010 f = env.File('$FOO')
3011 assert f == 'File(foofile)', f
3013 f = env.File('${BAR}_$BAR')
3014 assert f == 'File(barfile_barfile)', f
3016 f = env.File(['file1'])
3017 assert f == ['File(file1)'], f
3019 f = env.File(['file1', 'file2'])
3020 assert f == ['File(file1)', 'File(file2)'], f
3022 def test_FindFile(self):
3023 """Test the FindFile() method"""
3024 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
3026 r = env.FindFile('foo', ['no_such_directory'])
3031 def test_Flatten(self):
3032 """Test the Flatten() method"""
3034 l = env.Flatten([1])
3036 l = env.Flatten([1, [2, [3, [4]]]])
3037 assert l == [1, 2, 3, 4], l
3039 def test_GetBuildPath(self):
3040 """Test the GetBuildPath() method."""
3041 env = self.TestEnvironment(MAGIC = 'xyzzy')
3043 p = env.GetBuildPath('foo')
3044 assert p == 'foo', p
3046 p = env.GetBuildPath('$MAGIC')
3047 assert p == 'xyzzy', p
3049 def test_Ignore(self):
3050 """Test the explicit Ignore method."""
3051 env = self.TestEnvironment(FOO='yyy', BAR='zzz')
3057 t = env.Ignore(target='targ.py', dependency='dep.py')[0]
3058 assert t.__class__.__name__ == 'Entry', t.__class__.__name__
3059 assert t.path == 'targ.py'
3060 assert len(t.ignore) == 1
3062 assert i.__class__.__name__ == 'Entry', i.__class__.__name__
3063 assert i.path == 'dep.py'
3065 t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0]
3066 assert t.__class__.__name__ == 'File', t.__class__.__name__
3067 assert t.path == 'yyyzzz'
3068 assert len(t.ignore) == 1
3070 assert i.__class__.__name__ == 'File', i.__class__.__name__
3071 assert i.path == 'zzzyyy'
3073 t = env.Ignore(target='dir1', dependency='dir2')[0]
3074 assert t.__class__.__name__ == 'Dir', t.__class__.__name__
3075 assert t.path == 'dir1'
3076 assert len(t.ignore) == 1
3078 assert i.__class__.__name__ == 'Dir', i.__class__.__name__
3079 assert i.path == 'dir2'
3081 def test_Literal(self):
3082 """Test the Literal() method"""
3083 env = self.TestEnvironment(FOO='fff', BAR='bbb')
3084 list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0]
3085 assert list == ['$FOO', 'bbb'], list
3086 list = env.subst_list(['$FOO', env.Literal('$BAR')])[0]
3087 assert list == ['fff', '$BAR'], list
3089 def test_Local(self):
3090 """Test the Local() method."""
3091 env = self.TestEnvironment(FOO='lll')
3093 l = env.Local(env.fs.File('fff'))
3094 assert str(l[0]) == 'fff', l[0]
3096 l = env.Local('ggg', '$FOO')
3097 assert str(l[0]) == 'ggg', l[0]
3098 assert str(l[1]) == 'lll', l[1]
3100 def test_Precious(self):
3101 """Test the Precious() method"""
3102 env = self.TestEnvironment(FOO='ggg', BAR='hhh')
3105 t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
3107 assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
3108 assert t[0].path == 'p_a'
3109 assert t[0].precious
3110 assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
3111 assert t[1].path == 'p_hhhb'
3112 assert t[1].precious
3113 assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
3114 assert t[2].path == 'p_c'
3115 assert t[2].precious
3116 assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
3117 assert t[3].path == 'p_d'
3118 assert t[3].precious
3119 assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
3120 assert t[4].path == 'p_ggg'
3121 assert t[4].precious
3123 def test_Repository(self):
3124 """Test the Repository() method."""
3128 def Repository(self, *dirs):
3129 self.list.extend(list(dirs))
3130 def Dir(self, name):
3132 env = self.TestEnvironment(FOO='rrr', BAR='sss')
3134 env.Repository('/tmp/foo')
3135 env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
3136 expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
3137 assert env.fs.list == expect, env.fs.list
3139 def test_Scanner(self):
3140 """Test the Scanner() method"""
3141 def scan(node, env, target, arg):
3144 env = self.TestEnvironment(FOO = scan)
3146 s = env.Scanner('foo')
3147 assert s is not None, s
3149 s = env.Scanner(function = 'foo')
3150 assert s is not None, s
3153 s = env.Scanner('$FOO')
3154 assert s is not None, s
3156 s = env.Scanner(function = '$FOO')
3157 assert s is not None, s
3159 def test_SConsignFile(self):
3160 """Test the SConsignFile() method"""
3161 import SCons.SConsign
3164 SConstruct_dir = os.sep + 'dir'
3166 env = self.TestEnvironment(FOO = 'SConsign',
3167 BAR = os.path.join(os.sep, 'File'))
3169 env.Execute = lambda action: None
3174 def capture(name, dbm_module, fnames=fnames, dbms=dbms):
3176 dbms.append(dbm_module)
3178 save_SConsign_File = SCons.SConsign.File
3179 SCons.SConsign.File = capture
3181 env.SConsignFile('foo')
3182 assert fnames[-1] == os.path.join(os.sep, 'dir', 'foo'), fnames
3183 assert dbms[-1] is None, dbms
3185 env.SConsignFile('$FOO')
3186 assert fnames[-1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
3187 assert dbms[-1] is None, dbms
3189 env.SConsignFile('/$FOO')
3190 assert fnames[-1] == os.sep + 'SConsign', fnames
3191 assert dbms[-1] is None, dbms
3193 env.SConsignFile(os.sep + '$FOO')
3194 assert fnames[-1] == os.sep + 'SConsign', fnames
3195 assert dbms[-1] is None, dbms
3197 env.SConsignFile('$BAR', 'x')
3198 assert fnames[-1] == os.path.join(os.sep, 'File'), fnames
3199 assert dbms[-1] == 'x', dbms
3201 env.SConsignFile('__$BAR', 7)
3202 assert fnames[-1] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
3203 assert dbms[-1] == 7, dbms
3206 assert fnames[-1] == os.path.join(os.sep, 'dir', '.sconsign'), fnames
3207 assert dbms[-1] is None, dbms
3209 env.SConsignFile(None)
3210 assert fnames[-1] is None, fnames
3211 assert dbms[-1] is None, dbms
3213 SCons.SConsign.File = save_SConsign_File
3215 def test_SideEffect(self):
3216 """Test the SideEffect() method"""
3217 env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb')
3218 env.File('mylll.pdb')
3219 env.Dir('mymmm.pdb')
3221 foo = env.Object('foo.obj', 'foo.cpp')[0]
3222 bar = env.Object('bar.obj', 'bar.cpp')[0]
3223 s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])[0]
3224 assert s.__class__.__name__ == 'Entry', s.__class__.__name__
3225 assert s.path == 'mylib.pdb'
3226 assert s.side_effect
3227 assert foo.side_effects == [s]
3228 assert bar.side_effects == [s]
3230 fff = env.Object('fff.obj', 'fff.cpp')[0]
3231 bbb = env.Object('bbb.obj', 'bbb.cpp')[0]
3232 s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])[0]
3233 assert s.__class__.__name__ == 'File', s.__class__.__name__
3234 assert s.path == 'mylll.pdb'
3235 assert s.side_effect
3236 assert fff.side_effects == [s], fff.side_effects
3237 assert bbb.side_effects == [s], bbb.side_effects
3239 ggg = env.Object('ggg.obj', 'ggg.cpp')[0]
3240 ccc = env.Object('ccc.obj', 'ccc.cpp')[0]
3241 s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])[0]
3242 assert s.__class__.__name__ == 'Dir', s.__class__.__name__
3243 assert s.path == 'mymmm.pdb'
3244 assert s.side_effect
3245 assert ggg.side_effects == [s], ggg.side_effects
3246 assert ccc.side_effects == [s], ccc.side_effects
3248 def test_SourceCode(self):
3249 """Test the SourceCode() method."""
3250 env = self.TestEnvironment(FOO='mmm', BAR='nnn')
3251 e = env.SourceCode('foo', None)[0]
3252 assert e.path == 'foo'
3257 e = env.SourceCode(e, b)[0]
3258 assert e.path == 'foo'
3262 e = env.SourceCode('$BAR$FOO', None)[0]
3263 assert e.path == 'nnnmmm'
3267 def test_SourceSignatures(type):
3268 """Test the SourceSignatures() method"""
3271 env = type.TestEnvironment(M = 'MD5', T = 'timestamp')
3275 env.SourceSignatures('invalid_type')
3276 except SCons.Errors.UserError:
3278 assert exc_caught, "did not catch expected UserError"
3280 env.SourceSignatures('MD5')
3281 assert env.src_sig_type == 'MD5', env.src_sig_type
3283 env.SourceSignatures('$M')
3284 assert env.src_sig_type == 'MD5', env.src_sig_type
3286 env.SourceSignatures('timestamp')
3287 assert env.src_sig_type == 'timestamp', env.src_sig_type
3289 env.SourceSignatures('$T')
3290 assert env.src_sig_type == 'timestamp', env.src_sig_type
3294 save_md5 = SCons.Util.md5
3295 SCons.Util.md5 = None
3297 env.SourceSignatures('MD5')
3298 except SCons.Errors.UserError:
3301 self.fail('Did not catch expected UserError')
3303 SCons.Util.md5 = save_md5
3305 def test_Split(self):
3306 """Test the Split() method"""
3307 env = self.TestEnvironment(FOO='fff', BAR='bbb')
3308 s = env.Split("foo bar")
3309 assert s == ["foo", "bar"], s
3310 s = env.Split("$FOO bar")
3311 assert s == ["fff", "bar"], s
3312 s = env.Split(["foo", "bar"])
3313 assert s == ["foo", "bar"], s
3314 s = env.Split(["foo", "${BAR}-bbb"])
3315 assert s == ["foo", "bbb-bbb"], s
3316 s = env.Split("foo")
3317 assert s == ["foo"], s
3318 s = env.Split("$FOO$BAR")
3319 assert s == ["fffbbb"], s
3321 def test_TargetSignatures(type):
3322 """Test the TargetSignatures() method"""
3325 env = type.TestEnvironment(B = 'build', C = 'content')
3329 env.TargetSignatures('invalid_type')
3330 except SCons.Errors.UserError:
3332 assert exc_caught, "did not catch expected UserError"
3333 assert not hasattr(env, '_build_signature')
3335 env.TargetSignatures('build')
3336 assert env.tgt_sig_type == 'build', env.tgt_sig_type
3338 env.TargetSignatures('$B')
3339 assert env.tgt_sig_type == 'build', env.tgt_sig_type
3341 env.TargetSignatures('content')
3342 assert env.tgt_sig_type == 'content', env.tgt_sig_type
3344 env.TargetSignatures('$C')
3345 assert env.tgt_sig_type == 'content', env.tgt_sig_type
3347 env.TargetSignatures('MD5')
3348 assert env.tgt_sig_type == 'MD5', env.tgt_sig_type
3350 env.TargetSignatures('timestamp')
3351 assert env.tgt_sig_type == 'timestamp', env.tgt_sig_type
3355 save_md5 = SCons.Util.md5
3356 SCons.Util.md5 = None
3358 env.TargetSignatures('MD5')
3359 except SCons.Errors.UserError:
3362 self.fail('Did not catch expected UserError')
3364 env.TargetSignatures('content')
3365 except SCons.Errors.UserError:
3368 self.fail('Did not catch expected UserError')
3370 SCons.Util.md5 = save_md5
3372 def test_Value(self):
3373 """Test creating a Value() object
3377 assert v1.value == 'a', v1.value
3380 v2 = env.Value(value2)
3381 assert v2.value == value2, v2.value
3382 assert v2.value is value2, v2.value
3385 assert v1.value == v2.value
3387 v3 = env.Value('c', 'build-c')
3388 assert v3.value == 'c', v3.value
3392 def test_Environment_global_variable(type):
3393 """Test setting Environment variable to an Environment.Base subclass"""
3394 class MyEnv(SCons.Environment.Base):
3395 def xxx(self, string):
3396 return self.subst(string)
3398 SCons.Environment.Environment = MyEnv
3400 env = SCons.Environment.Environment(FOO = 'foo')
3402 f = env.subst('$FOO')
3403 assert f == 'foo', f
3406 assert f == 'foo', f
3408 def test_bad_keywords(self):
3409 """Test trying to use reserved keywords in an Environment"""
3412 env = self.TestEnvironment(TARGETS = 'targets',
3413 SOURCES = 'sources',
3416 CHANGED_SOURCES = 'changed_sources',
3417 CHANGED_TARGETS = 'changed_targets',
3418 UNCHANGED_SOURCES = 'unchanged_sources',
3419 UNCHANGED_TARGETS = 'unchanged_targets',
3421 bad_msg = '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'
3422 added.append('INIT')
3423 for x in self.reserved_variables:
3424 assert x not in env, env[x]
3426 assert x in env, bad_msg % x
3428 env.Append(TARGETS = 'targets',
3429 SOURCES = 'sources',
3432 CHANGED_SOURCES = 'changed_sources',
3433 CHANGED_TARGETS = 'changed_targets',
3434 UNCHANGED_SOURCES = 'unchanged_sources',
3435 UNCHANGED_TARGETS = 'unchanged_targets',
3437 added.append('APPEND')
3438 for x in self.reserved_variables:
3439 assert x not in env, env[x]
3441 assert x in env, bad_msg % x
3443 env.AppendUnique(TARGETS = 'targets',
3444 SOURCES = 'sources',
3447 CHANGED_SOURCES = 'changed_sources',
3448 CHANGED_TARGETS = 'changed_targets',
3449 UNCHANGED_SOURCES = 'unchanged_sources',
3450 UNCHANGED_TARGETS = 'unchanged_targets',
3451 APPENDUNIQUE = 'appendunique')
3452 added.append('APPENDUNIQUE')
3453 for x in self.reserved_variables:
3454 assert x not in env, env[x]
3456 assert x in env, bad_msg % x
3458 env.Prepend(TARGETS = 'targets',
3459 SOURCES = 'sources',
3462 CHANGED_SOURCES = 'changed_sources',
3463 CHANGED_TARGETS = 'changed_targets',
3464 UNCHANGED_SOURCES = 'unchanged_sources',
3465 UNCHANGED_TARGETS = 'unchanged_targets',
3466 PREPEND = 'prepend')
3467 added.append('PREPEND')
3468 for x in self.reserved_variables:
3469 assert x not in env, env[x]
3471 assert x in env, bad_msg % x
3473 env.Prepend(TARGETS = 'targets',
3474 SOURCES = 'sources',
3477 CHANGED_SOURCES = 'changed_sources',
3478 CHANGED_TARGETS = 'changed_targets',
3479 UNCHANGED_SOURCES = 'unchanged_sources',
3480 UNCHANGED_TARGETS = 'unchanged_targets',
3481 PREPENDUNIQUE = 'prependunique')
3482 added.append('PREPENDUNIQUE')
3483 for x in self.reserved_variables:
3484 assert x not in env, env[x]
3486 assert x in env, bad_msg % x
3488 env.Replace(TARGETS = 'targets',
3489 SOURCES = 'sources',
3492 CHANGED_SOURCES = 'changed_sources',
3493 CHANGED_TARGETS = 'changed_targets',
3494 UNCHANGED_SOURCES = 'unchanged_sources',
3495 UNCHANGED_TARGETS = 'unchanged_targets',
3496 REPLACE = 'replace')
3497 added.append('REPLACE')
3498 for x in self.reserved_variables:
3499 assert x not in env, env[x]
3501 assert x in env, bad_msg % x
3503 copy = env.Clone(TARGETS = 'targets',
3504 SOURCES = 'sources',
3507 CHANGED_SOURCES = 'changed_sources',
3508 CHANGED_TARGETS = 'changed_targets',
3509 UNCHANGED_SOURCES = 'unchanged_sources',
3510 UNCHANGED_TARGETS = 'unchanged_targets',
3512 for x in self.reserved_variables:
3513 assert x not in copy, env[x]
3514 for x in added + ['COPY']:
3515 assert x in copy, bad_msg % x
3517 over = env.Override({'TARGETS' : 'targets',
3518 'SOURCES' : 'sources',
3519 'SOURCE' : 'source',
3520 'TARGET' : 'target',
3521 'CHANGED_SOURCES' : 'changed_sources',
3522 'CHANGED_TARGETS' : 'changed_targets',
3523 'UNCHANGED_SOURCES' : 'unchanged_sources',
3524 'UNCHANGED_TARGETS' : 'unchanged_targets',
3525 'OVERRIDE' : 'override'})
3526 for x in self.reserved_variables:
3527 assert x not in over, over[x]
3528 for x in added + ['OVERRIDE']:
3529 assert x in over, bad_msg % x
3531 def test_parse_flags(self):
3532 '''Test the Base class parse_flags argument'''
3533 # all we have to show is that it gets to MergeFlags internally
3534 env = Environment(tools=[], parse_flags = '-X')
3535 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
3537 env = Environment(tools=[], CCFLAGS=None, parse_flags = '-Y')
3538 assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS']
3540 env = Environment(tools=[], CPPDEFINES = 'FOO', parse_flags = '-std=c99 -X -DBAR')
3541 assert env['CFLAGS'] == ['-std=c99'], env['CFLAGS']
3542 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
3543 assert env['CPPDEFINES'] == ['FOO', 'BAR'], env['CPPDEFINES']
3545 def test_clone_parse_flags(self):
3546 '''Test the env.Clone() parse_flags argument'''
3547 # all we have to show is that it gets to MergeFlags internally
3548 env = Environment(tools = [])
3549 env2 = env.Clone(parse_flags = '-X')
3550 assert 'CCFLAGS' not in env
3551 assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS']
3553 env = Environment(tools = [], CCFLAGS=None)
3554 env2 = env.Clone(parse_flags = '-Y')
3555 assert env['CCFLAGS'] is None, env['CCFLAGS']
3556 assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS']
3558 env = Environment(tools = [], CPPDEFINES = 'FOO')
3559 env2 = env.Clone(parse_flags = '-std=c99 -X -DBAR')
3560 assert 'CFLAGS' not in env
3561 assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS']
3562 assert 'CCFLAGS' not in env
3563 assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS']
3564 assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES']
3565 assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES']
3569 class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture):
3573 env._dict = {'XXX' : 'x', 'YYY' : 'y'}
3574 env2 = OverrideEnvironment(env, {'XXX' : 'x2'})
3575 env3 = OverrideEnvironment(env2, {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'})
3576 self.envs = [ env, env2, env3 ]
3578 def checkpath(self, node, expect):
3579 return str(node) == os.path.normpath(expect)
3581 def test___init__(self):
3582 """Test OverrideEnvironment initialization"""
3583 env, env2, env3 = self.envs
3584 assert env['XXX'] == 'x', env['XXX']
3585 assert env2['XXX'] == 'x2', env2['XXX']
3586 assert env3['XXX'] == 'x3', env3['XXX']
3587 assert env['YYY'] == 'y', env['YYY']
3588 assert env2['YYY'] == 'y', env2['YYY']
3589 assert env3['YYY'] == 'y3', env3['YYY']
3591 def test___delitem__(self):
3592 """Test deleting variables from an OverrideEnvironment"""
3593 env, env2, env3 = self.envs
3596 assert 'XXX' not in env, "env has XXX?"
3597 assert 'XXX' not in env2, "env2 has XXX?"
3598 assert 'XXX' not in env3, "env3 has XXX?"
3601 assert 'YYY' not in env, "env has YYY?"
3602 assert 'YYY' not in env2, "env2 has YYY?"
3603 assert 'YYY' not in env3, "env3 has YYY?"
3606 assert 'ZZZ' not in env, "env has ZZZ?"
3607 assert 'ZZZ' not in env2, "env2 has ZZZ?"
3608 assert 'ZZZ' not in env3, "env3 has ZZZ?"
3611 """Test the OverrideEnvironment get() method"""
3612 env, env2, env3 = self.envs
3613 assert env.get('XXX') == 'x', env.get('XXX')
3614 assert env2.get('XXX') == 'x2', env2.get('XXX')
3615 assert env3.get('XXX') == 'x3', env3.get('XXX')
3616 assert env.get('YYY') == 'y', env.get('YYY')
3617 assert env2.get('YYY') == 'y', env2.get('YYY')
3618 assert env3.get('YYY') == 'y3', env3.get('YYY')
3619 assert env.get('ZZZ') is None, env.get('ZZZ')
3620 assert env2.get('ZZZ') is None, env2.get('ZZZ')
3621 assert env3.get('ZZZ') == 'z3', env3.get('ZZZ')
3623 def test_has_key(self):
3624 """Test the OverrideEnvironment has_key() method"""
3625 env, env2, env3 = self.envs
3626 assert 'XXX' in env, 'XXX' in env
3627 assert 'XXX' in env2, 'XXX' in env2
3628 assert 'XXX' in env3, 'XXX' in env3
3629 assert 'YYY' in env, 'YYY' in env
3630 assert 'YYY' in env2, 'YYY' in env2
3631 assert 'YYY' in env3, 'YYY' in env3
3632 assert 'ZZZ' not in env, 'ZZZ' in env
3633 assert 'ZZZ' not in env2, 'ZZZ' in env2
3634 assert 'ZZZ' in env3, 'ZZZ' in env3
3636 def test_contains(self):
3637 """Test the OverrideEnvironment __contains__() method"""
3642 # An early version of Python that doesn't support "in"
3643 # on dictionaries. Just pass the test.
3646 env, env2, env3 = self.envs
3648 assert 'XXX' in env2
3649 assert 'XXX' in env3
3651 assert 'YYY' in env2
3652 assert 'YYY' in env3
3653 assert not 'ZZZ' in env
3654 assert not 'ZZZ' in env2
3655 assert 'ZZZ' in env3
3657 def test_items(self):
3658 """Test the OverrideEnvironment Dictionary() method"""
3659 env, env2, env3 = self.envs
3660 items = env.Dictionary()
3661 assert items == {'XXX' : 'x', 'YYY' : 'y'}, items
3662 items = env2.Dictionary()
3663 assert items == {'XXX' : 'x2', 'YYY' : 'y'}, items
3664 items = env3.Dictionary()
3665 assert items == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, items
3667 def test_items(self):
3668 """Test the OverrideEnvironment items() method"""
3669 env, env2, env3 = self.envs
3672 assert items == [('XXX', 'x'), ('YYY', 'y')], items
3673 items = env2.items()
3675 assert items == [('XXX', 'x2'), ('YYY', 'y')], items
3676 items = env3.items()
3678 assert items == [('XXX', 'x3'), ('YYY', 'y3'), ('ZZZ', 'z3')], items
3680 def test_gvars(self):
3681 """Test the OverrideEnvironment gvars() method"""
3682 env, env2, env3 = self.envs
3684 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3685 gvars = env2.gvars()
3686 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3687 gvars = env3.gvars()
3688 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3690 def test_lvars(self):
3691 """Test the OverrideEnvironment lvars() method"""
3692 env, env2, env3 = self.envs
3694 assert lvars == {}, lvars
3695 lvars = env2.lvars()
3696 assert lvars == {'XXX' : 'x2'}, lvars
3697 lvars = env3.lvars()
3698 assert lvars == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, lvars
3700 def test_Replace(self):
3701 """Test the OverrideEnvironment Replace() method"""
3702 env, env2, env3 = self.envs
3703 assert env['XXX'] == 'x', env['XXX']
3704 assert env2['XXX'] == 'x2', env2['XXX']
3705 assert env3['XXX'] == 'x3', env3['XXX']
3706 assert env['YYY'] == 'y', env['YYY']
3707 assert env2['YYY'] == 'y', env2['YYY']
3708 assert env3['YYY'] == 'y3', env3['YYY']
3710 env.Replace(YYY = 'y4')
3712 assert env['XXX'] == 'x', env['XXX']
3713 assert env2['XXX'] == 'x2', env2['XXX']
3714 assert env3['XXX'] == 'x3', env3['XXX']
3715 assert env['YYY'] == 'y4', env['YYY']
3716 assert env2['YYY'] == 'y4', env2['YYY']
3717 assert env3['YYY'] == 'y3', env3['YYY']
3719 # Tests a number of Base methods through an OverrideEnvironment to
3720 # make sure they handle overridden constructionv variables properly.
3722 # The following Base methods also call self.subst(), and so could
3723 # theoretically be subject to problems with evaluating overridden
3724 # variables, but they're never really called that way in the rest
3725 # of our code, so we won't worry about them (at least for now):
3740 # SourceSignatures()
3741 # TargetSignatures()
3743 # It's unlikely Clone() will ever be called this way, so let the
3744 # other methods test that handling overridden values works.
3745 #def test_Clone(self):
3746 # """Test the OverrideEnvironment Clone() method"""
3749 def test_FindIxes(self):
3750 """Test the OverrideEnvironment FindIxes() method"""
3751 env, env2, env3 = self.envs
3752 x = env.FindIxes(['xaaay'], 'XXX', 'YYY')
3753 assert x == 'xaaay', x
3754 x = env2.FindIxes(['x2aaay'], 'XXX', 'YYY')
3755 assert x == 'x2aaay', x
3756 x = env3.FindIxes(['x3aaay3'], 'XXX', 'YYY')
3757 assert x == 'x3aaay3', x
3759 def test_ReplaceIxes(self):
3760 """Test the OverrideEnvironment ReplaceIxes() method"""
3761 env, env2, env3 = self.envs
3762 x = env.ReplaceIxes('xaaay', 'XXX', 'YYY', 'YYY', 'XXX')
3763 assert x == 'yaaax', x
3764 x = env2.ReplaceIxes('x2aaay', 'XXX', 'YYY', 'YYY', 'XXX')
3765 assert x == 'yaaax2', x
3766 x = env3.ReplaceIxes('x3aaay3', 'XXX', 'YYY', 'YYY', 'XXX')
3767 assert x == 'y3aaax3', x
3769 # It's unlikely WhereIs() will ever be called this way, so let the
3770 # other methods test that handling overridden values works.
3771 #def test_WhereIs(self):
3772 # """Test the OverrideEnvironment WhereIs() method"""
3776 """Test the OverrideEnvironment Dir() method"""
3777 env, env2, env3 = self.envs
3778 x = env.Dir('ddir/$XXX')
3779 assert self.checkpath(x, 'ddir/x'), str(x)
3780 x = env2.Dir('ddir/$XXX')
3781 assert self.checkpath(x, 'ddir/x2'), str(x)
3782 x = env3.Dir('ddir/$XXX')
3783 assert self.checkpath(x, 'ddir/x3'), str(x)
3785 def test_Entry(self):
3786 """Test the OverrideEnvironment Entry() method"""
3787 env, env2, env3 = self.envs
3788 x = env.Entry('edir/$XXX')
3789 assert self.checkpath(x, 'edir/x'), str(x)
3790 x = env2.Entry('edir/$XXX')
3791 assert self.checkpath(x, 'edir/x2'), str(x)
3792 x = env3.Entry('edir/$XXX')
3793 assert self.checkpath(x, 'edir/x3'), str(x)
3795 def test_File(self):
3796 """Test the OverrideEnvironment File() method"""
3797 env, env2, env3 = self.envs
3798 x = env.File('fdir/$XXX')
3799 assert self.checkpath(x, 'fdir/x'), str(x)
3800 x = env2.File('fdir/$XXX')
3801 assert self.checkpath(x, 'fdir/x2'), str(x)
3802 x = env3.File('fdir/$XXX')
3803 assert self.checkpath(x, 'fdir/x3'), str(x)
3805 def test_Split(self):
3806 """Test the OverrideEnvironment Split() method"""
3807 env, env2, env3 = self.envs
3808 env['AAA'] = '$XXX $YYY $ZZZ'
3809 x = env.Split('$AAA')
3810 assert x == ['x', 'y'], x
3811 x = env2.Split('$AAA')
3812 assert x == ['x2', 'y'], x
3813 x = env3.Split('$AAA')
3814 assert x == ['x3', 'y3', 'z3'], x
3816 def test_parse_flags(self):
3817 '''Test the OverrideEnvironment parse_flags argument'''
3818 # all we have to show is that it gets to MergeFlags internally
3819 env = SubstitutionEnvironment()
3820 env2 = env.Override({'parse_flags' : '-X'})
3821 assert 'CCFLAGS' not in env
3822 assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS']
3824 env = SubstitutionEnvironment(CCFLAGS=None)
3825 env2 = env.Override({'parse_flags' : '-Y'})
3826 assert env['CCFLAGS'] is None, env['CCFLAGS']
3827 assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS']
3829 env = SubstitutionEnvironment(CPPDEFINES = 'FOO')
3830 env2 = env.Override({'parse_flags' : '-std=c99 -X -DBAR'})
3831 assert 'CFLAGS' not in env
3832 assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS']
3833 assert 'CCFLAGS' not in env
3834 assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS']
3835 assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES']
3836 assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES']
3840 class NoSubstitutionProxyTestCase(unittest.TestCase,TestEnvironmentFixture):
3842 def test___init__(self):
3843 """Test NoSubstitutionProxy initialization"""
3844 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3845 assert env['XXX'] == 'x', env['XXX']
3846 assert env['YYY'] == 'y', env['YYY']
3848 proxy = NoSubstitutionProxy(env)
3849 assert proxy['XXX'] == 'x', proxy['XXX']
3850 assert proxy['YYY'] == 'y', proxy['YYY']
3852 def test_attributes(self):
3853 """Test getting and setting NoSubstitutionProxy attributes"""
3855 setattr(env, 'env_attr', 'value1')
3857 proxy = NoSubstitutionProxy(env)
3858 setattr(proxy, 'proxy_attr', 'value2')
3860 x = getattr(env, 'env_attr')
3861 assert x == 'value1', x
3862 x = getattr(proxy, 'env_attr')
3863 assert x == 'value1', x
3865 x = getattr(env, 'proxy_attr')
3866 assert x == 'value2', x
3867 x = getattr(proxy, 'proxy_attr')
3868 assert x == 'value2', x
3870 def test_subst(self):
3871 """Test the NoSubstitutionProxy.subst() method"""
3872 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3873 assert env['XXX'] == 'x', env['XXX']
3874 assert env['YYY'] == 'y', env['YYY']
3876 proxy = NoSubstitutionProxy(env)
3877 assert proxy['XXX'] == 'x', proxy['XXX']
3878 assert proxy['YYY'] == 'y', proxy['YYY']
3880 x = env.subst('$XXX')
3882 x = proxy.subst('$XXX')
3883 assert x == '$XXX', x
3885 x = proxy.subst('$YYY', raw=7, target=None, source=None,
3887 extra_meaningless_keyword_argument=None)
3888 assert x == '$YYY', x
3890 def test_subst_kw(self):
3891 """Test the NoSubstitutionProxy.subst_kw() method"""
3892 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3893 assert env['XXX'] == 'x', env['XXX']
3894 assert env['YYY'] == 'y', env['YYY']
3896 proxy = NoSubstitutionProxy(env)
3897 assert proxy['XXX'] == 'x', proxy['XXX']
3898 assert proxy['YYY'] == 'y', proxy['YYY']
3900 x = env.subst_kw({'$XXX':'$YYY'})
3901 assert x == {'x':'y'}, x
3902 x = proxy.subst_kw({'$XXX':'$YYY'})
3903 assert x == {'$XXX':'$YYY'}, x
3905 def test_subst_list(self):
3906 """Test the NoSubstitutionProxy.subst_list() method"""
3907 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3908 assert env['XXX'] == 'x', env['XXX']
3909 assert env['YYY'] == 'y', env['YYY']
3911 proxy = NoSubstitutionProxy(env)
3912 assert proxy['XXX'] == 'x', proxy['XXX']
3913 assert proxy['YYY'] == 'y', proxy['YYY']
3915 x = env.subst_list('$XXX')
3916 assert x == [['x']], x
3917 x = proxy.subst_list('$XXX')
3920 x = proxy.subst_list('$YYY', raw=0, target=None, source=None, conv=None)
3923 def test_subst_target_source(self):
3924 """Test the NoSubstitutionProxy.subst_target_source() method"""
3925 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3926 assert env['XXX'] == 'x', env['XXX']
3927 assert env['YYY'] == 'y', env['YYY']
3929 proxy = NoSubstitutionProxy(env)
3930 assert proxy['XXX'] == 'x', proxy['XXX']
3931 assert proxy['YYY'] == 'y', proxy['YYY']
3933 args = ('$XXX $TARGET $SOURCE $YYY',)
3934 kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')}
3935 x = env.subst_target_source(*args, **kw)
3936 assert x == 'x ttt sss y', x
3937 x = proxy.subst_target_source(*args, **kw)
3938 assert x == ' ttt sss ', x
3940 class EnvironmentVariableTestCase(unittest.TestCase):
3942 def test_is_valid_construction_var(self):
3943 """Testing is_valid_construction_var()"""
3944 r = is_valid_construction_var("_a")
3945 assert r is not None, r
3946 r = is_valid_construction_var("z_")
3947 assert r is not None, r
3948 r = is_valid_construction_var("X_")
3949 assert r is not None, r
3950 r = is_valid_construction_var("2a")
3952 r = is_valid_construction_var("a2_")
3953 assert r is not None, r
3954 r = is_valid_construction_var("/")
3956 r = is_valid_construction_var("_/")
3958 r = is_valid_construction_var("a/")
3960 r = is_valid_construction_var(".b")
3962 r = is_valid_construction_var("_.b")
3964 r = is_valid_construction_var("b1._")
3966 r = is_valid_construction_var("-b")
3968 r = is_valid_construction_var("_-b")
3970 r = is_valid_construction_var("b1-_")
3975 if __name__ == "__main__":
3976 suite = unittest.TestSuite()
3977 tclasses = [ SubstitutionTestCase,
3979 OverrideEnvironmentTestCase,
3980 NoSubstitutionProxyTestCase,
3981 EnvironmentVariableTestCase ]
3982 for tclass in tclasses:
3983 names = unittest.getTestCaseNames(tclass, 'test_')
3984 suite.addTests(list(map(tclass, names)))
3985 if not unittest.TextTestRunner().run(suite).wasSuccessful():
3990 # indent-tabs-mode:nil
3992 # vim: set expandtab tabstop=4 shiftwidth=4: