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__"
35 from SCons.Environment import *
38 def diff_env(env1, env2):
42 for k in env1._dict.keys() + env2._dict.keys():
49 if env1[k] != env2[k]:
50 s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n"
51 s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n"
53 s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n"
55 s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n"
60 def diff_dict(d1, d2):
64 for k in d1.keys() + d2.keys():
72 s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n"
73 s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n"
75 s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n"
77 s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n"
86 """A dummy Builder class for testing purposes. "Building"
87 a target is simply setting a value in the dictionary.
89 def __init__(self, name = None):
92 def __call__(self, env, target=None, source=None, **kw):
94 called_it['target'] = target
95 called_it['source'] = source
98 def execute(self, target = None, **kw):
107 """A dummy Scanner class for testing purposes. "Scanning"
108 a target is simply setting a value in the dictionary.
110 def __init__(self, name, skeys=[]):
114 def __call__(self, filename):
116 scanned_it[filename] = 1
118 def __cmp__(self, other):
120 return cmp(self.__dict__, other.__dict__)
121 except AttributeError:
124 def get_skeys(self, env):
132 class CLVar(UserList.UserList):
133 def __init__(self, seq):
134 if type(seq) == type(''):
135 seq = string.split(seq)
136 UserList.UserList.__init__(self, seq)
137 def __coerce__(self, other):
138 return (self, CLVar(other))
143 def __init__(self, name):
149 def get_subst_proxy(self):
152 def test_tool( env ):
153 env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
155 class TestEnvironmentFixture:
156 def TestEnvironment(self, *args, **kw):
157 if not kw or not kw.has_key('tools'):
158 kw['tools'] = [test_tool]
159 default_keys = { 'CC' : 'cc',
160 'CCFLAGS' : '-DNDEBUG',
161 'ENV' : { 'TMP' : '/tmp' } }
162 for key, value in default_keys.items():
163 if not kw.has_key(key):
165 if not kw.has_key('BUILDERS'):
166 static_obj = SCons.Builder.Builder(action = {},
170 kw['BUILDERS'] = {'Object' : static_obj}
172 env = apply(Environment, args, kw)
175 class SubstitutionTestCase(unittest.TestCase):
177 def test___init__(self):
178 """Test initializing a SubstitutionEnvironment
180 env = SubstitutionEnvironment()
181 assert not env.has_key('__env__')
183 def test___cmp__(self):
184 """Test comparing SubstitutionEnvironments
187 env1 = SubstitutionEnvironment(XXX = 'x')
188 env2 = SubstitutionEnvironment(XXX = 'x')
189 env3 = SubstitutionEnvironment(XXX = 'xxx')
190 env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x')
196 def test___delitem__(self):
197 """Test deleting a variable from a SubstitutionEnvironment
199 env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
200 env2 = SubstitutionEnvironment(XXX = 'x')
204 def test___getitem__(self):
205 """Test fetching a variable from a SubstitutionEnvironment
207 env = SubstitutionEnvironment(XXX = 'x')
208 assert env['XXX'] == 'x', env['XXX']
210 def test___setitem__(self):
211 """Test setting a variable in a SubstitutionEnvironment
213 env1 = SubstitutionEnvironment(XXX = 'x')
214 env2 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
219 """Test the SubstitutionEnvironment get() method
221 env = SubstitutionEnvironment(XXX = 'x')
222 assert env.get('XXX') == 'x', env.get('XXX')
223 assert env.get('YYY') is None, env.get('YYY')
225 def test_has_key(self):
226 """Test the SubstitutionEnvironment has_key() method
228 env = SubstitutionEnvironment(XXX = 'x')
229 assert env.has_key('XXX')
230 assert not env.has_key('YYY')
232 def test_items(self):
233 """Test the SubstitutionEnvironment items() method
235 env = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
237 assert items == [('XXX','x'), ('YYY','y')], items
239 def test_arg2nodes(self):
240 """Test the arg2nodes method
242 env = SubstitutionEnvironment()
244 class X(SCons.Node.Node):
246 def Factory(name, directory = None, create = 1, dict=dict, X=X):
247 if not dict.has_key(name):
249 dict[name].name = name
252 nodes = env.arg2nodes("Util.py UtilTests.py", Factory)
253 assert len(nodes) == 1, nodes
254 assert isinstance(nodes[0], X)
255 assert nodes[0].name == "Util.py UtilTests.py"
258 if hasattr(types, 'UnicodeType'):
260 nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
261 assert len(nodes) == 1, nodes
262 assert isinstance(nodes[0], X)
263 assert nodes[0].name == u"Util.py UtilTests.py"
265 exec code in globals(), locals()
267 nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
268 assert len(nodes) == 2, nodes
269 assert isinstance(nodes[0], X)
270 assert isinstance(nodes[1], X)
271 assert nodes[0].name == "Util.py"
272 assert nodes[1].name == "UtilTests.py"
274 n1 = Factory("Util.py")
275 nodes = env.arg2nodes([n1, "UtilTests.py"], Factory)
276 assert len(nodes) == 2, nodes
277 assert isinstance(nodes[0], X)
278 assert isinstance(nodes[1], X)
279 assert nodes[0].name == "Util.py"
280 assert nodes[1].name == "UtilTests.py"
282 class SConsNode(SCons.Node.Node):
284 nodes = env.arg2nodes(SConsNode())
285 assert len(nodes) == 1, nodes
286 assert isinstance(nodes[0], SConsNode), node
290 nodes = env.arg2nodes(OtherNode())
291 assert len(nodes) == 1, nodes
292 assert isinstance(nodes[0], OtherNode), node
294 def lookup_a(str, F=Factory):
302 def lookup_b(str, F=Factory):
310 env_ll = SubstitutionEnvironment()
311 env_ll.lookup_list = [lookup_a, lookup_b]
313 nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
314 assert len(nodes) == 3, nodes
316 assert nodes[0].name == 'aaa', nodes[0]
317 assert nodes[0].a == 1, nodes[0]
318 assert not hasattr(nodes[0], 'b'), nodes[0]
320 assert nodes[1].name == 'bbb'
321 assert not hasattr(nodes[1], 'a'), nodes[1]
322 assert nodes[1].b == 1, nodes[1]
324 assert nodes[2].name == 'ccc'
325 assert not hasattr(nodes[2], 'a'), nodes[1]
326 assert not hasattr(nodes[2], 'b'), nodes[1]
328 def lookup_bbbb(str, F=Factory):
336 def lookup_c(str, F=Factory):
344 nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
345 [lookup_c, lookup_bbbb, lookup_b])
346 assert len(nodes) == 2, nodes
348 assert nodes[0].name == 'bbbb'
349 assert not hasattr(nodes[0], 'a'), nodes[1]
350 assert not hasattr(nodes[0], 'b'), nodes[1]
351 assert nodes[0].bbbb == 1, nodes[1]
352 assert not hasattr(nodes[0], 'c'), nodes[0]
354 assert nodes[1].name == 'ccc'
355 assert not hasattr(nodes[1], 'a'), nodes[1]
356 assert not hasattr(nodes[1], 'b'), nodes[1]
357 assert not hasattr(nodes[1], 'bbbb'), nodes[0]
358 assert nodes[1].c == 1, nodes[1]
360 def test_gvars(self):
361 """Test the base class gvars() method"""
362 env = SubstitutionEnvironment()
364 assert gvars == {}, gvars
366 def test_lvars(self):
367 """Test the base class lvars() method"""
368 env = SubstitutionEnvironment()
370 assert lvars == {}, lvars
372 def test_subst(self):
373 """Test substituting construction variables within strings
375 Check various combinations, including recursive expansion
376 of variables into other variables.
378 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
379 mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
380 assert mystr == "a aA b", mystr
382 # Changed the tests below to reflect a bug fix in
384 env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
385 mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
386 assert mystr == "b bA bB b", mystr
388 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
389 mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
390 assert mystr == "c cA cB c", mystr
393 env = SubstitutionEnvironment(AAA = ['a', 'aa', 'aaa'])
394 mystr = env.subst("$AAA")
395 assert mystr == "a aa aaa", mystr
398 env = SubstitutionEnvironment(AAA = ('a', 'aa', 'aaa'))
399 mystr = env.subst("$AAA")
400 assert mystr == "a aa aaa", mystr
407 env = SubstitutionEnvironment(AAA = 'aaa')
408 s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
409 assert s == "aaa t1 s1 s2", s
410 s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
411 assert s == "aaa t1 t2 s1", s
413 # Test callables in the SubstitutionEnvironment
414 def foo(target, source, env, for_signature):
415 assert str(target) == 't', target
416 assert str(source) == 's', source
419 env = SubstitutionEnvironment(BAR=foo, FOO='baz')
423 subst = env.subst('test $BAR', target=t, source=s)
424 assert subst == 'test baz', subst
426 # Test not calling callables in the SubstitutionEnvironment
428 # This will take some serious surgery to subst() and
429 # subst_list(), so just leave these tests out until we can
434 env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
436 subst = env.subst('$BAR', call=None)
437 assert subst is bar, subst
439 subst = env.subst('$FOO', call=None)
440 assert subst is bar, subst
442 def test_subst_kw(self):
443 """Test substituting construction variables within dictionaries"""
444 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
445 kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
446 assert len(kw) == 2, kw
447 assert kw['a'] == 'aaa', kw['a']
448 assert kw['bbb'] == 'b', kw['bbb']
450 def test_subst_list(self):
451 """Test substituting construction variables in command lists
453 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
454 l = env.subst_list("$AAA ${AAA}A $BBBB $BBB")
455 assert l == [["a", "aA", "b"]], l
457 # Changed the tests below to reflect a bug fix in
459 env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
460 l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
461 assert l == [["b", "bA", "bB", "b"]], l
463 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
464 l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
465 assert l == [["c", "cA", "cB", "c"]], mystr
467 env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
468 lst = env.subst_list([ "$AAA", "B $CCC" ])
469 assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst
476 env = SubstitutionEnvironment(AAA = 'aaa')
477 s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
478 assert s == [["aaa", "t1", "s1", "s2"]], s
479 s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
480 assert s == [["aaa", "t1", "t2", "s1"]], s
482 # Test callables in the SubstitutionEnvironment
483 def foo(target, source, env, for_signature):
484 assert str(target) == 't', target
485 assert str(source) == 's', source
488 env = SubstitutionEnvironment(BAR=foo, FOO='baz')
492 lst = env.subst_list('test $BAR', target=t, source=s)
493 assert lst == [['test', 'baz']], lst
495 # Test not calling callables in the SubstitutionEnvironment
497 # This will take some serious surgery to subst() and
498 # subst_list(), so just leave these tests out until we can
503 env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
505 subst = env.subst_list('$BAR', call=None)
506 assert subst is bar, subst
508 subst = env.subst_list('$FOO', call=None)
509 assert subst is bar, subst
511 def test_subst_path(self):
512 """Test substituting a path list
515 def __init__(self, val):
518 return self.val + '-proxy'
521 def __init__(self, val):
523 def get_subst_proxy(self):
531 env = SubstitutionEnvironment(FOO='foo', BAR='bar', PROXY=MyProxy('my1'))
533 r = env.subst_path('$FOO')
534 assert r == ['foo'], r
536 r = env.subst_path(['$FOO', 'xxx', '$BAR'])
537 assert r == ['foo', 'xxx', 'bar'], r
539 r = env.subst_path(['$FOO', '$TARGET', '$SOURCE', '$BAR'])
540 assert r == ['foo', '', '', 'bar'], r
542 r = env.subst_path(['$FOO', '$TARGET', '$BAR'], target=MyNode('ttt'))
543 assert map(str, r) == ['foo', 'ttt', 'bar'], r
545 r = env.subst_path(['$FOO', '$SOURCE', '$BAR'], source=MyNode('sss'))
546 assert map(str, r) == ['foo', 'sss', 'bar'], r
550 r = env.subst_path(['$PROXY', MyProxy('my2'), n])
551 assert r == ['my1-proxy', 'my2-proxy', n], r
554 def __init__(self, s):
559 env = SubstitutionEnvironment(FOO=StringableObj("foo"),
560 BAR=StringableObj("bar"))
562 r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ])
563 assert r == [ "foo/bar", "bar/baz" ]
565 r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ])
566 assert r == [ "bar/foo", "baz/bar" ]
568 r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ])
569 assert r == [ "bar/foo/bar", "baz/bar/baz" ]
571 def test_subst_target_source(self):
572 """Test the base environment subst_target_source() method"""
573 env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
574 mystr = env.subst_target_source("$AAA ${AAA}A $BBBB $BBB")
575 assert mystr == "a aA b", mystr
577 def test_backtick(self):
578 """Test the backtick() method for capturing command output"""
579 env = SubstitutionEnvironment()
581 test = TestCmd.TestCmd(workdir = '')
582 test.write('stdout.py', """\
584 sys.stdout.write('this came from stdout.py\\n')
587 test.write('stderr.py', """\
589 sys.stderr.write('this came from stderr.py\\n')
592 test.write('fail.py', """\
597 save_stderr = sys.stderr
599 python = '"' + sys.executable + '"'
602 cmd = '%s %s' % (python, test.workpath('stdout.py'))
603 output = env.backtick(cmd)
605 assert output == 'this came from stdout.py\n', output
607 sys.stderr = StringIO.StringIO()
609 cmd = '%s %s' % (python, test.workpath('stderr.py'))
610 output = env.backtick(cmd)
611 errout = sys.stderr.getvalue()
613 assert output == '', output
614 assert errout == 'this came from stderr.py\n', errout
616 sys.stderr = StringIO.StringIO()
618 cmd = '%s %s' % (python, test.workpath('fail.py'))
622 assert str(e) == "'%s' exited 1" % cmd, str(e)
624 self.fail("did not catch expected OSError")
627 sys.stderr = save_stderr
629 def test_Override(self):
630 "Test overriding construction variables"
631 env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4)
632 assert env['ONE'] == 1, env['ONE']
633 assert env['TWO'] == 2, env['TWO']
634 assert env['THREE'] == 3, env['THREE']
635 assert env['FOUR'] == 4, env['FOUR']
637 env2 = env.Override({'TWO' : '10',
638 'THREE' :'x $THREE y',
639 'FOUR' : ['x', '$FOUR', 'y']})
640 assert env2['ONE'] == 1, env2['ONE']
641 assert env2['TWO'] == '10', env2['TWO']
642 assert env2['THREE'] == 'x 3 y', env2['THREE']
643 assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR']
645 assert env['ONE'] == 1, env['ONE']
646 assert env['TWO'] == 2, env['TWO']
647 assert env['THREE'] == 3, env['THREE']
648 assert env['FOUR'] == 4, env['FOUR']
650 env2.Replace(ONE = "won")
651 assert env2['ONE'] == "won", env2['ONE']
652 assert env['ONE'] == 1, env['ONE']
654 def test_ParseFlags(self):
655 """Test the ParseFlags() method
657 env = SubstitutionEnvironment()
665 'FRAMEWORKPATH' : [],
673 d = env.ParseFlags(None)
676 d = env.ParseFlags('')
679 d = env.ParseFlags([])
682 s = "-I/usr/include/fum -I bar -X\n" + \
683 "-L/usr/fax -L foo -lxxx -l yyy " + \
684 "-Wa,-as -Wl,-link " + \
685 "-Wl,-rpath=rpath1 " + \
689 "-framework Carbon " + \
690 "-frameworkdir=fwd1 " + \
694 "-mno-cygwin -mwindows " + \
695 "-arch i386 -isysroot /tmp +DD64 " + \
698 d = env.ParseFlags(s)
700 assert d['ASFLAGS'] == ['-as'], d['ASFLAGS']
701 assert d['CCFLAGS'] == ['-X', '-Wa,-as',
702 '-pthread', '-mno-cygwin',
703 ('-arch', 'i386'), ('-isysroot', '/tmp'),
704 '+DD64'], d['CCFLAGS']
705 assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value']], d['CPPDEFINES']
706 assert d['CPPFLAGS'] == ['-Wp,-cpp'], d['CPPFLAGS']
707 assert d['CPPPATH'] == ['/usr/include/fum', 'bar'], d['CPPPATH']
708 assert d['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], d['FRAMEWORKPATH']
709 assert d['FRAMEWORKS'] == ['Carbon'], d['FRAMEWORKS']
710 assert d['LIBPATH'] == ['/usr/fax', 'foo'], d['LIBPATH']
711 assert d['LIBS'] == ['xxx', 'yyy'], d['LIBS']
712 assert d['LINKFLAGS'] == ['-Wl,-link', '-pthread',
713 '-mno-cygwin', '-mwindows',
715 ('-isysroot', '/tmp'),
716 '+DD64'], d['LINKFLAGS']
717 assert d['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], d['RPATH']
720 def test_MergeFlags(self):
721 """Test the MergeFlags() method
723 env = SubstitutionEnvironment()
725 assert env['CCFLAGS'] == [], env['CCFLAGS']
727 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
729 assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
731 env = SubstitutionEnvironment()
732 env.MergeFlags({'A':['aaa'], 'B':['bbb']})
733 assert env['A'] == ['aaa'], env['A']
734 assert env['B'] == ['bbb'], env['B']
738 class BaseTestCase(unittest.TestCase,TestEnvironmentFixture):
740 def test___init__(self):
741 """Test construction Environment creation
743 Create two with identical arguments and check that
744 they compare the same.
746 env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
747 env2 = self.TestEnvironment(XXX = 'x', YYY = 'y')
748 assert env1 == env2, diff_env(env1, env2)
750 assert not env1.has_key('__env__')
751 assert not env2.has_key('__env__')
753 def test_options(self):
754 """Test that options only get applied once."""
756 def __init__(self, key, val):
762 def Update(self, env):
763 env[self.key] = self.val
764 self.calls = self.calls + 1
766 o = FakeOptions('AAA', 'fake_opt')
767 env = Environment(options=o, AAA='keyword_arg')
768 assert o.calls == 1, o.calls
769 assert env['AAA'] == 'fake_opt', env['AAA']
772 """Test the get() method."""
773 env = self.TestEnvironment(aaa = 'AAA')
777 x = env.get('aaa', 'XXX')
781 x = env.get('bbb', 'XXX')
784 def test_Builder_calls(self):
785 """Test Builder calls through different environments
793 env.Replace(BUILDERS = { 'builder1' : b1,
797 assert called_it['target'] == None, called_it
798 assert called_it['source'] == ['in1'], called_it
801 env.builder2(source = 'in2', xyzzy = 1)
802 assert called_it['target'] == None, called_it
803 assert called_it['source'] == ['in2'], called_it
804 assert called_it['xyzzy'] == 1, called_it
807 env.builder1(foo = 'bar')
808 assert called_it['foo'] == 'bar', called_it
809 assert called_it['target'] == None, called_it
810 assert called_it['source'] == None, called_it
814 def test_Builder_execs(self):
815 """Test Builder execution through different environments
817 One environment is initialized with a single
818 Builder object, one with a list of a single Builder
819 object, and one with a list of two Builder objects.
828 env3.Replace(BUILDERS = { 'builder1' : b1,
830 env3.builder1.execute(target = 'out1')
831 env3.builder2.execute(target = 'out2')
832 env3.builder1.execute(target = 'out3')
833 assert built_it['out1']
834 assert built_it['out2']
835 assert built_it['out3']
838 assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
839 assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
841 # Now test BUILDERS as a dictionary.
843 env5 = self.TestEnvironment(BUILDERS={ 'foo' : b1 })
844 env5['BUILDERS']['bar'] = b2
845 env5.foo.execute(target='out1')
846 env5.bar.execute(target='out2')
847 assert built_it['out1']
848 assert built_it['out2']
852 env6['BUILDERS'] = { 'foo' : b1,
854 env6.foo.execute(target='out1')
855 env6.bar.execute(target='out2')
856 assert built_it['out1']
857 assert built_it['out2']
859 def test_Scanners(self):
860 """Test setting SCANNERS in various ways
862 One environment is initialized with a single
863 Scanner object, one with a list of a single Scanner
864 object, and one with a list of two Scanner objects.
868 s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
869 s2 = Scanner(name = 'scanner2', skeys = [".m4"])
870 s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"])
872 # XXX Tests for scanner execution through different environments,
873 # XXX if we ever want to do that some day
875 # env1 = self.TestEnvironment(SCANNERS = s1)
876 # env1.scanner1(filename = 'out1')
877 # assert scanned_it['out1']
880 # env2 = self.TestEnvironment(SCANNERS = [s1])
881 # env1.scanner1(filename = 'out1')
882 # assert scanned_it['out1']
885 # env3 = Environment()
886 # env3.Replace(SCANNERS = [s1])
887 # env3.scanner1(filename = 'out1')
888 # env3.scanner2(filename = 'out2')
889 # env3.scanner1(filename = 'out3')
890 # assert scanned_it['out1']
891 # assert scanned_it['out2']
892 # assert scanned_it['out3']
894 suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"]
897 try: del env['SCANNERS']
898 except KeyError: pass
899 s = map(env.get_scanner, suffixes)
900 assert s == [None, None, None, None, None], s
902 env = self.TestEnvironment(SCANNERS = [])
903 s = map(env.get_scanner, suffixes)
904 assert s == [None, None, None, None, None], s
906 env.Replace(SCANNERS = [s1])
907 s = map(env.get_scanner, suffixes)
908 assert s == [s1, s1, None, None, None], s
910 env.Append(SCANNERS = [s2])
911 s = map(env.get_scanner, suffixes)
912 assert s == [s1, s1, None, s2, None], s
914 env.AppendUnique(SCANNERS = [s3])
915 s = map(env.get_scanner, suffixes)
916 assert s == [s1, s1, None, s2, s3], s
918 env = env.Copy(SCANNERS = [s2])
919 s = map(env.get_scanner, suffixes)
920 assert s == [None, None, None, s2, None], s
922 env['SCANNERS'] = [s1]
923 s = map(env.get_scanner, suffixes)
924 assert s == [s1, s1, None, None, None], s
926 env.PrependUnique(SCANNERS = [s2, s1])
927 s = map(env.get_scanner, suffixes)
928 assert s == [s1, s1, None, s2, None], s
930 env.Prepend(SCANNERS = [s3])
931 s = map(env.get_scanner, suffixes)
932 assert s == [s1, s1, None, s3, s3], s
935 """Test setting the external ENV in Environments
938 assert env.Dictionary().has_key('ENV')
940 env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' })
941 assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
943 def test_ReservedVariables(self):
944 """Test generation of warnings when reserved variable names
945 are set in an environment."""
947 SCons.Warnings.enableWarningClass(SCons.Warnings.ReservedVariableWarning)
948 old = SCons.Warnings.warningAsException(1)
952 for kw in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
956 except SCons.Warnings.ReservedVariableWarning:
958 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw
959 assert not env4.has_key(kw), "`%s' variable was incorrectly set" % kw
961 SCons.Warnings.warningAsException(old)
963 def test_IllegalVariables(self):
964 """Test that use of illegal variables raises an exception"""
966 def test_it(var, env=env):
970 except SCons.Errors.UserError:
972 assert exc_caught, "did not catch UserError for '%s'" % var
974 assert env['aaa'] == 1, env['aaa']
979 def test_autogenerate(dict):
980 """Test autogenerating variables in a dictionary."""
982 drive, p = os.path.splitdrive(os.getcwd())
983 def normalize_path(path, drive=drive):
986 path = os.path.normpath(path)
987 drive, path = os.path.splitdrive(path)
988 return string.lower(drive) + path
990 env = dict.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ],
991 LIBLINKPREFIX = 'foo',
992 LIBLINKSUFFIX = 'bar')
994 def RDirs(pathlist, fs=env.fs):
995 return fs.Rfindalldirs(pathlist, fs.Dir('xx'))
998 flags = env.subst_list('$_LIBFLAGS', 1)[0]
999 assert flags == ['foobar', 'foobar', 'foobazbar'], flags
1001 blat = env.fs.Dir('blat')
1003 env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ],
1007 flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1009 normalize_path('foo'),
1010 normalize_path('xx/foobar'),
1011 normalize_path('foo'),
1012 normalize_path('xx/baz/bar'),
1013 normalize_path('foo'),
1014 normalize_path('blatbar'),
1017 assert flags == expect, flags
1019 env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ],
1023 flags = env.subst_list('$_F77INCFLAGS', 1)[0]
1025 normalize_path('foo'),
1026 normalize_path('xx/foobar'),
1027 normalize_path('foo'),
1028 normalize_path('xx/baz/bar'),
1029 normalize_path('foo'),
1030 normalize_path('blatbar'),
1033 assert flags == expect, flags
1035 env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '')
1036 l = env.subst_list('$_CPPINCFLAGS')
1038 l = env.subst_list('$_F77INCFLAGS')
1040 l = env.subst_list('$_LIBDIRFLAGS')
1043 env.fs.Repository('/rep1')
1044 env.fs.Repository('/rep2')
1045 env.Replace(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
1049 flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1051 '-I', normalize_path('xx/fooXXX'),
1052 '-I', normalize_path('/rep1/xx/fooXXX'),
1053 '-I', normalize_path('/rep2/xx/fooXXX'),
1054 '-I', normalize_path('/a/bXXX'),
1055 '-I', normalize_path('xx/baz/barXXX'),
1056 '-I', normalize_path('/rep1/xx/baz/barXXX'),
1057 '-I', normalize_path('/rep2/xx/baz/barXXX'),
1058 '-I', normalize_path('blatXXX'),
1061 def normalize_if_path(arg, np=normalize_path):
1062 if arg not in ('$(','$)','-I'):
1065 flags = map(normalize_if_path, flags)
1066 assert flags == expect, flags
1068 def test_platform(self):
1069 """Test specifying a platform callable when instantiating."""
1071 def __str__(self): return "TestPlatform"
1072 def __call__(self, env): env['XYZZY'] = 777
1075 env['SET_TOOL'] = 'initialized'
1076 assert env['PLATFORM'] == "TestPlatform"
1078 env = self.TestEnvironment(platform = platform(), tools = [tool])
1079 assert env['XYZZY'] == 777, env
1080 assert env['PLATFORM'] == "TestPlatform"
1081 assert env['SET_TOOL'] == "initialized"
1083 def test_Default_PLATFORM(self):
1084 """Test overriding the default PLATFORM variable"""
1086 def __str__(self): return "DefaultTestPlatform"
1087 def __call__(self, env): env['XYZZY'] = 888
1090 env['SET_TOOL'] = 'abcde'
1091 assert env['PLATFORM'] == "DefaultTestPlatform"
1093 import SCons.Defaults
1094 save = SCons.Defaults.ConstructionEnvironment.copy()
1096 import SCons.Defaults
1097 SCons.Defaults.ConstructionEnvironment.update({
1098 'PLATFORM' : platform(),
1100 env = self.TestEnvironment(tools = [tool])
1101 assert env['XYZZY'] == 888, env
1102 assert env['PLATFORM'] == "DefaultTestPlatform"
1103 assert env['SET_TOOL'] == "abcde"
1105 SCons.Defaults.ConstructionEnvironment = save
1107 def test_tools(self):
1108 """Test specifying a tool callable when instantiating."""
1114 env['AAA'] = env['XYZ']
1117 env = self.TestEnvironment(tools = [t1, t2, t3], XYZ = 'aaa')
1118 assert env['TOOL1'] == 111, env['TOOL1']
1119 assert env['TOOL2'] == 222, env
1120 assert env['AAA'] == 'aaa', env
1122 assert env['TOOL4'] == 444, env
1124 test = TestCmd.TestCmd(workdir = '')
1125 test.write('faketool.py', """\
1126 def generate(env, **kw):
1127 for k, v in kw.items():
1134 env = self.TestEnvironment(tools = [('faketool', {'a':1, 'b':2, 'c':3})],
1135 toolpath = [test.workpath('')])
1136 assert env['a'] == 1, env['a']
1137 assert env['b'] == 2, env['b']
1138 assert env['c'] == 3, env['c']
1140 def test_Default_TOOLS(self):
1141 """Test overriding the default TOOLS variable"""
1147 env['BBB'] = env['XYZ']
1151 import SCons.Defaults
1152 save = SCons.Defaults.ConstructionEnvironment.copy()
1154 SCons.Defaults.ConstructionEnvironment.update({
1155 'TOOLS' : [t5, t6, t7],
1157 env = Environment(XYZ = 'bbb')
1158 assert env['TOOL5'] == 555, env['TOOL5']
1159 assert env['TOOL6'] == 666, env
1160 assert env['BBB'] == 'bbb', env
1162 assert env['TOOL8'] == 888, env
1164 SCons.Defaults.ConstructionEnvironment = save
1166 def test_null_tools(self):
1167 """Test specifying a tool of None is OK."""
1172 env = self.TestEnvironment(tools = [t1, None, t2], XYZ = 'aaa')
1173 assert env['TOOL1'] == 111, env['TOOL1']
1174 assert env['TOOL2'] == 222, env
1175 assert env['XYZ'] == 'aaa', env
1176 env = self.TestEnvironment(tools = [None], XYZ = 'xyz')
1177 assert env['XYZ'] == 'xyz', env
1178 env = self.TestEnvironment(tools = [t1, '', t2], XYZ = 'ddd')
1179 assert env['TOOL1'] == 111, env['TOOL1']
1180 assert env['TOOL2'] == 222, env
1181 assert env['XYZ'] == 'ddd', env
1183 def test_concat(self):
1185 e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
1187 x = s("${_concat('', '', '', __env__)}")
1189 x = s("${_concat('', [], '', __env__)}")
1191 x = s("${_concat(PRE, '', SUF, __env__)}")
1193 x = s("${_concat(PRE, STR, SUF, __env__)}")
1194 assert x == 'prea bsuf', x
1195 x = s("${_concat(PRE, LIST, SUF, __env__)}")
1196 assert x == 'preasuf prebsuf', x
1198 def test_gvars(self):
1199 """Test the Environment gvars() method"""
1200 env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1202 assert gvars['XXX'] == 'x', gvars['XXX']
1203 assert gvars['YYY'] == 'y', gvars['YYY']
1204 assert gvars['ZZZ'] == 'z', gvars['ZZZ']
1206 def test__update(self):
1207 """Test the _update() method"""
1208 env = self.TestEnvironment(X = 'x', Y = 'y', Z = 'z')
1209 assert env['X'] == 'x', env['X']
1210 assert env['Y'] == 'y', env['Y']
1211 assert env['Z'] == 'z', env['Z']
1212 env._update({'X' : 'xxx',
1218 assert env['X'] == 'xxx', env['X']
1219 assert env['Y'] == 'y', env['Y']
1220 assert env['Z'] == 'zzz', env['Z']
1221 assert env['TARGET'] == 't', env['TARGET']
1222 assert env['TARGETS'] == 'ttt', env['TARGETS']
1223 assert env['SOURCE'] == 's', env['SOURCE']
1224 assert env['SOURCES'] == 'sss', env['SOURCES']
1228 def test_Append(self):
1229 """Test appending to construction variables in an Environment
1232 b1 = Environment()['BUILDERS']
1233 b2 = Environment()['BUILDERS']
1234 assert b1 == b2, diff_dict(b1, b2)
1237 UD = UserDict.UserDict
1239 UL = UserList.UserList
1243 'a2', ['A2'], ['a2', 'A2'],
1244 'a3', UL(['A3']), UL(['a', '3', 'A3']),
1247 'a6', UL([]), UL(['a', '6']),
1248 'a7', [''], ['a7', ''],
1249 'a8', UL(['']), UL(['a', '8', '']),
1251 ['e1'], 'E1', ['e1', 'E1'],
1252 ['e2'], ['E2'], ['e2', 'E2'],
1253 ['e3'], UL(['E3']), UL(['e3', 'E3']),
1256 ['e6'], UL([]), UL(['e6']),
1257 ['e7'], [''], ['e7', ''],
1258 ['e8'], UL(['']), UL(['e8', '']),
1260 UL(['i1']), 'I1', UL(['i1', 'I', '1']),
1261 UL(['i2']), ['I2'], UL(['i2', 'I2']),
1262 UL(['i3']), UL(['I3']), UL(['i3', 'I3']),
1263 UL(['i4']), '', UL(['i4']),
1264 UL(['i5']), [], UL(['i5']),
1265 UL(['i6']), UL([]), UL(['i6']),
1266 UL(['i7']), [''], UL(['i7', '']),
1267 UL(['i8']), UL(['']), UL(['i8', '']),
1269 {'d1':1}, 'D1', {'d1':1, 'D1':None},
1270 {'d2':1}, ['D2'], {'d2':1, 'D2':None},
1271 {'d3':1}, UL(['D3']), {'d3':1, 'D3':None},
1272 {'d4':1}, {'D4':1}, {'d4':1, 'D4':1},
1273 {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}),
1275 UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}),
1276 UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}),
1277 UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}),
1278 UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}),
1279 UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
1283 '', UL(['M3']), UL(['M3']),
1288 '', UL(['']), UL(['']),
1292 [], UL(['N3']), UL(['N3']),
1297 [], UL(['']), UL(['']),
1299 UL([]), 'O1', ['O', '1'],
1300 UL([]), ['O2'], ['O2'],
1301 UL([]), UL(['O3']), UL(['O3']),
1304 UL([]), UL([]), UL([]),
1305 UL([]), [''], UL(['']),
1306 UL([]), UL(['']), UL(['']),
1308 [''], 'P1', ['', 'P1'],
1309 [''], ['P2'], ['', 'P2'],
1310 [''], UL(['P3']), UL(['', 'P3']),
1313 [''], UL([]), UL(['']),
1314 [''], [''], ['', ''],
1315 [''], UL(['']), UL(['', '']),
1317 UL(['']), 'Q1', ['', 'Q', '1'],
1318 UL(['']), ['Q2'], ['', 'Q2'],
1319 UL(['']), UL(['Q3']), UL(['', 'Q3']),
1320 UL(['']), '', UL(['']),
1321 UL(['']), [], UL(['']),
1322 UL(['']), UL([]), UL(['']),
1323 UL(['']), [''], UL(['', '']),
1324 UL(['']), UL(['']), UL(['', '']),
1330 input, append, expect = cases[:3]
1331 env['XXX'] = copy.copy(input)
1333 env.Append(XXX = append)
1334 except Exception, e:
1335 if failed == 0: print
1336 print " %s Append %s exception: %s" % \
1337 (repr(input), repr(append), e)
1341 if result != expect:
1342 if failed == 0: print
1343 print " %s Append %s => %s did not match %s" % \
1344 (repr(input), repr(append), repr(result), repr(expect))
1347 assert failed == 0, "%d Append() cases failed" % failed
1349 env['UL'] = UL(['foo'])
1350 env.Append(UL = 'bar')
1352 assert isinstance(result, UL), repr(result)
1353 assert result == ['foo', 'b', 'a', 'r'], result
1355 env['CLVar'] = CLVar(['foo'])
1356 env.Append(CLVar = 'bar')
1357 result = env['CLVar']
1358 assert isinstance(result, CLVar), repr(result)
1359 assert result == ['foo', 'bar'], result
1362 def __init__(self, name):
1366 def __cmp__(self, other):
1367 raise "should not compare"
1371 env2 = self.TestEnvironment(CCC1 = ['c1'], CCC2 = ccc)
1372 env2.Append(CCC1 = ccc, CCC2 = ['c2'])
1373 assert env2['CCC1'][0] == 'c1', env2['CCC1']
1374 assert env2['CCC1'][1] is ccc, env2['CCC1']
1375 assert env2['CCC2'][0] is ccc, env2['CCC2']
1376 assert env2['CCC2'][1] == 'c2', env2['CCC2']
1378 env3 = self.TestEnvironment(X = {'x1' : 7})
1379 env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1380 assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X']
1381 assert env3['Y'] == {'y1': 10}, env3['Y']
1383 env4 = self.TestEnvironment(BUILDERS = {'z1' : 11})
1384 env4.Append(BUILDERS = {'z2' : 12})
1385 assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1386 assert hasattr(env4, 'z1')
1387 assert hasattr(env4, 'z2')
1389 def test_AppendENVPath(self):
1390 """Test appending to an ENV path."""
1391 env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1392 MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1393 # have to include the pathsep here so that the test will work on UNIX too.
1394 env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
1395 env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
1396 env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
1397 env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
1398 assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
1399 assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
1401 def test_AppendUnique(self):
1402 """Test appending to unique values to construction variables
1404 This strips values that are already present when lists are
1406 env = self.TestEnvironment(AAA1 = 'a1',
1418 env.AppendUnique(AAA1 = 'a1',
1420 AAA3 = ['a3', 'b', 'c', 'a3'],
1425 BBB3 = ['b3', 'c', 'd', 'b3'],
1431 assert env['AAA1'] == 'a1a1', env['AAA1']
1432 assert env['AAA2'] == ['a2'], env['AAA2']
1433 assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3']
1434 assert env['AAA4'] == 'a4a4.new', env['AAA4']
1435 assert env['AAA5'] == ['a5', 'a5.new'], env['AAA5']
1436 assert env['BBB1'] == ['b1'], env['BBB1']
1437 assert env['BBB2'] == ['b2'], env['BBB2']
1438 assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3']
1439 assert env['BBB4'] == ['b4', 'b4.new'], env['BBB4']
1440 assert env['BBB5'] == ['b5', 'b5.new'], env['BBB5']
1441 assert env['CCC1'] == 'c1', env['CCC1']
1442 assert env['CCC2'] == ['c2'], env['CCC2']
1444 env['CLVar'] = CLVar([])
1445 env.AppendUnique(CLVar = 'bar')
1446 result = env['CLVar']
1447 if sys.version[0] == '1':
1448 # Python 1.5.2 has a quirky behavior where CLVar([]) actually
1449 # matches '' and [] due to different __coerce__() semantics
1450 # in the UserList implementation. It isn't worth a lot of
1451 # effort to get this corner case to work identically (support
1452 # for Python 1.5 support will die soon anyway), so just treat
1453 # it separately for now.
1454 assert result == 'bar', result
1456 assert isinstance(result, CLVar), repr(result)
1457 assert result == ['bar'], result
1459 env['CLVar'] = CLVar(['abc'])
1460 env.AppendUnique(CLVar = 'bar')
1461 result = env['CLVar']
1462 assert isinstance(result, CLVar), repr(result)
1463 assert result == ['abc', 'bar'], result
1465 env['CLVar'] = CLVar(['bar'])
1466 env.AppendUnique(CLVar = 'bar')
1467 result = env['CLVar']
1468 assert isinstance(result, CLVar), repr(result)
1469 assert result == ['bar'], result
1471 def test_Copy(self):
1472 """Test construction environment copying
1474 Update the copy independently afterwards and check that
1475 the original remains intact (that is, no dangling
1476 references point to objects in the copied environment).
1477 Copy the original with some construction variable
1478 updates and check that the original remains intact
1479 and the copy has the updated values.
1481 env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
1483 env1copy = env1.Copy()
1484 assert env1copy == env1copy
1486 env2.Replace(YYY = 'yyy')
1489 assert env1 == env1copy
1491 env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
1493 assert env3.Dictionary('XXX') == 'x3'
1494 assert env3.Dictionary('YYY') == 'y'
1495 assert env3.Dictionary('ZZZ') == 'z3'
1496 assert env1 == env1copy
1498 # Ensure that lists and dictionaries are
1499 # deep copied, but not instances.
1502 env1 = self.TestEnvironment(XXX=TestA(), YYY = [ 1, 2, 3 ],
1505 env2.Dictionary('YYY').append(4)
1506 env2.Dictionary('ZZZ')[5] = 6
1507 assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
1508 assert 4 in env2.Dictionary('YYY')
1509 assert not 4 in env1.Dictionary('YYY')
1510 assert env2.Dictionary('ZZZ').has_key(5)
1511 assert not env1.Dictionary('ZZZ').has_key(5)
1514 env1 = self.TestEnvironment(BUILDERS = {'b1' : 1})
1515 assert hasattr(env1, 'b1'), "env1.b1 was not set"
1516 assert env1.b1.env == env1, "b1.env doesn't point to env1"
1517 env2 = env1.Copy(BUILDERS = {'b2' : 2})
1520 assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
1521 assert env1.b1.env == env1, "b1.env was changed"
1522 assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
1523 assert hasattr(env2, 'b2'), "env2.b2 was not set"
1524 assert env2.b2.env == env2, "b2.env doesn't point to env2"
1526 # Ensure that specifying new tools in a copied environment
1528 def foo(env): env['FOO'] = 1
1529 def bar(env): env['BAR'] = 2
1530 def baz(env): env['BAZ'] = 3
1531 env1 = self.TestEnvironment(tools=[foo])
1533 env3 = env1.Copy(tools=[bar, baz])
1535 assert env1.get('FOO') is 1
1536 assert env1.get('BAR') is None
1537 assert env1.get('BAZ') is None
1538 assert env2.get('FOO') is 1
1539 assert env2.get('BAR') is None
1540 assert env2.get('BAZ') is None
1541 assert env3.get('FOO') is 1
1542 assert env3.get('BAR') is 2
1543 assert env3.get('BAZ') is 3
1545 # Ensure that recursive variable substitution when copying
1546 # environments works properly.
1547 env1 = self.TestEnvironment(CCFLAGS = '-DFOO', XYZ = '-DXYZ')
1548 env2 = env1.Copy(CCFLAGS = '$CCFLAGS -DBAR',
1549 XYZ = ['-DABC', 'x $XYZ y', '-DDEF'])
1550 x = env2.get('CCFLAGS')
1551 assert x == '-DFOO -DBAR', x
1553 assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x
1555 # Ensure that special properties of a class don't get
1557 env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2'))
1558 x = env1.get('FLAGS')
1559 assert x == ['flag1', 'flag2'], x
1561 env2.Append(FLAGS = 'flag3 flag4')
1562 x = env2.get('FLAGS')
1563 assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
1565 # Test that the environment stores the toolpath and
1566 # re-uses it for copies.
1567 test = TestCmd.TestCmd(workdir = '')
1569 test.write('xxx.py', """\
1576 test.write('yyy.py', """\
1583 env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
1584 assert env['XXX'] == 'one', env['XXX']
1585 env = env.Copy(tools=['yyy'])
1586 assert env['YYY'] == 'two', env['YYY']
1588 def test_Detect(self):
1589 """Test Detect()ing tools"""
1590 test = TestCmd.TestCmd(workdir = '')
1591 test.subdir('sub1', 'sub2')
1592 sub1 = test.workpath('sub1')
1593 sub2 = test.workpath('sub2')
1595 if sys.platform == 'win32':
1596 test.write(['sub1', 'xxx'], "sub1/xxx\n")
1597 test.write(['sub2', 'xxx'], "sub2/xxx\n")
1599 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1601 x = env.Detect('xxx.exe')
1604 test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1606 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1608 x = env.Detect('xxx.exe')
1609 assert x == 'xxx.exe', x
1611 test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1613 x = env.Detect('xxx.exe')
1614 assert x == 'xxx.exe', x
1617 test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1618 test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1620 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1622 x = env.Detect('xxx.exe')
1625 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1626 os.chmod(sub2_xxx_exe, 0755)
1628 env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1630 x = env.Detect('xxx.exe')
1631 assert x == 'xxx.exe', x
1633 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1634 os.chmod(sub1_xxx_exe, 0755)
1636 x = env.Detect('xxx.exe')
1637 assert x == 'xxx.exe', x
1639 env = self.TestEnvironment(ENV = { 'PATH' : [] })
1640 x = env.Detect('xxx.exe')
1643 def test_Dictionary(self):
1644 """Test retrieval of known construction variables
1646 Fetch them from the Dictionary and check for well-known
1647 defaults that get inserted.
1649 env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1650 assert env.Dictionary('XXX') == 'x'
1651 assert env.Dictionary('YYY') == 'y'
1652 assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
1653 xxx, zzz = env.Dictionary('XXX', 'ZZZ')
1656 assert env.Dictionary().has_key('BUILDERS')
1657 assert env.Dictionary().has_key('CC')
1658 assert env.Dictionary().has_key('CCFLAGS')
1659 assert env.Dictionary().has_key('ENV')
1661 assert env['XXX'] == 'x'
1663 assert env.Dictionary('XXX') == 'foo'
1665 assert not env.Dictionary().has_key('XXX')
1667 def test_FindIxes(self):
1669 env = self.TestEnvironment(LIBPREFIX='lib',
1676 paths = [os.path.join('dir', 'libfoo.a'),
1677 os.path.join('dir', 'libfoo.so')]
1679 assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1680 assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1681 assert None == env.FindIxes(paths, 'PREFIX', 'POST')
1683 paths = ['libfoo.a', 'prefoopost']
1685 assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1686 assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1687 assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
1689 def test_ParseConfig(self):
1690 """Test the ParseConfig() method"""
1691 env = self.TestEnvironment(COMMAND='command',
1692 ASFLAGS='assembler',
1704 orig_backtick = env.backtick
1706 def __init__(self, save_command, output):
1707 self.save_command = save_command
1708 self.output = output
1709 def __call__(self, command):
1710 self.save_command.append(command)
1715 env.backtick = my_backtick(save_command,
1716 "-I/usr/include/fum -I bar -X\n" + \
1717 "-L/usr/fax -L foo -lxxx -l yyy " + \
1718 "-Wa,-as -Wl,-link " + \
1719 "-Wl,-rpath=rpath1 " + \
1720 "-Wl,-R,rpath2 " + \
1723 "-framework Carbon " + \
1724 "-frameworkdir=fwd1 " + \
1728 "-mno-cygwin -mwindows " + \
1729 "-arch i386 -isysroot /tmp +DD64 " + \
1730 "-DFOO -DBAR=value")
1731 env.ParseConfig("fake $COMMAND")
1732 assert save_command == ['fake command'], save_command
1733 assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS']
1734 assert env['CCFLAGS'] == ['', '-X', '-Wa,-as',
1735 '-pthread', '-mno-cygwin',
1736 ('-arch', 'i386'), ('-isysroot', '/tmp'),
1737 '+DD64'], env['CCFLAGS']
1738 assert env['CPPDEFINES'] == ['FOO', ['BAR', 'value']], env['CPPDEFINES']
1739 assert env['CPPFLAGS'] == ['', '-Wp,-cpp'], env['CPPFLAGS']
1740 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1741 assert env['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], env['FRAMEWORKPATH']
1742 assert env['FRAMEWORKS'] == ['Carbon'], env['FRAMEWORKS']
1743 assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
1744 assert env['LIBS'] == ['xxx', 'yyy', env.File('abc')], env['LIBS']
1745 assert env['LINKFLAGS'] == ['', '-Wl,-link', '-pthread',
1746 '-mno-cygwin', '-mwindows',
1748 ('-isysroot', '/tmp'),
1749 '+DD64'], env['LINKFLAGS']
1750 assert env['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], env['RPATH']
1752 env.backtick = my_backtick([], "-Ibar")
1753 env.ParseConfig("fake2")
1754 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1755 env.ParseConfig("fake2", unique=0)
1756 assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar', 'bar'], env['CPPPATH']
1758 env.backtick = orig_backtick
1760 def test_ParseDepends(self):
1761 """Test the ParseDepends() method"""
1762 test = TestCmd.TestCmd(workdir = '')
1764 test.write('single', """
1774 test.write('multiple', """
1785 env = self.TestEnvironment(SINGLE = test.workpath('single'))
1789 def my_depends(target, dependency, tlist=tlist, dlist=dlist):
1790 tlist.extend(target)
1791 dlist.extend(dependency)
1793 env.Depends = my_depends
1795 env.ParseDepends(test.workpath('does_not_exist'))
1799 env.ParseDepends(test.workpath('does_not_exist'), must_exist=1)
1802 assert exc_caught, "did not catch expected IOError"
1807 env.ParseDepends('$SINGLE', only_one=1)
1810 assert t == ['f0'], t
1811 assert d == ['d1', 'd2', 'd3'], d
1816 env.ParseDepends(test.workpath('multiple'))
1819 assert t == ['f1', 'f2', 'f3', 'f4', 'f5'], t
1820 assert d == ['foo', 'bar', 'abc', 'def', 'ghi', 'jkl', 'mno'], d
1824 env.ParseDepends(test.workpath('multiple'), only_one=1)
1825 except SCons.Errors.UserError:
1827 assert exc_caught, "did not catch expected UserError"
1829 def test_Platform(self):
1830 """Test the Platform() method"""
1831 env = self.TestEnvironment(WIN32='win32', NONE='no-such-platform')
1835 env.Platform('does_not_exist')
1836 except SCons.Errors.UserError:
1838 assert exc_caught, "did not catch expected UserError"
1842 env.Platform('$NONE')
1843 except SCons.Errors.UserError:
1845 assert exc_caught, "did not catch expected UserError"
1847 env.Platform('posix')
1848 assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
1850 env.Platform('$WIN32')
1851 assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
1853 def test_Prepend(self):
1854 """Test prepending to construction variables in an Environment
1857 UD = UserDict.UserDict
1859 UL = UserList.UserList
1863 'a2', ['A2'], ['A2', 'a2'],
1864 'a3', UL(['A3']), UL(['A3', 'a', '3']),
1867 'a6', UL([]), UL(['a', '6']),
1868 'a7', [''], ['', 'a7'],
1869 'a8', UL(['']), UL(['', 'a', '8']),
1871 ['e1'], 'E1', ['E1', 'e1'],
1872 ['e2'], ['E2'], ['E2', 'e2'],
1873 ['e3'], UL(['E3']), UL(['E3', 'e3']),
1876 ['e6'], UL([]), UL(['e6']),
1877 ['e7'], [''], ['', 'e7'],
1878 ['e8'], UL(['']), UL(['', 'e8']),
1880 UL(['i1']), 'I1', UL(['I', '1', 'i1']),
1881 UL(['i2']), ['I2'], UL(['I2', 'i2']),
1882 UL(['i3']), UL(['I3']), UL(['I3', 'i3']),
1883 UL(['i4']), '', UL(['i4']),
1884 UL(['i5']), [], UL(['i5']),
1885 UL(['i6']), UL([]), UL(['i6']),
1886 UL(['i7']), [''], UL(['', 'i7']),
1887 UL(['i8']), UL(['']), UL(['', 'i8']),
1889 {'d1':1}, 'D1', {'d1':1, 'D1':None},
1890 {'d2':1}, ['D2'], {'d2':1, 'D2':None},
1891 {'d3':1}, UL(['D3']), {'d3':1, 'D3':None},
1892 {'d4':1}, {'D4':1}, {'d4':1, 'D4':1},
1893 {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}),
1895 UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}),
1896 UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}),
1897 UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}),
1898 UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}),
1899 UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
1903 '', UL(['M3']), UL(['M3']),
1908 '', UL(['']), UL(['']),
1912 [], UL(['N3']), UL(['N3']),
1917 [], UL(['']), UL(['']),
1919 UL([]), 'O1', UL(['O', '1']),
1920 UL([]), ['O2'], UL(['O2']),
1921 UL([]), UL(['O3']), UL(['O3']),
1924 UL([]), UL([]), UL([]),
1925 UL([]), [''], UL(['']),
1926 UL([]), UL(['']), UL(['']),
1928 [''], 'P1', ['P1', ''],
1929 [''], ['P2'], ['P2', ''],
1930 [''], UL(['P3']), UL(['P3', '']),
1933 [''], UL([]), UL(['']),
1934 [''], [''], ['', ''],
1935 [''], UL(['']), UL(['', '']),
1937 UL(['']), 'Q1', UL(['Q', '1', '']),
1938 UL(['']), ['Q2'], UL(['Q2', '']),
1939 UL(['']), UL(['Q3']), UL(['Q3', '']),
1940 UL(['']), '', UL(['']),
1941 UL(['']), [], UL(['']),
1942 UL(['']), UL([]), UL(['']),
1943 UL(['']), [''], UL(['', '']),
1944 UL(['']), UL(['']), UL(['', '']),
1950 input, prepend, expect = cases[:3]
1951 env['XXX'] = copy.copy(input)
1953 env.Prepend(XXX = prepend)
1954 except Exception, e:
1955 if failed == 0: print
1956 print " %s Prepend %s exception: %s" % \
1957 (repr(input), repr(prepend), e)
1961 if result != expect:
1962 if failed == 0: print
1963 print " %s Prepend %s => %s did not match %s" % \
1964 (repr(input), repr(prepend), repr(result), repr(expect))
1967 assert failed == 0, "%d Prepend() cases failed" % failed
1969 env['UL'] = UL(['foo'])
1970 env.Prepend(UL = 'bar')
1972 assert isinstance(result, UL), repr(result)
1973 assert result == ['b', 'a', 'r', 'foo'], result
1975 env['CLVar'] = CLVar(['foo'])
1976 env.Prepend(CLVar = 'bar')
1977 result = env['CLVar']
1978 assert isinstance(result, CLVar), repr(result)
1979 assert result == ['bar', 'foo'], result
1981 env3 = self.TestEnvironment(X = {'x1' : 7})
1982 env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1983 assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
1984 assert env3['Y'] == {'y1': 10}, env3['Y']
1986 env4 = self.TestEnvironment(BUILDERS = {'z1' : 11})
1987 env4.Prepend(BUILDERS = {'z2' : 12})
1988 assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1989 assert hasattr(env4, 'z1')
1990 assert hasattr(env4, 'z2')
1992 def test_PrependENVPath(self):
1993 """Test prepending to an ENV path."""
1994 env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1995 MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1996 # have to include the pathsep here so that the test will work on UNIX too.
1997 env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
1998 env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
1999 env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
2000 env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
2001 assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
2002 assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
2004 def test_PrependENVPath(self):
2005 """Test prepending to an ENV path."""
2006 env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
2007 MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
2008 # have to include the pathsep here so that the test will work on UNIX too.
2009 env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
2010 env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
2011 env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
2012 env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
2013 assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
2014 assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
2016 def test_PrependUnique(self):
2017 """Test prepending unique values to construction variables
2019 This strips values that are already present when lists are
2021 env = self.TestEnvironment(AAA1 = 'a1',
2033 env.PrependUnique(AAA1 = 'a1',
2035 AAA3 = ['a3', 'b', 'c', 'a3'],
2040 BBB3 = ['b3', 'b', 'c', 'b3'],
2045 assert env['AAA1'] == 'a1a1', env['AAA1']
2046 assert env['AAA2'] == ['a2'], env['AAA2']
2047 assert env['AAA3'] == ['b', 'c', 'a3'], env['AAA3']
2048 assert env['AAA4'] == 'a4.newa4', env['AAA4']
2049 assert env['AAA5'] == ['a5.new', 'a5'], env['AAA5']
2050 assert env['BBB1'] == ['b1'], env['BBB1']
2051 assert env['BBB2'] == ['b2'], env['BBB2']
2052 assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3']
2053 assert env['BBB4'] == ['b4.new', 'b4'], env['BBB4']
2054 assert env['BBB5'] == ['b5.new', 'b5'], env['BBB5']
2055 assert env['CCC1'] == 'c1', env['CCC1']
2056 assert env['CCC2'] == ['c2'], env['CCC2']
2058 env['CLVar'] = CLVar([])
2059 env.PrependUnique(CLVar = 'bar')
2060 result = env['CLVar']
2061 if sys.version[0] == '1':
2062 # Python 1.5.2 has a quirky behavior where CLVar([]) actually
2063 # matches '' and [] due to different __coerce__() semantics
2064 # in the UserList implementation. It isn't worth a lot of
2065 # effort to get this corner case to work identically (support
2066 # for Python 1.5 support will die soon anyway), so just treat
2067 # it separately for now.
2068 assert result == 'bar', result
2070 assert isinstance(result, CLVar), repr(result)
2071 assert result == ['bar'], result
2073 env['CLVar'] = CLVar(['abc'])
2074 env.PrependUnique(CLVar = 'bar')
2075 result = env['CLVar']
2076 assert isinstance(result, CLVar), repr(result)
2077 assert result == ['bar', 'abc'], result
2079 env['CLVar'] = CLVar(['bar'])
2080 env.PrependUnique(CLVar = 'bar')
2081 result = env['CLVar']
2082 assert isinstance(result, CLVar), repr(result)
2083 assert result == ['bar'], result
2085 def test_Replace(self):
2086 """Test replacing construction variables in an Environment
2088 After creation of the Environment, of course.
2090 env1 = self.TestEnvironment(AAA = 'a', BBB = 'b')
2091 env1.Replace(BBB = 'bbb', CCC = 'ccc')
2093 env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
2094 assert env1 == env2, diff_env(env1, env2)
2096 env3 = self.TestEnvironment(BUILDERS = {'b1' : 1})
2097 assert hasattr(env3, 'b1'), "b1 was not set"
2098 env3.Replace(BUILDERS = {'b2' : 2})
2099 assert not hasattr(env3, 'b1'), "b1 was not cleared"
2100 assert hasattr(env3, 'b2'), "b2 was not set"
2102 def test_ReplaceIxes(self):
2103 "Test ReplaceIxes()"
2104 env = self.TestEnvironment(LIBPREFIX='lib',
2111 assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
2112 'SHLIBPREFIX', 'SHLIBSUFFIX',
2113 'LIBPREFIX', 'LIBSUFFIX')
2115 assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
2116 'SHLIBPREFIX', 'SHLIBSUFFIX',
2117 'LIBPREFIX', 'LIBSUFFIX')
2119 assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
2121 'LIBPREFIX', 'LIBSUFFIX')
2123 def test_SetDefault(self):
2124 """Test the SetDefault method"""
2125 env = self.TestEnvironment(tools = [])
2126 env.SetDefault(V1 = 1)
2127 env.SetDefault(V1 = 2)
2128 assert env['V1'] == 1
2130 env.SetDefault(V2 = 1)
2131 assert env['V2'] == 2
2133 def test_Tool(self):
2134 """Test the Tool() method"""
2135 env = self.TestEnvironment(LINK='link', NONE='no-such-tool')
2139 env.Tool('does_not_exist')
2140 except SCons.Errors.UserError:
2142 assert exc_caught, "did not catch expected UserError"
2147 except SCons.Errors.UserError:
2149 assert exc_caught, "did not catch expected UserError"
2151 # Use a non-existent toolpath directory just to make sure we
2152 # can call Tool() with the keyword argument.
2153 env.Tool('cc', toolpath=['/no/such/directory'])
2154 assert env['CC'] == 'cc', env['CC']
2157 assert env['LINK'] == '$SMARTLINK', env['LINK']
2159 # Test that the environment stores the toolpath and
2160 # re-uses it for later calls.
2161 test = TestCmd.TestCmd(workdir = '')
2163 test.write('xxx.py', """\
2170 test.write('yyy.py', """\
2177 env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
2178 assert env['XXX'] == 'one', env['XXX']
2180 assert env['YYY'] == 'two', env['YYY']
2182 def test_WhereIs(self):
2183 """Test the WhereIs() method"""
2184 test = TestCmd.TestCmd(workdir = '')
2186 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
2187 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
2188 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
2189 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
2191 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
2193 if sys.platform != 'win32':
2194 test.write(sub1_xxx_exe, "\n")
2196 os.mkdir(sub2_xxx_exe)
2198 test.write(sub3_xxx_exe, "\n")
2199 os.chmod(sub3_xxx_exe, 0777)
2201 test.write(sub4_xxx_exe, "\n")
2202 os.chmod(sub4_xxx_exe, 0777)
2204 env_path = os.environ['PATH']
2206 pathdirs_1234 = [ test.workpath('sub1'),
2207 test.workpath('sub2'),
2208 test.workpath('sub3'),
2209 test.workpath('sub4'),
2210 ] + string.split(env_path, os.pathsep)
2212 pathdirs_1243 = [ test.workpath('sub1'),
2213 test.workpath('sub2'),
2214 test.workpath('sub4'),
2215 test.workpath('sub3'),
2216 ] + string.split(env_path, os.pathsep)
2218 path = string.join(pathdirs_1234, os.pathsep)
2219 env = self.TestEnvironment(ENV = {'PATH' : path})
2220 wi = env.WhereIs('xxx.exe')
2221 assert wi == test.workpath(sub3_xxx_exe), wi
2222 wi = env.WhereIs('xxx.exe', pathdirs_1243)
2223 assert wi == test.workpath(sub4_xxx_exe), wi
2224 wi = env.WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
2225 assert wi == test.workpath(sub4_xxx_exe), wi
2227 wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe)
2228 assert wi == test.workpath(sub4_xxx_exe), wi
2229 wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
2230 assert wi == test.workpath(sub4_xxx_exe), wi
2232 path = string.join(pathdirs_1243, os.pathsep)
2233 env = self.TestEnvironment(ENV = {'PATH' : path})
2234 wi = env.WhereIs('xxx.exe')
2235 assert wi == test.workpath(sub4_xxx_exe), wi
2236 wi = env.WhereIs('xxx.exe', pathdirs_1234)
2237 assert wi == test.workpath(sub3_xxx_exe), wi
2238 wi = env.WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
2239 assert wi == test.workpath(sub3_xxx_exe), wi
2241 if sys.platform == 'win32':
2242 wi = env.WhereIs('xxx', pathext = '')
2243 assert wi is None, wi
2245 wi = env.WhereIs('xxx', pathext = '.exe')
2246 assert wi == test.workpath(sub4_xxx_exe), wi
2248 wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
2249 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
2251 # Test that we return a normalized path even when
2252 # the path contains forward slashes.
2253 forward_slash = test.workpath('') + '/sub3'
2254 wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE')
2255 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
2259 def test_Action(self):
2260 """Test the Action() method"""
2263 env = self.TestEnvironment(FOO = 'xyzzy')
2265 a = env.Action('foo')
2267 assert a.__class__ is SCons.Action.CommandAction, a.__class__
2269 a = env.Action('$FOO')
2271 assert a.__class__ is SCons.Action.CommandAction, a.__class__
2273 a = env.Action('$$FOO')
2275 assert a.__class__ is SCons.Action.LazyAction, a.__class__
2277 a = env.Action(['$FOO', 'foo'])
2279 assert a.__class__ is SCons.Action.ListAction, a.__class__
2283 a = env.Action(func)
2285 assert a.__class__ is SCons.Action.FunctionAction, a.__class__
2287 def test_AddPostAction(self):
2288 """Test the AddPostAction() method"""
2289 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2291 n = env.AddPostAction('$FOO', lambda x: x)
2292 assert str(n[0]) == 'fff', n[0]
2294 n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
2295 assert str(n[0]) == 'ggg', n[0]
2296 assert str(n[1]) == 'bbb', n[1]
2298 def test_AddPreAction(self):
2299 """Test the AddPreAction() method"""
2300 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2302 n = env.AddPreAction('$FOO', lambda x: x)
2303 assert str(n[0]) == 'fff', n[0]
2305 n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
2306 assert str(n[0]) == 'ggg', n[0]
2307 assert str(n[1]) == 'bbb', n[1]
2309 def test_Alias(self):
2310 """Test the Alias() method"""
2311 env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_alias')
2313 tgt = env.Alias('new_alias')[0]
2314 assert str(tgt) == 'new_alias', tgt
2315 assert tgt.sources == [], tgt.sources
2316 assert not hasattr(tgt, 'builder'), tgt.builder
2318 tgt = env.Alias('None_alias', None)[0]
2319 assert str(tgt) == 'None_alias', tgt
2320 assert tgt.sources == [], tgt.sources
2322 tgt = env.Alias('empty_list', [])[0]
2323 assert str(tgt) == 'empty_list', tgt
2324 assert tgt.sources == [], tgt.sources
2326 tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0]
2327 assert str(tgt) == 'export_alias', tgt
2328 assert len(tgt.sources) == 2, map(str, tgt.sources)
2329 assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources)
2330 assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources)
2332 n = env.Alias(tgt, source = ['$BAR', 'asrc4'])[0]
2334 assert len(tgt.sources) == 4, map(str, tgt.sources)
2335 assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources)
2336 assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources)
2338 n = env.Alias('$EA', 'asrc5')[0]
2340 assert len(tgt.sources) == 5, map(str, tgt.sources)
2341 assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources)
2343 t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
2344 assert str(t1) == 't1', t1
2345 assert str(t2) == 't2', t2
2346 assert len(t1.sources) == 2, map(str, t1.sources)
2347 assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources)
2348 assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources)
2349 assert len(t2.sources) == 2, map(str, t2.sources)
2350 assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources)
2351 assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources)
2353 tgt = env.Alias('add', 's1')
2354 tgt = env.Alias('add', 's2')[0]
2355 s = map(str, tgt.sources)
2356 assert s == ['s1', 's2'], s
2357 tgt = env.Alias(tgt, 's3')[0]
2358 s = map(str, tgt.sources)
2359 assert s == ['s1', 's2', 's3'], s
2361 tgt = env.Alias('act', None, "action1")[0]
2362 s = str(tgt.builder.action)
2363 assert s == "action1", s
2364 tgt = env.Alias('act', None, "action2")[0]
2365 s = str(tgt.builder.action)
2366 assert s == "action1\naction2", s
2367 tgt = env.Alias(tgt, None, "action3")[0]
2368 s = str(tgt.builder.action)
2369 assert s == "action1\naction2\naction3", s
2371 def test_AlwaysBuild(self):
2372 """Test the AlwaysBuild() method"""
2373 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2374 t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR')
2375 assert t[0].__class__.__name__ == 'File'
2376 assert t[0].path == 'a'
2377 assert t[0].always_build
2378 assert t[1].__class__.__name__ == 'File'
2379 assert t[1].path == 'bfff'
2380 assert t[1].always_build
2381 assert t[2].__class__.__name__ == 'File'
2382 assert t[2].path == 'c'
2383 assert t[2].always_build
2384 assert t[3].__class__.__name__ == 'File'
2385 assert t[3].path == 'd'
2386 assert t[3].always_build
2387 assert t[4].__class__.__name__ == 'File'
2388 assert t[4].path == 'bbb'
2389 assert t[4].always_build
2391 def test_BuildDir(self):
2392 """Test the BuildDir() method"""
2394 def Dir(self, name):
2396 def BuildDir(self, build_dir, src_dir, duplicate):
2397 self.build_dir = build_dir
2398 self.src_dir = src_dir
2399 self.duplicate = duplicate
2401 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2404 env.BuildDir('build', 'src')
2405 assert env.fs.build_dir == 'build', env.fs.build_dir
2406 assert env.fs.src_dir == 'src', env.fs.src_dir
2407 assert env.fs.duplicate == 1, env.fs.duplicate
2409 env.BuildDir('build${FOO}', '${BAR}src', 0)
2410 assert env.fs.build_dir == 'buildfff', env.fs.build_dir
2411 assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir
2412 assert env.fs.duplicate == 0, env.fs.duplicate
2414 def test_Builder(self):
2415 """Test the Builder() method"""
2416 env = self.TestEnvironment(FOO = 'xyzzy')
2418 b = env.Builder(action = 'foo')
2419 assert not b is None, b
2421 b = env.Builder(action = '$FOO')
2422 assert not b is None, b
2424 b = env.Builder(action = ['$FOO', 'foo'])
2425 assert not b is None, b
2429 b = env.Builder(action = func)
2430 assert not b is None, b
2431 b = env.Builder(generator = func)
2432 assert not b is None, b
2434 def test_CacheDir(self):
2435 """Test the CacheDir() method"""
2437 def CacheDir(self, path):
2440 env = self.TestEnvironment(CD = 'CacheDir')
2444 assert env.fs.CD == 'foo', env.fs.CD
2447 assert env.fs.CD == 'CacheDir', env.fs.CD
2449 def test_Clean(self):
2450 """Test the Clean() method"""
2451 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2453 CT = SCons.Environment.CleanTargets
2455 foo = env.arg2nodes('foo')[0]
2456 fff = env.arg2nodes('fff')[0]
2458 t = env.Clean('foo', 'aaa')
2459 l = map(str, CT[foo])
2460 assert l == ['aaa'], l
2462 t = env.Clean(foo, ['$BAR', 'ccc'])
2463 l = map(str, CT[foo])
2464 assert l == ['aaa', 'bbb', 'ccc'], l
2466 eee = env.arg2nodes('eee')[0]
2468 t = env.Clean('$FOO', 'ddd')
2469 l = map(str, CT[fff])
2470 assert l == ['ddd'], l
2471 t = env.Clean(fff, [eee, 'fff'])
2472 l = map(str, CT[fff])
2473 assert l == ['ddd', 'eee', 'fff'], l
2475 def test_Command(self):
2476 """Test the Command() method."""
2478 t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
2479 action='buildfoo $target $source')[0]
2480 assert not t.builder is None
2481 assert t.builder.action.__class__.__name__ == 'CommandAction'
2482 assert t.builder.action.cmd_list == 'buildfoo $target $source'
2483 assert 'foo1.in' in map(lambda x: x.path, t.sources)
2484 assert 'foo2.in' in map(lambda x: x.path, t.sources)
2486 sub = env.fs.Dir('sub')
2487 t = env.Command(target='bar.out', source='sub',
2488 action='buildbar $target $source')[0]
2489 assert 'sub' in map(lambda x: x.path, t.sources)
2491 def testFunc(env, target, source):
2492 assert str(target[0]) == 'foo.out'
2493 assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
2495 t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
2497 assert not t.builder is None
2498 assert t.builder.action.__class__.__name__ == 'FunctionAction'
2500 assert 'foo1.in' in map(lambda x: x.path, t.sources)
2501 assert 'foo2.in' in map(lambda x: x.path, t.sources)
2504 def test2(baz, x=x):
2506 env = self.TestEnvironment(TEST2 = test2)
2507 t = env.Command(target='baz.out', source='baz.in',
2508 action='${TEST2(XYZ)}',
2509 XYZ='magic word')[0]
2510 assert not t.builder is None
2512 assert x[0] == 'magic word', x
2514 t = env.Command(target='${X}.out', source='${X}.in',
2517 assert str(t) == 'xxx.out', str(t)
2518 assert 'xxx.in' in map(lambda x: x.path, t.sources)
2520 env = self.TestEnvironment(source_scanner = 'should_not_find_this')
2521 t = env.Command(target='file.out', source='file.in',
2523 source_scanner = 'fake')[0]
2524 assert t.builder.source_scanner == 'fake', t.builder.source_scanner
2526 def test_Configure(self):
2527 """Test the Configure() method"""
2528 # Configure() will write to a local temporary file.
2529 test = TestCmd.TestCmd(workdir = '')
2533 os.chdir(test.workpath())
2535 env = self.TestEnvironment(FOO = 'xyzzy')
2541 assert not c is None, c
2544 c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
2545 assert not c is None, c
2546 assert hasattr(c, 'foo')
2547 assert hasattr(c, 'xyzzy')
2552 def test_Depends(self):
2553 """Test the explicit Depends method."""
2554 env = self.TestEnvironment(FOO = 'xxx', BAR='yyy')
2559 t = env.Depends(target='EnvironmentTest.py',
2560 dependency='Environment.py')[0]
2561 assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2562 assert t.path == 'EnvironmentTest.py'
2563 assert len(t.depends) == 1
2565 assert d.__class__.__name__ == 'Entry', d.__class__.__name__
2566 assert d.path == 'Environment.py'
2568 t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0]
2569 assert t.__class__.__name__ == 'File', t.__class__.__name__
2570 assert t.path == 'xxx.py'
2571 assert len(t.depends) == 1
2573 assert d.__class__.__name__ == 'File', d.__class__.__name__
2574 assert d.path == 'yyy.py'
2576 t = env.Depends(target='dir1', dependency='dir2')[0]
2577 assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2578 assert t.path == 'dir1'
2579 assert len(t.depends) == 1
2581 assert d.__class__.__name__ == 'Dir', d.__class__.__name__
2582 assert d.path == 'dir2'
2585 """Test the Dir() method"""
2587 def Dir(self, name):
2588 return 'Dir(%s)' % name
2590 env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir')
2594 assert d == 'Dir(d)', d
2597 assert d == 'Dir(foodir)', d
2599 d = env.Dir('${BAR}_$BAR')
2600 assert d == 'Dir(bardir_bardir)', d
2602 def test_NoClean(self):
2603 """Test the NoClean() method"""
2604 env = self.TestEnvironment(FOO='ggg', BAR='hhh')
2607 t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2609 assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2610 assert t[0].path == 'p_a'
2612 assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2613 assert t[1].path == 'p_hhhb'
2615 assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2616 assert t[2].path == 'p_c'
2618 assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2619 assert t[3].path == 'p_d'
2621 assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2622 assert t[4].path == 'p_ggg'
2625 def test_Dump(self):
2626 """Test the Dump() method"""
2628 env = self.TestEnvironment(FOO = 'foo')
2629 assert env.Dump('FOO') == "'foo'", env.Dump('FOO')
2630 assert len(env.Dump()) > 200, env.Dump() # no args version
2632 def test_Environment(self):
2633 """Test the Environment() method"""
2634 env = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy')
2636 e2 = env.Environment(X = '$FOO', Y = '$BAR')
2637 assert e2['X'] == 'xxx', e2['X']
2638 assert e2['Y'] == 'yyy', e2['Y']
2640 def test_Execute(self):
2641 """Test the Execute() method"""
2644 def __init__(self, *args, **kw):
2646 def __call__(self, target, source, env):
2647 return "%s executed" % self.args
2650 env.Action = MyAction
2652 result = env.Execute("foo")
2653 assert result == "foo executed", result
2655 def test_Entry(self):
2656 """Test the Entry() method"""
2658 def Entry(self, name):
2659 return 'Entry(%s)' % name
2661 env = self.TestEnvironment(FOO = 'fooentry', BAR = 'barentry')
2665 assert e == 'Entry(e)', e
2667 e = env.Entry('$FOO')
2668 assert e == 'Entry(fooentry)', e
2670 e = env.Entry('${BAR}_$BAR')
2671 assert e == 'Entry(barentry_barentry)', e
2673 def test_File(self):
2674 """Test the File() method"""
2676 def File(self, name):
2677 return 'File(%s)' % name
2679 env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile')
2683 assert f == 'File(f)', f
2685 f = env.File('$FOO')
2686 assert f == 'File(foofile)', f
2688 f = env.File('${BAR}_$BAR')
2689 assert f == 'File(barfile_barfile)', f
2691 def test_FindFile(self):
2692 """Test the FindFile() method"""
2693 env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2695 r = env.FindFile('foo', ['no_such_directory'])
2700 def test_Flatten(self):
2701 """Test the Flatten() method"""
2703 l = env.Flatten([1])
2705 l = env.Flatten([1, [2, [3, [4]]]])
2706 assert l == [1, 2, 3, 4], l
2708 def test_GetBuildPath(self):
2709 """Test the GetBuildPath() method."""
2710 env = self.TestEnvironment(MAGIC = 'xyzzy')
2712 p = env.GetBuildPath('foo')
2713 assert p == 'foo', p
2715 p = env.GetBuildPath('$MAGIC')
2716 assert p == 'xyzzy', p
2718 def test_Ignore(self):
2719 """Test the explicit Ignore method."""
2720 env = self.TestEnvironment(FOO='yyy', BAR='zzz')
2726 t = env.Ignore(target='targ.py', dependency='dep.py')[0]
2727 assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2728 assert t.path == 'targ.py'
2729 assert len(t.ignore) == 1
2731 assert i.__class__.__name__ == 'Entry', i.__class__.__name__
2732 assert i.path == 'dep.py'
2734 t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0]
2735 assert t.__class__.__name__ == 'File', t.__class__.__name__
2736 assert t.path == 'yyyzzz'
2737 assert len(t.ignore) == 1
2739 assert i.__class__.__name__ == 'File', i.__class__.__name__
2740 assert i.path == 'zzzyyy'
2742 t = env.Ignore(target='dir1', dependency='dir2')[0]
2743 assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2744 assert t.path == 'dir1'
2745 assert len(t.ignore) == 1
2747 assert i.__class__.__name__ == 'Dir', i.__class__.__name__
2748 assert i.path == 'dir2'
2750 def test_Install(self):
2751 """Test the Install method"""
2752 env = self.TestEnvironment(FOO='iii', BAR='jjj')
2754 tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
2755 paths = map(str, tgt)
2757 expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
2758 assert paths == expect, paths
2760 assert tnode.builder == InstallBuilder
2762 tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
2763 paths = map(str, tgt)
2765 expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
2766 assert paths == expect, paths
2768 assert tnode.builder == InstallBuilder
2770 tgt = env.Install('export', 'build')
2771 paths = map(str, tgt)
2773 expect = ['export/build']
2774 assert paths == expect, paths
2776 assert tnode.builder == InstallBuilder
2778 tgt = env.Install('export', ['build', 'build/foo1'])
2779 paths = map(str, tgt)
2781 expect = ['export/build', 'export/foo1']
2782 assert paths == expect, paths
2784 assert tnode.builder == InstallBuilder
2786 env.File('export/foo1')
2790 tgt = env.Install('export/foo1', 'build/foo1')
2791 except SCons.Errors.UserError, e:
2793 assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
2794 expect = "Target `export/foo1' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?"
2795 assert str(e) == expect, e
2797 def test_InstallAs(self):
2798 """Test the InstallAs method"""
2799 env = self.TestEnvironment(FOO='iii', BAR='jjj')
2801 tgt = env.InstallAs(target=string.split('foo1 foo2'),
2802 source=string.split('bar1 bar2'))
2803 assert len(tgt) == 2, len(tgt)
2804 paths = map(lambda x: str(x.sources[0]), tgt)
2806 expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
2807 assert paths == expect, paths
2809 assert tnode.builder == InstallBuilder
2811 tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')[0]
2812 assert tgt.path == 'iii.t'
2813 assert tgt.sources[0].path == 'jjj.s'
2814 assert tgt.builder == InstallBuilder
2816 def test_Literal(self):
2817 """Test the Literal() method"""
2818 env = self.TestEnvironment(FOO='fff', BAR='bbb')
2819 list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0]
2820 assert list == ['$FOO', 'bbb'], list
2821 list = env.subst_list(['$FOO', env.Literal('$BAR')])[0]
2822 assert list == ['fff', '$BAR'], list
2824 def test_Local(self):
2825 """Test the Local() method."""
2826 env = self.TestEnvironment(FOO='lll')
2828 l = env.Local(env.fs.File('fff'))
2829 assert str(l[0]) == 'fff', l[0]
2831 l = env.Local('ggg', '$FOO')
2832 assert str(l[0]) == 'ggg', l[0]
2833 assert str(l[1]) == 'lll', l[1]
2835 def test_Precious(self):
2836 """Test the Precious() method"""
2837 env = self.TestEnvironment(FOO='ggg', BAR='hhh')
2840 t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2842 assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2843 assert t[0].path == 'p_a'
2844 assert t[0].precious
2845 assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2846 assert t[1].path == 'p_hhhb'
2847 assert t[1].precious
2848 assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2849 assert t[2].path == 'p_c'
2850 assert t[2].precious
2851 assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2852 assert t[3].path == 'p_d'
2853 assert t[3].precious
2854 assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2855 assert t[4].path == 'p_ggg'
2856 assert t[4].precious
2858 def test_Repository(self):
2859 """Test the Repository() method."""
2863 def Repository(self, *dirs):
2864 self.list.extend(list(dirs))
2865 def Dir(self, name):
2867 env = self.TestEnvironment(FOO='rrr', BAR='sss')
2869 env.Repository('/tmp/foo')
2870 env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
2871 expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
2872 assert env.fs.list == expect, env.fs.list
2874 def test_Scanner(self):
2875 """Test the Scanner() method"""
2876 def scan(node, env, target, arg):
2879 env = self.TestEnvironment(FOO = scan)
2881 s = env.Scanner('foo')
2882 assert not s is None, s
2884 s = env.Scanner(function = 'foo')
2885 assert not s is None, s
2888 s = env.Scanner('$FOO')
2889 assert not s is None, s
2891 s = env.Scanner(function = '$FOO')
2892 assert not s is None, s
2894 def test_SConsignFile(self):
2895 """Test the SConsignFile() method"""
2896 import SCons.SConsign
2899 SConstruct_dir = os.sep + 'dir'
2901 env = self.TestEnvironment(FOO = 'SConsign',
2902 BAR = os.path.join(os.sep, 'File'))
2908 def capture(name, dbm_module, fnames=fnames, dbms=dbms):
2910 dbms.append(dbm_module)
2912 save_SConsign_File = SCons.SConsign.File
2913 SCons.SConsign.File = capture
2915 env.SConsignFile('foo')
2916 assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames
2917 assert dbms[0] == None, dbms
2919 env.SConsignFile('$FOO')
2920 assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
2921 assert dbms[1] == None, dbms
2923 env.SConsignFile('/$FOO')
2924 assert fnames[2] == '/SConsign', fnames
2925 assert dbms[2] == None, dbms
2927 env.SConsignFile('$BAR', 'x')
2928 assert fnames[3] == os.path.join(os.sep, 'File'), fnames
2929 assert dbms[3] == 'x', dbms
2931 env.SConsignFile('__$BAR', 7)
2932 assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
2933 assert dbms[4] == 7, dbms
2936 assert fnames[5] == os.path.join(os.sep, 'dir', '.sconsign'), fnames
2937 assert dbms[5] == None, dbms
2939 env.SConsignFile(None)
2940 assert fnames[6] == None, fnames
2941 assert dbms[6] == None, dbms
2943 SCons.SConsign.File = save_SConsign_File
2945 def test_SideEffect(self):
2946 """Test the SideEffect() method"""
2947 env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb')
2948 env.File('mylll.pdb')
2949 env.Dir('mymmm.pdb')
2951 foo = env.Object('foo.obj', 'foo.cpp')[0]
2952 bar = env.Object('bar.obj', 'bar.cpp')[0]
2953 s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])[0]
2954 assert s.__class__.__name__ == 'Entry', s.__class__.__name__
2955 assert s.path == 'mylib.pdb'
2956 assert s.side_effect
2957 assert foo.side_effects == [s]
2958 assert bar.side_effects == [s]
2960 fff = env.Object('fff.obj', 'fff.cpp')[0]
2961 bbb = env.Object('bbb.obj', 'bbb.cpp')[0]
2962 s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])[0]
2963 assert s.__class__.__name__ == 'File', s.__class__.__name__
2964 assert s.path == 'mylll.pdb'
2965 assert s.side_effect
2966 assert fff.side_effects == [s], fff.side_effects
2967 assert bbb.side_effects == [s], bbb.side_effects
2969 ggg = env.Object('ggg.obj', 'ggg.cpp')[0]
2970 ccc = env.Object('ccc.obj', 'ccc.cpp')[0]
2971 s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])[0]
2972 assert s.__class__.__name__ == 'Dir', s.__class__.__name__
2973 assert s.path == 'mymmm.pdb'
2974 assert s.side_effect
2975 assert ggg.side_effects == [s], ggg.side_effects
2976 assert ccc.side_effects == [s], ccc.side_effects
2978 def test_SourceCode(self):
2979 """Test the SourceCode() method."""
2980 env = self.TestEnvironment(FOO='mmm', BAR='nnn')
2981 e = env.SourceCode('foo', None)[0]
2982 assert e.path == 'foo'
2987 e = env.SourceCode(e, b)[0]
2988 assert e.path == 'foo'
2992 e = env.SourceCode('$BAR$FOO', None)[0]
2993 assert e.path == 'nnnmmm'
2997 def test_SourceSignatures(type):
2998 """Test the SourceSignatures() method"""
2999 env = type.TestEnvironment(M = 'MD5', T = 'timestamp')
3003 env.SourceSignatures('invalid_type')
3004 except SCons.Errors.UserError:
3006 assert exc_caught, "did not catch expected UserError"
3007 assert not hasattr(env, '_calc_module')
3009 env.SourceSignatures('MD5')
3010 m = env._calc_module
3012 env.SourceSignatures('$M')
3013 assert env._calc_module is m
3015 env.SourceSignatures('timestamp')
3016 t = env._calc_module
3018 env.SourceSignatures('$T')
3019 assert env._calc_module is t
3021 def test_Split(self):
3022 """Test the Split() method"""
3023 env = self.TestEnvironment(FOO='fff', BAR='bbb')
3024 s = env.Split("foo bar")
3025 assert s == ["foo", "bar"], s
3026 s = env.Split("$FOO bar")
3027 assert s == ["fff", "bar"], s
3028 s = env.Split(["foo", "bar"])
3029 assert s == ["foo", "bar"], s
3030 s = env.Split(["foo", "${BAR}-bbb"])
3031 assert s == ["foo", "bbb-bbb"], s
3032 s = env.Split("foo")
3033 assert s == ["foo"], s
3034 s = env.Split("$FOO$BAR")
3035 assert s == ["fffbbb"], s
3037 def test_TargetSignatures(type):
3038 """Test the TargetSignatures() method"""
3039 env = type.TestEnvironment(B = 'build', C = 'content')
3043 env.TargetSignatures('invalid_type')
3044 except SCons.Errors.UserError:
3046 assert exc_caught, "did not catch expected UserError"
3047 assert not hasattr(env, '_build_signature')
3049 env.TargetSignatures('build')
3050 assert env._build_signature == 1, env._build_signature
3052 env.TargetSignatures('content')
3053 assert env._build_signature == 0, env._build_signature
3055 env.TargetSignatures('$B')
3056 assert env._build_signature == 1, env._build_signature
3058 env.TargetSignatures('$C')
3059 assert env._build_signature == 0, env._build_signature
3061 def test_Value(self):
3062 """Test creating a Value() object
3066 assert v1.value == 'a', v1.value
3069 v2 = env.Value(value2)
3070 assert v2.value == value2, v2.value
3071 assert v2.value is value2, v2.value
3074 assert v1.value == v2.value
3076 v3 = env.Value('c', 'build-c')
3077 assert v3.value == 'c', v3.value
3081 def test_Environment_global_variable(type):
3082 """Test setting Environment variable to an Environment.Base subclass"""
3083 class MyEnv(SCons.Environment.Base):
3084 def xxx(self, string):
3085 return self.subst(string)
3087 SCons.Environment.Environment = MyEnv
3089 env = SCons.Environment.Environment(FOO = 'foo')
3091 f = env.subst('$FOO')
3092 assert f == 'foo', f
3095 assert f == 'foo', f
3097 def test_bad_keywords(type):
3098 """Test trying to use reserved keywords in an Environment"""
3099 reserved = ['TARGETS','SOURCES', 'SOURCE','TARGET']
3102 env = type.TestEnvironment(TARGETS = 'targets',
3103 SOURCES = 'sources',
3107 bad_msg = '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'
3108 added.append('INIT')
3110 assert not env.has_key(x), env[x]
3112 assert env.has_key(x), bad_msg % x
3114 env.Append(TARGETS = 'targets',
3115 SOURCES = 'sources',
3119 added.append('APPEND')
3121 assert not env.has_key(x), env[x]
3123 assert env.has_key(x), bad_msg % x
3125 env.AppendUnique(TARGETS = 'targets',
3126 SOURCES = 'sources',
3129 APPENDUNIQUE = 'appendunique')
3130 added.append('APPENDUNIQUE')
3132 assert not env.has_key(x), env[x]
3134 assert env.has_key(x), bad_msg % x
3136 env.Prepend(TARGETS = 'targets',
3137 SOURCES = 'sources',
3140 PREPEND = 'prepend')
3141 added.append('PREPEND')
3143 assert not env.has_key(x), env[x]
3145 assert env.has_key(x), bad_msg % x
3147 env.Prepend(TARGETS = 'targets',
3148 SOURCES = 'sources',
3151 PREPENDUNIQUE = 'prependunique')
3152 added.append('PREPENDUNIQUE')
3154 assert not env.has_key(x), env[x]
3156 assert env.has_key(x), bad_msg % x
3158 env.Replace(TARGETS = 'targets',
3159 SOURCES = 'sources',
3162 REPLACE = 'replace')
3163 added.append('REPLACE')
3165 assert not env.has_key(x), env[x]
3167 assert env.has_key(x), bad_msg % x
3169 copy = env.Copy(TARGETS = 'targets',
3170 SOURCES = 'sources',
3175 assert not copy.has_key(x), env[x]
3176 for x in added + ['COPY']:
3177 assert copy.has_key(x), bad_msg % x
3179 over = env.Override({'TARGETS' : 'targets',
3180 'SOURCES' : 'sources',
3181 'SOURCE' : 'source',
3182 'TARGET' : 'target',
3183 'OVERRIDE' : 'override'})
3185 assert not over.has_key(x), over[x]
3186 for x in added + ['OVERRIDE']:
3187 assert over.has_key(x), bad_msg % x
3191 class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture):
3195 env._dict = {'XXX' : 'x', 'YYY' : 'y'}
3196 env2 = OverrideEnvironment(env, {'XXX' : 'x2'})
3197 env3 = OverrideEnvironment(env2, {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'})
3198 self.envs = [ env, env2, env3 ]
3200 def checkpath(self, node, expect):
3201 return str(node) == os.path.normpath(expect)
3203 def test___init__(self):
3204 """Test OverrideEnvironment initialization"""
3205 env, env2, env3 = self.envs
3206 assert env['XXX'] == 'x', env['XXX']
3207 assert env2['XXX'] == 'x2', env2['XXX']
3208 assert env3['XXX'] == 'x3', env3['XXX']
3209 assert env['YYY'] == 'y', env['YYY']
3210 assert env2['YYY'] == 'y', env2['YYY']
3211 assert env3['YYY'] == 'y3', env3['YYY']
3213 def test___delitem__(self):
3214 """Test deleting variables from an OverrideEnvironment"""
3215 env, env2, env3 = self.envs
3218 assert not env.has_key('XXX'), "env has XXX?"
3219 assert not env2.has_key('XXX'), "env2 has XXX?"
3220 assert not env3.has_key('XXX'), "env3 has XXX?"
3223 assert not env.has_key('YYY'), "env has YYY?"
3224 assert not env2.has_key('YYY'), "env2 has YYY?"
3225 assert not env3.has_key('YYY'), "env3 has YYY?"
3228 assert not env.has_key('ZZZ'), "env has ZZZ?"
3229 assert not env2.has_key('ZZZ'), "env2 has ZZZ?"
3230 assert not env3.has_key('ZZZ'), "env3 has ZZZ?"
3233 """Test the OverrideEnvironment get() method"""
3234 env, env2, env3 = self.envs
3235 assert env.get('XXX') == 'x', env.get('XXX')
3236 assert env2.get('XXX') == 'x2', env2.get('XXX')
3237 assert env3.get('XXX') == 'x3', env3.get('XXX')
3238 assert env.get('YYY') == 'y', env.get('YYY')
3239 assert env2.get('YYY') == 'y', env2.get('YYY')
3240 assert env3.get('YYY') == 'y3', env3.get('YYY')
3241 assert env.get('ZZZ') == None, env.get('ZZZ')
3242 assert env2.get('ZZZ') == None, env2.get('ZZZ')
3243 assert env3.get('ZZZ') == 'z3', env3.get('ZZZ')
3245 def test_has_key(self):
3246 """Test the OverrideEnvironment has_key() method"""
3247 env, env2, env3 = self.envs
3248 assert env.has_key('XXX'), env.has_key('XXX')
3249 assert env2.has_key('XXX'), env2.has_key('XXX')
3250 assert env3.has_key('XXX'), env3.has_key('XXX')
3251 assert env.has_key('YYY'), env.has_key('YYY')
3252 assert env2.has_key('YYY'), env2.has_key('YYY')
3253 assert env3.has_key('YYY'), env3.has_key('YYY')
3254 assert not env.has_key('ZZZ'), env.has_key('ZZZ')
3255 assert not env2.has_key('ZZZ'), env2.has_key('ZZZ')
3256 assert env3.has_key('ZZZ'), env3.has_key('ZZZ')
3258 def test_items(self):
3259 """Test the OverrideEnvironment Dictionary() method"""
3260 env, env2, env3 = self.envs
3261 items = env.Dictionary()
3262 assert items == {'XXX' : 'x', 'YYY' : 'y'}, items
3263 items = env2.Dictionary()
3264 assert items == {'XXX' : 'x2', 'YYY' : 'y'}, items
3265 items = env3.Dictionary()
3266 assert items == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, items
3268 def test_items(self):
3269 """Test the OverrideEnvironment items() method"""
3270 env, env2, env3 = self.envs
3273 assert items == [('XXX', 'x'), ('YYY', 'y')], items
3274 items = env2.items()
3276 assert items == [('XXX', 'x2'), ('YYY', 'y')], items
3277 items = env3.items()
3279 assert items == [('XXX', 'x3'), ('YYY', 'y3'), ('ZZZ', 'z3')], items
3281 def test_gvars(self):
3282 """Test the OverrideEnvironment gvars() method"""
3283 env, env2, env3 = self.envs
3285 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3286 gvars = env2.gvars()
3287 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3288 gvars = env3.gvars()
3289 assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3291 def test_lvars(self):
3292 """Test the OverrideEnvironment lvars() method"""
3293 env, env2, env3 = self.envs
3295 assert lvars == {}, lvars
3296 lvars = env2.lvars()
3297 assert lvars == {'XXX' : 'x2'}, lvars
3298 lvars = env3.lvars()
3299 assert lvars == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, lvars
3301 def test_Replace(self):
3302 """Test the OverrideEnvironment Replace() method"""
3303 env, env2, env3 = self.envs
3304 assert env['XXX'] == 'x', env['XXX']
3305 assert env2['XXX'] == 'x2', env2['XXX']
3306 assert env3['XXX'] == 'x3', env3['XXX']
3307 assert env['YYY'] == 'y', env['YYY']
3308 assert env2['YYY'] == 'y', env2['YYY']
3309 assert env3['YYY'] == 'y3', env3['YYY']
3311 env.Replace(YYY = 'y4')
3313 assert env['XXX'] == 'x', env['XXX']
3314 assert env2['XXX'] == 'x2', env2['XXX']
3315 assert env3['XXX'] == 'x3', env3['XXX']
3316 assert env['YYY'] == 'y4', env['YYY']
3317 assert env2['YYY'] == 'y4', env2['YYY']
3318 assert env3['YYY'] == 'y3', env3['YYY']
3320 # Tests a number of Base methods through an OverrideEnvironment to
3321 # make sure they handle overridden constructionv variables properly.
3323 # The following Base methods also call self.subst(), and so could
3324 # theoretically be subject to problems with evaluating overridden
3325 # variables, but they're never really called that way in the rest
3326 # of our code, so we won't worry about them (at least for now):
3341 # SourceSignatures()
3342 # TargetSignatures()
3344 # It's unlikely Copy() will ever be called this way, so let the
3345 # other methods test that handling overridden values works.
3346 #def test_Copy(self):
3347 # """Test the OverrideEnvironment Copy() method"""
3350 def test_FindIxes(self):
3351 """Test the OverrideEnvironment FindIxes() method"""
3352 env, env2, env3 = self.envs
3353 x = env.FindIxes(['xaaay'], 'XXX', 'YYY')
3354 assert x == 'xaaay', x
3355 x = env2.FindIxes(['x2aaay'], 'XXX', 'YYY')
3356 assert x == 'x2aaay', x
3357 x = env3.FindIxes(['x3aaay3'], 'XXX', 'YYY')
3358 assert x == 'x3aaay3', x
3360 def test_ReplaceIxes(self):
3361 """Test the OverrideEnvironment ReplaceIxes() method"""
3362 env, env2, env3 = self.envs
3363 x = env.ReplaceIxes('xaaay', 'XXX', 'YYY', 'YYY', 'XXX')
3364 assert x == 'yaaax', x
3365 x = env2.ReplaceIxes('x2aaay', 'XXX', 'YYY', 'YYY', 'XXX')
3366 assert x == 'yaaax2', x
3367 x = env3.ReplaceIxes('x3aaay3', 'XXX', 'YYY', 'YYY', 'XXX')
3368 assert x == 'y3aaax3', x
3370 # It's unlikely WhereIs() will ever be called this way, so let the
3371 # other methods test that handling overridden values works.
3372 #def test_WhereIs(self):
3373 # """Test the OverrideEnvironment WhereIs() method"""
3377 """Test the OverrideEnvironment Dir() method"""
3378 env, env2, env3 = self.envs
3379 x = env.Dir('ddir/$XXX')
3380 assert self.checkpath(x, 'ddir/x'), str(x)
3381 x = env2.Dir('ddir/$XXX')
3382 assert self.checkpath(x, 'ddir/x2'), str(x)
3383 x = env3.Dir('ddir/$XXX')
3384 assert self.checkpath(x, 'ddir/x3'), str(x)
3386 def test_Entry(self):
3387 """Test the OverrideEnvironment Entry() method"""
3388 env, env2, env3 = self.envs
3389 x = env.Entry('edir/$XXX')
3390 assert self.checkpath(x, 'edir/x'), str(x)
3391 x = env2.Entry('edir/$XXX')
3392 assert self.checkpath(x, 'edir/x2'), str(x)
3393 x = env3.Entry('edir/$XXX')
3394 assert self.checkpath(x, 'edir/x3'), str(x)
3396 def test_File(self):
3397 """Test the OverrideEnvironment File() method"""
3398 env, env2, env3 = self.envs
3399 x = env.File('fdir/$XXX')
3400 assert self.checkpath(x, 'fdir/x'), str(x)
3401 x = env2.File('fdir/$XXX')
3402 assert self.checkpath(x, 'fdir/x2'), str(x)
3403 x = env3.File('fdir/$XXX')
3404 assert self.checkpath(x, 'fdir/x3'), str(x)
3406 def test_Split(self):
3407 """Test the OverrideEnvironment Split() method"""
3408 env, env2, env3 = self.envs
3409 env['AAA'] = '$XXX $YYY $ZZZ'
3410 x = env.Split('$AAA')
3411 assert x == ['x', 'y'], x
3412 x = env2.Split('$AAA')
3413 assert x == ['x2', 'y'], x
3414 x = env3.Split('$AAA')
3415 assert x == ['x3', 'y3', 'z3'], x
3419 class NoSubstitutionProxyTestCase(unittest.TestCase,TestEnvironmentFixture):
3421 def test___init__(self):
3422 """Test NoSubstitutionProxy initialization"""
3423 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3424 assert env['XXX'] == 'x', env['XXX']
3425 assert env['YYY'] == 'y', env['YYY']
3427 proxy = NoSubstitutionProxy(env)
3428 assert proxy['XXX'] == 'x', proxy['XXX']
3429 assert proxy['YYY'] == 'y', proxy['YYY']
3431 def test_attributes(self):
3432 """Test getting and setting NoSubstitutionProxy attributes"""
3434 setattr(env, 'env_attr', 'value1')
3436 proxy = NoSubstitutionProxy(env)
3437 setattr(proxy, 'proxy_attr', 'value2')
3439 x = getattr(env, 'env_attr')
3440 assert x == 'value1', x
3441 x = getattr(proxy, 'env_attr')
3442 assert x == 'value1', x
3444 x = getattr(env, 'proxy_attr')
3445 assert x == 'value2', x
3446 x = getattr(proxy, 'proxy_attr')
3447 assert x == 'value2', x
3449 def test_subst(self):
3450 """Test the NoSubstitutionProxy.subst() method"""
3451 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3452 assert env['XXX'] == 'x', env['XXX']
3453 assert env['YYY'] == 'y', env['YYY']
3455 proxy = NoSubstitutionProxy(env)
3456 assert proxy['XXX'] == 'x', proxy['XXX']
3457 assert proxy['YYY'] == 'y', proxy['YYY']
3459 x = env.subst('$XXX')
3461 x = proxy.subst('$XXX')
3462 assert x == '$XXX', x
3464 x = proxy.subst('$YYY', raw=7, target=None, source=None,
3466 extra_meaningless_keyword_argument=None)
3467 assert x == '$YYY', x
3469 def test_subst_kw(self):
3470 """Test the NoSubstitutionProxy.subst_kw() method"""
3471 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3472 assert env['XXX'] == 'x', env['XXX']
3473 assert env['YYY'] == 'y', env['YYY']
3475 proxy = NoSubstitutionProxy(env)
3476 assert proxy['XXX'] == 'x', proxy['XXX']
3477 assert proxy['YYY'] == 'y', proxy['YYY']
3479 x = env.subst_kw({'$XXX':'$YYY'})
3480 assert x == {'x':'y'}, x
3481 x = proxy.subst_kw({'$XXX':'$YYY'})
3482 assert x == {'$XXX':'$YYY'}, x
3484 def test_subst_list(self):
3485 """Test the NoSubstitutionProxy.subst_list() method"""
3486 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3487 assert env['XXX'] == 'x', env['XXX']
3488 assert env['YYY'] == 'y', env['YYY']
3490 proxy = NoSubstitutionProxy(env)
3491 assert proxy['XXX'] == 'x', proxy['XXX']
3492 assert proxy['YYY'] == 'y', proxy['YYY']
3494 x = env.subst_list('$XXX')
3495 assert x == [['x']], x
3496 x = proxy.subst_list('$XXX')
3499 x = proxy.subst_list('$YYY', raw=0, target=None, source=None, conv=None)
3502 def test_subst_target_source(self):
3503 """Test the NoSubstitutionProxy.subst_target_source() method"""
3504 env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3505 assert env['XXX'] == 'x', env['XXX']
3506 assert env['YYY'] == 'y', env['YYY']
3508 proxy = NoSubstitutionProxy(env)
3509 assert proxy['XXX'] == 'x', proxy['XXX']
3510 assert proxy['YYY'] == 'y', proxy['YYY']
3512 args = ('$XXX $TARGET $SOURCE $YYY',)
3513 kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')}
3514 x = apply(env.subst_target_source, args, kw)
3515 assert x == 'x ttt sss y', x
3516 x = apply(proxy.subst_target_source, args, kw)
3517 assert x == ' ttt sss ', x
3521 if __name__ == "__main__":
3522 suite = unittest.TestSuite()
3523 tclasses = [ SubstitutionTestCase,
3525 OverrideEnvironmentTestCase,
3526 NoSubstitutionProxyTestCase ]
3527 for tclass in tclasses:
3528 names = unittest.getTestCaseNames(tclass, 'test_')
3529 suite.addTests(map(tclass, names))
3530 if not unittest.TextTestRunner().run(suite).wasSuccessful():