Fix custom scanner behavior when setting/copying/replacing the SCANNERS construction...
[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 os
27 import string
28 import sys
29 import TestCmd
30 import unittest
31 import UserList
32
33 from SCons.Environment import *
34 import SCons.Warnings
35
36 def diff_env(env1, env2):
37     s1 = "env1 = {\n"
38     s2 = "env2 = {\n"
39     d = {}
40     for k in env1._dict.keys() + env2._dict.keys():
41         d[k] = None
42     keys = d.keys()
43     keys.sort()
44     for k in keys:
45         if env1.has_key(k):
46            if env2.has_key(k):
47                if env1[k] != env2[k]:
48                    s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
49                    s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
50            else:
51                s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
52         elif env2.has_key(k):
53            s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
54     s1 = s1 + "}\n"
55     s2 = s2 + "}\n"
56     return s1 + s2
57
58 def diff_dict(d1, d2):
59     s1 = "d1 = {\n"
60     s2 = "d2 = {\n"
61     d = {}
62     for k in d1.keys() + d2.keys():
63         d[k] = None
64     keys = d.keys()
65     keys.sort()
66     for k in keys:
67         if d1.has_key(k):
68            if d2.has_key(k):
69                if d1[k] != d2[k]:
70                    s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
71                    s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
72            else:
73                s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
74         elif env2.has_key(k):
75            s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
76     s1 = s1 + "}\n"
77     s2 = s2 + "}\n"
78     return s1 + s2
79
80 called_it = {}
81 built_it = {}
82
83 class Builder:
84     """A dummy Builder class for testing purposes.  "Building"
85     a target is simply setting a value in the dictionary.
86     """
87     def __init__(self, name = None):
88         self.name = name
89
90     def __call__(self, env, **kw):
91         global called_it
92         called_it.update(kw)
93
94     def execute(self, target = None, **kw):
95         global built_it
96         built_it[target] = 1
97
98
99
100 scanned_it = {}
101
102 class Scanner:
103     """A dummy Scanner class for testing purposes.  "Scanning"
104     a target is simply setting a value in the dictionary.
105     """
106     def __init__(self, name, skeys=[]):
107         self.name = name
108         self.skeys = skeys
109
110     def __call__(self, filename):
111         global scanned_it
112         scanned_it[filename] = 1
113
114     def __cmp__(self, other):
115         try:
116             return cmp(self.__dict__, other.__dict__)
117         except AttributeError:
118             return 1
119
120     def get_skeys(self, env):
121         return self.skeys
122
123
124
125 class CLVar(UserList.UserList):
126     def __init__(self, seq):
127         if type(seq) == type(''):
128             seq = string.split(seq)
129         UserList.UserList.__init__(self, seq)
130     def __coerce__(self, other):
131         return (self, CLVar(other))
132
133
134
135 class DummyNode:
136     def __init__(self, name):
137         self.name = name
138     def __str__(self):
139         return self.name
140     def rfile(self):
141         return self
142     def get_subst_proxy(self):
143         return self
144
145
146
147 class EnvironmentTestCase(unittest.TestCase):
148
149     def test___init__(self):
150         """Test construction Environment creation
151
152         Create two with identical arguments and check that
153         they compare the same.
154         """
155         env1 = Environment(XXX = 'x', YYY = 'y')
156         env2 = Environment(XXX = 'x', YYY = 'y')
157         assert env1 == env2, diff_env(env1, env2)
158
159         assert env1['__env__'] is env1, env1['__env__']
160         assert env2['__env__'] is env2, env2['__env__']
161
162     def test_get(self):
163         """Test the get() method."""
164         env = Environment(aaa = 'AAA')
165
166         x = env.get('aaa')
167         assert x == 'AAA', x
168         x = env.get('aaa', 'XXX')
169         assert x == 'AAA', x
170         x = env.get('bbb')
171         assert x is None, x
172         x = env.get('bbb', 'XXX')
173         assert x == 'XXX', x
174
175     def test_arg2nodes(self):
176         """Test the arg2nodes method
177         """
178         env = Environment()
179         dict = {}
180         class X(SCons.Node.Node):
181             pass
182         def Factory(name, directory = None, create = 1, dict=dict, X=X):
183             if not dict.has_key(name):
184                 dict[name] = X()
185                 dict[name].name = name
186             return dict[name]
187
188         nodes = env.arg2nodes("Util.py UtilTests.py", Factory)
189         assert len(nodes) == 1, nodes
190         assert isinstance(nodes[0], X)
191         assert nodes[0].name == "Util.py UtilTests.py"
192
193         import types
194         if hasattr(types, 'UnicodeType'):
195             code = """if 1:
196                 nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
197                 assert len(nodes) == 1, nodes
198                 assert isinstance(nodes[0], X)
199                 assert nodes[0].name == u"Util.py UtilTests.py"
200                 \n"""
201             exec code in globals(), locals()
202
203         nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
204         assert len(nodes) == 2, nodes
205         assert isinstance(nodes[0], X)
206         assert isinstance(nodes[1], X)
207         assert nodes[0].name == "Util.py"
208         assert nodes[1].name == "UtilTests.py"
209
210         n1 = Factory("Util.py")
211         nodes = env.arg2nodes([n1, "UtilTests.py"], Factory)
212         assert len(nodes) == 2, nodes
213         assert isinstance(nodes[0], X)
214         assert isinstance(nodes[1], X)
215         assert nodes[0].name == "Util.py"
216         assert nodes[1].name == "UtilTests.py"
217
218         class SConsNode(SCons.Node.Node):
219             pass
220         nodes = env.arg2nodes(SConsNode())
221         assert len(nodes) == 1, nodes
222         assert isinstance(nodes[0], SConsNode), node
223
224         class OtherNode:
225             pass
226         nodes = env.arg2nodes(OtherNode())
227         assert len(nodes) == 1, nodes
228         assert isinstance(nodes[0], OtherNode), node
229
230         def lookup_a(str, F=Factory):
231             if str[0] == 'a':
232                 n = F(str)
233                 n.a = 1
234                 return n
235             else:
236                 return None
237
238         def lookup_b(str, F=Factory):
239             if str[0] == 'b':
240                 n = F(str)
241                 n.b = 1
242                 return n
243             else:
244                 return None
245
246         env_ll = env.Copy()
247         env_ll.lookup_list = [lookup_a, lookup_b]
248
249         nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
250         assert len(nodes) == 3, nodes
251
252         assert nodes[0].name == 'aaa', nodes[0]
253         assert nodes[0].a == 1, nodes[0]
254         assert not hasattr(nodes[0], 'b'), nodes[0]
255
256         assert nodes[1].name == 'bbb'
257         assert not hasattr(nodes[1], 'a'), nodes[1]
258         assert nodes[1].b == 1, nodes[1]
259
260         assert nodes[2].name == 'ccc'
261         assert not hasattr(nodes[2], 'a'), nodes[1]
262         assert not hasattr(nodes[2], 'b'), nodes[1]
263
264         def lookup_bbbb(str, F=Factory):
265             if str == 'bbbb':
266                 n = F(str)
267                 n.bbbb = 1
268                 return n
269             else:
270                 return None
271
272         def lookup_c(str, F=Factory):
273             if str[0] == 'c':
274                 n = F(str)
275                 n.c = 1
276                 return n
277             else:
278                 return None
279
280         nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
281                                      [lookup_c, lookup_bbbb, lookup_b])
282         assert len(nodes) == 2, nodes
283
284         assert nodes[0].name == 'bbbb'
285         assert not hasattr(nodes[0], 'a'), nodes[1]
286         assert not hasattr(nodes[0], 'b'), nodes[1]
287         assert nodes[0].bbbb == 1, nodes[1]
288         assert not hasattr(nodes[0], 'c'), nodes[0]
289
290         assert nodes[1].name == 'ccc'
291         assert not hasattr(nodes[1], 'a'), nodes[1]
292         assert not hasattr(nodes[1], 'b'), nodes[1]
293         assert not hasattr(nodes[1], 'bbbb'), nodes[0]
294         assert nodes[1].c == 1, nodes[1]
295
296     def test_subst(self):
297         """Test substituting construction variables within strings
298
299         Check various combinations, including recursive expansion
300         of variables into other variables.
301         """
302         env = Environment(AAA = 'a', BBB = 'b')
303         mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
304         assert mystr == "a aA b", mystr
305
306         # Changed the tests below to reflect a bug fix in
307         # subst()
308         env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
309         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
310         assert mystr == "b bA bB b", mystr
311
312         env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
313         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
314         assert mystr == "c cA cB c", mystr
315
316         t1 = DummyNode('t1')
317         t2 = DummyNode('t2')
318         s1 = DummyNode('s1')
319         s2 = DummyNode('s2')
320
321         env = Environment(AAA = 'aaa')
322         s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
323         assert s == "aaa t1 s1 s2", s
324         s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
325         assert s == "aaa t1 t2 s1", s
326         s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2], dict={})
327         assert s == "aaa", s
328
329         # Test callables in the Environment
330         def foo(target, source, env, for_signature):
331             assert str(target) == 't', target
332             assert str(source) == 's', source
333             return env["FOO"]
334
335         env = Environment(BAR=foo, FOO='baz')
336         t = DummyNode('t')
337         s = DummyNode('s')
338
339         subst = env.subst('test $BAR', target=t, source=s)
340         assert subst == 'test baz', subst
341
342         # Test not calling callables in the Environment
343         if 0:
344             # This will take some serious surgery to subst() and
345             # subst_list(), so just leave these tests out until we can
346             # do that.
347             def bar(arg):
348                 pass
349
350             env = Environment(BAR=bar, FOO='$BAR')
351
352             subst = env.subst('$BAR', call=None)
353             assert subst is bar, subst
354
355             subst = env.subst('$FOO', call=None)
356             assert subst is bar, subst
357
358     def test_subst_kw(self):
359         """Test substituting construction variables within dictionaries"""
360         env = Environment(AAA = 'a', BBB = 'b')
361         kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
362         assert len(kw) == 2, kw
363         assert kw['a'] == 'aaa', kw['a']
364         assert kw['bbb'] == 'b', kw['bbb']
365
366     def test_subst_list(self):
367         """Test substituting construction variables in command lists
368         """
369         env = Environment(AAA = 'a', BBB = 'b')
370         l = env.subst_list("$AAA ${AAA}A $BBBB $BBB")
371         assert l == [["a", "aA", "b"]], l
372
373         # Changed the tests below to reflect a bug fix in
374         # subst()
375         env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
376         l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
377         assert l == [["b", "bA", "bB", "b"]], l
378
379         env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
380         l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB")
381         assert l == [["c", "cA", "cB", "c"]], mystr
382
383         env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
384         lst = env.subst_list([ "$AAA", "B $CCC" ])
385         assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst
386
387         t1 = DummyNode('t1')
388         t2 = DummyNode('t2')
389         s1 = DummyNode('s1')
390         s2 = DummyNode('s2')
391
392         env = Environment(AAA = 'aaa')
393         s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2])
394         assert s == [["aaa", "t1", "s1", "s2"]], s
395         s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2])
396         assert s == [["aaa", "t1", "t2", "s1"]], s
397         s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2], dict={})
398         assert s == [["aaa"]], s
399
400         # Test callables in the Environment
401         def foo(target, source, env, for_signature):
402             assert str(target) == 't', target
403             assert str(source) == 's', source
404             return env["FOO"]
405
406         env = Environment(BAR=foo, FOO='baz')
407         t = DummyNode('t')
408         s = DummyNode('s')
409
410         lst = env.subst_list('test $BAR', target=t, source=s)
411         assert lst == [['test', 'baz']], lst
412
413         # Test not calling callables in the Environment
414         if 0:
415             # This will take some serious surgery to subst() and
416             # subst_list(), so just leave these tests out until we can
417             # do that.
418             def bar(arg):
419                 pass
420
421             env = Environment(BAR=bar, FOO='$BAR')
422
423             subst = env.subst_list('$BAR', call=None)
424             assert subst is bar, subst
425
426             subst = env.subst_list('$FOO', call=None)
427             assert subst is bar, subst
428
429     def test_subst_path(self):
430         """Test substituting a path list
431         """
432         class MyProxy:
433             def __init__(self, val):
434                 self.val = val
435             def get(self):
436                 return self.val + '-proxy'
437
438         class MyObj:
439             pass
440
441         env = Environment(FOO='foo', BAR='bar', PROXY=MyProxy('my1'))
442
443         r = env.subst_path('$FOO')
444         assert r == ['foo'], r
445
446         r = env.subst_path(['$FOO', 'xxx', '$BAR'])
447         assert r == ['foo', 'xxx', 'bar'], r
448
449         n = MyObj()
450
451         r = env.subst_path(['$PROXY', MyProxy('my2'), n])
452         assert r == ['my1-proxy', 'my2-proxy', n], r
453
454         class StringableObj:
455             def __init__(self, s):
456                 self.s = s
457             def __str__(self):
458                 return self.s
459
460         env = Environment(FOO=StringableObj("foo"),
461                           BAR=StringableObj("bar"))
462
463         r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ])
464         assert r == [ "foo/bar", "bar/baz" ]
465
466         r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ])
467         assert r == [ "bar/foo", "baz/bar" ]
468
469         r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ])
470         assert r == [ "bar/foo/bar", "baz/bar/baz" ]
471
472     def test_Builder_calls(self):
473         """Test Builder calls through different environments
474         """
475         global called_it
476
477         b1 = Builder()
478         b2 = Builder()
479
480         env = Environment()
481         env.Replace(BUILDERS = { 'builder1' : b1,
482                                  'builder2' : b2 })
483         called_it = {}
484         env.builder1(target = 'out1')
485         assert called_it['target'] == 'out1', called_it
486         assert not called_it.has_key('source')
487
488         called_it = {}
489         env.builder2(target = 'out2', xyzzy = 1)
490         assert called_it['target'] == 'out2', called_it
491         assert called_it['xyzzy'] == 1, called_it
492         assert not called_it.has_key('source')
493
494         called_it = {}
495         env.builder1(foo = 'bar')
496         assert called_it['foo'] == 'bar', called_it
497         assert not called_it.has_key('target')
498         assert not called_it.has_key('source')
499
500
501
502     def test_Builder_execs(self):
503         """Test Builder execution through different environments
504
505         One environment is initialized with a single
506         Builder object, one with a list of a single Builder
507         object, and one with a list of two Builder objects.
508         """
509         global built_it
510
511         b1 = Builder()
512         b2 = Builder()
513
514         built_it = {}
515         env3 = Environment()
516         env3.Replace(BUILDERS = { 'builder1' : b1,
517                                   'builder2' : b2 })
518         env3.builder1.execute(target = 'out1')
519         env3.builder2.execute(target = 'out2')
520         env3.builder1.execute(target = 'out3')
521         assert built_it['out1']
522         assert built_it['out2']
523         assert built_it['out3']
524
525         env4 = env3.Copy()
526         assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
527         assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
528
529         # Now test BUILDERS as a dictionary.
530         built_it = {}
531         env5 = Environment(BUILDERS={ 'foo' : b1 })
532         env5['BUILDERS']['bar'] = b2
533         env5.foo.execute(target='out1')
534         env5.bar.execute(target='out2')
535         assert built_it['out1']
536         assert built_it['out2']
537
538         built_it = {}
539         env6 = Environment()
540         env6['BUILDERS'] = { 'foo' : b1,
541                              'bar' : b2 }
542         env6.foo.execute(target='out1')
543         env6.bar.execute(target='out2')
544         assert built_it['out1']
545         assert built_it['out2']
546
547     def test_Scanners(self):
548         """Test setting SCANNERS in various ways
549
550         One environment is initialized with a single
551         Scanner object, one with a list of a single Scanner
552         object, and one with a list of two Scanner objects.
553         """
554         global scanned_it
555
556         s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
557         s2 = Scanner(name = 'scanner2', skeys = [".m4"])
558         s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"])
559
560 #        XXX Tests for scanner execution through different environments,
561 #        XXX if we ever want to do that some day
562 #        scanned_it = {}
563 #        env1 = Environment(SCANNERS = s1)
564 #        env1.scanner1(filename = 'out1')
565 #        assert scanned_it['out1']
566 #
567 #        scanned_it = {}
568 #        env2 = Environment(SCANNERS = [s1])
569 #        env1.scanner1(filename = 'out1')
570 #        assert scanned_it['out1']
571 #
572 #        scanned_it = {}
573 #        env3 = Environment()
574 #        env3.Replace(SCANNERS = [s1])
575 #        env3.scanner1(filename = 'out1')
576 #        env3.scanner2(filename = 'out2')
577 #        env3.scanner1(filename = 'out3')
578 #        assert scanned_it['out1']
579 #        assert scanned_it['out2']
580 #        assert scanned_it['out3']
581
582         suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"]
583
584         env = Environment(SCANNERS = [])
585         s = map(env.get_scanner, suffixes)
586         assert s == [None, None, None, None, None], s
587
588         env.Replace(SCANNERS = [s1])
589         s = map(env.get_scanner, suffixes)
590         assert s == [s1, s1, None, None, None], s
591
592         env.Append(SCANNERS = [s2])
593         s = map(env.get_scanner, suffixes)
594         assert s == [s1, s1, None, s2, None], s
595
596         env.AppendUnique(SCANNERS = [s3])
597         s = map(env.get_scanner, suffixes)
598         assert s == [s1, s1, None, s2, s3], s
599
600         env = env.Copy(SCANNERS = [s2])
601         s = map(env.get_scanner, suffixes)
602         assert s == [None, None, None, s2, None], s
603
604         env['SCANNERS'] = [s1]
605         s = map(env.get_scanner, suffixes)
606         assert s == [s1, s1, None, None, None], s
607
608         env.PrependUnique(SCANNERS = [s2, s1])
609         s = map(env.get_scanner, suffixes)
610         assert s == [s1, s1, None, s2, None], s
611
612         env.Prepend(SCANNERS = [s3])
613         s = map(env.get_scanner, suffixes)
614         assert s == [s1, s1, None, s3, s3], s
615
616     def test_ENV(self):
617         """Test setting the external ENV in Environments
618         """
619         env = Environment()
620         assert env.Dictionary().has_key('ENV')
621
622         env = Environment(ENV = { 'PATH' : '/foo:/bar' })
623         assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
624
625     def test_ReservedVariables(self):
626         """Test generation of warnings when reserved variable names
627         are set in an environment."""
628
629         SCons.Warnings.enableWarningClass(SCons.Warnings.ReservedVariableWarning)
630         old = SCons.Warnings.warningAsException(1)
631
632         try:
633             env4 = Environment()
634             for kw in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
635                 exc_caught = None
636                 try:
637                     env4[kw] = 'xyzzy'
638                 except SCons.Warnings.ReservedVariableWarning:
639                     exc_caught = 1
640                 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw
641                 assert not env4.has_key(kw), "`%s' variable was incorrectly set" % kw
642         finally:
643             SCons.Warnings.warningAsException(old)
644
645     def test_IllegalVariables(self):
646         """Test that use of illegal variables raises an exception"""
647         env = Environment()
648         def test_it(var, env=env):
649             exc_caught = None
650             try:
651                 env[var] = 1
652             except SCons.Errors.UserError:
653                 exc_caught = 1
654             assert exc_caught, "did not catch UserError for '%s'" % var
655         env['aaa'] = 1
656         assert env['aaa'] == 1, env['aaa']
657         test_it('foo/bar')
658         test_it('foo.bar')
659         test_it('foo-bar')
660
661     def test_autogenerate(dict):
662         """Test autogenerating variables in a dictionary."""
663
664         def RDirs(pathlist):
665             return SCons.Node.FS.default_fs.Rsearchall(pathlist,
666                                                        clazz=SCons.Node.FS.Dir,
667                                                        must_exist=0,
668                                                        cwd=SCons.Node.FS.default_fs.Dir('xx'))
669
670         env = Environment(LIBS = [ 'foo', 'bar', 'baz' ],
671                           LIBLINKPREFIX = 'foo',
672                           LIBLINKSUFFIX = 'bar',
673                           RDirs=RDirs)
674         flags = env.subst_list('$_LIBFLAGS', 1)[0]
675         assert len(flags) == 3, flags
676         assert flags[0] == 'foobar', \
677                flags[0]
678         assert flags[1] == 'foobar', \
679                flags[1]
680         assert flags[2] == 'foobazbar', \
681                flags[2]
682
683         blat = SCons.Node.FS.default_fs.Dir('blat')
684
685         env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ],
686                           INCPREFIX = 'foo ',
687                           INCSUFFIX = 'bar',
688                           FOO = 'baz',
689                           RDirs=RDirs)
690         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
691         assert len(flags) == 8, flags
692         assert flags[0] == '$(', \
693                flags[0]
694         assert flags[1] == os.path.normpath('foo'), \
695                flags[1]
696         assert flags[2] == os.path.normpath('xx/foobar'), \
697                flags[2]
698         assert flags[3] == os.path.normpath('foo'), \
699                flags[3]
700         assert flags[4] == os.path.normpath('xx/baz/bar'), \
701                flags[4]
702         assert flags[5] == os.path.normpath('foo'), \
703                flags[5]
704         assert flags[6] == os.path.normpath('blatbar'), \
705                flags[6]
706         assert flags[7] == '$)', \
707                flags[7]
708
709         env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ],
710                           INCPREFIX = 'foo ',
711                           INCSUFFIX = 'bar',
712                           FOO = 'baz',
713                           RDirs=RDirs)
714         flags = env.subst_list('$_F77INCFLAGS', 1)[0]
715         assert len(flags) == 8, flags
716         assert flags[0] == '$(', \
717                flags[0]
718         assert flags[1] == os.path.normpath('foo'), \
719                flags[1]
720         assert flags[2] == os.path.normpath('xx/foobar'), \
721                flags[2]
722         assert flags[3] == os.path.normpath('foo'), \
723                flags[3]
724         assert flags[4] == os.path.normpath('xx/baz/bar'), \
725                flags[4]
726         assert flags[5] == os.path.normpath('foo'), \
727                flags[5]
728         assert flags[6] == os.path.normpath('blatbar'), \
729                flags[6]
730         assert flags[7] == '$)', \
731                flags[7]
732
733         env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '',
734                           RDirs=RDirs)
735         l = env.subst_list('$_CPPINCFLAGS')
736         assert len(l[0]) == 0, l[0]
737         l = env.subst_list('$_F77INCFLAGS')
738         assert len(l[0]) == 0, l[0]
739         l = env.subst_list('$_LIBDIRFLAGS')
740         assert len(l[0]) == 0, l[0]
741
742         SCons.Node.FS.default_fs.Repository('/rep1')
743         SCons.Node.FS.default_fs.Repository('/rep2')
744         env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
745                           INCPREFIX = '-I ',
746                           INCSUFFIX = 'XXX',
747                           FOO = 'baz',
748                           RDirs=RDirs)
749         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
750         assert flags[0] == '$(', \
751                flags[0]
752         assert flags[1] == '-I', \
753                flags[1]
754         assert flags[2] == os.path.normpath('xx/fooXXX'), \
755                flags[2]
756         assert flags[3] == '-I', \
757                flags[3]
758         assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \
759                flags[4]
760         assert flags[5] == '-I', \
761                flags[5]
762         assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \
763                flags[6]
764         assert flags[7] == '-I', \
765                flags[7]
766         assert flags[8] == os.path.normpath('/a/bXXX'), \
767                flags[8]
768         assert flags[9] == '-I', \
769                flags[9]
770         assert flags[10] == os.path.normpath('xx/baz/barXXX'), \
771                flags[10]
772         assert flags[11] == '-I', \
773                flags[11]
774         assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \
775                flags[12]
776         assert flags[13] == '-I', \
777                flags[13]
778         assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \
779                flags[14]
780         assert flags[15] == '-I', \
781                flags[15]
782         assert flags[16] == os.path.normpath('blatXXX'), \
783                flags[16]
784         assert flags[17] == '$)', \
785                flags[17]
786
787     def test_platform(self):
788         """Test specifying a platform callable when instantiating."""
789         class platform:
790             def __str__(self):        return "TestPlatform"
791             def __call__(self, env):  env['XYZZY'] = 777
792
793         def tool(env):
794             env['SET_TOOL'] = 'initialized'
795             assert env['PLATFORM'] == "TestPlatform"
796
797         env = Environment(platform = platform(), tools = [tool])
798         assert env['XYZZY'] == 777, env
799         assert env['PLATFORM'] == "TestPlatform"
800         assert env['SET_TOOL'] == "initialized"
801
802     def test_Default_PLATFORM(self):
803         """Test overriding the default PLATFORM variable"""
804         class platform:
805             def __str__(self):        return "DefaultTestPlatform"
806             def __call__(self, env):  env['XYZZY'] = 888
807
808         def tool(env):
809             env['SET_TOOL'] = 'abcde'
810             assert env['PLATFORM'] == "DefaultTestPlatform"
811
812         import SCons.Defaults
813         save = SCons.Defaults.ConstructionEnvironment.copy()
814         try:
815             import SCons.Defaults
816             SCons.Defaults.ConstructionEnvironment.update({
817                 'PLATFORM' : platform(),
818             })
819             env = Environment(tools = [tool])
820             assert env['XYZZY'] == 888, env
821             assert env['PLATFORM'] == "DefaultTestPlatform"
822             assert env['SET_TOOL'] == "abcde"
823         finally:
824             SCons.Defaults.ConstructionEnvironment = save
825
826     def test_tools(self):
827         """Test specifying a tool callable when instantiating."""
828         def t1(env):
829             env['TOOL1'] = 111
830         def t2(env):
831             env['TOOL2'] = 222
832         def t3(env):
833             env['AAA'] = env['XYZ']
834         def t4(env):
835             env['TOOL4'] = 444
836         env = Environment(tools = [t1, t2, t3], XYZ = 'aaa')
837         assert env['TOOL1'] == 111, env['TOOL1']
838         assert env['TOOL2'] == 222, env
839         assert env['AAA'] == 'aaa', env
840         t4(env)
841         assert env['TOOL4'] == 444, env
842
843     def test_Default_TOOLS(self):
844         """Test overriding the default TOOLS variable"""
845         def t5(env):
846             env['TOOL5'] = 555
847         def t6(env):
848             env['TOOL6'] = 666
849         def t7(env):
850             env['BBB'] = env['XYZ']
851         def t8(env):
852             env['TOOL8'] = 888
853
854         import SCons.Defaults
855         save = SCons.Defaults.ConstructionEnvironment.copy()
856         try:
857             SCons.Defaults.ConstructionEnvironment.update({
858                 'TOOLS' : [t5, t6, t7],
859             })
860             env = Environment(XYZ = 'bbb')
861             assert env['TOOL5'] == 555, env['TOOL5']
862             assert env['TOOL6'] == 666, env
863             assert env['BBB'] == 'bbb', env
864             t8(env)
865             assert env['TOOL8'] == 888, env
866         finally:
867             SCons.Defaults.ConstructionEnvironment = save
868
869     def test_concat(self):
870         "Test _concat()"
871         e1 = Environment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
872         s = e1.subst
873         x = s("${_concat('', '', '', __env__)}")
874         assert x == '', x
875         x = s("${_concat('', [], '', __env__)}")
876         assert x == '', x
877         x = s("${_concat(PRE, '', SUF, __env__)}")
878         assert x == '', x
879         x = s("${_concat(PRE, STR, SUF, __env__)}")
880         assert x == 'prea bsuf', x
881         x = s("${_concat(PRE, LIST, SUF, __env__)}")
882         assert x == 'preasuf prebsuf', x
883
884     def test__update(self):
885         """Test the _update() method"""
886         env = Environment(X = 'x', Y = 'y', Z = 'z')
887         assert env['X'] == 'x', env['X']
888         assert env['Y'] == 'y', env['Y']
889         assert env['Z'] == 'z', env['Z']
890         env._update({'X'       : 'xxx',
891                      'TARGET'  : 't',
892                      'TARGETS' : 'ttt',
893                      'SOURCE'  : 's',
894                      'SOURCES' : 'sss',
895                      'Z'       : 'zzz'})
896         assert env['X'] == 'xxx', env['X']
897         assert env['Y'] == 'y', env['Y']
898         assert env['Z'] == 'zzz', env['Z']
899         assert env['TARGET'] == 't', env['TARGET']
900         assert env['TARGETS'] == 'ttt', env['TARGETS']
901         assert env['SOURCE'] == 's', env['SOURCE']
902         assert env['SOURCES'] == 'sss', env['SOURCES']
903
904
905
906     def test_Append(self):
907         """Test appending to construction variables in an Environment
908         """
909
910         b1 = Environment()['BUILDERS']
911         b2 = Environment()['BUILDERS']
912         assert b1 == b2, diff_dict(b1, b2)
913
914         import UserList
915         UL = UserList.UserList
916
917         cases = [
918             'a1',       'A1',           'a1A1',
919             'a2',       ['A2'],         ['a2', 'A2'],
920             'a3',       UL(['A3']),     UL(['a', '3', 'A3']),
921             'a4',       '',             'a4',
922             'a5',       [],             ['a5'],
923             'a6',       UL([]),         UL(['a', '6']),
924             'a7',       [''],           ['a7', ''],
925             'a8',       UL(['']),       UL(['a', '8', '']),
926
927             ['e1'],     'E1',           ['e1', 'E1'],
928             ['e2'],     ['E2'],         ['e2', 'E2'],
929             ['e3'],     UL(['E3']),     UL(['e3', 'E3']),
930             ['e4'],     '',             ['e4'],
931             ['e5'],     [],             ['e5'],
932             ['e6'],     UL([]),         UL(['e6']),
933             ['e7'],     [''],           ['e7', ''],
934             ['e8'],     UL(['']),       UL(['e8', '']),
935
936             UL(['i1']), 'I1',           UL(['i1', 'I', '1']),
937             UL(['i2']), ['I2'],         UL(['i2', 'I2']),
938             UL(['i3']), UL(['I3']),     UL(['i3', 'I3']),
939             UL(['i4']), '',             UL(['i4']),
940             UL(['i5']), [],             UL(['i5']),
941             UL(['i6']), UL([]),         UL(['i6']),
942             UL(['i7']), [''],           UL(['i7', '']),
943             UL(['i8']), UL(['']),       UL(['i8', '']),
944
945             '',         'M1',           'M1',
946             '',         ['M2'],         ['M2'],
947             '',         UL(['M3']),     UL(['M3']),
948             '',         '',             '',
949             '',         [],             [],
950             '',         UL([]),         UL([]),
951             '',         [''],           [''],
952             '',         UL(['']),       UL(['']),
953
954             [],         'N1',           ['N1'],
955             [],         ['N2'],         ['N2'],
956             [],         UL(['N3']),     UL(['N3']),
957             [],         '',             [],
958             [],         [],             [],
959             [],         UL([]),         UL([]),
960             [],         [''],           [''],
961             [],         UL(['']),       UL(['']),
962
963             UL([]),     'O1',           ['O', '1'],
964             UL([]),     ['O2'],         ['O2'],
965             UL([]),     UL(['O3']),     UL(['O3']),
966             UL([]),     '',             UL([]),
967             UL([]),     [],             UL([]),
968             UL([]),     UL([]),         UL([]),
969             UL([]),     [''],           UL(['']),
970             UL([]),     UL(['']),       UL(['']),
971
972             [''],       'P1',           ['', 'P1'],
973             [''],       ['P2'],         ['', 'P2'],
974             [''],       UL(['P3']),     UL(['', 'P3']),
975             [''],       '',             [''],
976             [''],       [],             [''],
977             [''],       UL([]),         UL(['']),
978             [''],       [''],           ['', ''],
979             [''],       UL(['']),       UL(['', '']),
980
981             UL(['']),   'Q1',           ['', 'Q', '1'],
982             UL(['']),   ['Q2'],         ['', 'Q2'],
983             UL(['']),   UL(['Q3']),     UL(['', 'Q3']),
984             UL(['']),   '',             UL(['']),
985             UL(['']),   [],             UL(['']),
986             UL(['']),   UL([]),         UL(['']),
987             UL(['']),   [''],           UL(['', '']),
988             UL(['']),   UL(['']),       UL(['', '']),
989         ]
990
991         env = Environment()
992         failed = 0
993         while cases:
994             input, append, expect = cases[:3]
995             env['XXX'] = input
996             env.Append(XXX = append)
997             result = env['XXX']
998             if result != expect:
999                 if failed == 0: print
1000                 print "    %s Append %s => %s did not match %s" % \
1001                       (repr(input), repr(append), repr(result), repr(expect))
1002                 failed = failed + 1
1003             del cases[:3]
1004         assert failed == 0, "%d Append() cases failed" % failed
1005
1006         env['UL'] = UL(['foo'])
1007         env.Append(UL = 'bar')
1008         result = env['UL']
1009         assert isinstance(result, UL), repr(result)
1010         assert result == ['foo', 'b', 'a', 'r'], result
1011
1012         env['CLVar'] = CLVar(['foo'])
1013         env.Append(CLVar = 'bar')
1014         result = env['CLVar']
1015         assert isinstance(result, CLVar), repr(result)
1016         assert result == ['foo', 'bar'], result
1017
1018         class C:
1019             def __init__(self, name):
1020                 self.name = name
1021             def __str__(self):
1022                 return self.name
1023             def __cmp__(self, other):
1024                 raise "should not compare"
1025
1026         ccc = C('ccc')
1027
1028         env2 = Environment(CCC1 = ['c1'], CCC2 = ccc)
1029         env2.Append(CCC1 = ccc, CCC2 = ['c2'])
1030         assert env2['CCC1'][0] == 'c1', env2['CCC1']
1031         assert env2['CCC1'][1] is ccc, env2['CCC1']
1032         assert env2['CCC2'][0] is ccc, env2['CCC2']
1033         assert env2['CCC2'][1] == 'c2', env2['CCC2']
1034
1035         env3 = Environment(X = {'x1' : 7})
1036         env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1037         assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X']
1038         assert env3['Y'] == {'y1': 10}, env3['Y']
1039
1040         env4 = Environment(BUILDERS = {'z1' : 11})
1041         env4.Append(BUILDERS = {'z2' : 12})
1042         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1043         assert hasattr(env4, 'z1')
1044         assert hasattr(env4, 'z2')
1045
1046     def test_AppendENVPath(self):
1047         """Test appending to an ENV path."""
1048         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1049                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1050         # have to include the pathsep here so that the test will work on UNIX too.
1051         env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
1052         env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
1053         env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
1054         env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
1055         assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
1056         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
1057
1058     def test_AppendUnique(self):
1059         """Test appending to unique values to construction variables
1060
1061         This strips values that are already present when lists are
1062         involved."""
1063         env = Environment(AAA1 = 'a1',
1064                           AAA2 = 'a2',
1065                           AAA3 = 'a3',
1066                           BBB1 = ['b1'],
1067                           BBB2 = ['b2'],
1068                           BBB3 = ['b3'])
1069         env.AppendUnique(AAA1 = 'a1',
1070                          AAA2 = ['a2'],
1071                          AAA3 = ['a3', 'b', 'c', 'a3'],
1072                          BBB1 = 'b1',
1073                          BBB2 = ['b2'],
1074                          BBB3 = ['b3', 'c', 'd', 'b3'])
1075         assert env['AAA1'] == 'a1a1', env['AAA1']
1076         assert env['AAA2'] == ['a2'], env['AAA2']
1077         assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3']
1078         assert env['BBB1'] == ['b1'], env['BBB1']
1079         assert env['BBB2'] == ['b2'], env['BBB2']
1080         assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3']
1081
1082     def test_Copy(self):
1083         """Test construction Environment copying
1084
1085         Update the copy independently afterwards and check that
1086         the original remains intact (that is, no dangling
1087         references point to objects in the copied environment).
1088         Copy the original with some construction variable
1089         updates and check that the original remains intact
1090         and the copy has the updated values.
1091         """
1092         env1 = Environment(XXX = 'x', YYY = 'y')
1093         env2 = env1.Copy()
1094         env1copy = env1.Copy()
1095         env2.Replace(YYY = 'yyy')
1096         assert env1 != env2
1097         assert env1 == env1copy
1098
1099         env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
1100         assert env3.Dictionary('XXX') == 'x3'
1101         assert env3.Dictionary('YYY') == 'y'
1102         assert env3.Dictionary('ZZZ') == 'z3'
1103         assert env1 == env1copy
1104
1105         assert env1['__env__'] is env1, env1['__env__']
1106         assert env2['__env__'] is env2, env2['__env__']
1107         assert env3['__env__'] is env3, env3['__env__']
1108
1109         # Ensure that lists and dictionaries are
1110         # deep copied, but not instances.
1111         class TestA:
1112             pass
1113         env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
1114                            ZZZ = { 1:2, 3:4 })
1115         env2=env1.Copy()
1116         env2.Dictionary('YYY').append(4)
1117         env2.Dictionary('ZZZ')[5] = 6
1118         assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
1119         assert 4 in env2.Dictionary('YYY')
1120         assert not 4 in env1.Dictionary('YYY')
1121         assert env2.Dictionary('ZZZ').has_key(5)
1122         assert not env1.Dictionary('ZZZ').has_key(5)
1123
1124         #
1125         env1 = Environment(BUILDERS = {'b1' : 1})
1126         assert hasattr(env1, 'b1'), "env1.b1 was not set"
1127         assert env1.b1.env == env1, "b1.env doesn't point to env1"
1128         env2 = env1.Copy(BUILDERS = {'b2' : 2})
1129         assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
1130         assert env1.b1.env == env1, "b1.env was changed"
1131         assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
1132         assert hasattr(env2, 'b2'), "env2.b2 was not set"
1133         assert env2.b2.env == env2, "b2.env doesn't point to env2"
1134
1135         # Ensure that specifying new tools in a copied environment
1136         # works.
1137         def foo(env): env['FOO'] = 1
1138         def bar(env): env['BAR'] = 2
1139         def baz(env): env['BAZ'] = 3
1140         env1 = Environment(tools=[foo])
1141         env2 = env1.Copy()
1142         env3 = env1.Copy(tools=[bar, baz])
1143
1144         assert env1.get('FOO') is 1
1145         assert env1.get('BAR') is None
1146         assert env1.get('BAZ') is None
1147         assert env2.get('FOO') is 1
1148         assert env2.get('BAR') is None
1149         assert env2.get('BAZ') is None
1150         assert env3.get('FOO') is 1
1151         assert env3.get('BAR') is 2
1152         assert env3.get('BAZ') is 3
1153
1154         # Ensure that recursive variable substitution when copying
1155         # environments works properly.
1156         env1 = Environment(CCFLAGS = '-DFOO', XYZ = '-DXYZ')
1157         env2 = env1.Copy(CCFLAGS = '$CCFLAGS -DBAR',
1158                          XYZ = ['-DABC', 'x $XYZ y', '-DDEF'])
1159         x = env2.get('CCFLAGS')
1160         assert x == '-DFOO -DBAR', x
1161         x = env2.get('XYZ')
1162         assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x
1163
1164         # Ensure that special properties of a class don't get
1165         # lost on copying.
1166         env1 = Environment(FLAGS = CLVar('flag1 flag2'))
1167         x = env1.get('FLAGS')
1168         assert x == ['flag1', 'flag2'], x
1169         env2 = env1.Copy()
1170         env2.Append(FLAGS = 'flag3 flag4')
1171         x = env2.get('FLAGS')
1172         assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x
1173
1174     def test_Detect(self):
1175         """Test Detect()ing tools"""
1176         test = TestCmd.TestCmd(workdir = '')
1177         test.subdir('sub1', 'sub2')
1178         sub1 = test.workpath('sub1')
1179         sub2 = test.workpath('sub2')
1180
1181         if sys.platform == 'win32':
1182             test.write(['sub1', 'xxx'], "sub1/xxx\n")
1183             test.write(['sub2', 'xxx'], "sub2/xxx\n")
1184
1185             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
1186
1187             x = env.Detect('xxx.exe')
1188             assert x is None, x
1189
1190             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1191
1192             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
1193
1194             x = env.Detect('xxx.exe')
1195             assert x == 'xxx.exe', x
1196
1197             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1198
1199             x = env.Detect('xxx.exe')
1200             assert x == 'xxx.exe', x
1201
1202         else:
1203             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
1204             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
1205
1206             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
1207
1208             x = env.Detect('xxx.exe')
1209             assert x is None, x
1210
1211             sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1212             os.chmod(sub2_xxx_exe, 0755)
1213
1214             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
1215
1216             x = env.Detect('xxx.exe')
1217             assert x == 'xxx.exe', x
1218
1219             sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1220             os.chmod(sub1_xxx_exe, 0755)
1221
1222             x = env.Detect('xxx.exe')
1223             assert x == 'xxx.exe', x
1224
1225         env = Environment(ENV = { 'PATH' : [] })
1226         x = env.Detect('xxx.exe')
1227         assert x is None, x
1228
1229     def test_Dictionary(self):
1230         """Test retrieval of known construction variables
1231
1232         Fetch them from the Dictionary and check for well-known
1233         defaults that get inserted.
1234         """
1235         env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z')
1236         assert env.Dictionary('XXX') == 'x'
1237         assert env.Dictionary('YYY') == 'y'
1238         assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
1239         xxx, zzz = env.Dictionary('XXX', 'ZZZ')
1240         assert xxx == 'x'
1241         assert zzz == 'z'
1242         assert env.Dictionary().has_key('BUILDERS')
1243         assert env.Dictionary().has_key('CC')
1244         assert env.Dictionary().has_key('CCFLAGS')
1245         assert env.Dictionary().has_key('ENV')
1246
1247         assert env['XXX'] == 'x'
1248         env['XXX'] = 'foo'
1249         assert env.Dictionary('XXX') == 'foo'
1250         del env['XXX']
1251         assert not env.Dictionary().has_key('XXX')
1252
1253     def test_FindIxes(self):
1254         "Test FindIxes()"
1255         env = Environment(LIBPREFIX='lib',
1256                           LIBSUFFIX='.a',
1257                           SHLIBPREFIX='lib',
1258                           SHLIBSUFFIX='.so',
1259                           PREFIX='pre',
1260                           SUFFIX='post')
1261
1262         paths = [os.path.join('dir', 'libfoo.a'),
1263                  os.path.join('dir', 'libfoo.so')]
1264
1265         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1266         assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1267         assert None == env.FindIxes(paths, 'PREFIX', 'POST')
1268
1269         paths = ['libfoo.a', 'prefoopost']
1270
1271         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
1272         assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
1273         assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
1274
1275     def test_Override(self):
1276         "Test overriding construction variables"
1277         env = Environment(ONE=1, TWO=2, THREE=3, FOUR=4)
1278         assert env['ONE'] == 1, env['ONE']
1279         assert env['TWO'] == 2, env['TWO']
1280         assert env['THREE'] == 3, env['THREE']
1281         assert env['FOUR'] == 4, env['FOUR']
1282
1283         env2 = env.Override({'TWO'   : '10',
1284                              'THREE' :'x $THREE y',
1285                              'FOUR'  : ['x', '$FOUR', 'y']})
1286         assert env2['ONE'] == 1, env2['ONE']
1287         assert env2['TWO'] == '10', env2['TWO']
1288         assert env2['THREE'] == 'x 3 y', env2['THREE']
1289         assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR']
1290
1291         assert env['ONE'] == 1, env['ONE']
1292         assert env['TWO'] == 2, env['TWO']
1293         assert env['THREE'] == 3, env['THREE']
1294         assert env['FOUR'] == 4, env['FOUR']
1295
1296         env2.Replace(ONE = "won")
1297         assert env2['ONE'] == "won", env2['ONE']
1298         assert env['ONE'] == 1, env['ONE']
1299
1300         assert env['__env__'] is env, env['__env__']
1301         assert env2['__env__'] is env2, env2['__env__']
1302
1303     def test_ParseConfig(self):
1304         """Test the ParseConfig() method"""
1305         env = Environment(COMMAND='command',
1306                           CPPPATH='string',
1307                           LIBPATH=['list'],
1308                           LIBS='',
1309                           CCFLAGS=[''])
1310         save_command = []
1311         orig_popen = os.popen
1312         def my_popen(command, save_command=save_command):
1313             save_command.append(command)
1314             class fake_file:
1315                 def read(self):
1316                     return "-I/usr/include/fum -Ibar -X\n" + \
1317                            "-L/usr/fax -Lfoo -lxxx abc"
1318             return fake_file()
1319         try:
1320             os.popen = my_popen
1321             libs = env.ParseConfig("fake $COMMAND")
1322             assert save_command == ['fake command'], save_command
1323             assert libs == ['abc'], libs
1324             assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1325             assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
1326             assert env['LIBS'] == ['xxx'], env['LIBS']
1327             assert env['CCFLAGS'] == ['', '-X'], env['CCFLAGS']
1328         finally:
1329             os.popen = orig_popen
1330
1331     def test_Platform(self):
1332         """Test the Platform() method"""
1333         env = Environment(WIN32='win32', NONE='no-such-platform')
1334
1335         exc_caught = None
1336         try:
1337             env.Platform('does_not_exist')
1338         except SCons.Errors.UserError:
1339             exc_caught = 1
1340         assert exc_caught, "did not catch expected UserError"
1341
1342         exc_caught = None
1343         try:
1344             env.Platform('$NONE')
1345         except SCons.Errors.UserError:
1346             exc_caught = 1
1347         assert exc_caught, "did not catch expected UserError"
1348
1349         env.Platform('posix')
1350         assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
1351
1352         env.Platform('$WIN32')
1353         assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
1354
1355     def test_Prepend(self):
1356         """Test prepending to construction variables in an Environment
1357         """
1358         import UserList
1359         UL = UserList.UserList
1360
1361         cases = [
1362             'a1',       'A1',           'A1a1',
1363             'a2',       ['A2'],         ['A2', 'a2'],
1364             'a3',       UL(['A3']),     UL(['A3', 'a', '3']),
1365             'a4',       '',             'a4',
1366             'a5',       [],             ['a5'],
1367             'a6',       UL([]),         UL(['a', '6']),
1368             'a7',       [''],           ['', 'a7'],
1369             'a8',       UL(['']),       UL(['', 'a', '8']),
1370
1371             ['e1'],     'E1',           ['E1', 'e1'],
1372             ['e2'],     ['E2'],         ['E2', 'e2'],
1373             ['e3'],     UL(['E3']),     UL(['E3', 'e3']),
1374             ['e4'],     '',             ['e4'],
1375             ['e5'],     [],             ['e5'],
1376             ['e6'],     UL([]),         UL(['e6']),
1377             ['e7'],     [''],           ['', 'e7'],
1378             ['e8'],     UL(['']),       UL(['', 'e8']),
1379
1380             UL(['i1']), 'I1',           UL(['I', '1', 'i1']),
1381             UL(['i2']), ['I2'],         UL(['I2', 'i2']),
1382             UL(['i3']), UL(['I3']),     UL(['I3', 'i3']),
1383             UL(['i4']), '',             UL(['i4']),
1384             UL(['i5']), [],             UL(['i5']),
1385             UL(['i6']), UL([]),         UL(['i6']),
1386             UL(['i7']), [''],           UL(['', 'i7']),
1387             UL(['i8']), UL(['']),       UL(['', 'i8']),
1388
1389             '',         'M1',           'M1',
1390             '',         ['M2'],         ['M2'],
1391             '',         UL(['M3']),     UL(['M3']),
1392             '',         '',             '',
1393             '',         [],             [],
1394             '',         UL([]),         UL([]),
1395             '',         [''],           [''],
1396             '',         UL(['']),       UL(['']),
1397
1398             [],         'N1',           ['N1'],
1399             [],         ['N2'],         ['N2'],
1400             [],         UL(['N3']),     UL(['N3']),
1401             [],         '',             [],
1402             [],         [],             [],
1403             [],         UL([]),         UL([]),
1404             [],         [''],           [''],
1405             [],         UL(['']),       UL(['']),
1406
1407             UL([]),     'O1',           UL(['O', '1']),
1408             UL([]),     ['O2'],         UL(['O2']),
1409             UL([]),     UL(['O3']),     UL(['O3']),
1410             UL([]),     '',             UL([]),
1411             UL([]),     [],             UL([]),
1412             UL([]),     UL([]),         UL([]),
1413             UL([]),     [''],           UL(['']),
1414             UL([]),     UL(['']),       UL(['']),
1415
1416             [''],       'P1',           ['P1', ''],
1417             [''],       ['P2'],         ['P2', ''],
1418             [''],       UL(['P3']),     UL(['P3', '']),
1419             [''],       '',             [''],
1420             [''],       [],             [''],
1421             [''],       UL([]),         UL(['']),
1422             [''],       [''],           ['', ''],
1423             [''],       UL(['']),       UL(['', '']),
1424
1425             UL(['']),   'Q1',           UL(['Q', '1', '']),
1426             UL(['']),   ['Q2'],         UL(['Q2', '']),
1427             UL(['']),   UL(['Q3']),     UL(['Q3', '']),
1428             UL(['']),   '',             UL(['']),
1429             UL(['']),   [],             UL(['']),
1430             UL(['']),   UL([]),         UL(['']),
1431             UL(['']),   [''],           UL(['', '']),
1432             UL(['']),   UL(['']),       UL(['', '']),
1433         ]
1434
1435         env = Environment()
1436         failed = 0
1437         while cases:
1438             input, prepend, expect = cases[:3]
1439             env['XXX'] = input
1440             env.Prepend(XXX = prepend)
1441             result = env['XXX']
1442             if result != expect:
1443                 if failed == 0: print
1444                 print "    %s Prepend %s => %s did not match %s" % \
1445                       (repr(input), repr(prepend), repr(result), repr(expect))
1446                 failed = failed + 1
1447             del cases[:3]
1448         assert failed == 0, "%d Prepend() cases failed" % failed
1449
1450         env['UL'] = UL(['foo'])
1451         env.Prepend(UL = 'bar')
1452         result = env['UL']
1453         assert isinstance(result, UL), repr(result)
1454         assert result == ['b', 'a', 'r', 'foo'], result
1455
1456         env['CLVar'] = CLVar(['foo'])
1457         env.Prepend(CLVar = 'bar')
1458         result = env['CLVar']
1459         assert isinstance(result, CLVar), repr(result)
1460         assert result == ['bar', 'foo'], result
1461
1462         env3 = Environment(X = {'x1' : 7})
1463         env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1464         assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
1465         assert env3['Y'] == {'y1': 10}, env3['Y']
1466
1467         env4 = Environment(BUILDERS = {'z1' : 11})
1468         env4.Prepend(BUILDERS = {'z2' : 12})
1469         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1470         assert hasattr(env4, 'z1')
1471         assert hasattr(env4, 'z2')
1472
1473     def test_PrependENVPath(self):
1474         """Test prepending to an ENV path."""
1475         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1476                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1477         # have to include the pathsep here so that the test will work on UNIX too.
1478         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
1479         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
1480         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
1481         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
1482         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
1483         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
1484
1485     def test_PrependENVPath(self):
1486         """Test prepending to an ENV path."""
1487         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1488                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1489         # have to include the pathsep here so that the test will work on UNIX too.
1490         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
1491         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
1492         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
1493         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
1494         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
1495         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
1496
1497     def test_PrependUnique(self):
1498         """Test prepending unique values to construction variables
1499
1500         This strips values that are already present when lists are
1501         involved."""
1502         env = Environment(AAA1 = 'a1',
1503                           AAA2 = 'a2',
1504                           AAA3 = 'a3',
1505                           BBB1 = ['b1'],
1506                           BBB2 = ['b2'],
1507                           BBB3 = ['b3'])
1508         env.PrependUnique(AAA1 = 'a1',
1509                           AAA2 = ['a2'],
1510                           AAA3 = ['a3', 'b', 'c', 'a3'],
1511                           BBB1 = 'b1',
1512                           BBB2 = ['b2'],
1513                           BBB3 = ['b3', 'b', 'c', 'b3'])
1514         assert env['AAA1'] == 'a1a1', env['AAA1']
1515         assert env['AAA2'] == ['a2'], env['AAA2']
1516         assert env['AAA3'] == ['b', 'c', 'a3'], env['AAA3']
1517         assert env['BBB1'] == ['b1'], env['BBB1']
1518         assert env['BBB2'] == ['b2'], env['BBB2']
1519         assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3']
1520
1521     def test_Replace(self):
1522         """Test replacing construction variables in an Environment
1523
1524         After creation of the Environment, of course.
1525         """
1526         env1 = Environment(AAA = 'a', BBB = 'b')
1527         env1.Replace(BBB = 'bbb', CCC = 'ccc')
1528
1529         env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
1530         assert env1 == env2, diff_env(env1, env2)
1531
1532         env3 = Environment(BUILDERS = {'b1' : 1})
1533         assert hasattr(env3, 'b1'), "b1 was not set"
1534         env3.Replace(BUILDERS = {'b2' : 2})
1535         assert not hasattr(env3, 'b1'), "b1 was not cleared"
1536         assert hasattr(env3, 'b2'), "b2 was not set"
1537
1538     def test_ReplaceIxes(self):
1539         "Test ReplaceIxes()"
1540         env = Environment(LIBPREFIX='lib',
1541                           LIBSUFFIX='.a',
1542                           SHLIBPREFIX='lib',
1543                           SHLIBSUFFIX='.so',
1544                           PREFIX='pre',
1545                           SUFFIX='post')
1546
1547         assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
1548                                              'SHLIBPREFIX', 'SHLIBSUFFIX',
1549                                              'LIBPREFIX', 'LIBSUFFIX')
1550
1551         assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
1552                                                                    'SHLIBPREFIX', 'SHLIBSUFFIX',
1553                                                                    'LIBPREFIX', 'LIBSUFFIX')
1554
1555         assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
1556                                              'PREFIX', 'SUFFIX',
1557                                              'LIBPREFIX', 'LIBSUFFIX')
1558
1559     def test_Tool(self):
1560         """Test the Tool() method"""
1561         env = Environment(LINK='link', NONE='no-such-tool')
1562
1563         exc_caught = None
1564         try:
1565             env.Tool('does_not_exist')
1566         except SCons.Errors.UserError:
1567             exc_caught = 1
1568         assert exc_caught, "did not catch expected UserError"
1569
1570         exc_caught = None
1571         try:
1572             env.Tool('$NONE')
1573         except SCons.Errors.UserError:
1574             exc_caught = 1
1575         assert exc_caught, "did not catch expected UserError"
1576
1577         # Use a non-existent toolpath directory just to make sure we
1578         # can call Tool() with the keyword argument.
1579         env.Tool('cc', toolpath=['/no/such/directory'])
1580         assert env['CC'] == 'cc', env['CC']
1581
1582         env.Tool('$LINK')
1583         assert env['LINK'] == '$SMARTLINK', env['LINK']
1584
1585     def test_WhereIs(self):
1586         """Test the WhereIs() method"""
1587         test = TestCmd.TestCmd(workdir = '')
1588
1589         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1590         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1591         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
1592         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
1593
1594         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
1595
1596         if sys.platform != 'win32':
1597             test.write(sub1_xxx_exe, "\n")
1598
1599         os.mkdir(sub2_xxx_exe)
1600
1601         test.write(sub3_xxx_exe, "\n")
1602         os.chmod(sub3_xxx_exe, 0777)
1603
1604         test.write(sub4_xxx_exe, "\n")
1605         os.chmod(sub4_xxx_exe, 0777)
1606
1607         env_path = os.environ['PATH']
1608
1609         pathdirs_1234 = [ test.workpath('sub1'),
1610                           test.workpath('sub2'),
1611                           test.workpath('sub3'),
1612                           test.workpath('sub4'),
1613                         ] + string.split(env_path, os.pathsep)
1614
1615         pathdirs_1243 = [ test.workpath('sub1'),
1616                           test.workpath('sub2'),
1617                           test.workpath('sub4'),
1618                           test.workpath('sub3'),
1619                         ] + string.split(env_path, os.pathsep)
1620
1621         path = string.join(pathdirs_1234, os.pathsep)
1622         env = Environment(ENV = {'PATH' : path})
1623         wi = env.WhereIs('xxx.exe')
1624         assert wi == test.workpath(sub3_xxx_exe), wi
1625         wi = env.WhereIs('xxx.exe', pathdirs_1243)
1626         assert wi == test.workpath(sub4_xxx_exe), wi
1627         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
1628         assert wi == test.workpath(sub4_xxx_exe), wi
1629
1630         wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe)
1631         assert wi == test.workpath(sub4_xxx_exe), wi
1632         wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
1633         assert wi == test.workpath(sub4_xxx_exe), wi
1634
1635         path = string.join(pathdirs_1243, os.pathsep)
1636         env = Environment(ENV = {'PATH' : path})
1637         wi = env.WhereIs('xxx.exe')
1638         assert wi == test.workpath(sub4_xxx_exe), wi
1639         wi = env.WhereIs('xxx.exe', pathdirs_1234)
1640         assert wi == test.workpath(sub3_xxx_exe), wi
1641         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
1642         assert wi == test.workpath(sub3_xxx_exe), wi
1643
1644         if sys.platform == 'win32':
1645             wi = env.WhereIs('xxx', pathext = '')
1646             assert wi is None, wi
1647
1648             wi = env.WhereIs('xxx', pathext = '.exe')
1649             assert wi == test.workpath(sub4_xxx_exe), wi
1650
1651             wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
1652             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
1653
1654             # Test that we return a normalized path even when
1655             # the path contains forward slashes.
1656             forward_slash = test.workpath('') + '/sub3'
1657             wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE')
1658             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
1659
1660
1661
1662     def test_Action(self):
1663         """Test the Action() method"""
1664         import SCons.Action
1665
1666         env = Environment(FOO = 'xyzzy')
1667
1668         a = env.Action('foo')
1669         assert a, a
1670         assert a.__class__ is SCons.Action.CommandAction, a
1671
1672         a = env.Action('$FOO')
1673         assert a, a
1674         assert a.__class__ is SCons.Action.CommandGeneratorAction, a
1675
1676         a = env.Action(['$FOO', 'foo'])
1677         assert a, a
1678         assert a.__class__ is SCons.Action.ListAction, a
1679
1680         def func(arg):
1681             pass
1682         a = env.Action(func)
1683         assert a, a
1684         assert a.__class__ is SCons.Action.FunctionAction, a
1685
1686     def test_AddPostAction(self):
1687         """Test the AddPostAction() method"""
1688         env = Environment(FOO='fff', BAR='bbb')
1689
1690         n = env.AddPostAction('$FOO', lambda x: x)
1691         assert str(n[0]) == 'fff', n[0]
1692
1693         n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
1694         assert str(n[0]) == 'ggg', n[0]
1695         assert str(n[1]) == 'bbb', n[1]
1696
1697     def test_AddPreAction(self):
1698         """Test the AddPreAction() method"""
1699         env = Environment(FOO='fff', BAR='bbb')
1700
1701         n = env.AddPreAction('$FOO', lambda x: x)
1702         assert str(n[0]) == 'fff', n[0]
1703
1704         n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
1705         assert str(n[0]) == 'ggg', n[0]
1706         assert str(n[1]) == 'bbb', n[1]
1707
1708     def test_Alias(self):
1709         """Test the Alias() method"""
1710         env = Environment(FOO='kkk', BAR='lll', EA='export_alias')
1711
1712         tgt = env.Alias('new_alias')
1713         assert str(tgt) == 'new_alias', tgt
1714         assert tgt.sources == [], tgt.sources
1715
1716         tgt = env.Alias('None_alias', None)
1717         assert str(tgt) == 'None_alias', tgt
1718         assert tgt.sources == [], tgt.sources
1719
1720         tgt = env.Alias('empty_list', [])
1721         assert str(tgt) == 'empty_list', tgt
1722         assert tgt.sources == [], tgt.sources
1723
1724         tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])
1725         assert str(tgt) == 'export_alias', tgt
1726         assert len(tgt.sources) == 2, map(str, tgt.sources)
1727         assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources)
1728         assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources)
1729
1730         n = env.Alias(tgt, source = ['$BAR', 'asrc4'])
1731         assert n is tgt, n
1732         assert len(tgt.sources) == 4, map(str, tgt.sources)
1733         assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources)
1734         assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources)
1735
1736         n = env.Alias('$EA', 'asrc5')
1737         assert n is tgt, n
1738         assert len(tgt.sources) == 5, map(str, tgt.sources)
1739         assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources)
1740
1741         t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
1742         assert str(t1) == 't1', t1
1743         assert str(t2) == 't2', t2
1744         assert len(t1.sources) == 2, map(str, t1.sources)
1745         assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources)
1746         assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources)
1747         assert len(t2.sources) == 2, map(str, t2.sources)
1748         assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources)
1749         assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources)
1750
1751     def test_AlwaysBuild(self):
1752         """Test the AlwaysBuild() method"""
1753         env = Environment(FOO='fff', BAR='bbb')
1754         t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR')
1755         assert t[0].__class__.__name__ == 'File'
1756         assert t[0].path == 'a'
1757         assert t[0].always_build
1758         assert t[1].__class__.__name__ == 'File'
1759         assert t[1].path == 'bfff'
1760         assert t[1].always_build
1761         assert t[2].__class__.__name__ == 'File'
1762         assert t[2].path == 'c'
1763         assert t[2].always_build
1764         assert t[3].__class__.__name__ == 'File'
1765         assert t[3].path == 'd'
1766         assert t[3].always_build
1767         assert t[4].__class__.__name__ == 'File'
1768         assert t[4].path == 'bbb'
1769         assert t[4].always_build
1770
1771     def test_BuildDir(self):
1772         """Test the BuildDir() method"""
1773         class MyFS:
1774              def Dir(self, name):
1775                  return name
1776              def BuildDir(self, build_dir, src_dir, duplicate):
1777                  self.build_dir = build_dir
1778                  self.src_dir = src_dir
1779                  self.duplicate = duplicate
1780
1781         env = Environment(FOO = 'fff', BAR = 'bbb')
1782         env.fs = MyFS()
1783
1784         env.BuildDir('build', 'src')
1785         assert env.fs.build_dir == 'build', env.fs.build_dir
1786         assert env.fs.src_dir == 'src', env.fs.src_dir
1787         assert env.fs.duplicate == 1, env.fs.duplicate
1788
1789         env.BuildDir('build${FOO}', '${BAR}src', 0)
1790         assert env.fs.build_dir == 'buildfff', env.fs.build_dir
1791         assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir
1792         assert env.fs.duplicate == 0, env.fs.duplicate
1793
1794     def test_Builder(self):
1795         """Test the Builder() method"""
1796         env = Environment(FOO = 'xyzzy')
1797
1798         b = env.Builder(action = 'foo')
1799         assert not b is None, b
1800
1801         b = env.Builder(action = '$FOO')
1802         assert not b is None, b
1803
1804         b = env.Builder(action = ['$FOO', 'foo'])
1805         assert not b is None, b
1806
1807         def func(arg):
1808             pass
1809         b = env.Builder(action = func)
1810         assert not b is None, b
1811         b = env.Builder(generator = func)
1812         assert not b is None, b
1813
1814     def test_CacheDir(self):
1815         """Test the CacheDir() method"""
1816         class MyFS:
1817             def CacheDir(self, path):
1818                 self.CD = path
1819
1820         env = Environment(CD = 'CacheDir')
1821         env.fs = MyFS()
1822
1823         env.CacheDir('foo')
1824         assert env.fs.CD == 'foo', env.fs.CD
1825
1826         env.CacheDir('$CD')
1827         assert env.fs.CD == 'CacheDir', env.fs.CD
1828
1829     def test_Clean(self):
1830         """Test the Clean() method"""
1831         env = Environment(FOO = 'fff', BAR = 'bbb')
1832
1833         CT = SCons.Environment.CleanTargets
1834
1835         foo = env.arg2nodes('foo')[0]
1836         fff = env.arg2nodes('fff')[0]
1837
1838         t = env.Clean('foo', 'aaa')
1839         l = map(str, CT[foo])
1840         assert l == ['aaa'], l
1841
1842         t = env.Clean(foo, ['$BAR', 'ccc'])
1843         l = map(str, CT[foo])
1844         assert l == ['aaa', 'bbb', 'ccc'], l
1845
1846         eee = env.arg2nodes('eee')[0]
1847
1848         t = env.Clean('$FOO', 'ddd')
1849         l = map(str, CT[fff])
1850         assert l == ['ddd'], l
1851         t = env.Clean(fff, [eee, 'fff'])
1852         l = map(str, CT[fff])
1853         assert l == ['ddd', 'eee', 'fff'], l
1854
1855     def test_Command(self):
1856         """Test the Command() method."""
1857         env = Environment()
1858         t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
1859                         action='buildfoo $target $source')
1860         assert not t.builder is None
1861         assert t.builder.action.__class__.__name__ == 'CommandAction'
1862         assert t.builder.action.cmd_list == 'buildfoo $target $source'
1863         assert 'foo1.in' in map(lambda x: x.path, t.sources)
1864         assert 'foo2.in' in map(lambda x: x.path, t.sources)
1865
1866         sub = SCons.Node.FS.default_fs.Dir('sub')
1867         t = env.Command(target='bar.out', source='sub',
1868                         action='buildbar $target $source')
1869         assert 'sub' in map(lambda x: x.path, t.sources)
1870
1871         def testFunc(env, target, source):
1872             assert str(target[0]) == 'foo.out'
1873             assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
1874             return 0
1875         t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
1876                         action=testFunc)
1877         assert not t.builder is None
1878         assert t.builder.action.__class__.__name__ == 'FunctionAction'
1879         t.build()
1880         assert 'foo1.in' in map(lambda x: x.path, t.sources)
1881         assert 'foo2.in' in map(lambda x: x.path, t.sources)
1882
1883         x = []
1884         def test2(baz, x=x):
1885             x.append(baz)
1886         env = Environment(TEST2 = test2)
1887         t = env.Command(target='baz.out', source='baz.in',
1888                         action='${TEST2(XYZ)}',
1889                         XYZ='magic word')
1890         assert not t.builder is None
1891         t.build()
1892         assert x[0] == 'magic word', x
1893
1894     def test_Configure(self):
1895         """Test the Configure() method"""
1896         # Configure() will write to a local temporary file.
1897         test = TestCmd.TestCmd(workdir = '')
1898         save = os.getcwd()
1899         # Configure() will test, if we are reading a SConscript file
1900         import SCons.Script.SConscript
1901         SCons.Script.SConscript.sconscript_reading = 1
1902
1903         try:
1904             os.chdir(test.workpath())
1905
1906             env = Environment(FOO = 'xyzzy')
1907
1908             def func(arg):
1909                 pass
1910
1911             c = env.Configure()
1912             assert not c is None, c
1913             c.Finish()
1914
1915             c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
1916             assert not c is None, c
1917             assert hasattr(c, 'foo')
1918             assert hasattr(c, 'xyzzy')
1919             c.Finish()
1920         finally:
1921             os.chdir(save)
1922
1923     def test_Depends(self):
1924         """Test the explicit Depends method."""
1925         env = Environment(FOO = 'xxx', BAR='yyy')
1926         env.Dir('dir1')
1927         env.Dir('dir2')
1928         env.File('xxx.py')
1929         env.File('yyy.py')
1930         t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py')
1931         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
1932         assert t.path == 'EnvironmentTest.py'
1933         assert len(t.depends) == 1
1934         d = t.depends[0]
1935         assert d.__class__.__name__ == 'Entry', d.__class__.__name__
1936         assert d.path == 'Environment.py'
1937
1938         t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')
1939         assert t.__class__.__name__ == 'File', t.__class__.__name__
1940         assert t.path == 'xxx.py'
1941         assert len(t.depends) == 1
1942         d = t.depends[0]
1943         assert d.__class__.__name__ == 'File', d.__class__.__name__
1944         assert d.path == 'yyy.py'
1945
1946         t = env.Depends(target='dir1', dependency='dir2')
1947         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
1948         assert t.path == 'dir1'
1949         assert len(t.depends) == 1
1950         d = t.depends[0]
1951         assert d.__class__.__name__ == 'Dir', d.__class__.__name__
1952         assert d.path == 'dir2'
1953
1954     def test_Dir(self):
1955         """Test the Dir() method"""
1956         class MyFS:
1957             def Dir(self, name):
1958                 return 'Dir(%s)' % name
1959
1960         env = Environment(FOO = 'foodir', BAR = 'bardir')
1961         env.fs = MyFS()
1962
1963         d = env.Dir('d')
1964         assert d == 'Dir(d)', d
1965
1966         d = env.Dir('$FOO')
1967         assert d == 'Dir(foodir)', d
1968
1969         d = env.Dir('${BAR}_$BAR')
1970         assert d == 'Dir(bardir_bardir)', d
1971
1972     def test_Environment(self):
1973         """Test the Environment() method"""
1974         env = Environment(FOO = 'xxx', BAR = 'yyy')
1975
1976         e2 = env.Environment(X = '$FOO', Y = '$BAR')
1977         assert e2['X'] == 'xxx', e2['X']
1978         assert e2['Y'] == 'yyy', e2['Y']
1979
1980     def test_Execute(self):
1981         """Test the Execute() method"""
1982
1983         class MyAction:
1984             def __init__(self, *args, **kw):
1985                 self.args = args
1986             def __call__(self, target, source, env):
1987                 return "%s executed" % self.args
1988
1989         env = Environment()
1990         env.Action = MyAction
1991
1992         result = env.Execute("foo")
1993         assert result == "foo executed", result
1994
1995     def test_File(self):
1996         """Test the File() method"""
1997         class MyFS:
1998             def File(self, name):
1999                 return 'File(%s)' % name
2000
2001         env = Environment(FOO = 'foofile', BAR = 'barfile')
2002         env.fs = MyFS()
2003
2004         f = env.File('f')
2005         assert f == 'File(f)', f
2006
2007         f = env.File('$FOO')
2008         assert f == 'File(foofile)', f
2009
2010         f = env.File('${BAR}_$BAR')
2011         assert f == 'File(barfile_barfile)', f
2012
2013     def test_FindFile(self):
2014         """Test the FindFile() method"""
2015         env = Environment(FOO = 'fff', BAR = 'bbb')
2016
2017         r = env.FindFile('foo', ['no_such_directory'])
2018         assert r is None, r
2019
2020         # XXX
2021
2022     def test_GetBuildPath(self):
2023         """Test the GetBuildPath() method."""
2024         env = Environment(MAGIC = 'xyzzy')
2025
2026         p = env.GetBuildPath('foo')
2027         assert p == 'foo', p
2028
2029         p = env.GetBuildPath('$MAGIC')
2030         assert p == 'xyzzy', p
2031
2032     def test_Ignore(self):
2033         """Test the explicit Ignore method."""
2034         env = Environment(FOO='yyy', BAR='zzz')
2035         env.Dir('dir1')
2036         env.Dir('dir2')
2037         env.File('yyyzzz')
2038         env.File('zzzyyy')
2039
2040         t = env.Ignore(target='targ.py', dependency='dep.py')
2041         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
2042         assert t.path == 'targ.py'
2043         assert len(t.ignore) == 1
2044         i = t.ignore[0]
2045         assert i.__class__.__name__ == 'Entry', i.__class__.__name__
2046         assert i.path == 'dep.py'
2047
2048         t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')
2049         assert t.__class__.__name__ == 'File', t.__class__.__name__
2050         assert t.path == 'yyyzzz'
2051         assert len(t.ignore) == 1
2052         i = t.ignore[0]
2053         assert i.__class__.__name__ == 'File', i.__class__.__name__
2054         assert i.path == 'zzzyyy'
2055
2056         t = env.Ignore(target='dir1', dependency='dir2')
2057         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
2058         assert t.path == 'dir1'
2059         assert len(t.ignore) == 1
2060         i = t.ignore[0]
2061         assert i.__class__.__name__ == 'Dir', i.__class__.__name__
2062         assert i.path == 'dir2'
2063
2064     def test_Install(self):
2065         """Test the Install method"""
2066         env = Environment(FOO='iii', BAR='jjj')
2067
2068         tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
2069         paths = map(str, tgt)
2070         paths.sort()
2071         expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
2072         assert paths == expect, paths
2073         for tnode in tgt:
2074             assert tnode.builder == InstallBuilder
2075
2076         tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
2077         paths = map(str, tgt)
2078         paths.sort()
2079         expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
2080         assert paths == expect, paths
2081         for tnode in tgt:
2082             assert tnode.builder == InstallBuilder
2083
2084         exc_caught = None
2085         try:
2086             tgt = env.Install('export', 'export')
2087         except SCons.Errors.UserError, e:
2088             exc_caught = 1
2089         assert exc_caught, "UserError should be thrown when Install() target is not a file."
2090         match = str(e) == "Source `export' of Install() is not a file.  Install() source must be one or more files."
2091         assert match, e
2092
2093         exc_caught = None
2094         try:
2095             tgt = env.Install('export', ['export', 'build/foo1'])
2096         except SCons.Errors.UserError, e:
2097             exc_caught = 1
2098         assert exc_caught, "UserError should be thrown when Install() target containins non-files."
2099         match = str(e) == "Source `['export', 'build/foo1']' of Install() contains one or more non-files.  Install() source must be one or more files."
2100         assert match, e
2101
2102         exc_caught = None
2103         try:
2104             tgt = env.Install('export/foo1', 'build/foo1')
2105         except SCons.Errors.UserError, e:
2106             exc_caught = 1
2107         assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
2108         match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?"
2109         assert match, e
2110
2111     def test_InstallAs(self):
2112         """Test the InstallAs method"""
2113         env = Environment(FOO='iii', BAR='jjj')
2114
2115         tgt = env.InstallAs(target=string.split('foo1 foo2'),
2116                             source=string.split('bar1 bar2'))
2117         assert len(tgt) == 2, len(tgt)
2118         paths = map(lambda x: str(x.sources[0]), tgt)
2119         paths.sort()
2120         expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
2121         assert paths == expect, paths
2122         for tnode in tgt:
2123             assert tnode.builder == InstallBuilder
2124
2125         tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')
2126         assert tgt.path == 'iii.t'
2127         assert tgt.sources[0].path == 'jjj.s'
2128         assert tgt.builder == InstallBuilder
2129
2130     def test_Literal(self):
2131         """Test the Literal() method"""
2132         env = Environment(FOO='fff', BAR='bbb')
2133         list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0]
2134         assert list == ['$FOO', 'bbb'], list
2135         list = env.subst_list(['$FOO', env.Literal('$BAR')])[0]
2136         assert list == ['fff', '$BAR'], list
2137
2138     def test_Local(self):
2139         """Test the Local() method."""
2140         env = Environment(FOO='lll')
2141
2142         l = env.Local(env.fs.File('fff'))
2143         assert str(l[0]) == 'fff', l[0]
2144
2145         l = env.Local('ggg', '$FOO')
2146         assert str(l[0]) == 'ggg', l[0]
2147         assert str(l[1]) == 'lll', l[1]
2148
2149     def test_Precious(self):
2150         """Test the Precious() method"""
2151         env = Environment(FOO='ggg', BAR='hhh')
2152         env.Dir('p_hhhb')
2153         env.File('p_d')
2154         t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
2155
2156         assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
2157         assert t[0].path == 'p_a'
2158         assert t[0].precious
2159         assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
2160         assert t[1].path == 'p_hhhb'
2161         assert t[1].precious
2162         assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
2163         assert t[2].path == 'p_c'
2164         assert t[2].precious
2165         assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
2166         assert t[3].path == 'p_d'
2167         assert t[3].precious
2168         assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
2169         assert t[4].path == 'p_ggg'
2170         assert t[4].precious
2171
2172     def test_Repository(self):
2173         """Test the Repository() method."""
2174         class MyFS:
2175             def __init__(self):
2176                 self.list = []
2177             def Repository(self, *dirs):
2178                 self.list.extend(list(dirs))
2179             def Dir(self, name):
2180                 return name
2181         env = Environment(FOO='rrr', BAR='sss')
2182         env.fs = MyFS()
2183         env.Repository('/tmp/foo')
2184         env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
2185         expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
2186         assert env.fs.list == expect, env.fs.list
2187
2188     def test_Scanner(self):
2189         """Test the Scanner() method"""
2190         def scan(node, env, target, arg):
2191             pass
2192
2193         env = Environment(FOO = scan)
2194
2195         s = env.Scanner('foo')
2196         assert not s is None, s
2197
2198         s = env.Scanner(function = 'foo')
2199         assert not s is None, s
2200
2201         if 0:
2202             s = env.Scanner('$FOO')
2203             assert not s is None, s
2204
2205             s = env.Scanner(function = '$FOO')
2206             assert not s is None, s
2207
2208     def test_SConsignFile(self):
2209         """Test the SConsignFile() method"""
2210         import SCons.Sig
2211
2212         class MyFS:
2213             SConstruct_dir = os.sep + 'dir'
2214
2215         env = Environment(FOO = 'SConsign',
2216                           BAR = os.path.join(os.sep, 'File'))
2217         env.fs = MyFS()
2218
2219         try:
2220             fnames = []
2221             dbms = []
2222             def capture(name, dbm_module, fnames=fnames, dbms=dbms):
2223                 fnames.append(name)
2224                 dbms.append(dbm_module)
2225
2226             save_Sig_SConsignFile = SCons.Sig.SConsignFile
2227             SCons.Sig.SConsignFile = capture
2228
2229             env.SConsignFile('foo')
2230             assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames
2231             assert dbms[0] == None, dbms
2232
2233             env.SConsignFile('$FOO')
2234             assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
2235             assert dbms[1] == None, dbms
2236
2237             env.SConsignFile('/$FOO')
2238             assert fnames[2] == '/SConsign', fnames
2239             assert dbms[2] == None, dbms
2240
2241             env.SConsignFile('$BAR', 'x')
2242             assert fnames[3] == os.path.join(os.sep, 'File'), fnames
2243             assert dbms[3] == 'x', dbms
2244
2245             env.SConsignFile('__$BAR', 7)
2246             assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
2247             assert dbms[4] == 7, dbms
2248         finally:
2249             SCons.Sig.SConsignFile = save_Sig_SConsignFile
2250
2251     def test_SideEffect(self):
2252         """Test the SideEffect() method"""
2253         env = Environment(LIB='lll', FOO='fff', BAR='bbb')
2254         env.File('mylll.pdb')
2255         env.Dir('mymmm.pdb')
2256
2257         foo = env.Object('foo.obj', 'foo.cpp')
2258         bar = env.Object('bar.obj', 'bar.cpp')
2259         s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])
2260         assert s.__class__.__name__ == 'Entry', s.__class__.__name__
2261         assert s.path == 'mylib.pdb'
2262         assert s.side_effect
2263         assert foo.side_effects == [s]
2264         assert bar.side_effects == [s]
2265         assert s.depends_on([bar])
2266         assert s.depends_on([foo])
2267
2268         fff = env.Object('fff.obj', 'fff.cpp')
2269         bbb = env.Object('bbb.obj', 'bbb.cpp')
2270         s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])
2271         assert s.__class__.__name__ == 'File', s.__class__.__name__
2272         assert s.path == 'mylll.pdb'
2273         assert s.side_effect
2274         assert fff.side_effects == [s], fff.side_effects
2275         assert bbb.side_effects == [s], bbb.side_effects
2276         assert s.depends_on([bbb])
2277         assert s.depends_on([fff])
2278
2279         ggg = env.Object('ggg.obj', 'ggg.cpp')
2280         ccc = env.Object('ccc.obj', 'ccc.cpp')
2281         s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])
2282         assert s.__class__.__name__ == 'Dir', s.__class__.__name__
2283         assert s.path == 'mymmm.pdb'
2284         assert s.side_effect
2285         assert ggg.side_effects == [s], ggg.side_effects
2286         assert ccc.side_effects == [s], ccc.side_effects
2287         assert s.depends_on([ccc])
2288         assert s.depends_on([ggg])
2289
2290     def test_SourceCode(self):
2291         """Test the SourceCode() method."""
2292         env = Environment(FOO='mmm', BAR='nnn')
2293         e = env.SourceCode('foo', None)
2294         assert e.path == 'foo'
2295         s = e.src_builder()
2296         assert s is None, s
2297
2298         b = Builder()
2299         e = env.SourceCode(e, b)
2300         assert e.path == 'foo'
2301         s = e.src_builder()
2302         assert s is b, s
2303
2304         e = env.SourceCode('$BAR$FOO', None)
2305         assert e.path == 'nnnmmm'
2306         s = e.src_builder()
2307         assert s is None, s
2308
2309     def test_SourceSignatures(type):
2310         """Test the SourceSignatures() method"""
2311         env = Environment(M = 'MD5', T = 'timestamp')
2312
2313         exc_caught = None
2314         try:
2315             env.SourceSignatures('invalid_type')
2316         except SCons.Errors.UserError:
2317             exc_caught = 1
2318         assert exc_caught, "did not catch expected UserError"
2319         assert not hasattr(env, '_calc_module')
2320
2321         env.SourceSignatures('MD5')
2322         m = env._calc_module
2323
2324         env.SourceSignatures('$M')
2325         assert env._calc_module is m
2326
2327         env.SourceSignatures('timestamp')
2328         t = env._calc_module
2329
2330         env.SourceSignatures('$T')
2331         assert env._calc_module is t
2332
2333     def test_Split(self):
2334         """Test the Split() method"""
2335         env = Environment(FOO='fff', BAR='bbb')
2336         s = env.Split("foo bar")
2337         assert s == ["foo", "bar"], s
2338         s = env.Split("$FOO bar")
2339         assert s == ["fff", "bar"], s
2340         s = env.Split(["foo", "bar"])
2341         assert s == ["foo", "bar"], s
2342         s = env.Split(["foo", "${BAR}-bbb"])
2343         assert s == ["foo", "bbb-bbb"], s
2344         s = env.Split("foo")
2345         assert s == ["foo"], s
2346         s = env.Split("$FOO$BAR")
2347         assert s == ["fffbbb"], s
2348
2349     def test_TargetSignatures(type):
2350         """Test the TargetSignatures() method"""
2351         env = Environment(B = 'build', C = 'content')
2352
2353         exc_caught = None
2354         try:
2355             env.TargetSignatures('invalid_type')
2356         except SCons.Errors.UserError:
2357             exc_caught = 1
2358         assert exc_caught, "did not catch expected UserError"
2359         assert not hasattr(env, '_build_signature')
2360
2361         env.TargetSignatures('build')
2362         assert env._build_signature == 1, env._build_signature
2363
2364         env.TargetSignatures('content')
2365         assert env._build_signature == 0, env._build_signature
2366
2367         env.TargetSignatures('$B')
2368         assert env._build_signature == 1, env._build_signature
2369
2370         env.TargetSignatures('$C')
2371         assert env._build_signature == 0, env._build_signature
2372
2373     def test_Value(self):
2374         """Test creating a Value() object
2375         """
2376         env = Environment()
2377         v1 = env.Value('a')
2378         assert v1.value == 'a', v1.value
2379
2380         value2 = 'a'
2381         v2 = env.Value(value2)
2382         assert v2.value == value2, v2.value
2383         assert v2.value is value2, v2.value
2384
2385         assert not v1 is v2
2386         assert v1.value == v2.value
2387
2388
2389
2390     def test_Environment_global_variable(type):
2391         """Test setting Environment variable to an Environment.Base subclass"""
2392         class MyEnv(SCons.Environment.Base):
2393             def xxx(self, string):
2394                 return self.subst(string)
2395
2396         SCons.Environment.Environment = MyEnv
2397
2398         env = SCons.Environment.Environment(FOO = 'foo')
2399
2400         f = env.subst('$FOO')
2401         assert f == 'foo', f
2402
2403         f = env.xxx('$FOO')
2404         assert f == 'foo', f
2405
2406     def test_bad_keywords(type):
2407         """Test trying to use reserved keywords in an Environment"""
2408         reserved = ['TARGETS','SOURCES', 'SOURCE','TARGET']
2409         added = []
2410
2411         env = SCons.Environment.Environment(TARGETS = 'targets',
2412                                             SOURCES = 'sources',
2413                                             SOURCE = 'source',
2414                                             TARGET = 'target',
2415                                             INIT = 'init')
2416         added.append('INIT')
2417         for x in reserved:
2418             assert not env.has_key(x), env[x]
2419         for x in added:
2420             assert env.has_key(x), \
2421                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2422
2423         env.Append(TARGETS = 'targets',
2424                    SOURCES = 'sources',
2425                    SOURCE = 'source',
2426                    TARGET = 'target',
2427                    APPEND = 'append')
2428         added.append('APPEND')
2429         for x in reserved:
2430             assert not env.has_key(x), env[x]
2431         for x in added:
2432             assert env.has_key(x), \
2433                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2434
2435         env.AppendUnique(TARGETS = 'targets',
2436                          SOURCES = 'sources',
2437                          SOURCE = 'source',
2438                          TARGET = 'target',
2439                          APPENDUNIQUE = 'appendunique')
2440         added.append('APPENDUNIQUE')
2441         for x in reserved:
2442             assert not env.has_key(x), env[x]
2443         for x in added:
2444             assert env.has_key(x), \
2445                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2446
2447         env.Prepend(TARGETS = 'targets',
2448                     SOURCES = 'sources',
2449                     SOURCE = 'source',
2450                     TARGET = 'target',
2451                     PREPEND = 'prepend')
2452         added.append('PREPEND')
2453         for x in reserved:
2454             assert not env.has_key(x), env[x]
2455         for x in added:
2456             assert env.has_key(x), \
2457                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2458
2459         env.Prepend(TARGETS = 'targets',
2460                     SOURCES = 'sources',
2461                     SOURCE = 'source',
2462                     TARGET = 'target',
2463                     PREPENDUNIQUE = 'prependunique')
2464         added.append('PREPENDUNIQUE')
2465         for x in reserved:
2466             assert not env.has_key(x), env[x]
2467         for x in added:
2468             assert env.has_key(x), \
2469                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2470
2471         env.Replace(TARGETS = 'targets',
2472                     SOURCES = 'sources',
2473                     SOURCE = 'source',
2474                     TARGET = 'target',
2475                     REPLACE = 'replace')
2476         added.append('REPLACE')
2477         for x in reserved:
2478             assert not env.has_key(x), env[x]
2479         for x in added:
2480             assert env.has_key(x), \
2481                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2482
2483         copy = env.Copy(TARGETS = 'targets',
2484                         SOURCES = 'sources',
2485                         SOURCE = 'source',
2486                         TARGET = 'target',
2487                         COPY = 'copy')
2488         for x in reserved:
2489             assert not copy.has_key(x), env[x]
2490         for x in added + ['COPY']:
2491             assert copy.has_key(x), \
2492                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2493
2494         over = env.Override({'TARGETS' : 'targets',
2495                              'SOURCES' : 'sources',
2496                              'SOURCE' : 'source',
2497                              'TARGET' : 'target',
2498                              'OVERRIDE' : 'override'})
2499         for x in reserved:
2500             assert not over.has_key(x), over[x]
2501         for x in added + ['OVERRIDE']:
2502             assert over.has_key(x), \
2503                    '%s is not reserved, but got omitted; see Environment.construction_var_name_ok'%x
2504
2505
2506
2507 class NoSubstitutionProxyTestCase(unittest.TestCase):
2508
2509     def test___init__(self):
2510         """Test NoSubstitutionProxy initialization"""
2511         env = Environment(XXX = 'x', YYY = 'y')
2512         assert env['XXX'] == 'x', env['XXX']
2513         assert env['YYY'] == 'y', env['YYY']
2514
2515         proxy = NoSubstitutionProxy(env)
2516         assert proxy['XXX'] == 'x', proxy['XXX']
2517         assert proxy['YYY'] == 'y', proxy['YYY']
2518
2519     def test_attributes(self):
2520         """Test getting and setting NoSubstitutionProxy attributes"""
2521         env = Environment()
2522         setattr(env, 'env_attr', 'value1')
2523
2524         proxy = NoSubstitutionProxy(env)
2525         setattr(proxy, 'proxy_attr', 'value2')
2526
2527         x = getattr(env, 'env_attr')
2528         assert x == 'value1', x
2529         x = getattr(proxy, 'env_attr')
2530         assert x == 'value1', x
2531
2532         x = getattr(env, 'proxy_attr')
2533         assert x == 'value2', x
2534         x = getattr(proxy, 'proxy_attr')
2535         assert x == 'value2', x
2536
2537     def test_subst(self):
2538         """Test the NoSubstitutionProxy.subst() method"""
2539         env = Environment(XXX = 'x', YYY = 'y')
2540         assert env['XXX'] == 'x', env['XXX']
2541         assert env['YYY'] == 'y', env['YYY']
2542
2543         proxy = NoSubstitutionProxy(env)
2544         assert proxy['XXX'] == 'x', proxy['XXX']
2545         assert proxy['YYY'] == 'y', proxy['YYY']
2546
2547         x = env.subst('$XXX')
2548         assert x == 'x', x
2549         x = proxy.subst('$XXX')
2550         assert x == '$XXX', x
2551
2552         x = proxy.subst('$YYY', raw=7, target=None, source=None,
2553                         dict=None, conv=None,
2554                         extra_meaningless_keyword_argument=None)
2555         assert x == '$YYY', x
2556
2557     def test_subst_kw(self):
2558         """Test the NoSubstitutionProxy.subst_kw() method"""
2559         env = Environment(XXX = 'x', YYY = 'y')
2560         assert env['XXX'] == 'x', env['XXX']
2561         assert env['YYY'] == 'y', env['YYY']
2562
2563         proxy = NoSubstitutionProxy(env)
2564         assert proxy['XXX'] == 'x', proxy['XXX']
2565         assert proxy['YYY'] == 'y', proxy['YYY']
2566
2567         x = env.subst_kw({'$XXX':'$YYY'})
2568         assert x == {'x':'y'}, x
2569         x = proxy.subst_kw({'$XXX':'$YYY'})
2570         assert x == {'$XXX':'$YYY'}, x
2571
2572     def test_subst_list(self):
2573         """Test the NoSubstitutionProxy.subst_list() method"""
2574         env = Environment(XXX = 'x', YYY = 'y')
2575         assert env['XXX'] == 'x', env['XXX']
2576         assert env['YYY'] == 'y', env['YYY']
2577
2578         proxy = NoSubstitutionProxy(env)
2579         assert proxy['XXX'] == 'x', proxy['XXX']
2580         assert proxy['YYY'] == 'y', proxy['YYY']
2581
2582         x = env.subst_list('$XXX')
2583         assert x == [['x']], x
2584         x = proxy.subst_list('$XXX')
2585         assert x == [[]], x
2586
2587         x = proxy.subst_list('$YYY', raw=0, target=None, source=None,
2588                              dict=None, conv=None)
2589         assert x == [[]], x
2590
2591     def test_subst_target_source(self):
2592         """Test the NoSubstitutionProxy.subst_target_source() method"""
2593         env = Environment(XXX = 'x', YYY = 'y')
2594         assert env['XXX'] == 'x', env['XXX']
2595         assert env['YYY'] == 'y', env['YYY']
2596
2597         proxy = NoSubstitutionProxy(env)
2598         assert proxy['XXX'] == 'x', proxy['XXX']
2599         assert proxy['YYY'] == 'y', proxy['YYY']
2600
2601         args = ('$XXX $TARGET $SOURCE $YYY',)
2602         kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')}
2603         x = apply(env.subst_target_source, args, kw)
2604         assert x == 'x ttt sss y', x
2605         x = apply(proxy.subst_target_source, args, kw)
2606         assert x == ' ttt sss ', x
2607
2608
2609
2610 if __name__ == "__main__":
2611     suite = unittest.TestSuite()
2612     tclasses = [ EnvironmentTestCase,
2613                  NoSubstitutionProxyTestCase ]
2614     for tclass in tclasses:
2615         names = unittest.getTestCaseNames(tclass, 'test_')
2616         suite.addTests(map(tclass, names))
2617     if not unittest.TextTestRunner().run(suite).wasSuccessful():
2618         sys.exit(1)