Merged revisions 1907-1940,1942-1967 via svnmerge from
[scons.git] / src / engine / SCons / EnvironmentTests.py
1 #
2 # __COPYRIGHT__
3 #
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:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
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.
22 #
23
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25
26 import copy
27 import os
28 import string
29 import StringIO
30 import sys
31 import TestCmd
32 import unittest
33 import UserList
34
35 from SCons.Environment import *
36 import SCons.Warnings
37
38 def diff_env(env1, env2):
39     s1 = "env1 = {\n"
40     s2 = "env2 = {\n"
41     d = {}
42     for k in env1._dict.keys() + env2._dict.keys():
43         d[k] = None
44     keys = d.keys()
45     keys.sort()
46     for k in keys:
47         if env1.has_key(k):
48            if env2.has_key(k):
49                if env1[k] != env2[k]:
50                    s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
51                    s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
52            else:
53                s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
54         elif env2.has_key(k):
55            s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
56     s1 = s1 + "}\n"
57     s2 = s2 + "}\n"
58     return s1 + s2
59
60 def diff_dict(d1, d2):
61     s1 = "d1 = {\n"
62     s2 = "d2 = {\n"
63     d = {}
64     for k in d1.keys() + d2.keys():
65         d[k] = None
66     keys = d.keys()
67     keys.sort()
68     for k in keys:
69         if d1.has_key(k):
70            if d2.has_key(k):
71                if d1[k] != d2[k]:
72                    s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
73                    s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
74            else:
75                s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
76         elif env2.has_key(k):
77            s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
78     s1 = s1 + "}\n"
79     s2 = s2 + "}\n"
80     return s1 + s2
81
82 called_it = {}
83 built_it = {}
84
85 class Builder:
86     """A dummy Builder class for testing purposes.  "Building"
87     a target is simply setting a value in the dictionary.
88     """
89     def __init__(self, name = None):
90         self.name = name
91
92     def __call__(self, env, target=None, source=None, **kw):
93         global called_it
94         called_it['target'] = target
95         called_it['source'] = source
96         called_it.update(kw)
97
98     def execute(self, target = None, **kw):
99         global built_it
100         built_it[target] = 1
101
102
103
104 scanned_it = {}
105
106 class Scanner:
107     """A dummy Scanner class for testing purposes.  "Scanning"
108     a target is simply setting a value in the dictionary.
109     """
110     def __init__(self, name, skeys=[]):
111         self.name = name
112         self.skeys = skeys
113
114     def __call__(self, filename):
115         global scanned_it
116         scanned_it[filename] = 1
117
118     def __cmp__(self, other):
119         try:
120             return cmp(self.__dict__, other.__dict__)
121         except AttributeError:
122             return 1
123
124     def get_skeys(self, env):
125         return self.skeys
126
127     def __str__(self):
128         return self.name
129
130
131
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))
139
140
141
142 class DummyNode:
143     def __init__(self, name):
144         self.name = name
145     def __str__(self):
146         return self.name
147     def rfile(self):
148         return self
149     def get_subst_proxy(self):
150         return self
151
152 def test_tool( env ):
153     env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
154
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):
164                 kw[key] = value
165         if not kw.has_key('BUILDERS'):
166             static_obj = SCons.Builder.Builder(action = {},
167                                                emitter = {},
168                                                suffix = '.o',
169                                                single_source = 1)
170             kw['BUILDERS'] = {'Object' : static_obj}
171             
172         env = apply(Environment, args, kw)
173         return env
174
175 class SubstitutionTestCase(unittest.TestCase):
176
177     def test___init__(self):
178         """Test initializing a SubstitutionEnvironment
179         """
180         env = SubstitutionEnvironment()
181         assert not env.has_key('__env__')
182
183     def test___cmp__(self):
184         """Test comparing SubstitutionEnvironments
185         """
186
187         env1 = SubstitutionEnvironment(XXX = 'x')
188         env2 = SubstitutionEnvironment(XXX = 'x')
189         env3 = SubstitutionEnvironment(XXX = 'xxx')
190         env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x')
191
192         assert env1 == env2
193         assert env1 != env3
194         assert env1 != env4
195
196     def test___delitem__(self):
197         """Test deleting a variable from a SubstitutionEnvironment
198         """
199         env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
200         env2 = SubstitutionEnvironment(XXX = 'x')
201         del env1['YYY']
202         assert env1 == env2
203
204     def test___getitem__(self):
205         """Test fetching a variable from a SubstitutionEnvironment
206         """
207         env = SubstitutionEnvironment(XXX = 'x')
208         assert env['XXX'] == 'x', env['XXX']
209
210     def test___setitem__(self):
211         """Test setting a variable in a SubstitutionEnvironment
212         """
213         env1 = SubstitutionEnvironment(XXX = 'x')
214         env2 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
215         env1['YYY'] = 'y'
216         assert env1 == env2
217
218     def test_get(self):
219         """Test the SubstitutionEnvironment get() method
220         """
221         env = SubstitutionEnvironment(XXX = 'x')
222         assert env.get('XXX') == 'x', env.get('XXX')
223         assert env.get('YYY') is None, env.get('YYY')
224
225     def test_has_key(self):
226         """Test the SubstitutionEnvironment has_key() method
227         """
228         env = SubstitutionEnvironment(XXX = 'x')
229         assert env.has_key('XXX')
230         assert not env.has_key('YYY')
231
232     def test_items(self):
233         """Test the SubstitutionEnvironment items() method
234         """
235         env = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
236         items = env.items()
237         assert items == [('XXX','x'), ('YYY','y')], items
238
239     def test_arg2nodes(self):
240         """Test the arg2nodes method
241         """
242         env = SubstitutionEnvironment()
243         dict = {}
244         class X(SCons.Node.Node):
245             pass
246         def Factory(name, directory = None, create = 1, dict=dict, X=X):
247             if not dict.has_key(name):
248                 dict[name] = X()
249                 dict[name].name = name
250             return dict[name]
251
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"
256
257         import types
258         if hasattr(types, 'UnicodeType'):
259             code = """if 1:
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"
264                 \n"""
265             exec code in globals(), locals()
266
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"
273
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"
281
282         class SConsNode(SCons.Node.Node):
283             pass
284         nodes = env.arg2nodes(SConsNode())
285         assert len(nodes) == 1, nodes
286         assert isinstance(nodes[0], SConsNode), node
287
288         class OtherNode:
289             pass
290         nodes = env.arg2nodes(OtherNode())
291         assert len(nodes) == 1, nodes
292         assert isinstance(nodes[0], OtherNode), node
293
294         def lookup_a(str, F=Factory):
295             if str[0] == 'a':
296                 n = F(str)
297                 n.a = 1
298                 return n
299             else:
300                 return None
301
302         def lookup_b(str, F=Factory):
303             if str[0] == 'b':
304                 n = F(str)
305                 n.b = 1
306                 return n
307             else:
308                 return None
309
310         env_ll = SubstitutionEnvironment()
311         env_ll.lookup_list = [lookup_a, lookup_b]
312
313         nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
314         assert len(nodes) == 3, nodes
315
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]
319
320         assert nodes[1].name == 'bbb'
321         assert not hasattr(nodes[1], 'a'), nodes[1]
322         assert nodes[1].b == 1, nodes[1]
323
324         assert nodes[2].name == 'ccc'
325         assert not hasattr(nodes[2], 'a'), nodes[1]
326         assert not hasattr(nodes[2], 'b'), nodes[1]
327
328         def lookup_bbbb(str, F=Factory):
329             if str == 'bbbb':
330                 n = F(str)
331                 n.bbbb = 1
332                 return n
333             else:
334                 return None
335
336         def lookup_c(str, F=Factory):
337             if str[0] == 'c':
338                 n = F(str)
339                 n.c = 1
340                 return n
341             else:
342                 return None
343
344         nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
345                                      [lookup_c, lookup_bbbb, lookup_b])
346         assert len(nodes) == 2, nodes
347
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]
353
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]
359
360     def test_arg2nodes_target_source(self):
361         """Test the arg2nodes method with target= and source= keywords
362         """
363         targets = [DummyNode('t1'), DummyNode('t2')]
364         sources = [DummyNode('s1'), DummyNode('s2')]
365         env = SubstitutionEnvironment()
366         nodes = env.arg2nodes(['${TARGET}-a',
367                                '${SOURCE}-b',
368                                '${TARGETS[1]}-c',
369                                '${SOURCES[1]}-d'],
370                               DummyNode,
371                               target=targets,
372                               source=sources)
373         names = map(lambda n: n.name, nodes)
374         assert names == ['t1-a', 's1-b', 't2-c', 's2-d'], names
375
376     def test_gvars(self):
377         """Test the base class gvars() method"""
378         env = SubstitutionEnvironment()
379         gvars = env.gvars()
380         assert gvars == {}, gvars
381
382     def test_lvars(self):
383         """Test the base class lvars() method"""
384         env = SubstitutionEnvironment()
385         lvars = env.lvars()
386         assert lvars == {}, lvars
387
388     def test_subst(self):
389         """Test substituting construction variables within strings
390
391         Check various combinations, including recursive expansion
392         of variables into other variables.
393         """
394         env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
395         mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
396         assert mystr == "a aA b", mystr
397
398         # Changed the tests below to reflect a bug fix in
399         # subst()
400         env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
401         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
402         assert mystr == "b bA bB b", mystr
403
404         env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
405         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
406         assert mystr == "c cA cB c", mystr
407
408         # Lists:
409         env = SubstitutionEnvironment(AAA = ['a', 'aa', 'aaa'])
410         mystr = env.subst("$AAA")
411         assert mystr == "a aa aaa", mystr
412
413         # Tuples:
414         env = SubstitutionEnvironment(AAA = ('a', 'aa', 'aaa'))
415         mystr = env.subst("$AAA")
416         assert mystr == "a aa aaa", mystr
417
418         t1 = DummyNode('t1')
419         t2 = DummyNode('t2')
420         s1 = DummyNode('s1')
421         s2 = DummyNode('s2')
422
423         env = SubstitutionEnvironment(AAA = 'aaa')
424         s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
425         assert s == "aaa t1 s1 s2", s
426         s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
427         assert s == "aaa t1 t2 s1", s
428
429         # Test callables in the SubstitutionEnvironment
430         def foo(target, source, env, for_signature):
431             assert str(target) == 't', target
432             assert str(source) == 's', source
433             return env["FOO"]
434
435         env = SubstitutionEnvironment(BAR=foo, FOO='baz')
436         t = DummyNode('t')
437         s = DummyNode('s')
438
439         subst = env.subst('test $BAR', target=t, source=s)
440         assert subst == 'test baz', subst
441
442         # Test not calling callables in the SubstitutionEnvironment
443         if 0:
444             # This will take some serious surgery to subst() and
445             # subst_list(), so just leave these tests out until we can
446             # do that.
447             def bar(arg):
448                 pass
449
450             env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
451
452             subst = env.subst('$BAR', call=None)
453             assert subst is bar, subst
454
455             subst = env.subst('$FOO', call=None)
456             assert subst is bar, subst
457
458     def test_subst_kw(self):
459         """Test substituting construction variables within dictionaries"""
460         env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
461         kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
462         assert len(kw) == 2, kw
463         assert kw['a'] == 'aaa', kw['a']
464         assert kw['bbb'] == 'b', kw['bbb']
465
466     def test_subst_list(self):
467         """Test substituting construction variables in command lists
468         """
469         env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
470         l = env.subst_list("$AAA ${AAA}A $BBBB $BBB")
471         assert l == [["a", "aA", "b"]], l
472
473         # Changed the tests below to reflect a bug fix in
474         # subst()
475         env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
476         l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
477         assert l == [["b", "bA", "bB", "b"]], l
478
479         env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
480         l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
481         assert l == [["c", "cA", "cB", "c"]], mystr
482
483         env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
484         lst = env.subst_list([ "$AAA", "B $CCC" ])
485         assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst
486
487         t1 = DummyNode('t1')
488         t2 = DummyNode('t2')
489         s1 = DummyNode('s1')
490         s2 = DummyNode('s2')
491
492         env = SubstitutionEnvironment(AAA = 'aaa')
493         s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
494         assert s == [["aaa", "t1", "s1", "s2"]], s
495         s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
496         assert s == [["aaa", "t1", "t2", "s1"]], s
497
498         # Test callables in the SubstitutionEnvironment
499         def foo(target, source, env, for_signature):
500             assert str(target) == 't', target
501             assert str(source) == 's', source
502             return env["FOO"]
503
504         env = SubstitutionEnvironment(BAR=foo, FOO='baz')
505         t = DummyNode('t')
506         s = DummyNode('s')
507
508         lst = env.subst_list('test $BAR', target=t, source=s)
509         assert lst == [['test', 'baz']], lst
510
511         # Test not calling callables in the SubstitutionEnvironment
512         if 0:
513             # This will take some serious surgery to subst() and
514             # subst_list(), so just leave these tests out until we can
515             # do that.
516             def bar(arg):
517                 pass
518
519             env = SubstitutionEnvironment(BAR=bar, FOO='$BAR')
520
521             subst = env.subst_list('$BAR', call=None)
522             assert subst is bar, subst
523
524             subst = env.subst_list('$FOO', call=None)
525             assert subst is bar, subst
526
527     def test_subst_path(self):
528         """Test substituting a path list
529         """
530         class MyProxy:
531             def __init__(self, val):
532                 self.val = val
533             def get(self):
534                 return self.val + '-proxy'
535
536         class MyNode:
537             def __init__(self, val):
538                 self.val = val
539             def get_subst_proxy(self):
540                 return self
541             def __str__(self):
542                 return self.val
543
544         class MyObj:
545             pass
546
547         env = SubstitutionEnvironment(FOO='foo', BAR='bar', PROXY=MyProxy('my1'))
548
549         r = env.subst_path('$FOO')
550         assert r == ['foo'], r
551
552         r = env.subst_path(['$FOO', 'xxx', '$BAR'])
553         assert r == ['foo', 'xxx', 'bar'], r
554
555         r = env.subst_path(['$FOO', '$TARGET', '$SOURCE', '$BAR'])
556         assert r == ['foo', '', '', 'bar'], r
557
558         r = env.subst_path(['$FOO', '$TARGET', '$BAR'], target=MyNode('ttt'))
559         assert map(str, r) == ['foo', 'ttt', 'bar'], r
560
561         r = env.subst_path(['$FOO', '$SOURCE', '$BAR'], source=MyNode('sss'))
562         assert map(str, r) == ['foo', 'sss', 'bar'], r
563
564         n = MyObj()
565
566         r = env.subst_path(['$PROXY', MyProxy('my2'), n])
567         assert r == ['my1-proxy', 'my2-proxy', n], r
568
569         class StringableObj:
570             def __init__(self, s):
571                 self.s = s
572             def __str__(self):
573                 return self.s
574
575         env = SubstitutionEnvironment(FOO=StringableObj("foo"),
576                           BAR=StringableObj("bar"))
577
578         r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ])
579         assert r == [ "foo/bar", "bar/baz" ]
580
581         r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ])
582         assert r == [ "bar/foo", "baz/bar" ]
583
584         r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ])
585         assert r == [ "bar/foo/bar", "baz/bar/baz" ]
586
587     def test_subst_target_source(self):
588         """Test the base environment subst_target_source() method"""
589         env = SubstitutionEnvironment(AAA = 'a', BBB = 'b')
590         mystr = env.subst_target_source("$AAA ${AAA}A $BBBB $BBB")
591         assert mystr == "a aA b", mystr
592
593     def test_backtick(self):
594         """Test the backtick() method for capturing command output"""
595         env = SubstitutionEnvironment()
596
597         test = TestCmd.TestCmd(workdir = '')
598         test.write('stdout.py', """\
599 import sys
600 sys.stdout.write('this came from stdout.py\\n')
601 sys.exit(0)
602 """)
603         test.write('stderr.py', """\
604 import sys
605 sys.stderr.write('this came from stderr.py\\n')
606 sys.exit(0)
607 """)
608         test.write('fail.py', """\
609 import sys
610 sys.exit(1)
611 """)
612
613         save_stderr = sys.stderr
614
615         python = '"' + sys.executable + '"'
616
617         try:
618             cmd = '%s %s' % (python, test.workpath('stdout.py'))
619             output = env.backtick(cmd)
620
621             assert output == 'this came from stdout.py\n', output
622
623             sys.stderr = StringIO.StringIO()
624
625             cmd = '%s %s' % (python, test.workpath('stderr.py'))
626             output = env.backtick(cmd)
627             errout = sys.stderr.getvalue()
628
629             assert output == '', output
630             assert errout == 'this came from stderr.py\n', errout
631
632             sys.stderr = StringIO.StringIO()
633
634             cmd = '%s %s' % (python, test.workpath('fail.py'))
635             try:
636                 env.backtick(cmd)
637             except OSError, e:
638                 assert str(e) == "'%s' exited 1" % cmd, str(e)
639             else:
640                 self.fail("did not catch expected OSError")
641
642         finally:
643             sys.stderr = save_stderr
644
645     def test_AddMethod(self):
646         """Test the AddMethod() method"""
647         env = SubstitutionEnvironment(FOO = 'foo')
648
649         def func(self):
650             return 'func-' + self['FOO']
651
652         assert not hasattr(env, 'func')
653         env.AddMethod(func)
654         r = env.func()
655         assert r == 'func-foo', r
656
657         assert not hasattr(env, 'bar')
658         env.AddMethod(func, 'bar')
659         r = env.bar()
660         assert r == 'func-foo', r
661
662         def func2(self, arg=''):
663             return 'func2-' + self['FOO'] + arg
664
665         env.AddMethod(func2)
666         r = env.func2()
667         assert r == 'func2-foo', r
668         r = env.func2('-xxx')
669         assert r == 'func2-foo-xxx', r
670
671         env.AddMethod(func2, 'func')
672         r = env.func()
673         assert r == 'func2-foo', r
674         r = env.func('-yyy')
675         assert r == 'func2-foo-yyy', r
676
677     def test_Override(self):
678         "Test overriding construction variables"
679         env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4)
680         assert env['ONE'] == 1, env['ONE']
681         assert env['TWO'] == 2, env['TWO']
682         assert env['THREE'] == 3, env['THREE']
683         assert env['FOUR'] == 4, env['FOUR']
684
685         env2 = env.Override({'TWO'   : '10',
686                              'THREE' :'x $THREE y',
687                              'FOUR'  : ['x', '$FOUR', 'y']})
688         assert env2['ONE'] == 1, env2['ONE']
689         assert env2['TWO'] == '10', env2['TWO']
690         assert env2['THREE'] == 'x 3 y', env2['THREE']
691         assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR']
692
693         assert env['ONE'] == 1, env['ONE']
694         assert env['TWO'] == 2, env['TWO']
695         assert env['THREE'] == 3, env['THREE']
696         assert env['FOUR'] == 4, env['FOUR']
697
698         env2.Replace(ONE = "won")
699         assert env2['ONE'] == "won", env2['ONE']
700         assert env['ONE'] == 1, env['ONE']
701
702     def test_ParseFlags(self):
703         """Test the ParseFlags() method
704         """
705         env = SubstitutionEnvironment()
706
707         empty = {
708             'ASFLAGS'       : [],
709             'CFLAGS'        : [],
710             'CCFLAGS'       : [],
711             'CPPDEFINES'    : [],
712             'CPPFLAGS'      : [],
713             'CPPPATH'       : [],
714             'FRAMEWORKPATH' : [],
715             'FRAMEWORKS'    : [],
716             'LIBPATH'       : [],
717             'LIBS'          : [],
718             'LINKFLAGS'     : [],
719             'RPATH'         : [],
720         }
721
722         d = env.ParseFlags(None)
723         assert d == empty, d
724
725         d = env.ParseFlags('')
726         assert d == empty, d
727
728         d = env.ParseFlags([])
729         assert d == empty, d
730
731         s = "-I/usr/include/fum -I bar -X\n" + \
732             "-L/usr/fax -L foo -lxxx -l yyy " + \
733             "-Wa,-as -Wl,-link " + \
734             "-Wl,-rpath=rpath1 " + \
735             "-Wl,-R,rpath2 " + \
736             "-Wl,-Rrpath3 " + \
737             "-Wp,-cpp " + \
738             "-std=c99 " + \
739             "-framework Carbon " + \
740             "-frameworkdir=fwd1 " + \
741             "-Ffwd2 " + \
742             "-F fwd3 " + \
743             "-pthread " + \
744             "-mno-cygwin -mwindows " + \
745             "-arch i386 -isysroot /tmp +DD64 " + \
746             "-DFOO -DBAR=value -D BAZ"
747
748         d = env.ParseFlags(s)
749
750         assert d['ASFLAGS'] == ['-as'], d['ASFLAGS']
751         assert d['CFLAGS']  == ['-std=c99']
752         assert d['CCFLAGS'] == ['-X', '-Wa,-as',
753                                   '-pthread', '-mno-cygwin',
754                                   ('-arch', 'i386'), ('-isysroot', '/tmp'),
755                                   '+DD64'], d['CCFLAGS']
756         assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES']
757         assert d['CPPFLAGS'] == ['-Wp,-cpp'], d['CPPFLAGS']
758         assert d['CPPPATH'] == ['/usr/include/fum', 'bar'], d['CPPPATH']
759         assert d['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], d['FRAMEWORKPATH']
760         assert d['FRAMEWORKS'] == ['Carbon'], d['FRAMEWORKS']
761         assert d['LIBPATH'] == ['/usr/fax', 'foo'], d['LIBPATH']
762         assert d['LIBS'] == ['xxx', 'yyy'], d['LIBS']
763         assert d['LINKFLAGS'] == ['-Wl,-link', '-pthread',
764                                   '-mno-cygwin', '-mwindows',
765                                   ('-arch', 'i386'),
766                                   ('-isysroot', '/tmp'),
767                                   '+DD64'], d['LINKFLAGS']
768         assert d['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], d['RPATH']
769
770
771     def test_MergeFlags(self):
772         """Test the MergeFlags() method
773         """
774         env = SubstitutionEnvironment()
775         env.MergeFlags('')
776         assert not env.has_key('CCFLAGS'), env['CCFLAGS']
777         env.MergeFlags('-X')
778         assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
779         env.MergeFlags('-X')
780         assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
781
782         env = SubstitutionEnvironment(CCFLAGS=None)
783         env.MergeFlags('-Y')
784         assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS']
785
786         env = SubstitutionEnvironment()
787         env.MergeFlags({'A':['aaa'], 'B':['bbb']})
788         assert env['A'] == ['aaa'], env['A']
789         assert env['B'] == ['bbb'], env['B']
790
791
792
793 class BaseTestCase(unittest.TestCase,TestEnvironmentFixture):
794
795     def test___init__(self):
796         """Test construction Environment creation
797
798         Create two with identical arguments and check that
799         they compare the same.
800         """
801         env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
802         env2 = self.TestEnvironment(XXX = 'x', YYY = 'y')
803         assert env1 == env2, diff_env(env1, env2)
804
805         assert not env1.has_key('__env__')
806         assert not env2.has_key('__env__')
807
808     def test_options(self):
809         """Test that options only get applied once."""
810         class FakeOptions:
811             def __init__(self, key, val):
812                 self.calls = 0
813                 self.key = key
814                 self.val = val
815             def keys(self):
816                 return [self.key]
817             def Update(self, env):
818                 env[self.key] = self.val
819                 self.calls = self.calls + 1
820
821         o = FakeOptions('AAA', 'fake_opt')
822         env = Environment(options=o, AAA='keyword_arg')
823         assert o.calls == 1, o.calls
824         assert env['AAA'] == 'fake_opt', env['AAA']
825
826     def test_get(self):
827         """Test the get() method."""
828         env = self.TestEnvironment(aaa = 'AAA')
829
830         x = env.get('aaa')
831         assert x == 'AAA', x
832         x = env.get('aaa', 'XXX')
833         assert x == 'AAA', x
834         x = env.get('bbb')
835         assert x is None, x
836         x = env.get('bbb', 'XXX')
837         assert x == 'XXX', x
838
839     def test_Builder_calls(self):
840         """Test Builder calls through different environments
841         """
842         global called_it
843
844         b1 = Builder()
845         b2 = Builder()
846
847         env = Environment()
848         env.Replace(BUILDERS = { 'builder1' : b1,
849                                  'builder2' : b2 })
850         called_it = {}
851         env.builder1('in1')
852         assert called_it['target'] == None, called_it
853         assert called_it['source'] == ['in1'], called_it
854
855         called_it = {}
856         env.builder2(source = 'in2', xyzzy = 1)
857         assert called_it['target'] == None, called_it
858         assert called_it['source'] == ['in2'], called_it
859         assert called_it['xyzzy'] == 1, called_it
860
861         called_it = {}
862         env.builder1(foo = 'bar')
863         assert called_it['foo'] == 'bar', called_it
864         assert called_it['target'] == None, called_it
865         assert called_it['source'] == None, called_it
866
867
868
869     def test_Builder_execs(self):
870         """Test Builder execution through different environments
871
872         One environment is initialized with a single
873         Builder object, one with a list of a single Builder
874         object, and one with a list of two Builder objects.
875         """
876         global built_it
877
878         b1 = Builder()
879         b2 = Builder()
880
881         built_it = {}
882         env3 = Environment()
883         env3.Replace(BUILDERS = { 'builder1' : b1,
884                                   'builder2' : b2 })
885         env3.builder1.execute(target = 'out1')
886         env3.builder2.execute(target = 'out2')
887         env3.builder1.execute(target = 'out3')
888         assert built_it['out1']
889         assert built_it['out2']
890         assert built_it['out3']
891
892         env4 = env3.Clone()
893         assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
894         assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
895
896         # Now test BUILDERS as a dictionary.
897         built_it = {}
898         env5 = self.TestEnvironment(BUILDERS={ 'foo' : b1 })
899         env5['BUILDERS']['bar'] = b2
900         env5.foo.execute(target='out1')
901         env5.bar.execute(target='out2')
902         assert built_it['out1']
903         assert built_it['out2']
904
905         built_it = {}
906         env6 = Environment()
907         env6['BUILDERS'] = { 'foo' : b1,
908                              'bar' : b2 }
909         env6.foo.execute(target='out1')
910         env6.bar.execute(target='out2')
911         assert built_it['out1']
912         assert built_it['out2']
913
914     def test_Scanners(self):
915         """Test setting SCANNERS in various ways
916
917         One environment is initialized with a single
918         Scanner object, one with a list of a single Scanner
919         object, and one with a list of two Scanner objects.
920         """
921         global scanned_it
922
923         s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
924         s2 = Scanner(name = 'scanner2', skeys = [".m4"])
925         s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"])
926
927 #        XXX Tests for scanner execution through different environments,
928 #        XXX if we ever want to do that some day
929 #        scanned_it = {}
930 #        env1 = self.TestEnvironment(SCANNERS = s1)
931 #        env1.scanner1(filename = 'out1')
932 #        assert scanned_it['out1']
933 #
934 #        scanned_it = {}
935 #        env2 = self.TestEnvironment(SCANNERS = [s1])
936 #        env1.scanner1(filename = 'out1')
937 #        assert scanned_it['out1']
938 #
939 #        scanned_it = {}
940 #        env3 = Environment()
941 #        env3.Replace(SCANNERS = [s1])
942 #        env3.scanner1(filename = 'out1')
943 #        env3.scanner2(filename = 'out2')
944 #        env3.scanner1(filename = 'out3')
945 #        assert scanned_it['out1']
946 #        assert scanned_it['out2']
947 #        assert scanned_it['out3']
948
949         suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"]
950
951         env = Environment()
952         try: del env['SCANNERS']
953         except KeyError: pass
954         s = map(env.get_scanner, suffixes)
955         assert s == [None, None, None, None, None], s
956
957         env = self.TestEnvironment(SCANNERS = [])
958         s = map(env.get_scanner, suffixes)
959         assert s == [None, None, None, None, None], s
960
961         env.Replace(SCANNERS = [s1])
962         s = map(env.get_scanner, suffixes)
963         assert s == [s1, s1, None, None, None], s
964
965         env.Append(SCANNERS = [s2])
966         s = map(env.get_scanner, suffixes)
967         assert s == [s1, s1, None, s2, None], s
968
969         env.AppendUnique(SCANNERS = [s3])
970         s = map(env.get_scanner, suffixes)
971         assert s == [s1, s1, None, s2, s3], s
972
973         env = env.Clone(SCANNERS = [s2])
974         s = map(env.get_scanner, suffixes)
975         assert s == [None, None, None, s2, None], s
976
977         env['SCANNERS'] = [s1]
978         s = map(env.get_scanner, suffixes)
979         assert s == [s1, s1, None, None, None], s
980
981         env.PrependUnique(SCANNERS = [s2, s1])
982         s = map(env.get_scanner, suffixes)
983         assert s == [s1, s1, None, s2, None], s
984
985         env.Prepend(SCANNERS = [s3])
986         s = map(env.get_scanner, suffixes)
987         assert s == [s1, s1, None, s3, s3], s
988
989     def test_ENV(self):
990         """Test setting the external ENV in Environments
991         """
992         env = Environment()
993         assert env.Dictionary().has_key('ENV')
994
995         env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' })
996         assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
997
998     def test_ReservedVariables(self):
999         """Test generation of warnings when reserved variable names
1000         are set in an environment."""
1001
1002         SCons.Warnings.enableWarningClass(SCons.Warnings.ReservedVariableWarning)
1003         old = SCons.Warnings.warningAsException(1)
1004
1005         try:
1006             env4 = Environment()
1007             for kw in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
1008                 exc_caught = None
1009                 try:
1010                     env4[kw] = 'xyzzy'
1011                 except SCons.Warnings.ReservedVariableWarning:
1012                     exc_caught = 1
1013                 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw
1014                 assert not env4.has_key(kw), "`%s' variable was incorrectly set" % kw
1015         finally:
1016             SCons.Warnings.warningAsException(old)
1017
1018     def test_IllegalVariables(self):
1019         """Test that use of illegal variables raises an exception"""
1020         env = Environment()
1021         def test_it(var, env=env):
1022             exc_caught = None
1023             try:
1024                 env[var] = 1
1025             except SCons.Errors.UserError:
1026                 exc_caught = 1
1027             assert exc_caught, "did not catch UserError for '%s'" % var
1028         env['aaa'] = 1
1029         assert env['aaa'] == 1, env['aaa']
1030         test_it('foo/bar')
1031         test_it('foo.bar')
1032         test_it('foo-bar')
1033
1034     def test_autogenerate(dict):
1035         """Test autogenerating variables in a dictionary."""
1036
1037         drive, p = os.path.splitdrive(os.getcwd())
1038         def normalize_path(path, drive=drive):
1039             if path[0] in '\\/':
1040                 path = drive + path
1041             path = os.path.normpath(path)
1042             drive, path = os.path.splitdrive(path)
1043             return string.lower(drive) + path
1044
1045         env = dict.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ],
1046                           LIBLINKPREFIX = 'foo',
1047                           LIBLINKSUFFIX = 'bar')
1048
1049         def RDirs(pathlist, fs=env.fs):
1050             return fs.Dir('xx').Rfindalldirs(pathlist)
1051
1052         env['RDirs'] = RDirs
1053         flags = env.subst_list('$_LIBFLAGS', 1)[0]
1054         assert flags == ['foobar', 'foobar', 'foobazbar'], flags
1055
1056         blat = env.fs.Dir('blat')
1057
1058         env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ],
1059                     INCPREFIX = 'foo ',
1060                     INCSUFFIX = 'bar',
1061                     FOO = 'baz')
1062         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1063         expect = [ '$(',
1064                    normalize_path('foo'),
1065                    normalize_path('xx/foobar'),
1066                    normalize_path('foo'),
1067                    normalize_path('xx/baz/bar'),
1068                    normalize_path('foo'),
1069                    normalize_path('blatbar'),
1070                    '$)',
1071         ]
1072         assert flags == expect, flags
1073
1074         env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ],
1075                     INCPREFIX = 'foo ',
1076                     INCSUFFIX = 'bar',
1077                     FOO = 'baz')
1078         flags = env.subst_list('$_F77INCFLAGS', 1)[0]
1079         expect = [ '$(',
1080                    normalize_path('foo'),
1081                    normalize_path('xx/foobar'),
1082                    normalize_path('foo'),
1083                    normalize_path('xx/baz/bar'),
1084                    normalize_path('foo'),
1085                    normalize_path('blatbar'),
1086                    '$)',
1087         ]
1088         assert flags == expect, flags
1089
1090         env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '')
1091         l = env.subst_list('$_CPPINCFLAGS')
1092         assert l == [[]], l
1093         l = env.subst_list('$_F77INCFLAGS')
1094         assert l == [[]], l
1095         l = env.subst_list('$_LIBDIRFLAGS')
1096         assert l == [[]], l
1097
1098         env.fs.Repository('/rep1')
1099         env.fs.Repository('/rep2')
1100         env.Replace(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
1101                     INCPREFIX = '-I ',
1102                     INCSUFFIX = 'XXX',
1103                     FOO = 'baz')
1104         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
1105         expect = [ '$(',
1106                    '-I', normalize_path('xx/fooXXX'),
1107                    '-I', normalize_path('/rep1/xx/fooXXX'),
1108                    '-I', normalize_path('/rep2/xx/fooXXX'),
1109                    '-I', normalize_path('/a/bXXX'),
1110                    '-I', normalize_path('xx/baz/barXXX'),
1111                    '-I', normalize_path('/rep1/xx/baz/barXXX'),
1112                    '-I', normalize_path('/rep2/xx/baz/barXXX'),
1113                    '-I', normalize_path('blatXXX'),
1114                    '$)'
1115         ]
1116         def normalize_if_path(arg, np=normalize_path):
1117             if arg not in ('$(','$)','-I'):
1118                 return np(str(arg))
1119             return arg
1120         flags = map(normalize_if_path, flags)
1121         assert flags == expect, flags
1122
1123     def test_platform(self):
1124         """Test specifying a platform callable when instantiating."""
1125         class platform:
1126             def __str__(self):        return "TestPlatform"
1127             def __call__(self, env):  env['XYZZY'] = 777
1128
1129         def tool(env):
1130             env['SET_TOOL'] = 'initialized'
1131             assert env['PLATFORM'] == "TestPlatform"
1132
1133         env = self.TestEnvironment(platform = platform(), tools = [tool])
1134         assert env['XYZZY'] == 777, env
1135         assert env['PLATFORM'] == "TestPlatform"
1136         assert env['SET_TOOL'] == "initialized"
1137
1138     def test_Default_PLATFORM(self):
1139         """Test overriding the default PLATFORM variable"""
1140         class platform:
1141             def __str__(self):        return "DefaultTestPlatform"
1142             def __call__(self, env):  env['XYZZY'] = 888
1143
1144         def tool(env):
1145             env['SET_TOOL'] = 'abcde'
1146             assert env['PLATFORM'] == "DefaultTestPlatform"
1147
1148         import SCons.Defaults
1149         save = SCons.Defaults.ConstructionEnvironment.copy()
1150         try:
1151             import SCons.Defaults
1152             SCons.Defaults.ConstructionEnvironment.update({
1153                 'PLATFORM' : platform(),
1154             })
1155             env = self.TestEnvironment(tools = [tool])
1156             assert env['XYZZY'] == 888, env
1157             assert env['PLATFORM'] == "DefaultTestPlatform"
1158             assert env['SET_TOOL'] == "abcde"
1159         finally:
1160             SCons.Defaults.ConstructionEnvironment = save
1161
1162     def test_tools(self):
1163         """Test specifying a tool callable when instantiating."""
1164         def t1(env):
1165             env['TOOL1'] = 111
1166         def t2(env):
1167             env['TOOL2'] = 222
1168         def t3(env):
1169             env['AAA'] = env['XYZ']
1170         def t4(env):
1171             env['TOOL4'] = 444
1172         env = self.TestEnvironment(tools = [t1, t2, t3], XYZ = 'aaa')
1173         assert env['TOOL1'] == 111, env['TOOL1']
1174         assert env['TOOL2'] == 222, env
1175         assert env['AAA'] == 'aaa', env
1176         t4(env)
1177         assert env['TOOL4'] == 444, env
1178
1179         test = TestCmd.TestCmd(workdir = '')
1180         test.write('faketool.py', """\
1181 def generate(env, **kw):
1182     for k, v in kw.items():
1183         env[k] = v
1184
1185 def exists(env):
1186     return 1
1187 """)
1188
1189         env = self.TestEnvironment(tools = [('faketool', {'a':1, 'b':2, 'c':3})],
1190                           toolpath = [test.workpath('')])
1191         assert env['a'] == 1, env['a']
1192         assert env['b'] == 2, env['b']
1193         assert env['c'] == 3, env['c']
1194
1195     def test_Default_TOOLS(self):
1196         """Test overriding the default TOOLS variable"""
1197         def t5(env):
1198             env['TOOL5'] = 555
1199         def t6(env):
1200             env['TOOL6'] = 666
1201         def t7(env):
1202             env['BBB'] = env['XYZ']
1203         def t8(env):
1204             env['TOOL8'] = 888
1205
1206         import SCons.Defaults
1207         save = SCons.Defaults.ConstructionEnvironment.copy()
1208         try:
1209             SCons.Defaults.ConstructionEnvironment.update({
1210                 'TOOLS' : [t5, t6, t7],
1211             })
1212             env = Environment(XYZ = 'bbb')
1213             assert env['TOOL5'] == 555, env['TOOL5']
1214             assert env['TOOL6'] == 666, env
1215             assert env['BBB'] == 'bbb', env
1216             t8(env)
1217             assert env['TOOL8'] == 888, env
1218         finally:
1219             SCons.Defaults.ConstructionEnvironment = save
1220
1221     def test_null_tools(self):
1222         """Test specifying a tool of None is OK."""
1223         def t1(env):
1224             env['TOOL1'] = 111
1225         def t2(env):
1226             env['TOOL2'] = 222
1227         env = self.TestEnvironment(tools = [t1, None, t2], XYZ = 'aaa')
1228         assert env['TOOL1'] == 111, env['TOOL1']
1229         assert env['TOOL2'] == 222, env
1230         assert env['XYZ'] == 'aaa', env
1231         env = self.TestEnvironment(tools = [None], XYZ = 'xyz')
1232         assert env['XYZ'] == 'xyz', env
1233         env = self.TestEnvironment(tools = [t1, '', t2], XYZ = 'ddd')
1234         assert env['TOOL1'] == 111, env['TOOL1']
1235         assert env['TOOL2'] == 222, env
1236         assert env['XYZ'] == 'ddd', env
1237
1238     def test_concat(self):
1239         "Test _concat()"
1240         e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
1241         s = e1.subst
1242         x = s("${_concat('', '', '', __env__)}")
1243         assert x == '', x
1244         x = s("${_concat('', [], '', __env__)}")
1245         assert x == '', x
1246         x = s("${_concat(PRE, '', SUF, __env__)}")
1247         assert x == '', x
1248         x = s("${_concat(PRE, STR, SUF, __env__)}")
1249         assert x == 'prea bsuf', x
1250         x = s("${_concat(PRE, LIST, SUF, __env__)}")
1251         assert x == 'preasuf prebsuf', x
1252
1253     def test_gvars(self):
1254         """Test the Environment gvars() method"""
1255         env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1256         gvars = env.gvars()
1257         assert gvars['XXX'] == 'x', gvars['XXX']
1258         assert gvars['YYY'] == 'y', gvars['YYY']
1259         assert gvars['ZZZ'] == 'z', gvars['ZZZ']
1260
1261     def test__update(self):
1262         """Test the _update() method"""
1263         env = self.TestEnvironment(X = 'x', Y = 'y', Z = 'z')
1264         assert env['X'] == 'x', env['X']
1265         assert env['Y'] == 'y', env['Y']
1266         assert env['Z'] == 'z', env['Z']
1267         env._update({'X'       : 'xxx',
1268                      'TARGET'  : 't',
1269                      'TARGETS' : 'ttt',
1270                      'SOURCE'  : 's',
1271                      'SOURCES' : 'sss',
1272                      'Z'       : 'zzz'})
1273         assert env['X'] == 'xxx', env['X']
1274         assert env['Y'] == 'y', env['Y']
1275         assert env['Z'] == 'zzz', env['Z']
1276         assert env['TARGET'] == 't', env['TARGET']
1277         assert env['TARGETS'] == 'ttt', env['TARGETS']
1278         assert env['SOURCE'] == 's', env['SOURCE']
1279         assert env['SOURCES'] == 'sss', env['SOURCES']
1280
1281
1282
1283     def test_Append(self):
1284         """Test appending to construction variables in an Environment
1285         """
1286
1287         b1 = Environment()['BUILDERS']
1288         b2 = Environment()['BUILDERS']
1289         assert b1 == b2, diff_dict(b1, b2)
1290
1291         import UserDict
1292         UD = UserDict.UserDict
1293         import UserList
1294         UL = UserList.UserList
1295
1296         cases = [
1297             'a1',       'A1',           'a1A1',
1298             'a2',       ['A2'],         ['a2', 'A2'],
1299             'a3',       UL(['A3']),     UL(['a', '3', 'A3']),
1300             'a4',       '',             'a4',
1301             'a5',       [],             ['a5'],
1302             'a6',       UL([]),         UL(['a', '6']),
1303             'a7',       [''],           ['a7', ''],
1304             'a8',       UL(['']),       UL(['a', '8', '']),
1305
1306             ['e1'],     'E1',           ['e1', 'E1'],
1307             ['e2'],     ['E2'],         ['e2', 'E2'],
1308             ['e3'],     UL(['E3']),     UL(['e3', 'E3']),
1309             ['e4'],     '',             ['e4'],
1310             ['e5'],     [],             ['e5'],
1311             ['e6'],     UL([]),         UL(['e6']),
1312             ['e7'],     [''],           ['e7', ''],
1313             ['e8'],     UL(['']),       UL(['e8', '']),
1314
1315             UL(['i1']), 'I1',           UL(['i1', 'I', '1']),
1316             UL(['i2']), ['I2'],         UL(['i2', 'I2']),
1317             UL(['i3']), UL(['I3']),     UL(['i3', 'I3']),
1318             UL(['i4']), '',             UL(['i4']),
1319             UL(['i5']), [],             UL(['i5']),
1320             UL(['i6']), UL([]),         UL(['i6']),
1321             UL(['i7']), [''],           UL(['i7', '']),
1322             UL(['i8']), UL(['']),       UL(['i8', '']),
1323
1324             {'d1':1},   'D1',           {'d1':1, 'D1':None},
1325             {'d2':1},   ['D2'],         {'d2':1, 'D2':None},
1326             {'d3':1},   UL(['D3']),     {'d3':1, 'D3':None},
1327             {'d4':1},   {'D4':1},       {'d4':1, 'D4':1},
1328             {'d5':1},   UD({'D5':1}),   UD({'d5':1, 'D5':1}),
1329
1330             UD({'u1':1}), 'U1',         UD({'u1':1, 'U1':None}),
1331             UD({'u2':1}), ['U2'],       UD({'u2':1, 'U2':None}),
1332             UD({'u3':1}), UL(['U3']),   UD({'u3':1, 'U3':None}),
1333             UD({'u4':1}), {'U4':1},     UD({'u4':1, 'U4':1}),
1334             UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
1335
1336             '',         'M1',           'M1',
1337             '',         ['M2'],         ['M2'],
1338             '',         UL(['M3']),     UL(['M3']),
1339             '',         '',             '',
1340             '',         [],             [],
1341             '',         UL([]),         UL([]),
1342             '',         [''],           [''],
1343             '',         UL(['']),       UL(['']),
1344
1345             [],         'N1',           ['N1'],
1346             [],         ['N2'],         ['N2'],
1347             [],         UL(['N3']),     UL(['N3']),
1348             [],         '',             [],
1349             [],         [],             [],
1350             [],         UL([]),         UL([]),
1351             [],         [''],           [''],
1352             [],         UL(['']),       UL(['']),
1353
1354             UL([]),     'O1',           ['O', '1'],
1355             UL([]),     ['O2'],         ['O2'],
1356             UL([]),     UL(['O3']),     UL(['O3']),
1357             UL([]),     '',             UL([]),
1358             UL([]),     [],             UL([]),
1359             UL([]),     UL([]),         UL([]),
1360             UL([]),     [''],           UL(['']),
1361             UL([]),     UL(['']),       UL(['']),
1362
1363             [''],       'P1',           ['', 'P1'],
1364             [''],       ['P2'],         ['', 'P2'],
1365             [''],       UL(['P3']),     UL(['', 'P3']),
1366             [''],       '',             [''],
1367             [''],       [],             [''],
1368             [''],       UL([]),         UL(['']),
1369             [''],       [''],           ['', ''],
1370             [''],       UL(['']),       UL(['', '']),
1371
1372             UL(['']),   'Q1',           ['', 'Q', '1'],
1373             UL(['']),   ['Q2'],         ['', 'Q2'],
1374             UL(['']),   UL(['Q3']),     UL(['', 'Q3']),
1375             UL(['']),   '',             UL(['']),
1376             UL(['']),   [],             UL(['']),
1377             UL(['']),   UL([]),         UL(['']),
1378             UL(['']),   [''],           UL(['', '']),
1379             UL(['']),   UL(['']),       UL(['', '']),
1380         ]
1381
1382         env = Environment()
1383         failed = 0
1384         while cases:
1385             input, append, expect = cases[:3]
1386             env['XXX'] = copy.copy(input)
1387             try:
1388                 env.Append(XXX = append)
1389             except Exception, e:
1390                 if failed == 0: print
1391                 print "    %s Append %s exception: %s" % \
1392                       (repr(input), repr(append), e)
1393                 failed = failed + 1
1394             else:
1395                 result = env['XXX']
1396                 if result != expect:
1397                     if failed == 0: print
1398                     print "    %s Append %s => %s did not match %s" % \
1399                           (repr(input), repr(append), repr(result), repr(expect))
1400                     failed = failed + 1
1401             del cases[:3]
1402         assert failed == 0, "%d Append() cases failed" % failed
1403
1404         env['UL'] = UL(['foo'])
1405         env.Append(UL = 'bar')
1406         result = env['UL']
1407         assert isinstance(result, UL), repr(result)
1408         assert result == ['foo', 'b', 'a', 'r'], result
1409
1410         env['CLVar'] = CLVar(['foo'])
1411         env.Append(CLVar = 'bar')
1412         result = env['CLVar']
1413         assert isinstance(result, CLVar), repr(result)
1414         assert result == ['foo', 'bar'], result
1415
1416         class C:
1417             def __init__(self, name):
1418                 self.name = name
1419             def __str__(self):
1420                 return self.name
1421             def __cmp__(self, other):
1422                 raise "should not compare"
1423
1424         ccc = C('ccc')
1425
1426         env2 = self.TestEnvironment(CCC1 = ['c1'], CCC2 = ccc)
1427         env2.Append(CCC1 = ccc, CCC2 = ['c2'])
1428         assert env2['CCC1'][0] == 'c1', env2['CCC1']
1429         assert env2['CCC1'][1] is ccc, env2['CCC1']
1430         assert env2['CCC2'][0] is ccc, env2['CCC2']
1431         assert env2['CCC2'][1] == 'c2', env2['CCC2']
1432
1433         env3 = self.TestEnvironment(X = {'x1' : 7})
1434         env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1435         assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X']
1436         assert env3['Y'] == {'y1': 10}, env3['Y']
1437
1438         env4 = self.TestEnvironment(BUILDERS = {'z1' : 11})
1439         env4.Append(BUILDERS = {'z2' : 12})
1440         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1441         assert hasattr(env4, 'z1')
1442         assert hasattr(env4, 'z2')
1443
1444     def test_AppendENVPath(self):
1445         """Test appending to an ENV path."""
1446         env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1447                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1448         # have to include the pathsep here so that the test will work on UNIX too.
1449         env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
1450         env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
1451         env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
1452         env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
1453         assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
1454         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
1455
1456     def test_AppendUnique(self):
1457         """Test appending to unique values to construction variables
1458
1459         This strips values that are already present when lists are
1460         involved."""
1461         env = self.TestEnvironment(AAA1 = 'a1',
1462                           AAA2 = 'a2',
1463                           AAA3 = 'a3',
1464                           AAA4 = 'a4',
1465                           AAA5 = 'a5',
1466                           BBB1 = ['b1'],
1467                           BBB2 = ['b2'],
1468                           BBB3 = ['b3'],
1469                           BBB4 = ['b4'],
1470                           BBB5 = ['b5'],
1471                           CCC1 = '',
1472                           CCC2 = '')
1473         env.AppendUnique(AAA1 = 'a1',
1474                          AAA2 = ['a2'],
1475                          AAA3 = ['a3', 'b', 'c', 'a3'],
1476                          AAA4 = 'a4.new',
1477                          AAA5 = ['a5.new'],
1478                          BBB1 = 'b1',
1479                          BBB2 = ['b2'],
1480                          BBB3 = ['b3', 'c', 'd', 'b3'],
1481                          BBB4 = 'b4.new',
1482                          BBB5 = ['b5.new'],
1483                          CCC1 = 'c1',
1484                          CCC2 = ['c2'])
1485
1486         assert env['AAA1'] == 'a1a1', env['AAA1']
1487         assert env['AAA2'] == ['a2'], env['AAA2']
1488         assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3']
1489         assert env['AAA4'] == 'a4a4.new', env['AAA4']
1490         assert env['AAA5'] == ['a5', 'a5.new'], env['AAA5']
1491         assert env['BBB1'] == ['b1'], env['BBB1']
1492         assert env['BBB2'] == ['b2'], env['BBB2']
1493         assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3']
1494         assert env['BBB4'] == ['b4', 'b4.new'], env['BBB4']
1495         assert env['BBB5'] == ['b5', 'b5.new'], env['BBB5']
1496         assert env['CCC1'] == 'c1', env['CCC1']
1497         assert env['CCC2'] == ['c2'], env['CCC2']
1498
1499         env['CLVar'] = CLVar([])
1500         env.AppendUnique(CLVar = 'bar')
1501         result = env['CLVar']
1502         if sys.version[0] == '1':
1503             # Python 1.5.2 has a quirky behavior where CLVar([]) actually
1504             # matches '' and [] due to different __coerce__() semantics
1505             # in the UserList implementation.  It isn't worth a lot of
1506             # effort to get this corner case to work identically (support
1507             # for Python 1.5 support will die soon anyway), so just treat
1508             # it separately for now.
1509             assert result == 'bar', result
1510         else:
1511             assert isinstance(result, CLVar), repr(result)
1512             assert result == ['bar'], result
1513
1514         env['CLVar'] = CLVar(['abc'])
1515         env.AppendUnique(CLVar = 'bar')
1516         result = env['CLVar']
1517         assert isinstance(result, CLVar), repr(result)
1518         assert result == ['abc', 'bar'], result
1519
1520         env['CLVar'] = CLVar(['bar'])
1521         env.AppendUnique(CLVar = 'bar')
1522         result = env['CLVar']
1523         assert isinstance(result, CLVar), repr(result)
1524         assert result == ['bar'], result
1525
1526     def test_Clone(self):
1527         """Test construction environment copying
1528
1529         Update the copy independently afterwards and check that
1530         the original remains intact (that is, no dangling
1531         references point to objects in the copied environment).
1532         Clone the original with some construction variable
1533         updates and check that the original remains intact
1534         and the copy has the updated values.
1535         """
1536         env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
1537         env2 = env1.Clone()
1538         env1copy = env1.Clone()
1539         assert env1copy == env1copy
1540         assert env2 == env2
1541         env2.Replace(YYY = 'yyy')
1542         assert env2 == env2
1543         assert env1 != env2
1544         assert env1 == env1copy
1545
1546         env3 = env1.Clone(XXX = 'x3', ZZZ = 'z3')
1547         assert env3 == env3
1548         assert env3.Dictionary('XXX') == 'x3'
1549         assert env3.Dictionary('YYY') == 'y'
1550         assert env3.Dictionary('ZZZ') == 'z3'
1551         assert env1 == env1copy
1552
1553         # Ensure that lists and dictionaries are
1554         # deep copied, but not instances.
1555         class TestA:
1556             pass
1557         env1 = self.TestEnvironment(XXX=TestA(), YYY = [ 1, 2, 3 ],
1558                            ZZZ = { 1:2, 3:4 })
1559         env2=env1.Clone()
1560         env2.Dictionary('YYY').append(4)
1561         env2.Dictionary('ZZZ')[5] = 6
1562         assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
1563         assert 4 in env2.Dictionary('YYY')
1564         assert not 4 in env1.Dictionary('YYY')
1565         assert env2.Dictionary('ZZZ').has_key(5)
1566         assert not env1.Dictionary('ZZZ').has_key(5)
1567
1568         #
1569         env1 = self.TestEnvironment(BUILDERS = {'b1' : 1})
1570         assert hasattr(env1, 'b1'), "env1.b1 was not set"
1571         assert env1.b1.env == env1, "b1.env doesn't point to env1"
1572         env2 = env1.Clone(BUILDERS = {'b2' : 2})
1573         assert env2 is env2
1574         assert env2 == env2
1575         assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
1576         assert env1.b1.env == env1, "b1.env was changed"
1577         assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
1578         assert hasattr(env2, 'b2'), "env2.b2 was not set"
1579         assert env2.b2.env == env2, "b2.env doesn't point to env2"
1580
1581         # Ensure that specifying new tools in a copied environment
1582         # works.
1583         def foo(env): env['FOO'] = 1
1584         def bar(env): env['BAR'] = 2
1585         def baz(env): env['BAZ'] = 3
1586         env1 = self.TestEnvironment(tools=[foo])
1587         env2 = env1.Clone()
1588         env3 = env1.Clone(tools=[bar, baz])
1589
1590         assert env1.get('FOO') is 1
1591         assert env1.get('BAR') is None
1592         assert env1.get('BAZ') is None
1593         assert env2.get('FOO') is 1
1594         assert env2.get('BAR') is None
1595         assert env2.get('BAZ') is None
1596         assert env3.get('FOO') is 1
1597         assert env3.get('BAR') is 2
1598         assert env3.get('BAZ') is 3
1599
1600         # Ensure that recursive variable substitution when copying
1601         # environments works properly.
1602         env1 = self.TestEnvironment(CCFLAGS = '-DFOO', XYZ = '-DXYZ')
1603         env2 = env1.Clone(CCFLAGS = '$CCFLAGS -DBAR',
1604                          XYZ = ['-DABC', 'x $XYZ y', '-DDEF'])
1605         x = env2.get('CCFLAGS')
1606         assert x == '-DFOO -DBAR', x
1607         x = env2.get('XYZ')
1608         assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x
1609
1610         # Ensure that special properties of a class don't get
1611         # lost on copying.
1612         env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2'))
1613         x = env1.get('FLAGS')
1614         assert x == ['flag1', 'flag2'], x
1615         env2 = env1.Clone()
1616         env2.Append(FLAGS = 'flag3 flag4')
1617         x = env2.get('FLAGS')
1618         assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
1619
1620         # Test that the environment stores the toolpath and
1621         # re-uses it for copies.
1622         test = TestCmd.TestCmd(workdir = '')
1623
1624         test.write('xxx.py', """\
1625 def exists(env):
1626     1
1627 def generate(env):
1628     env['XXX'] = 'one'
1629 """)
1630
1631         test.write('yyy.py', """\
1632 def exists(env):
1633     1
1634 def generate(env):
1635     env['YYY'] = 'two'
1636 """)
1637
1638         env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
1639         assert env['XXX'] == 'one', env['XXX']
1640         env = env.Clone(tools=['yyy'])
1641         assert env['YYY'] == 'two', env['YYY']
1642
1643     def test_Copy(self):
1644         """Test copying using the old env.Copy() method"""
1645         env1 = self.TestEnvironment(XXX = 'x', YYY = 'y')
1646         env2 = env1.Copy()
1647         env1copy = env1.Copy()
1648         assert env1copy == env1copy
1649         assert env2 == env2
1650         env2.Replace(YYY = 'yyy')
1651         assert env2 == env2
1652         assert env1 != env2
1653         assert env1 == env1copy
1654
1655     def test_Detect(self):
1656         """Test Detect()ing tools"""
1657         test = TestCmd.TestCmd(workdir = '')
1658         test.subdir('sub1', 'sub2')
1659         sub1 = test.workpath('sub1')
1660         sub2 = test.workpath('sub2')
1661
1662         if sys.platform == 'win32':
1663             test.write(['sub1', 'xxx'], "sub1/xxx\n")
1664             test.write(['sub2', 'xxx'], "sub2/xxx\n")
1665
1666             env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1667
1668             x = env.Detect('xxx.exe')
1669             assert x is None, x
1670
1671             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1672
1673             env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1674
1675             x = env.Detect('xxx.exe')
1676             assert x == 'xxx.exe', x
1677
1678             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1679
1680             x = env.Detect('xxx.exe')
1681             assert x == 'xxx.exe', x
1682
1683         else:
1684             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1685             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1686
1687             env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1688
1689             x = env.Detect('xxx.exe')
1690             assert x is None, x
1691
1692             sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1693             os.chmod(sub2_xxx_exe, 0755)
1694
1695             env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] })
1696
1697             x = env.Detect('xxx.exe')
1698             assert x == 'xxx.exe', x
1699
1700             sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1701             os.chmod(sub1_xxx_exe, 0755)
1702
1703             x = env.Detect('xxx.exe')
1704             assert x == 'xxx.exe', x
1705
1706         env = self.TestEnvironment(ENV = { 'PATH' : [] })
1707         x = env.Detect('xxx.exe')
1708         assert x is None, x
1709
1710     def test_Dictionary(self):
1711         """Test retrieval of known construction variables
1712
1713         Fetch them from the Dictionary and check for well-known
1714         defaults that get inserted.
1715         """
1716         env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1717         assert env.Dictionary('XXX') == 'x'
1718         assert env.Dictionary('YYY') == 'y'
1719         assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
1720         xxx, zzz = env.Dictionary('XXX', 'ZZZ')
1721         assert xxx == 'x'
1722         assert zzz == 'z'
1723         assert env.Dictionary().has_key('BUILDERS')
1724         assert env.Dictionary().has_key('CC')
1725         assert env.Dictionary().has_key('CCFLAGS')
1726         assert env.Dictionary().has_key('ENV')
1727
1728         assert env['XXX'] == 'x'
1729         env['XXX'] = 'foo'
1730         assert env.Dictionary('XXX') == 'foo'
1731         del env['XXX']
1732         assert not env.Dictionary().has_key('XXX')
1733
1734     def test_FindIxes(self):
1735         "Test FindIxes()"
1736         env = self.TestEnvironment(LIBPREFIX='lib',
1737                           LIBSUFFIX='.a',
1738                           SHLIBPREFIX='lib',
1739                           SHLIBSUFFIX='.so',
1740                           PREFIX='pre',
1741                           SUFFIX='post')
1742
1743         paths = [os.path.join('dir', 'libfoo.a'),
1744                  os.path.join('dir', 'libfoo.so')]
1745
1746         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1747         assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1748         assert None == env.FindIxes(paths, 'PREFIX', 'POST')
1749
1750         paths = ['libfoo.a', 'prefoopost']
1751
1752         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1753         assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1754         assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
1755
1756     def test_ParseConfig(self):
1757         """Test the ParseConfig() method"""
1758         env = self.TestEnvironment(COMMAND='command',
1759                           ASFLAGS='assembler',
1760                           CCFLAGS=[''],
1761                           CPPDEFINES=[],
1762                           CPPFLAGS=[''],
1763                           CPPPATH='string',
1764                           FRAMEWORKPATH=[],
1765                           FRAMEWORKS=[],
1766                           LIBPATH=['list'],
1767                           LIBS='',
1768                           LINKFLAGS=[''],
1769                           RPATH=[])
1770
1771         orig_backtick = env.backtick
1772         class my_backtick:
1773             def __init__(self, save_command, output):
1774                 self.save_command = save_command
1775                 self.output = output
1776             def __call__(self, command):
1777                 self.save_command.append(command)
1778                 return self.output
1779
1780         try:
1781             save_command = []
1782             env.backtick = my_backtick(save_command, 
1783                                  "-I/usr/include/fum -I bar -X\n" + \
1784                                  "-L/usr/fax -L foo -lxxx -l yyy " + \
1785                                  "-Wa,-as -Wl,-link " + \
1786                                  "-Wl,-rpath=rpath1 " + \
1787                                  "-Wl,-R,rpath2 " + \
1788                                  "-Wl,-Rrpath3 " + \
1789                                  "-Wp,-cpp abc " + \
1790                                  "-framework Carbon " + \
1791                                  "-frameworkdir=fwd1 " + \
1792                                  "-Ffwd2 " + \
1793                                  "-F fwd3 " + \
1794                                  "-pthread " + \
1795                                  "-mno-cygwin -mwindows " + \
1796                                  "-arch i386 -isysroot /tmp +DD64 " + \
1797                                  "-DFOO -DBAR=value")
1798             env.ParseConfig("fake $COMMAND")
1799             assert save_command == ['fake command'], save_command
1800             assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS']
1801             assert env['CCFLAGS'] == ['', '-X', '-Wa,-as',
1802                                       '-pthread', '-mno-cygwin',
1803                                       ('-arch', 'i386'), ('-isysroot', '/tmp'),
1804                                       '+DD64'], env['CCFLAGS']
1805             assert env['CPPDEFINES'] == ['FOO', ['BAR', 'value']], env['CPPDEFINES']
1806             assert env['CPPFLAGS'] == ['', '-Wp,-cpp'], env['CPPFLAGS']
1807             assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1808             assert env['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], env['FRAMEWORKPATH']
1809             assert env['FRAMEWORKS'] == ['Carbon'], env['FRAMEWORKS']
1810             assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
1811             assert env['LIBS'] == ['xxx', 'yyy', env.File('abc')], env['LIBS']
1812             assert env['LINKFLAGS'] == ['', '-Wl,-link', '-pthread',
1813                                         '-mno-cygwin', '-mwindows',
1814                                         ('-arch', 'i386'),
1815                                         ('-isysroot', '/tmp'),
1816                                         '+DD64'], env['LINKFLAGS']
1817             assert env['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], env['RPATH']
1818
1819             env.backtick = my_backtick([], "-Ibar")
1820             env.ParseConfig("fake2")
1821             assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1822             env.ParseConfig("fake2", unique=0)
1823             assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar', 'bar'], env['CPPPATH']
1824         finally:
1825             env.backtick = orig_backtick
1826
1827     def test_ParseDepends(self):
1828         """Test the ParseDepends() method"""
1829         test = TestCmd.TestCmd(workdir = '')
1830
1831         test.write('single', """
1832 #file: dependency
1833
1834 f0: \
1835    d1 \
1836    d2 \
1837    d3 \
1838
1839 """)
1840
1841         test.write('multiple', """
1842 f1: foo
1843 f2 f3: bar
1844 f4: abc def
1845 #file: dependency
1846 f5: \
1847    ghi \
1848    jkl \
1849    mno \
1850 """)
1851
1852         env = self.TestEnvironment(SINGLE = test.workpath('single'))
1853
1854         tlist = []
1855         dlist = []
1856         def my_depends(target, dependency, tlist=tlist, dlist=dlist):
1857             tlist.extend(target)
1858             dlist.extend(dependency)
1859
1860         env.Depends = my_depends
1861
1862         env.ParseDepends(test.workpath('does_not_exist'))
1863
1864         exc_caught = None
1865         try:
1866             env.ParseDepends(test.workpath('does_not_exist'), must_exist=1)
1867         except IOError:
1868             exc_caught = 1
1869         assert exc_caught, "did not catch expected IOError"
1870
1871         del tlist[:]
1872         del dlist[:]
1873
1874         env.ParseDepends('$SINGLE', only_one=1)
1875         t = map(str, tlist)
1876         d = map(str, dlist)
1877         assert t == ['f0'], t
1878         assert d == ['d1', 'd2', 'd3'], d
1879
1880         del tlist[:]
1881         del dlist[:]
1882
1883         env.ParseDepends(test.workpath('multiple'))
1884         t = map(str, tlist)
1885         d = map(str, dlist)
1886         assert t == ['f1', 'f2', 'f3', 'f4', 'f5'], t
1887         assert d == ['foo', 'bar', 'abc', 'def', 'ghi', 'jkl', 'mno'], d
1888
1889         exc_caught = None
1890         try:
1891             env.ParseDepends(test.workpath('multiple'), only_one=1)
1892         except SCons.Errors.UserError:
1893             exc_caught = 1
1894         assert exc_caught, "did not catch expected UserError"
1895
1896     def test_Platform(self):
1897         """Test the Platform() method"""
1898         env = self.TestEnvironment(WIN32='win32', NONE='no-such-platform')
1899
1900         exc_caught = None
1901         try:
1902             env.Platform('does_not_exist')
1903         except SCons.Errors.UserError:
1904             exc_caught = 1
1905         assert exc_caught, "did not catch expected UserError"
1906
1907         exc_caught = None
1908         try:
1909             env.Platform('$NONE')
1910         except SCons.Errors.UserError:
1911             exc_caught = 1
1912         assert exc_caught, "did not catch expected UserError"
1913
1914         env.Platform('posix')
1915         assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
1916
1917         env.Platform('$WIN32')
1918         assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
1919
1920     def test_Prepend(self):
1921         """Test prepending to construction variables in an Environment
1922         """
1923         import UserDict
1924         UD = UserDict.UserDict
1925         import UserList
1926         UL = UserList.UserList
1927
1928         cases = [
1929             'a1',       'A1',           'A1a1',
1930             'a2',       ['A2'],         ['A2', 'a2'],
1931             'a3',       UL(['A3']),     UL(['A3', 'a', '3']),
1932             'a4',       '',             'a4',
1933             'a5',       [],             ['a5'],
1934             'a6',       UL([]),         UL(['a', '6']),
1935             'a7',       [''],           ['', 'a7'],
1936             'a8',       UL(['']),       UL(['', 'a', '8']),
1937
1938             ['e1'],     'E1',           ['E1', 'e1'],
1939             ['e2'],     ['E2'],         ['E2', 'e2'],
1940             ['e3'],     UL(['E3']),     UL(['E3', 'e3']),
1941             ['e4'],     '',             ['e4'],
1942             ['e5'],     [],             ['e5'],
1943             ['e6'],     UL([]),         UL(['e6']),
1944             ['e7'],     [''],           ['', 'e7'],
1945             ['e8'],     UL(['']),       UL(['', 'e8']),
1946
1947             UL(['i1']), 'I1',           UL(['I', '1', 'i1']),
1948             UL(['i2']), ['I2'],         UL(['I2', 'i2']),
1949             UL(['i3']), UL(['I3']),     UL(['I3', 'i3']),
1950             UL(['i4']), '',             UL(['i4']),
1951             UL(['i5']), [],             UL(['i5']),
1952             UL(['i6']), UL([]),         UL(['i6']),
1953             UL(['i7']), [''],           UL(['', 'i7']),
1954             UL(['i8']), UL(['']),       UL(['', 'i8']),
1955
1956             {'d1':1},   'D1',           {'d1':1, 'D1':None},
1957             {'d2':1},   ['D2'],         {'d2':1, 'D2':None},
1958             {'d3':1},   UL(['D3']),     {'d3':1, 'D3':None},
1959             {'d4':1},   {'D4':1},       {'d4':1, 'D4':1},
1960             {'d5':1},   UD({'D5':1}),   UD({'d5':1, 'D5':1}),
1961
1962             UD({'u1':1}), 'U1',         UD({'u1':1, 'U1':None}),
1963             UD({'u2':1}), ['U2'],       UD({'u2':1, 'U2':None}),
1964             UD({'u3':1}), UL(['U3']),   UD({'u3':1, 'U3':None}),
1965             UD({'u4':1}), {'U4':1},     UD({'u4':1, 'U4':1}),
1966             UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}),
1967
1968             '',         'M1',           'M1',
1969             '',         ['M2'],         ['M2'],
1970             '',         UL(['M3']),     UL(['M3']),
1971             '',         '',             '',
1972             '',         [],             [],
1973             '',         UL([]),         UL([]),
1974             '',         [''],           [''],
1975             '',         UL(['']),       UL(['']),
1976
1977             [],         'N1',           ['N1'],
1978             [],         ['N2'],         ['N2'],
1979             [],         UL(['N3']),     UL(['N3']),
1980             [],         '',             [],
1981             [],         [],             [],
1982             [],         UL([]),         UL([]),
1983             [],         [''],           [''],
1984             [],         UL(['']),       UL(['']),
1985
1986             UL([]),     'O1',           UL(['O', '1']),
1987             UL([]),     ['O2'],         UL(['O2']),
1988             UL([]),     UL(['O3']),     UL(['O3']),
1989             UL([]),     '',             UL([]),
1990             UL([]),     [],             UL([]),
1991             UL([]),     UL([]),         UL([]),
1992             UL([]),     [''],           UL(['']),
1993             UL([]),     UL(['']),       UL(['']),
1994
1995             [''],       'P1',           ['P1', ''],
1996             [''],       ['P2'],         ['P2', ''],
1997             [''],       UL(['P3']),     UL(['P3', '']),
1998             [''],       '',             [''],
1999             [''],       [],             [''],
2000             [''],       UL([]),         UL(['']),
2001             [''],       [''],           ['', ''],
2002             [''],       UL(['']),       UL(['', '']),
2003
2004             UL(['']),   'Q1',           UL(['Q', '1', '']),
2005             UL(['']),   ['Q2'],         UL(['Q2', '']),
2006             UL(['']),   UL(['Q3']),     UL(['Q3', '']),
2007             UL(['']),   '',             UL(['']),
2008             UL(['']),   [],             UL(['']),
2009             UL(['']),   UL([]),         UL(['']),
2010             UL(['']),   [''],           UL(['', '']),
2011             UL(['']),   UL(['']),       UL(['', '']),
2012         ]
2013
2014         env = Environment()
2015         failed = 0
2016         while cases:
2017             input, prepend, expect = cases[:3]
2018             env['XXX'] = copy.copy(input)
2019             try:
2020                 env.Prepend(XXX = prepend)
2021             except Exception, e:
2022                 if failed == 0: print
2023                 print "    %s Prepend %s exception: %s" % \
2024                       (repr(input), repr(prepend), e)
2025                 failed = failed + 1
2026             else:
2027                 result = env['XXX']
2028                 if result != expect:
2029                     if failed == 0: print
2030                     print "    %s Prepend %s => %s did not match %s" % \
2031                           (repr(input), repr(prepend), repr(result), repr(expect))
2032                     failed = failed + 1
2033             del cases[:3]
2034         assert failed == 0, "%d Prepend() cases failed" % failed
2035
2036         env['UL'] = UL(['foo'])
2037         env.Prepend(UL = 'bar')
2038         result = env['UL']
2039         assert isinstance(result, UL), repr(result)
2040         assert result == ['b', 'a', 'r', 'foo'], result
2041
2042         env['CLVar'] = CLVar(['foo'])
2043         env.Prepend(CLVar = 'bar')
2044         result = env['CLVar']
2045         assert isinstance(result, CLVar), repr(result)
2046         assert result == ['bar', 'foo'], result
2047
2048         env3 = self.TestEnvironment(X = {'x1' : 7})
2049         env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
2050         assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
2051         assert env3['Y'] == {'y1': 10}, env3['Y']
2052
2053         env4 = self.TestEnvironment(BUILDERS = {'z1' : 11})
2054         env4.Prepend(BUILDERS = {'z2' : 12})
2055         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
2056         assert hasattr(env4, 'z1')
2057         assert hasattr(env4, 'z2')
2058
2059     def test_PrependENVPath(self):
2060         """Test prepending to an ENV path."""
2061         env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
2062                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
2063         # have to include the pathsep here so that the test will work on UNIX too.
2064         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
2065         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
2066         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
2067         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
2068         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
2069         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
2070
2071     def test_PrependENVPath(self):
2072         """Test prepending to an ENV path."""
2073         env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
2074                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
2075         # have to include the pathsep here so that the test will work on UNIX too.
2076         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
2077         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
2078         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
2079         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
2080         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
2081         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
2082
2083     def test_PrependUnique(self):
2084         """Test prepending unique values to construction variables
2085
2086         This strips values that are already present when lists are
2087         involved."""
2088         env = self.TestEnvironment(AAA1 = 'a1',
2089                           AAA2 = 'a2',
2090                           AAA3 = 'a3',
2091                           AAA4 = 'a4',
2092                           AAA5 = 'a5',
2093                           BBB1 = ['b1'],
2094                           BBB2 = ['b2'],
2095                           BBB3 = ['b3'],
2096                           BBB4 = ['b4'],
2097                           BBB5 = ['b5'],
2098                           CCC1 = '',
2099                           CCC2 = '')
2100         env.PrependUnique(AAA1 = 'a1',
2101                           AAA2 = ['a2'],
2102                           AAA3 = ['a3', 'b', 'c', 'a3'],
2103                           AAA4 = 'a4.new',
2104                           AAA5 = ['a5.new'],
2105                           BBB1 = 'b1',
2106                           BBB2 = ['b2'],
2107                           BBB3 = ['b3', 'b', 'c', 'b3'],
2108                           BBB4 = 'b4.new',
2109                           BBB5 = ['b5.new'],
2110                           CCC1 = 'c1',
2111                           CCC2 = ['c2'])
2112         assert env['AAA1'] == 'a1a1', env['AAA1']
2113         assert env['AAA2'] == ['a2'], env['AAA2']
2114         assert env['AAA3'] == ['b', 'c', 'a3'], env['AAA3']
2115         assert env['AAA4'] == 'a4.newa4', env['AAA4']
2116         assert env['AAA5'] == ['a5.new', 'a5'], env['AAA5']
2117         assert env['BBB1'] == ['b1'], env['BBB1']
2118         assert env['BBB2'] == ['b2'], env['BBB2']
2119         assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3']
2120         assert env['BBB4'] == ['b4.new', 'b4'], env['BBB4']
2121         assert env['BBB5'] == ['b5.new', 'b5'], env['BBB5']
2122         assert env['CCC1'] == 'c1', env['CCC1']
2123         assert env['CCC2'] == ['c2'], env['CCC2']
2124
2125         env['CLVar'] = CLVar([])
2126         env.PrependUnique(CLVar = 'bar')
2127         result = env['CLVar']
2128         if sys.version[0] == '1':
2129             # Python 1.5.2 has a quirky behavior where CLVar([]) actually
2130             # matches '' and [] due to different __coerce__() semantics
2131             # in the UserList implementation.  It isn't worth a lot of
2132             # effort to get this corner case to work identically (support
2133             # for Python 1.5 support will die soon anyway), so just treat
2134             # it separately for now.
2135             assert result == 'bar', result
2136         else:
2137             assert isinstance(result, CLVar), repr(result)
2138             assert result == ['bar'], result
2139
2140         env['CLVar'] = CLVar(['abc'])
2141         env.PrependUnique(CLVar = 'bar')
2142         result = env['CLVar']
2143         assert isinstance(result, CLVar), repr(result)
2144         assert result == ['bar', 'abc'], result
2145
2146         env['CLVar'] = CLVar(['bar'])
2147         env.PrependUnique(CLVar = 'bar')
2148         result = env['CLVar']
2149         assert isinstance(result, CLVar), repr(result)
2150         assert result == ['bar'], result
2151
2152     def test_Replace(self):
2153         """Test replacing construction variables in an Environment
2154
2155         After creation of the Environment, of course.
2156         """
2157         env1 = self.TestEnvironment(AAA = 'a', BBB = 'b')
2158         env1.Replace(BBB = 'bbb', CCC = 'ccc')
2159
2160         env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
2161         assert env1 == env2, diff_env(env1, env2)
2162
2163         env3 = self.TestEnvironment(BUILDERS = {'b1' : 1})
2164         assert hasattr(env3, 'b1'), "b1 was not set"
2165         env3.Replace(BUILDERS = {'b2' : 2})
2166         assert not hasattr(env3, 'b1'), "b1 was not cleared"
2167         assert hasattr(env3, 'b2'), "b2 was not set"
2168
2169     def test_ReplaceIxes(self):
2170         "Test ReplaceIxes()"
2171         env = self.TestEnvironment(LIBPREFIX='lib',
2172                           LIBSUFFIX='.a',
2173                           SHLIBPREFIX='lib',
2174                           SHLIBSUFFIX='.so',
2175                           PREFIX='pre',
2176                           SUFFIX='post')
2177
2178         assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
2179                                              'SHLIBPREFIX', 'SHLIBSUFFIX',
2180                                              'LIBPREFIX', 'LIBSUFFIX')
2181
2182         assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
2183                                                                    'SHLIBPREFIX', 'SHLIBSUFFIX',
2184                                                                    'LIBPREFIX', 'LIBSUFFIX')
2185
2186         assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
2187                                              'PREFIX', 'SUFFIX',
2188                                              'LIBPREFIX', 'LIBSUFFIX')
2189
2190     def test_SetDefault(self):
2191         """Test the SetDefault method"""
2192         env = self.TestEnvironment(tools = [])
2193         env.SetDefault(V1 = 1)
2194         env.SetDefault(V1 = 2)
2195         assert env['V1'] == 1
2196         env['V2'] = 2
2197         env.SetDefault(V2 = 1)
2198         assert env['V2'] == 2
2199
2200     def test_Tool(self):
2201         """Test the Tool() method"""
2202         env = self.TestEnvironment(LINK='link', NONE='no-such-tool')
2203
2204         exc_caught = None
2205         try:
2206             env.Tool('does_not_exist')
2207         except SCons.Errors.UserError:
2208             exc_caught = 1
2209         assert exc_caught, "did not catch expected UserError"
2210
2211         exc_caught = None
2212         try:
2213             env.Tool('$NONE')
2214         except SCons.Errors.UserError:
2215             exc_caught = 1
2216         assert exc_caught, "did not catch expected UserError"
2217
2218         # Use a non-existent toolpath directory just to make sure we
2219         # can call Tool() with the keyword argument.
2220         env.Tool('cc', toolpath=['/no/such/directory'])
2221         assert env['CC'] == 'cc', env['CC']
2222
2223         env.Tool('$LINK')
2224         assert env['LINK'] == '$SMARTLINK', env['LINK']
2225
2226         # Test that the environment stores the toolpath and
2227         # re-uses it for later calls.
2228         test = TestCmd.TestCmd(workdir = '')
2229
2230         test.write('xxx.py', """\
2231 def exists(env):
2232     1
2233 def generate(env):
2234     env['XXX'] = 'one'
2235 """)
2236
2237         test.write('yyy.py', """\
2238 def exists(env):
2239     1
2240 def generate(env):
2241     env['YYY'] = 'two'
2242 """)
2243
2244         env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')])
2245         assert env['XXX'] == 'one', env['XXX']
2246         env.Tool('yyy')
2247         assert env['YYY'] == 'two', env['YYY']
2248
2249     def test_WhereIs(self):
2250         """Test the WhereIs() method"""
2251         test = TestCmd.TestCmd(workdir = '')
2252
2253         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
2254         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
2255         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
2256         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
2257
2258         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
2259
2260         if sys.platform != 'win32':
2261             test.write(sub1_xxx_exe, "\n")
2262
2263         os.mkdir(sub2_xxx_exe)
2264
2265         test.write(sub3_xxx_exe, "\n")
2266         os.chmod(sub3_xxx_exe, 0777)
2267
2268         test.write(sub4_xxx_exe, "\n")
2269         os.chmod(sub4_xxx_exe, 0777)
2270
2271         env_path = os.environ['PATH']
2272
2273         pathdirs_1234 = [ test.workpath('sub1'),
2274                           test.workpath('sub2'),
2275                           test.workpath('sub3'),
2276                           test.workpath('sub4'),
2277                         ] + string.split(env_path, os.pathsep)
2278
2279         pathdirs_1243 = [ test.workpath('sub1'),
2280                           test.workpath('sub2'),
2281                           test.workpath('sub4'),
2282                           test.workpath('sub3'),
2283                         ] + string.split(env_path, os.pathsep)
2284
2285         path = string.join(pathdirs_1234, os.pathsep)
2286         env = self.TestEnvironment(ENV = {'PATH' : path})
2287         wi = env.WhereIs('xxx.exe')
2288         assert wi == test.workpath(sub3_xxx_exe), wi
2289         wi = env.WhereIs('xxx.exe', pathdirs_1243)
2290         assert wi == test.workpath(sub4_xxx_exe), wi
2291         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
2292         assert wi == test.workpath(sub4_xxx_exe), wi
2293
2294         wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe)
2295         assert wi == test.workpath(sub4_xxx_exe), wi
2296         wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
2297         assert wi == test.workpath(sub4_xxx_exe), wi
2298
2299         path = string.join(pathdirs_1243, os.pathsep)
2300         env = self.TestEnvironment(ENV = {'PATH' : path})
2301         wi = env.WhereIs('xxx.exe')
2302         assert wi == test.workpath(sub4_xxx_exe), wi
2303         wi = env.WhereIs('xxx.exe', pathdirs_1234)
2304         assert wi == test.workpath(sub3_xxx_exe), wi
2305         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
2306         assert wi == test.workpath(sub3_xxx_exe), wi
2307
2308         if sys.platform == 'win32':
2309             wi = env.WhereIs('xxx', pathext = '')
2310             assert wi is None, wi
2311
2312             wi = env.WhereIs('xxx', pathext = '.exe')
2313             assert wi == test.workpath(sub4_xxx_exe), wi
2314
2315             wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
2316             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
2317
2318             # Test that we return a normalized path even when
2319             # the path contains forward slashes.
2320             forward_slash = test.workpath('') + '/sub3'
2321             wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE')
2322             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
2323
2324
2325
2326     def test_Action(self):
2327         """Test the Action() method"""
2328         import SCons.Action
2329
2330         env = self.TestEnvironment(FOO = 'xyzzy')
2331
2332         a = env.Action('foo')
2333         assert a, a
2334         assert a.__class__ is SCons.Action.CommandAction, a.__class__
2335
2336         a = env.Action('$FOO')
2337         assert a, a
2338         assert a.__class__ is SCons.Action.CommandAction, a.__class__
2339
2340         a = env.Action('$$FOO')
2341         assert a, a
2342         assert a.__class__ is SCons.Action.LazyAction, a.__class__
2343
2344         a = env.Action(['$FOO', 'foo'])
2345         assert a, a
2346         assert a.__class__ is SCons.Action.ListAction, a.__class__
2347
2348         def func(arg):
2349             pass
2350         a = env.Action(func)
2351         assert a, a
2352         assert a.__class__ is SCons.Action.FunctionAction, a.__class__
2353
2354     def test_AddPostAction(self):
2355         """Test the AddPostAction() method"""
2356         env = self.TestEnvironment(FOO='fff', BAR='bbb')
2357
2358         n = env.AddPostAction('$FOO', lambda x: x)
2359         assert str(n[0]) == 'fff', n[0]
2360
2361         n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
2362         assert str(n[0]) == 'ggg', n[0]
2363         assert str(n[1]) == 'bbb', n[1]
2364
2365     def test_AddPreAction(self):
2366         """Test the AddPreAction() method"""
2367         env = self.TestEnvironment(FOO='fff', BAR='bbb')
2368
2369         n = env.AddPreAction('$FOO', lambda x: x)
2370         assert str(n[0]) == 'fff', n[0]
2371
2372         n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
2373         assert str(n[0]) == 'ggg', n[0]
2374         assert str(n[1]) == 'bbb', n[1]
2375
2376     def test_Alias(self):
2377         """Test the Alias() method"""
2378         env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_alias')
2379
2380         tgt = env.Alias('new_alias')[0]
2381         assert str(tgt) == 'new_alias', tgt
2382         assert tgt.sources == [], tgt.sources
2383         assert not hasattr(tgt, 'builder'), tgt.builder
2384
2385         tgt = env.Alias('None_alias', None)[0]
2386         assert str(tgt) == 'None_alias', tgt
2387         assert tgt.sources == [], tgt.sources
2388
2389         tgt = env.Alias('empty_list', [])[0]
2390         assert str(tgt) == 'empty_list', tgt
2391         assert tgt.sources == [], tgt.sources
2392
2393         tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0]
2394         assert str(tgt) == 'export_alias', tgt
2395         assert len(tgt.sources) == 2, map(str, tgt.sources)
2396         assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources)
2397         assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources)
2398
2399         n = env.Alias(tgt, source = ['$BAR', 'asrc4'])[0]
2400         assert n is tgt, n
2401         assert len(tgt.sources) == 4, map(str, tgt.sources)
2402         assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources)
2403         assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources)
2404
2405         n = env.Alias('$EA', 'asrc5')[0]
2406         assert n is tgt, n
2407         assert len(tgt.sources) == 5, map(str, tgt.sources)
2408         assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources)
2409
2410         t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
2411         assert str(t1) == 't1', t1
2412         assert str(t2) == 't2', t2
2413         assert len(t1.sources) == 2, map(str, t1.sources)
2414         assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources)
2415         assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources)
2416         assert len(t2.sources) == 2, map(str, t2.sources)
2417         assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources)
2418         assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources)
2419
2420         tgt = env.Alias('add', 's1')
2421         tgt = env.Alias('add', 's2')[0]
2422         s = map(str, tgt.sources)
2423         assert s == ['s1', 's2'], s
2424         tgt = env.Alias(tgt, 's3')[0]
2425         s = map(str, tgt.sources)
2426         assert s == ['s1', 's2', 's3'], s
2427
2428         tgt = env.Alias('act', None, "action1")[0]
2429         s = str(tgt.builder.action)
2430         assert s == "action1", s
2431         tgt = env.Alias('act', None, "action2")[0]
2432         s = str(tgt.builder.action)
2433         assert s == "action1\naction2", s
2434         tgt = env.Alias(tgt, None, "action3")[0]
2435         s = str(tgt.builder.action)
2436         assert s == "action1\naction2\naction3", s
2437
2438     def test_AlwaysBuild(self):
2439         """Test the AlwaysBuild() method"""
2440         env = self.TestEnvironment(FOO='fff', BAR='bbb')
2441         t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR',
2442                             env.fs.Dir('dir'), env.fs.File('file'))
2443         assert t[0].__class__.__name__ == 'Entry'
2444         assert t[0].path == 'a'
2445         assert t[0].always_build
2446         assert t[1].__class__.__name__ == 'Entry'
2447         assert t[1].path == 'bfff'
2448         assert t[1].always_build
2449         assert t[2].__class__.__name__ == 'Entry'
2450         assert t[2].path == 'c'
2451         assert t[2].always_build
2452         assert t[3].__class__.__name__ == 'Entry'
2453         assert t[3].path == 'd'
2454         assert t[3].always_build
2455         assert t[4].__class__.__name__ == 'Entry'
2456         assert t[4].path == 'bbb'
2457         assert t[4].always_build
2458         assert t[5].__class__.__name__ == 'Dir'
2459         assert t[5].path == 'dir'
2460         assert t[5].always_build
2461         assert t[6].__class__.__name__ == 'File'
2462         assert t[6].path == 'file'
2463         assert t[6].always_build
2464
2465     def test_BuildDir(self):
2466         """Test the BuildDir() method"""
2467         class MyFS:
2468              def Dir(self, name):
2469                  return name
2470              def BuildDir(self, build_dir, src_dir, duplicate):
2471                  self.build_dir = build_dir
2472                  self.src_dir = src_dir
2473                  self.duplicate = duplicate
2474
2475         env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2476         env.fs = MyFS()
2477
2478         env.BuildDir('build', 'src')
2479         assert env.fs.build_dir == 'build', env.fs.build_dir
2480         assert env.fs.src_dir == 'src', env.fs.src_dir
2481         assert env.fs.duplicate == 1, env.fs.duplicate
2482
2483         env.BuildDir('build${FOO}', '${BAR}src', 0)
2484         assert env.fs.build_dir == 'buildfff', env.fs.build_dir
2485         assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir
2486         assert env.fs.duplicate == 0, env.fs.duplicate
2487
2488     def test_Builder(self):
2489         """Test the Builder() method"""
2490         env = self.TestEnvironment(FOO = 'xyzzy')
2491
2492         b = env.Builder(action = 'foo')
2493         assert not b is None, b
2494
2495         b = env.Builder(action = '$FOO')
2496         assert not b is None, b
2497
2498         b = env.Builder(action = ['$FOO', 'foo'])
2499         assert not b is None, b
2500
2501         def func(arg):
2502             pass
2503         b = env.Builder(action = func)
2504         assert not b is None, b
2505         b = env.Builder(generator = func)
2506         assert not b is None, b
2507
2508     def test_CacheDir(self):
2509         """Test the CacheDir() method"""
2510         class MyFS:
2511             def CacheDir(self, path):
2512                 self.CD = path
2513
2514         env = self.TestEnvironment(CD = 'CacheDir')
2515         env.fs = MyFS()
2516
2517         env.CacheDir('foo')
2518         assert env.fs.CD == 'foo', env.fs.CD
2519
2520         env.CacheDir('$CD')
2521         assert env.fs.CD == 'CacheDir', env.fs.CD
2522
2523     def test_Clean(self):
2524         """Test the Clean() method"""
2525         env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2526
2527         CT = SCons.Environment.CleanTargets
2528
2529         foo = env.arg2nodes('foo')[0]
2530         fff = env.arg2nodes('fff')[0]
2531
2532         t = env.Clean('foo', 'aaa')
2533         l = map(str, CT[foo])
2534         assert l == ['aaa'], l
2535
2536         t = env.Clean(foo, ['$BAR', 'ccc'])
2537         l = map(str, CT[foo])
2538         assert l == ['aaa', 'bbb', 'ccc'], l
2539
2540         eee = env.arg2nodes('eee')[0]
2541
2542         t = env.Clean('$FOO', 'ddd')
2543         l = map(str, CT[fff])
2544         assert l == ['ddd'], l
2545         t = env.Clean(fff, [eee, 'fff'])
2546         l = map(str, CT[fff])
2547         assert l == ['ddd', 'eee', 'fff'], l
2548
2549     def test_Command(self):
2550         """Test the Command() method."""
2551         env = Environment()
2552         t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
2553                         action='buildfoo $target $source')[0]
2554         assert not t.builder is None
2555         assert t.builder.action.__class__.__name__ == 'CommandAction'
2556         assert t.builder.action.cmd_list == 'buildfoo $target $source'
2557         assert 'foo1.in' in map(lambda x: x.path, t.sources)
2558         assert 'foo2.in' in map(lambda x: x.path, t.sources)
2559
2560         sub = env.fs.Dir('sub')
2561         t = env.Command(target='bar.out', source='sub',
2562                         action='buildbar $target $source')[0]
2563         assert 'sub' in map(lambda x: x.path, t.sources)
2564
2565         def testFunc(env, target, source):
2566             assert str(target[0]) == 'foo.out'
2567             assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
2568             return 0
2569         t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
2570                         action=testFunc)[0]
2571         assert not t.builder is None
2572         assert t.builder.action.__class__.__name__ == 'FunctionAction'
2573         t.build()
2574         assert 'foo1.in' in map(lambda x: x.path, t.sources)
2575         assert 'foo2.in' in map(lambda x: x.path, t.sources)
2576
2577         x = []
2578         def test2(baz, x=x):
2579             x.append(baz)
2580         env = self.TestEnvironment(TEST2 = test2)
2581         t = env.Command(target='baz.out', source='baz.in',
2582                         action='${TEST2(XYZ)}',
2583                         XYZ='magic word')[0]
2584         assert not t.builder is None
2585         t.build()
2586         assert x[0] == 'magic word', x
2587
2588         t = env.Command(target='${X}.out', source='${X}.in',
2589                         action = 'foo',
2590                         X = 'xxx')[0]
2591         assert str(t) == 'xxx.out', str(t)
2592         assert 'xxx.in' in map(lambda x: x.path, t.sources)
2593
2594         env = self.TestEnvironment(source_scanner = 'should_not_find_this')
2595         t = env.Command(target='file.out', source='file.in',
2596                         action = 'foo',
2597                         source_scanner = 'fake')[0]
2598         assert t.builder.source_scanner == 'fake', t.builder.source_scanner
2599
2600     def test_Configure(self):
2601         """Test the Configure() method"""
2602         # Configure() will write to a local temporary file.
2603         test = TestCmd.TestCmd(workdir = '')
2604         save = os.getcwd()
2605
2606         try:
2607             os.chdir(test.workpath())
2608
2609             env = self.TestEnvironment(FOO = 'xyzzy')
2610
2611             def func(arg):
2612                 pass
2613
2614             c = env.Configure()
2615             assert not c is None, c
2616             c.Finish()
2617
2618             c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
2619             assert not c is None, c
2620             assert hasattr(c, 'foo')
2621             assert hasattr(c, 'xyzzy')
2622             c.Finish()
2623         finally:
2624             os.chdir(save)
2625
2626     def test_Depends(self):
2627         """Test the explicit Depends method."""
2628         env = self.TestEnvironment(FOO = 'xxx', BAR='yyy')
2629         env.Dir('dir1')
2630         env.Dir('dir2')
2631         env.File('xxx.py')
2632         env.File('yyy.py')
2633         t = env.Depends(target='EnvironmentTest.py',
2634                         dependency='Environment.py')[0]
2635         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2636         assert t.path == 'EnvironmentTest.py'
2637         assert len(t.depends) == 1
2638         d = t.depends[0]
2639         assert d.__class__.__name__ == 'Entry', d.__class__.__name__
2640         assert d.path == 'Environment.py'
2641
2642         t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0]
2643         assert t.__class__.__name__ == 'File', t.__class__.__name__
2644         assert t.path == 'xxx.py'
2645         assert len(t.depends) == 1
2646         d = t.depends[0]
2647         assert d.__class__.__name__ == 'File', d.__class__.__name__
2648         assert d.path == 'yyy.py'
2649
2650         t = env.Depends(target='dir1', dependency='dir2')[0]
2651         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2652         assert t.path == 'dir1'
2653         assert len(t.depends) == 1
2654         d = t.depends[0]
2655         assert d.__class__.__name__ == 'Dir', d.__class__.__name__
2656         assert d.path == 'dir2'
2657
2658     def test_Dir(self):
2659         """Test the Dir() method"""
2660         class MyFS:
2661             def Dir(self, name):
2662                 return 'Dir(%s)' % name
2663
2664         env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir')
2665         env.fs = MyFS()
2666
2667         d = env.Dir('d')
2668         assert d == 'Dir(d)', d
2669
2670         d = env.Dir('$FOO')
2671         assert d == 'Dir(foodir)', d
2672
2673         d = env.Dir('${BAR}_$BAR')
2674         assert d == 'Dir(bardir_bardir)', d
2675
2676     def test_NoClean(self):
2677         """Test the NoClean() method"""
2678         env = self.TestEnvironment(FOO='ggg', BAR='hhh')
2679         env.Dir('p_hhhb')
2680         env.File('p_d')
2681         t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2682
2683         assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2684         assert t[0].path == 'p_a'
2685         assert t[0].noclean
2686         assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2687         assert t[1].path == 'p_hhhb'
2688         assert t[1].noclean
2689         assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2690         assert t[2].path == 'p_c'
2691         assert t[2].noclean
2692         assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2693         assert t[3].path == 'p_d'
2694         assert t[3].noclean
2695         assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2696         assert t[4].path == 'p_ggg'
2697         assert t[4].noclean
2698
2699     def test_Dump(self):
2700         """Test the Dump() method"""
2701
2702         env = self.TestEnvironment(FOO = 'foo')
2703         assert env.Dump('FOO') == "'foo'", env.Dump('FOO')
2704         assert len(env.Dump()) > 200, env.Dump()    # no args version
2705
2706     def test_Environment(self):
2707         """Test the Environment() method"""
2708         env = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy')
2709
2710         e2 = env.Environment(X = '$FOO', Y = '$BAR')
2711         assert e2['X'] == 'xxx', e2['X']
2712         assert e2['Y'] == 'yyy', e2['Y']
2713
2714     def test_Execute(self):
2715         """Test the Execute() method"""
2716
2717         class MyAction:
2718             def __init__(self, *args, **kw):
2719                 self.args = args
2720             def __call__(self, target, source, env):
2721                 return "%s executed" % self.args
2722
2723         env = Environment()
2724         env.Action = MyAction
2725
2726         result = env.Execute("foo")
2727         assert result == "foo executed", result
2728
2729     def test_Entry(self):
2730         """Test the Entry() method"""
2731         class MyFS:
2732             def Entry(self, name):
2733                 return 'Entry(%s)' % name
2734
2735         env = self.TestEnvironment(FOO = 'fooentry', BAR = 'barentry')
2736         env.fs = MyFS()
2737
2738         e = env.Entry('e')
2739         assert e == 'Entry(e)', e
2740
2741         e = env.Entry('$FOO')
2742         assert e == 'Entry(fooentry)', e
2743
2744         e = env.Entry('${BAR}_$BAR')
2745         assert e == 'Entry(barentry_barentry)', e
2746
2747     def test_File(self):
2748         """Test the File() method"""
2749         class MyFS:
2750             def File(self, name):
2751                 return 'File(%s)' % name
2752
2753         env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile')
2754         env.fs = MyFS()
2755
2756         f = env.File('f')
2757         assert f == 'File(f)', f
2758
2759         f = env.File('$FOO')
2760         assert f == 'File(foofile)', f
2761
2762         f = env.File('${BAR}_$BAR')
2763         assert f == 'File(barfile_barfile)', f
2764
2765     def test_FindFile(self):
2766         """Test the FindFile() method"""
2767         env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb')
2768
2769         r = env.FindFile('foo', ['no_such_directory'])
2770         assert r is None, r
2771
2772         # XXX
2773
2774     def test_Flatten(self):
2775         """Test the Flatten() method"""
2776         env = Environment()
2777         l = env.Flatten([1])
2778         assert l == [1]
2779         l = env.Flatten([1, [2, [3, [4]]]])
2780         assert l == [1, 2, 3, 4], l
2781
2782     def test_GetBuildPath(self):
2783         """Test the GetBuildPath() method."""
2784         env = self.TestEnvironment(MAGIC = 'xyzzy')
2785
2786         p = env.GetBuildPath('foo')
2787         assert p == 'foo', p
2788
2789         p = env.GetBuildPath('$MAGIC')
2790         assert p == 'xyzzy', p
2791
2792     def test_Ignore(self):
2793         """Test the explicit Ignore method."""
2794         env = self.TestEnvironment(FOO='yyy', BAR='zzz')
2795         env.Dir('dir1')
2796         env.Dir('dir2')
2797         env.File('yyyzzz')
2798         env.File('zzzyyy')
2799
2800         t = env.Ignore(target='targ.py', dependency='dep.py')[0]
2801         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2802         assert t.path == 'targ.py'
2803         assert len(t.ignore) == 1
2804         i = t.ignore[0]
2805         assert i.__class__.__name__ == 'Entry', i.__class__.__name__
2806         assert i.path == 'dep.py'
2807
2808         t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0]
2809         assert t.__class__.__name__ == 'File', t.__class__.__name__
2810         assert t.path == 'yyyzzz'
2811         assert len(t.ignore) == 1
2812         i = t.ignore[0]
2813         assert i.__class__.__name__ == 'File', i.__class__.__name__
2814         assert i.path == 'zzzyyy'
2815
2816         t = env.Ignore(target='dir1', dependency='dir2')[0]
2817         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2818         assert t.path == 'dir1'
2819         assert len(t.ignore) == 1
2820         i = t.ignore[0]
2821         assert i.__class__.__name__ == 'Dir', i.__class__.__name__
2822         assert i.path == 'dir2'
2823
2824     def test_Install(self):
2825         """Test the Install method"""
2826         env = self.TestEnvironment(FOO='iii', BAR='jjj')
2827
2828         tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
2829         paths = map(str, tgt)
2830         paths.sort()
2831         expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
2832         assert paths == expect, paths
2833         for tnode in tgt:
2834             assert tnode.builder == InstallBuilder
2835
2836         tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
2837         paths = map(str, tgt)
2838         paths.sort()
2839         expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
2840         assert paths == expect, paths
2841         for tnode in tgt:
2842             assert tnode.builder == InstallBuilder
2843
2844         tgt = env.Install('export', 'build')
2845         paths = map(str, tgt)
2846         paths.sort()
2847         expect = [os.path.join('export', 'build')]
2848         assert paths == expect, paths
2849         for tnode in tgt:
2850             assert tnode.builder == InstallBuilder
2851
2852         tgt = env.Install('export', ['build', 'build/foo1'])
2853         paths = map(str, tgt)
2854         paths.sort()
2855         expect = [
2856             os.path.join('export', 'build'),
2857             os.path.join('export', 'foo1'),
2858         ]
2859         assert paths == expect, paths
2860         for tnode in tgt:
2861             assert tnode.builder == InstallBuilder
2862
2863         tgt = env.Install('export', 'subdir/#file')
2864         assert str(tgt[0]) == os.path.normpath('export/#file'), str(tgt[0])
2865
2866         env.File('export/foo1')
2867
2868         exc_caught = None
2869         try:
2870             tgt = env.Install('export/foo1', 'build/foo1')
2871         except SCons.Errors.UserError, e:
2872             exc_caught = 1
2873         assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
2874         expect = "Target `export/foo1' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?"
2875         assert str(e) == expect, e
2876
2877     def test_InstallAs(self):
2878         """Test the InstallAs method"""
2879         env = self.TestEnvironment(FOO='iii', BAR='jjj')
2880
2881         tgt = env.InstallAs(target=string.split('foo1 foo2'),
2882                             source=string.split('bar1 bar2'))
2883         assert len(tgt) == 2, len(tgt)
2884         paths = map(lambda x: str(x.sources[0]), tgt)
2885         paths.sort()
2886         expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
2887         assert paths == expect, paths
2888         for tnode in tgt:
2889             assert tnode.builder == InstallBuilder
2890
2891         tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')[0]
2892         assert tgt.path == 'iii.t'
2893         assert tgt.sources[0].path == 'jjj.s'
2894         assert tgt.builder == InstallBuilder
2895
2896     def test_Literal(self):
2897         """Test the Literal() method"""
2898         env = self.TestEnvironment(FOO='fff', BAR='bbb')
2899         list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0]
2900         assert list == ['$FOO', 'bbb'], list
2901         list = env.subst_list(['$FOO', env.Literal('$BAR')])[0]
2902         assert list == ['fff', '$BAR'], list
2903
2904     def test_Local(self):
2905         """Test the Local() method."""
2906         env = self.TestEnvironment(FOO='lll')
2907
2908         l = env.Local(env.fs.File('fff'))
2909         assert str(l[0]) == 'fff', l[0]
2910
2911         l = env.Local('ggg', '$FOO')
2912         assert str(l[0]) == 'ggg', l[0]
2913         assert str(l[1]) == 'lll', l[1]
2914
2915     def test_Precious(self):
2916         """Test the Precious() method"""
2917         env = self.TestEnvironment(FOO='ggg', BAR='hhh')
2918         env.Dir('p_hhhb')
2919         env.File('p_d')
2920         t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2921
2922         assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2923         assert t[0].path == 'p_a'
2924         assert t[0].precious
2925         assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2926         assert t[1].path == 'p_hhhb'
2927         assert t[1].precious
2928         assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2929         assert t[2].path == 'p_c'
2930         assert t[2].precious
2931         assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2932         assert t[3].path == 'p_d'
2933         assert t[3].precious
2934         assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2935         assert t[4].path == 'p_ggg'
2936         assert t[4].precious
2937
2938     def test_Repository(self):
2939         """Test the Repository() method."""
2940         class MyFS:
2941             def __init__(self):
2942                 self.list = []
2943             def Repository(self, *dirs):
2944                 self.list.extend(list(dirs))
2945             def Dir(self, name):
2946                 return name
2947         env = self.TestEnvironment(FOO='rrr', BAR='sss')
2948         env.fs = MyFS()
2949         env.Repository('/tmp/foo')
2950         env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
2951         expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
2952         assert env.fs.list == expect, env.fs.list
2953
2954     def test_Scanner(self):
2955         """Test the Scanner() method"""
2956         def scan(node, env, target, arg):
2957             pass
2958
2959         env = self.TestEnvironment(FOO = scan)
2960
2961         s = env.Scanner('foo')
2962         assert not s is None, s
2963
2964         s = env.Scanner(function = 'foo')
2965         assert not s is None, s
2966
2967         if 0:
2968             s = env.Scanner('$FOO')
2969             assert not s is None, s
2970
2971             s = env.Scanner(function = '$FOO')
2972             assert not s is None, s
2973
2974     def test_SConsignFile(self):
2975         """Test the SConsignFile() method"""
2976         import SCons.SConsign
2977
2978         class MyFS:
2979             SConstruct_dir = os.sep + 'dir'
2980
2981         env = self.TestEnvironment(FOO = 'SConsign',
2982                           BAR = os.path.join(os.sep, 'File'))
2983         env.fs = MyFS()
2984
2985         try:
2986             fnames = []
2987             dbms = []
2988             def capture(name, dbm_module, fnames=fnames, dbms=dbms):
2989                 fnames.append(name)
2990                 dbms.append(dbm_module)
2991
2992             save_SConsign_File = SCons.SConsign.File
2993             SCons.SConsign.File = capture
2994
2995             env.SConsignFile('foo')
2996             assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames
2997             assert dbms[0] == None, dbms
2998
2999             env.SConsignFile('$FOO')
3000             assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
3001             assert dbms[1] == None, dbms
3002
3003             env.SConsignFile('/$FOO')
3004             assert fnames[2] == '/SConsign', fnames
3005             assert dbms[2] == None, dbms
3006
3007             env.SConsignFile('$BAR', 'x')
3008             assert fnames[3] == os.path.join(os.sep, 'File'), fnames
3009             assert dbms[3] == 'x', dbms
3010
3011             env.SConsignFile('__$BAR', 7)
3012             assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
3013             assert dbms[4] == 7, dbms
3014
3015             env.SConsignFile()
3016             assert fnames[5] == os.path.join(os.sep, 'dir', '.sconsign'), fnames
3017             assert dbms[5] == None, dbms
3018
3019             env.SConsignFile(None)
3020             assert fnames[6] == None, fnames
3021             assert dbms[6] == None, dbms
3022         finally:
3023             SCons.SConsign.File = save_SConsign_File
3024
3025     def test_SideEffect(self):
3026         """Test the SideEffect() method"""
3027         env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb')
3028         env.File('mylll.pdb')
3029         env.Dir('mymmm.pdb')
3030
3031         foo = env.Object('foo.obj', 'foo.cpp')[0]
3032         bar = env.Object('bar.obj', 'bar.cpp')[0]
3033         s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])[0]
3034         assert s.__class__.__name__ == 'Entry', s.__class__.__name__
3035         assert s.path == 'mylib.pdb'
3036         assert s.side_effect
3037         assert foo.side_effects == [s]
3038         assert bar.side_effects == [s]
3039
3040         fff = env.Object('fff.obj', 'fff.cpp')[0]
3041         bbb = env.Object('bbb.obj', 'bbb.cpp')[0]
3042         s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])[0]
3043         assert s.__class__.__name__ == 'File', s.__class__.__name__
3044         assert s.path == 'mylll.pdb'
3045         assert s.side_effect
3046         assert fff.side_effects == [s], fff.side_effects
3047         assert bbb.side_effects == [s], bbb.side_effects
3048
3049         ggg = env.Object('ggg.obj', 'ggg.cpp')[0]
3050         ccc = env.Object('ccc.obj', 'ccc.cpp')[0]
3051         s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])[0]
3052         assert s.__class__.__name__ == 'Dir', s.__class__.__name__
3053         assert s.path == 'mymmm.pdb'
3054         assert s.side_effect
3055         assert ggg.side_effects == [s], ggg.side_effects
3056         assert ccc.side_effects == [s], ccc.side_effects
3057
3058     def test_SourceCode(self):
3059         """Test the SourceCode() method."""
3060         env = self.TestEnvironment(FOO='mmm', BAR='nnn')
3061         e = env.SourceCode('foo', None)[0]
3062         assert e.path == 'foo'
3063         s = e.src_builder()
3064         assert s is None, s
3065
3066         b = Builder()
3067         e = env.SourceCode(e, b)[0]
3068         assert e.path == 'foo'
3069         s = e.src_builder()
3070         assert s is b, s
3071
3072         e = env.SourceCode('$BAR$FOO', None)[0]
3073         assert e.path == 'nnnmmm'
3074         s = e.src_builder()
3075         assert s is None, s
3076
3077     def test_SourceSignatures(type):
3078         """Test the SourceSignatures() method"""
3079         env = type.TestEnvironment(M = 'MD5', T = 'timestamp')
3080
3081         exc_caught = None
3082         try:
3083             env.SourceSignatures('invalid_type')
3084         except SCons.Errors.UserError:
3085             exc_caught = 1
3086         assert exc_caught, "did not catch expected UserError"
3087         assert not hasattr(env, '_calc_module')
3088
3089         env.SourceSignatures('MD5')
3090         m = env._calc_module
3091
3092         env.SourceSignatures('$M')
3093         assert env._calc_module is m
3094
3095         env.SourceSignatures('timestamp')
3096         t = env._calc_module
3097
3098         env.SourceSignatures('$T')
3099         assert env._calc_module is t
3100
3101     def test_Split(self):
3102         """Test the Split() method"""
3103         env = self.TestEnvironment(FOO='fff', BAR='bbb')
3104         s = env.Split("foo bar")
3105         assert s == ["foo", "bar"], s
3106         s = env.Split("$FOO bar")
3107         assert s == ["fff", "bar"], s
3108         s = env.Split(["foo", "bar"])
3109         assert s == ["foo", "bar"], s
3110         s = env.Split(["foo", "${BAR}-bbb"])
3111         assert s == ["foo", "bbb-bbb"], s
3112         s = env.Split("foo")
3113         assert s == ["foo"], s
3114         s = env.Split("$FOO$BAR")
3115         assert s == ["fffbbb"], s
3116
3117     def test_TargetSignatures(type):
3118         """Test the TargetSignatures() method"""
3119         env = type.TestEnvironment(B = 'build', C = 'content')
3120
3121         exc_caught = None
3122         try:
3123             env.TargetSignatures('invalid_type')
3124         except SCons.Errors.UserError:
3125             exc_caught = 1
3126         assert exc_caught, "did not catch expected UserError"
3127         assert not hasattr(env, '_build_signature')
3128
3129         env.TargetSignatures('build')
3130         assert env._build_signature == 1, env._build_signature
3131
3132         env.TargetSignatures('content')
3133         assert env._build_signature == 0, env._build_signature
3134
3135         env.TargetSignatures('$B')
3136         assert env._build_signature == 1, env._build_signature
3137
3138         env.TargetSignatures('$C')
3139         assert env._build_signature == 0, env._build_signature
3140
3141     def test_Value(self):
3142         """Test creating a Value() object
3143         """
3144         env = Environment()
3145         v1 = env.Value('a')
3146         assert v1.value == 'a', v1.value
3147
3148         value2 = 'a'
3149         v2 = env.Value(value2)
3150         assert v2.value == value2, v2.value
3151         assert v2.value is value2, v2.value
3152
3153         assert not v1 is v2
3154         assert v1.value == v2.value
3155
3156         v3 = env.Value('c', 'build-c')
3157         assert v3.value == 'c', v3.value
3158
3159
3160
3161     def test_Environment_global_variable(type):
3162         """Test setting Environment variable to an Environment.Base subclass"""
3163         class MyEnv(SCons.Environment.Base):
3164             def xxx(self, string):
3165                 return self.subst(string)
3166
3167         SCons.Environment.Environment = MyEnv
3168
3169         env = SCons.Environment.Environment(FOO = 'foo')
3170
3171         f = env.subst('$FOO')
3172         assert f == 'foo', f
3173
3174         f = env.xxx('$FOO')
3175         assert f == 'foo', f
3176
3177     def test_bad_keywords(type):
3178         """Test trying to use reserved keywords in an Environment"""
3179         reserved = ['TARGETS','SOURCES', 'SOURCE','TARGET']
3180         added = []
3181
3182         env = type.TestEnvironment(TARGETS = 'targets',
3183                                    SOURCES = 'sources',
3184                                    SOURCE = 'source',
3185                                    TARGET = 'target',
3186                                    INIT = 'init')
3187         bad_msg = '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'
3188         added.append('INIT')
3189         for x in reserved:
3190             assert not env.has_key(x), env[x]
3191         for x in added:
3192             assert env.has_key(x), bad_msg % x
3193
3194         env.Append(TARGETS = 'targets',
3195                    SOURCES = 'sources',
3196                    SOURCE = 'source',
3197                    TARGET = 'target',
3198                    APPEND = 'append')
3199         added.append('APPEND')
3200         for x in reserved:
3201             assert not env.has_key(x), env[x]
3202         for x in added:
3203             assert env.has_key(x), bad_msg % x
3204
3205         env.AppendUnique(TARGETS = 'targets',
3206                          SOURCES = 'sources',
3207                          SOURCE = 'source',
3208                          TARGET = 'target',
3209                          APPENDUNIQUE = 'appendunique')
3210         added.append('APPENDUNIQUE')
3211         for x in reserved:
3212             assert not env.has_key(x), env[x]
3213         for x in added:
3214             assert env.has_key(x), bad_msg % x
3215
3216         env.Prepend(TARGETS = 'targets',
3217                     SOURCES = 'sources',
3218                     SOURCE = 'source',
3219                     TARGET = 'target',
3220                     PREPEND = 'prepend')
3221         added.append('PREPEND')
3222         for x in reserved:
3223             assert not env.has_key(x), env[x]
3224         for x in added:
3225             assert env.has_key(x), bad_msg % x
3226
3227         env.Prepend(TARGETS = 'targets',
3228                     SOURCES = 'sources',
3229                     SOURCE = 'source',
3230                     TARGET = 'target',
3231                     PREPENDUNIQUE = 'prependunique')
3232         added.append('PREPENDUNIQUE')
3233         for x in reserved:
3234             assert not env.has_key(x), env[x]
3235         for x in added:
3236             assert env.has_key(x), bad_msg % x
3237
3238         env.Replace(TARGETS = 'targets',
3239                     SOURCES = 'sources',
3240                     SOURCE = 'source',
3241                     TARGET = 'target',
3242                     REPLACE = 'replace')
3243         added.append('REPLACE')
3244         for x in reserved:
3245             assert not env.has_key(x), env[x]
3246         for x in added:
3247             assert env.has_key(x), bad_msg % x
3248
3249         copy = env.Clone(TARGETS = 'targets',
3250                          SOURCES = 'sources',
3251                          SOURCE = 'source',
3252                          TARGET = 'target',
3253                          COPY = 'copy')
3254         for x in reserved:
3255             assert not copy.has_key(x), env[x]
3256         for x in added + ['COPY']:
3257             assert copy.has_key(x), bad_msg % x
3258
3259         over = env.Override({'TARGETS' : 'targets',
3260                              'SOURCES' : 'sources',
3261                              'SOURCE' : 'source',
3262                              'TARGET' : 'target',
3263                              'OVERRIDE' : 'override'})
3264         for x in reserved:
3265             assert not over.has_key(x), over[x]
3266         for x in added + ['OVERRIDE']:
3267             assert over.has_key(x), bad_msg % x
3268
3269
3270
3271 class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture):
3272
3273     def setUp(self):
3274         env = Environment()
3275         env._dict = {'XXX' : 'x', 'YYY' : 'y'}
3276         env2 = OverrideEnvironment(env, {'XXX' : 'x2'})
3277         env3 = OverrideEnvironment(env2, {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'})
3278         self.envs = [ env, env2, env3 ]
3279
3280     def checkpath(self, node, expect):
3281         return str(node) == os.path.normpath(expect)
3282
3283     def test___init__(self):
3284         """Test OverrideEnvironment initialization"""
3285         env, env2, env3 = self.envs
3286         assert env['XXX'] == 'x', env['XXX']
3287         assert env2['XXX'] == 'x2', env2['XXX']
3288         assert env3['XXX'] == 'x3', env3['XXX']
3289         assert env['YYY'] == 'y', env['YYY']
3290         assert env2['YYY'] == 'y', env2['YYY']
3291         assert env3['YYY'] == 'y3', env3['YYY']
3292
3293     def test___delitem__(self):
3294         """Test deleting variables from an OverrideEnvironment"""
3295         env, env2, env3 = self.envs
3296
3297         del env3['XXX']
3298         assert not env.has_key('XXX'), "env has XXX?"
3299         assert not env2.has_key('XXX'), "env2 has XXX?"
3300         assert not env3.has_key('XXX'), "env3 has XXX?"
3301
3302         del env3['YYY']
3303         assert not env.has_key('YYY'), "env has YYY?"
3304         assert not env2.has_key('YYY'), "env2 has YYY?"
3305         assert not env3.has_key('YYY'), "env3 has YYY?"
3306
3307         del env3['ZZZ']
3308         assert not env.has_key('ZZZ'), "env has ZZZ?"
3309         assert not env2.has_key('ZZZ'), "env2 has ZZZ?"
3310         assert not env3.has_key('ZZZ'), "env3 has ZZZ?"
3311
3312     def test_get(self):
3313         """Test the OverrideEnvironment get() method"""
3314         env, env2, env3 = self.envs
3315         assert env.get('XXX') == 'x', env.get('XXX')
3316         assert env2.get('XXX') == 'x2', env2.get('XXX')
3317         assert env3.get('XXX') == 'x3', env3.get('XXX')
3318         assert env.get('YYY') == 'y', env.get('YYY')
3319         assert env2.get('YYY') == 'y', env2.get('YYY')
3320         assert env3.get('YYY') == 'y3', env3.get('YYY')
3321         assert env.get('ZZZ') == None, env.get('ZZZ')
3322         assert env2.get('ZZZ') == None, env2.get('ZZZ')
3323         assert env3.get('ZZZ') == 'z3', env3.get('ZZZ')
3324
3325     def test_has_key(self):
3326         """Test the OverrideEnvironment has_key() method"""
3327         env, env2, env3 = self.envs
3328         assert env.has_key('XXX'), env.has_key('XXX')
3329         assert env2.has_key('XXX'), env2.has_key('XXX')
3330         assert env3.has_key('XXX'), env3.has_key('XXX')
3331         assert env.has_key('YYY'), env.has_key('YYY')
3332         assert env2.has_key('YYY'), env2.has_key('YYY')
3333         assert env3.has_key('YYY'), env3.has_key('YYY')
3334         assert not env.has_key('ZZZ'), env.has_key('ZZZ')
3335         assert not env2.has_key('ZZZ'), env2.has_key('ZZZ')
3336         assert env3.has_key('ZZZ'), env3.has_key('ZZZ')
3337
3338     def test_items(self):
3339         """Test the OverrideEnvironment Dictionary() method"""
3340         env, env2, env3 = self.envs
3341         items = env.Dictionary()
3342         assert items == {'XXX' : 'x', 'YYY' : 'y'}, items
3343         items = env2.Dictionary()
3344         assert items == {'XXX' : 'x2', 'YYY' : 'y'}, items
3345         items = env3.Dictionary()
3346         assert items == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, items
3347
3348     def test_items(self):
3349         """Test the OverrideEnvironment items() method"""
3350         env, env2, env3 = self.envs
3351         items = env.items()
3352         items.sort()
3353         assert items == [('XXX', 'x'), ('YYY', 'y')], items
3354         items = env2.items()
3355         items.sort()
3356         assert items == [('XXX', 'x2'), ('YYY', 'y')], items
3357         items = env3.items()
3358         items.sort()
3359         assert items == [('XXX', 'x3'), ('YYY', 'y3'), ('ZZZ', 'z3')], items
3360
3361     def test_gvars(self):
3362         """Test the OverrideEnvironment gvars() method"""
3363         env, env2, env3 = self.envs
3364         gvars = env.gvars()
3365         assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3366         gvars = env2.gvars()
3367         assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3368         gvars = env3.gvars()
3369         assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars
3370
3371     def test_lvars(self):
3372         """Test the OverrideEnvironment lvars() method"""
3373         env, env2, env3 = self.envs
3374         lvars = env.lvars()
3375         assert lvars == {}, lvars
3376         lvars = env2.lvars()
3377         assert lvars == {'XXX' : 'x2'}, lvars
3378         lvars = env3.lvars()
3379         assert lvars == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, lvars
3380
3381     def test_Replace(self):
3382         """Test the OverrideEnvironment Replace() method"""
3383         env, env2, env3 = self.envs
3384         assert env['XXX'] == 'x', env['XXX']
3385         assert env2['XXX'] == 'x2', env2['XXX']
3386         assert env3['XXX'] == 'x3', env3['XXX']
3387         assert env['YYY'] == 'y', env['YYY']
3388         assert env2['YYY'] == 'y', env2['YYY']
3389         assert env3['YYY'] == 'y3', env3['YYY']
3390
3391         env.Replace(YYY = 'y4')
3392
3393         assert env['XXX'] == 'x', env['XXX']
3394         assert env2['XXX'] == 'x2', env2['XXX']
3395         assert env3['XXX'] == 'x3', env3['XXX']
3396         assert env['YYY'] == 'y4', env['YYY']
3397         assert env2['YYY'] == 'y4', env2['YYY']
3398         assert env3['YYY'] == 'y3', env3['YYY']
3399
3400     # Tests a number of Base methods through an OverrideEnvironment to
3401     # make sure they handle overridden constructionv variables properly.
3402     #
3403     # The following Base methods also call self.subst(), and so could
3404     # theoretically be subject to problems with evaluating overridden
3405     # variables, but they're never really called that way in the rest
3406     # of our code, so we won't worry about them (at least for now):
3407     #
3408     # ParseConfig()
3409     # ParseDepends()
3410     # Platform()
3411     # Tool()
3412     #
3413     # Action()
3414     # Alias()
3415     # Builder()
3416     # CacheDir()
3417     # Configure()
3418     # Environment()
3419     # FindFile()
3420     # Scanner()
3421     # SourceSignatures()
3422     # TargetSignatures()
3423
3424     # It's unlikely Clone() will ever be called this way, so let the
3425     # other methods test that handling overridden values works.
3426     #def test_Clone(self):
3427     #    """Test the OverrideEnvironment Clone() method"""
3428     #    pass
3429
3430     def test_FindIxes(self):
3431         """Test the OverrideEnvironment FindIxes() method"""
3432         env, env2, env3 = self.envs
3433         x = env.FindIxes(['xaaay'], 'XXX', 'YYY')
3434         assert x == 'xaaay', x
3435         x = env2.FindIxes(['x2aaay'], 'XXX', 'YYY')
3436         assert x == 'x2aaay', x
3437         x = env3.FindIxes(['x3aaay3'], 'XXX', 'YYY')
3438         assert x == 'x3aaay3', x
3439
3440     def test_ReplaceIxes(self):
3441         """Test the OverrideEnvironment ReplaceIxes() method"""
3442         env, env2, env3 = self.envs
3443         x = env.ReplaceIxes('xaaay', 'XXX', 'YYY', 'YYY', 'XXX')
3444         assert x == 'yaaax', x
3445         x = env2.ReplaceIxes('x2aaay', 'XXX', 'YYY', 'YYY', 'XXX')
3446         assert x == 'yaaax2', x
3447         x = env3.ReplaceIxes('x3aaay3', 'XXX', 'YYY', 'YYY', 'XXX')
3448         assert x == 'y3aaax3', x
3449
3450     # It's unlikely WhereIs() will ever be called this way, so let the
3451     # other methods test that handling overridden values works.
3452     #def test_WhereIs(self):
3453     #    """Test the OverrideEnvironment WhereIs() method"""
3454     #    pass
3455
3456     def test_Dir(self):
3457         """Test the OverrideEnvironment Dir() method"""
3458         env, env2, env3 = self.envs
3459         x = env.Dir('ddir/$XXX')
3460         assert self.checkpath(x, 'ddir/x'), str(x)
3461         x = env2.Dir('ddir/$XXX')
3462         assert self.checkpath(x, 'ddir/x2'), str(x)
3463         x = env3.Dir('ddir/$XXX')
3464         assert self.checkpath(x, 'ddir/x3'), str(x)
3465
3466     def test_Entry(self):
3467         """Test the OverrideEnvironment Entry() method"""
3468         env, env2, env3 = self.envs
3469         x = env.Entry('edir/$XXX')
3470         assert self.checkpath(x, 'edir/x'), str(x)
3471         x = env2.Entry('edir/$XXX')
3472         assert self.checkpath(x, 'edir/x2'), str(x)
3473         x = env3.Entry('edir/$XXX')
3474         assert self.checkpath(x, 'edir/x3'), str(x)
3475
3476     def test_File(self):
3477         """Test the OverrideEnvironment File() method"""
3478         env, env2, env3 = self.envs
3479         x = env.File('fdir/$XXX')
3480         assert self.checkpath(x, 'fdir/x'), str(x)
3481         x = env2.File('fdir/$XXX')
3482         assert self.checkpath(x, 'fdir/x2'), str(x)
3483         x = env3.File('fdir/$XXX')
3484         assert self.checkpath(x, 'fdir/x3'), str(x)
3485
3486     def test_Split(self):
3487         """Test the OverrideEnvironment Split() method"""
3488         env, env2, env3 = self.envs
3489         env['AAA'] = '$XXX $YYY $ZZZ'
3490         x = env.Split('$AAA')
3491         assert x == ['x', 'y'], x
3492         x = env2.Split('$AAA')
3493         assert x == ['x2', 'y'], x
3494         x = env3.Split('$AAA')
3495         assert x == ['x3', 'y3', 'z3'], x
3496
3497
3498
3499 class NoSubstitutionProxyTestCase(unittest.TestCase,TestEnvironmentFixture):
3500
3501     def test___init__(self):
3502         """Test NoSubstitutionProxy initialization"""
3503         env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3504         assert env['XXX'] == 'x', env['XXX']
3505         assert env['YYY'] == 'y', env['YYY']
3506
3507         proxy = NoSubstitutionProxy(env)
3508         assert proxy['XXX'] == 'x', proxy['XXX']
3509         assert proxy['YYY'] == 'y', proxy['YYY']
3510
3511     def test_attributes(self):
3512         """Test getting and setting NoSubstitutionProxy attributes"""
3513         env = Environment()
3514         setattr(env, 'env_attr', 'value1')
3515
3516         proxy = NoSubstitutionProxy(env)
3517         setattr(proxy, 'proxy_attr', 'value2')
3518
3519         x = getattr(env, 'env_attr')
3520         assert x == 'value1', x
3521         x = getattr(proxy, 'env_attr')
3522         assert x == 'value1', x
3523
3524         x = getattr(env, 'proxy_attr')
3525         assert x == 'value2', x
3526         x = getattr(proxy, 'proxy_attr')
3527         assert x == 'value2', x
3528
3529     def test_subst(self):
3530         """Test the NoSubstitutionProxy.subst() method"""
3531         env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3532         assert env['XXX'] == 'x', env['XXX']
3533         assert env['YYY'] == 'y', env['YYY']
3534
3535         proxy = NoSubstitutionProxy(env)
3536         assert proxy['XXX'] == 'x', proxy['XXX']
3537         assert proxy['YYY'] == 'y', proxy['YYY']
3538
3539         x = env.subst('$XXX')
3540         assert x == 'x', x
3541         x = proxy.subst('$XXX')
3542         assert x == '$XXX', x
3543
3544         x = proxy.subst('$YYY', raw=7, target=None, source=None,
3545                         conv=None,
3546                         extra_meaningless_keyword_argument=None)
3547         assert x == '$YYY', x
3548
3549     def test_subst_kw(self):
3550         """Test the NoSubstitutionProxy.subst_kw() method"""
3551         env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3552         assert env['XXX'] == 'x', env['XXX']
3553         assert env['YYY'] == 'y', env['YYY']
3554
3555         proxy = NoSubstitutionProxy(env)
3556         assert proxy['XXX'] == 'x', proxy['XXX']
3557         assert proxy['YYY'] == 'y', proxy['YYY']
3558
3559         x = env.subst_kw({'$XXX':'$YYY'})
3560         assert x == {'x':'y'}, x
3561         x = proxy.subst_kw({'$XXX':'$YYY'})
3562         assert x == {'$XXX':'$YYY'}, x
3563
3564     def test_subst_list(self):
3565         """Test the NoSubstitutionProxy.subst_list() method"""
3566         env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3567         assert env['XXX'] == 'x', env['XXX']
3568         assert env['YYY'] == 'y', env['YYY']
3569
3570         proxy = NoSubstitutionProxy(env)
3571         assert proxy['XXX'] == 'x', proxy['XXX']
3572         assert proxy['YYY'] == 'y', proxy['YYY']
3573
3574         x = env.subst_list('$XXX')
3575         assert x == [['x']], x
3576         x = proxy.subst_list('$XXX')
3577         assert x == [[]], x
3578
3579         x = proxy.subst_list('$YYY', raw=0, target=None, source=None, conv=None)
3580         assert x == [[]], x
3581
3582     def test_subst_target_source(self):
3583         """Test the NoSubstitutionProxy.subst_target_source() method"""
3584         env = self.TestEnvironment(XXX = 'x', YYY = 'y')
3585         assert env['XXX'] == 'x', env['XXX']
3586         assert env['YYY'] == 'y', env['YYY']
3587
3588         proxy = NoSubstitutionProxy(env)
3589         assert proxy['XXX'] == 'x', proxy['XXX']
3590         assert proxy['YYY'] == 'y', proxy['YYY']
3591
3592         args = ('$XXX $TARGET $SOURCE $YYY',)
3593         kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')}
3594         x = apply(env.subst_target_source, args, kw)
3595         assert x == 'x ttt sss y', x
3596         x = apply(proxy.subst_target_source, args, kw)
3597         assert x == ' ttt sss ', x
3598
3599
3600
3601 if __name__ == "__main__":
3602     suite = unittest.TestSuite()
3603     tclasses = [ SubstitutionTestCase,
3604                  BaseTestCase,
3605                  OverrideEnvironmentTestCase,
3606                  NoSubstitutionProxyTestCase ]
3607     for tclass in tclasses:
3608         names = unittest.getTestCaseNames(tclass, 'test_')
3609         suite.addTests(map(tclass, names))
3610     if not unittest.TextTestRunner().run(suite).wasSuccessful():
3611         sys.exit(1)