Make Action() and env.Action() equivalent.
[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
32 from SCons.Environment import *
33 import SCons.Warnings
34
35 def diff_env(env1, env2):
36     s1 = "env1 = {\n"
37     s2 = "env2 = {\n"
38     d = {}
39     for k in env1._dict.keys() + env2._dict.keys():
40         d[k] = None
41     keys = d.keys()
42     keys.sort()
43     for k in keys:
44         if env1.has_key(k):
45            if env2.has_key(k):
46                if env1[k] != env2[k]:
47                    s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
48                    s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
49            else:
50                s1 = s1 + "    " + repr(k) + " : " + repr(env1[k]) + "\n"
51         elif env2.has_key(k):
52            s2 = s2 + "    " + repr(k) + " : " + repr(env2[k]) + "\n"
53     s1 = s1 + "}\n"
54     s2 = s2 + "}\n"
55     return s1 + s2
56
57 def diff_dict(d1, d2):
58     s1 = "d1 = {\n"
59     s2 = "d2 = {\n"
60     d = {}
61     for k in d1.keys() + d2.keys():
62         d[k] = None
63     keys = d.keys()
64     keys.sort()
65     for k in keys:
66         if d1.has_key(k):
67            if d2.has_key(k):
68                if d1[k] != d2[k]:
69                    s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
70                    s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
71            else:
72                s1 = s1 + "    " + repr(k) + " : " + repr(d1[k]) + "\n"
73         elif env2.has_key(k):
74            s2 = s2 + "    " + repr(k) + " : " + repr(d2[k]) + "\n"
75     s1 = s1 + "}\n"
76     s2 = s2 + "}\n"
77     return s1 + s2
78
79 called_it = {}
80 built_it = {}
81
82 class Builder:
83     """A dummy Builder class for testing purposes.  "Building"
84     a target is simply setting a value in the dictionary.
85     """
86     def __init__(self, name = None):
87         self.name = name
88
89     def __call__(self, env, **kw):
90         global called_it
91         called_it.update(kw)
92
93     def execute(self, target = None, **kw):
94         global built_it
95         built_it[target] = 1
96
97
98
99 scanned_it = {}
100
101 class Scanner:
102     """A dummy Scanner class for testing purposes.  "Scanning"
103     a target is simply setting a value in the dictionary.
104     """
105     def __init__(self, name, skeys=[]):
106         self.name = name
107         self.skeys = skeys
108
109     def __call__(self, filename):
110         scanned_it[filename] = 1
111
112     def __cmp__(self, other):
113         return cmp(self.__dict__, other.__dict__)
114
115
116
117 class EnvironmentTestCase(unittest.TestCase):
118
119     def test___init__(self):
120         """Test construction Environments creation
121         
122         Create two with identical arguments and check that
123         they compare the same.
124         """
125         env1 = Environment(XXX = 'x', YYY = 'y')
126         env2 = Environment(XXX = 'x', YYY = 'y')
127         assert env1 == env2, diff_env(env1, env2)
128
129     def test_get(self):
130         """Test the get() method."""
131         env = Environment(aaa = 'AAA')
132
133         x = env.get('aaa')
134         assert x == 'AAA', x
135         x = env.get('aaa', 'XXX')
136         assert x == 'AAA', x
137         x = env.get('bbb')
138         assert x is None, x
139         x = env.get('bbb', 'XXX')
140         assert x == 'XXX', x
141
142     def test_arg2nodes(self):
143         """Test the arg2nodes method
144         """
145         env = Environment()
146         dict = {}
147         class X(SCons.Node.Node):
148             pass
149         def Factory(name, directory = None, create = 1, dict=dict, X=X):
150             if not dict.has_key(name):
151                 dict[name] = X()
152                 dict[name].name = name
153             return dict[name]
154
155         nodes = env.arg2nodes("Util.py UtilTests.py", Factory)
156         assert len(nodes) == 1, nodes
157         assert isinstance(nodes[0], X)
158         assert nodes[0].name == "Util.py UtilTests.py"
159
160         import types
161         if hasattr(types, 'UnicodeType'):
162             code = """if 1:
163                 nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
164                 assert len(nodes) == 1, nodes
165                 assert isinstance(nodes[0], X)
166                 assert nodes[0].name == u"Util.py UtilTests.py"
167                 \n"""
168             exec code in globals(), locals()
169
170         nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
171         assert len(nodes) == 2, nodes
172         assert isinstance(nodes[0], X)
173         assert isinstance(nodes[1], X)
174         assert nodes[0].name == "Util.py"
175         assert nodes[1].name == "UtilTests.py"
176
177         n1 = Factory("Util.py")
178         nodes = env.arg2nodes([n1, "UtilTests.py"], Factory)
179         assert len(nodes) == 2, nodes
180         assert isinstance(nodes[0], X)
181         assert isinstance(nodes[1], X)
182         assert nodes[0].name == "Util.py"
183         assert nodes[1].name == "UtilTests.py"
184
185         class SConsNode(SCons.Node.Node):
186             pass
187         nodes = env.arg2nodes(SConsNode())
188         assert len(nodes) == 1, nodes
189         assert isinstance(nodes[0], SConsNode), node
190
191         class OtherNode:
192             pass
193         nodes = env.arg2nodes(OtherNode())
194         assert len(nodes) == 1, nodes
195         assert isinstance(nodes[0], OtherNode), node
196
197         def lookup_a(str, F=Factory):
198             if str[0] == 'a':
199                 n = F(str)
200                 n.a = 1
201                 return n
202             else:
203                 return None
204
205         def lookup_b(str, F=Factory):
206             if str[0] == 'b':
207                 n = F(str)
208                 n.b = 1
209                 return n
210             else:
211                 return None
212
213         env_ll = env.Copy()
214         env_ll.lookup_list = [lookup_a, lookup_b]
215
216         nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory)
217         assert len(nodes) == 3, nodes
218
219         assert nodes[0].name == 'aaa', nodes[0]
220         assert nodes[0].a == 1, nodes[0]
221         assert not hasattr(nodes[0], 'b'), nodes[0]
222
223         assert nodes[1].name == 'bbb'
224         assert not hasattr(nodes[1], 'a'), nodes[1]
225         assert nodes[1].b == 1, nodes[1]
226
227         assert nodes[2].name == 'ccc'
228         assert not hasattr(nodes[2], 'a'), nodes[1]
229         assert not hasattr(nodes[2], 'b'), nodes[1]
230
231         def lookup_bbbb(str, F=Factory):
232             if str == 'bbbb':
233                 n = F(str)
234                 n.bbbb = 1
235                 return n
236             else:
237                 return None
238
239         def lookup_c(str, F=Factory):
240             if str[0] == 'c':
241                 n = F(str)
242                 n.c = 1
243                 return n
244             else:
245                 return None
246
247         nodes = env.arg2nodes(['bbbb', 'ccc'], Factory,
248                                      [lookup_c, lookup_bbbb, lookup_b])
249         assert len(nodes) == 2, nodes
250
251         assert nodes[0].name == 'bbbb'
252         assert not hasattr(nodes[0], 'a'), nodes[1]
253         assert not hasattr(nodes[0], 'b'), nodes[1]
254         assert nodes[0].bbbb == 1, nodes[1]
255         assert not hasattr(nodes[0], 'c'), nodes[0]
256
257         assert nodes[1].name == 'ccc'
258         assert not hasattr(nodes[1], 'a'), nodes[1]
259         assert not hasattr(nodes[1], 'b'), nodes[1]
260         assert not hasattr(nodes[1], 'bbbb'), nodes[0]
261         assert nodes[1].c == 1, nodes[1]
262
263     def test_subst(self):
264         """Test substituting construction variables within strings
265
266         Check various combinations, including recursive expansion
267         of variables into other variables.
268         """
269         env = Environment(AAA = 'a', BBB = 'b')
270         mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
271         assert mystr == "a aA b", mystr
272
273         # Changed the tests below to reflect a bug fix in
274         # subst()
275         env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
276         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
277         assert mystr == "b bA bB b", mystr
278         env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
279         mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
280         assert mystr == "c cA cB c", mystr
281
282         env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
283         lst = env.subst_list([ "$AAA", "B $CCC" ])
284         assert lst == [ [ "a", "b" ], [ "c", "B a", "b" ], [ "c" ] ], lst
285
286         class DummyNode:
287             def __init__(self, name):
288                 self.name = name
289             def __str__(self):
290                 return self.name
291             def rfile(self):
292                 return self
293             def get_subst_proxy(self):
294                 return self
295
296         # Test callables in the Environment
297         def foo(target, source, env, for_signature):
298             assert str(target) == 't', target
299             assert str(source) == 's', source
300             return env["FOO"]
301
302         env = Environment(BAR=foo, FOO='baz')
303
304         subst = env.subst('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
305         assert subst == 'test baz', subst
306
307         lst = env.subst_list('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
308         assert lst[0][0] == 'test', lst[0][0]
309         assert lst[0][1] == 'baz', lst[0][1]
310
311         # Test not calling callables in the Environment
312         if 0:
313             # This will take some serious surgery to subst() and
314             # subst_list(), so just leave these tests out until we can
315             # do that.
316             def bar(arg):
317                 pass
318
319             env = Environment(BAR=bar, FOO='$BAR')
320
321             subst = env.subst('$BAR', call=None)
322             assert subst is bar, subst
323
324             subst = env.subst('$FOO', call=None)
325             assert subst is bar, subst
326
327             subst = env.subst_list('$BAR', call=None)
328             assert subst is bar, subst
329
330             subst = env.subst_list('$FOO', call=None)
331             assert subst is bar, subst
332
333     def test_subst_kw(self):
334         """Test substituting construction variables within dictionaries"""
335         env = Environment(AAA = 'a', BBB = 'b')
336         kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
337         assert len(kw) == 2, kw
338         assert kw['a'] == 'aaa', kw['a']
339         assert kw['bbb'] == 'b', kw['bbb']
340
341     def test_Builder_calls(self):
342         """Test Builder calls through different environments
343         """
344         global called_it
345
346         b1 = Builder()
347         b2 = Builder()
348
349         env = Environment()
350         env.Replace(BUILDERS = { 'builder1' : b1,
351                                  'builder2' : b2 })
352         called_it = {}
353         env.builder1(target = 'out1')
354         assert called_it['target'] == 'out1', called_it
355         assert not called_it.has_key('source')
356
357         called_it = {}
358         env.builder2(target = 'out2', xyzzy = 1)
359         assert called_it['target'] == 'out2', called_it
360         assert called_it['xyzzy'] == 1, called_it
361         assert not called_it.has_key('source')
362
363         called_it = {}
364         env.builder1(foo = 'bar')
365         assert called_it['foo'] == 'bar', called_it
366         assert not called_it.has_key('target')
367         assert not called_it.has_key('source')
368
369
370
371     def test_Builder_execs(self):
372         """Test Builder execution through different environments
373
374         One environment is initialized with a single
375         Builder object, one with a list of a single Builder
376         object, and one with a list of two Builder objects.
377         """
378         global built_it
379
380         b1 = Builder()
381         b2 = Builder()
382
383         built_it = {}
384         env3 = Environment()
385         env3.Replace(BUILDERS = { 'builder1' : b1,
386                                   'builder2' : b2 })
387         env3.builder1.execute(target = 'out1')
388         env3.builder2.execute(target = 'out2')
389         env3.builder1.execute(target = 'out3')
390         assert built_it['out1']
391         assert built_it['out2']
392         assert built_it['out3']
393
394         env4 = env3.Copy()
395         assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
396         assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % (env4.builder1.env, env3)
397
398         # Now test BUILDERS as a dictionary.
399         built_it = {}
400         env5 = Environment(BUILDERS={ 'foo' : b1 })
401         env5['BUILDERS']['bar'] = b2
402         env5.foo.execute(target='out1')
403         env5.bar.execute(target='out2')
404         assert built_it['out1']
405         assert built_it['out2']
406
407         built_it = {}
408         env6 = Environment()
409         env6['BUILDERS'] = { 'foo' : b1,
410                              'bar' : b2 }
411         env6.foo.execute(target='out1')
412         env6.bar.execute(target='out2')
413         assert built_it['out1']
414         assert built_it['out2']
415
416     def test_Scanners(self):
417         """Test Scanner execution through different environments
418
419         One environment is initialized with a single
420         Scanner object, one with a list of a single Scanner
421         object, and one with a list of two Scanner objects.
422         """
423 #        global scanned_it
424 #
425 #       s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
426 #       s2 = Scanner(name = 'scanner2', skeys = [".m4"])
427 #
428 #       scanned_it = {}
429 #       env1 = Environment(SCANNERS = s1)
430 #        env1.scanner1(filename = 'out1')
431 #       assert scanned_it['out1']
432 #
433 #       scanned_it = {}
434 #       env2 = Environment(SCANNERS = [s1])
435 #        env1.scanner1(filename = 'out1')
436 #       assert scanned_it['out1']
437 #
438 #       scanned_it = {}
439 #        env3 = Environment()
440 #        env3.Replace(SCANNERS = [s1, s2])
441 #        env3.scanner1(filename = 'out1')
442 #        env3.scanner2(filename = 'out2')
443 #        env3.scanner1(filename = 'out3')
444 #       assert scanned_it['out1']
445 #       assert scanned_it['out2']
446 #       assert scanned_it['out3']
447 #
448 #       s = env3.get_scanner(".c")
449 #       assert s == s1, s
450 #       s = env3.get_scanner(skey=".m4")
451 #       assert s == s2, s
452 #       s = env3.get_scanner(".cxx")
453 #       assert s == None, s
454
455     def test_ENV(self):
456         """Test setting the external ENV in Environments
457         """
458         env = Environment()
459         assert env.Dictionary().has_key('ENV')
460
461         env = Environment(ENV = { 'PATH' : '/foo:/bar' })
462         assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
463
464     def test_ReservedVariables(self):
465         """Test generation of warnings when reserved variable names
466         are set in an environment."""
467
468         SCons.Warnings.enableWarningClass(SCons.Warnings.ReservedVariableWarning)
469         old = SCons.Warnings.warningAsException(1)
470
471         try:
472             env4 = Environment()
473             for kw in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
474                 exc_caught = None
475                 try:
476                     env4[kw] = 'xyzzy'
477                 except SCons.Warnings.ReservedVariableWarning:
478                     exc_caught = 1
479                 assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw
480                 assert not env4.has_key(kw), "`%s' variable was incorrectly set" % kw
481         finally:
482             SCons.Warnings.warningAsException(old)
483
484     def test_IllegalVariables(self):
485         """Test that use of illegal variables raises an exception"""
486         env = Environment()
487         def test_it(var, env=env):
488             exc_caught = None
489             try:
490                 env[var] = 1
491             except SCons.Errors.UserError:
492                 exc_caught = 1
493             assert exc_caught, "did not catch UserError for '%s'" % var
494         env['aaa'] = 1
495         assert env['aaa'] == 1, env['aaa']
496         test_it('foo/bar')
497         test_it('foo.bar')
498         test_it('foo-bar')
499
500     def test_autogenerate(dict):
501         """Test autogenerating variables in a dictionary."""
502
503         def RDirs(pathlist):
504             return SCons.Node.FS.default_fs.Rsearchall(pathlist,
505                                                        clazz=SCons.Node.FS.Dir,
506                                                        must_exist=0,
507                                                        cwd=SCons.Node.FS.default_fs.Dir('xx'))
508
509         env = Environment(LIBS = [ 'foo', 'bar', 'baz' ],
510                           LIBLINKPREFIX = 'foo',
511                           LIBLINKSUFFIX = 'bar',
512                           RDirs=RDirs)
513         flags = env.subst_list('$_LIBFLAGS', 1)[0]
514         assert len(flags) == 3, flags
515         assert flags[0] == 'foofoobar', \
516                flags[0]
517         assert flags[1] == 'foobarbar', \
518                flags[1]
519         assert flags[2] == 'foobazbar', \
520                flags[2]
521
522         blat = SCons.Node.FS.default_fs.Dir('blat')
523
524         env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ],
525                           INCPREFIX = 'foo ',
526                           INCSUFFIX = 'bar',
527                           FOO = 'baz',
528                           RDirs=RDirs)
529         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
530         assert len(flags) == 8, flags
531         assert flags[0] == '$(', \
532                flags[0]
533         assert flags[1] == os.path.normpath('foo'), \
534                flags[1]
535         assert flags[2] == os.path.normpath('xx/foobar'), \
536                flags[2]
537         assert flags[3] == os.path.normpath('foo'), \
538                flags[3]
539         assert flags[4] == os.path.normpath('xx/baz/barbar'), \
540                flags[4]
541         assert flags[5] == os.path.normpath('foo'), \
542                flags[5]
543         assert flags[6] == os.path.normpath('blatbar'), \
544                flags[6]
545         assert flags[7] == '$)', \
546                flags[7]
547
548         env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ],
549                           INCPREFIX = 'foo ',
550                           INCSUFFIX = 'bar',
551                           FOO = 'baz',
552                           RDirs=RDirs)
553         flags = env.subst_list('$_F77INCFLAGS', 1)[0]
554         assert len(flags) == 8, flags
555         assert flags[0] == '$(', \
556                flags[0]
557         assert flags[1] == os.path.normpath('foo'), \
558                flags[1]
559         assert flags[2] == os.path.normpath('xx/foobar'), \
560                flags[2]
561         assert flags[3] == os.path.normpath('foo'), \
562                flags[3]
563         assert flags[4] == os.path.normpath('xx/baz/barbar'), \
564                flags[4]
565         assert flags[5] == os.path.normpath('foo'), \
566                flags[5]
567         assert flags[6] == os.path.normpath('blatbar'), \
568                flags[6]
569         assert flags[7] == '$)', \
570                flags[7]
571
572         env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '',
573                           RDirs=RDirs)
574         l = env.subst_list('$_CPPINCFLAGS')
575         assert len(l[0]) == 0, l[0]
576         l = env.subst_list('$_F77INCFLAGS')
577         assert len(l[0]) == 0, l[0]
578         l = env.subst_list('$_LIBDIRFLAGS')
579         assert len(l[0]) == 0, l[0]
580
581         SCons.Node.FS.default_fs.Repository('/rep1')
582         SCons.Node.FS.default_fs.Repository('/rep2')
583         env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
584                           INCPREFIX = '-I ',
585                           INCSUFFIX = 'XXX',
586                           FOO = 'baz',
587                           RDirs=RDirs)
588         flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
589         assert flags[0] == '$(', \
590                flags[0]
591         assert flags[1] == '-I', \
592                flags[1]
593         assert flags[2] == os.path.normpath('xx/fooXXX'), \
594                flags[2]
595         assert flags[3] == '-I', \
596                flags[3]
597         assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \
598                flags[4]
599         assert flags[5] == '-I', \
600                flags[5]
601         assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \
602                flags[6]
603         assert flags[7] == '-I', \
604                flags[7]
605         assert flags[8] == os.path.normpath('/a/bXXX'), \
606                flags[8]
607         assert flags[9] == '-I', \
608                flags[9]
609         assert flags[10] == os.path.normpath('xx/baz/barXXX'), \
610                flags[10]
611         assert flags[11] == '-I', \
612                flags[11]
613         assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \
614                flags[12]
615         assert flags[13] == '-I', \
616                flags[13]
617         assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \
618                flags[14]
619         assert flags[15] == '-I', \
620                flags[15]
621         assert flags[16] == os.path.normpath('blatXXX'), \
622                flags[16]
623         assert flags[17] == '$)', \
624                flags[17]
625
626     def test_platform(self):
627         """Test specifying a platform callable when instantiating."""
628         class platform:
629             def __str__(self):        return "TestPlatform"
630             def __call__(self, env):  env['XYZZY'] = 777
631
632         def tool(env):
633             env['SET_TOOL'] = 'initialized'
634             assert env['PLATFORM'] == "TestPlatform"
635
636         env = Environment(platform = platform(), tools = [tool])
637         assert env['XYZZY'] == 777, env
638         assert env['PLATFORM'] == "TestPlatform"
639         assert env['SET_TOOL'] == "initialized"
640
641     def test_Default_PLATFORM(self):
642         """Test overriding the default PLATFORM variable"""
643         class platform:
644             def __str__(self):        return "DefaultTestPlatform"
645             def __call__(self, env):  env['XYZZY'] = 888
646
647         def tool(env):
648             env['SET_TOOL'] = 'abcde'
649             assert env['PLATFORM'] == "DefaultTestPlatform"
650
651         import SCons.Defaults
652         save = SCons.Defaults.ConstructionEnvironment.copy()
653         try:
654             import SCons.Defaults
655             SCons.Defaults.ConstructionEnvironment.update({
656                 'PLATFORM' : platform(),
657             })
658             env = Environment(tools = [tool])
659             assert env['XYZZY'] == 888, env
660             assert env['PLATFORM'] == "DefaultTestPlatform"
661             assert env['SET_TOOL'] == "abcde"
662         finally:
663             SCons.Defaults.ConstructionEnvironment = save
664
665     def test_tools(self):
666         """Test specifying a tool callable when instantiating."""
667         def t1(env):
668             env['TOOL1'] = 111
669         def t2(env):
670             env['TOOL2'] = 222
671         def t3(env):
672             env['AAA'] = env['XYZ']
673         def t4(env):
674             env['TOOL4'] = 444
675         env = Environment(tools = [t1, t2, t3], XYZ = 'aaa')
676         assert env['TOOL1'] == 111, env['TOOL1']
677         assert env['TOOL2'] == 222, env
678         assert env['AAA'] == 'aaa', env
679         t4(env)
680         assert env['TOOL4'] == 444, env
681
682     def test_Default_TOOLS(self):
683         """Test overriding the default TOOLS variable"""
684         def t5(env):
685             env['TOOL5'] = 555
686         def t6(env):
687             env['TOOL6'] = 666
688         def t7(env):
689             env['BBB'] = env['XYZ']
690         def t8(env):
691             env['TOOL8'] = 888
692
693         import SCons.Defaults
694         save = SCons.Defaults.ConstructionEnvironment.copy()
695         try:
696             SCons.Defaults.ConstructionEnvironment.update({
697                 'TOOLS' : [t5, t6, t7],
698             })
699             env = Environment(XYZ = 'bbb')
700             assert env['TOOL5'] == 555, env['TOOL5']
701             assert env['TOOL6'] == 666, env
702             assert env['BBB'] == 'bbb', env
703             t8(env)
704             assert env['TOOL8'] == 888, env
705         finally:
706             SCons.Defaults.ConstructionEnvironment = save
707
708     def test_concat(self):
709         "Test _concat()"
710         e1 = Environment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
711         s = e1.subst
712         x = s("${_concat('', '', '', __env__)}")
713         assert x == '', x
714         x = s("${_concat('', [], '', __env__)}")
715         assert x == '', x
716         x = s("${_concat(PRE, '', SUF, __env__)}")
717         assert x == '', x
718         x = s("${_concat(PRE, STR, SUF, __env__)}")
719         assert x == 'prea bsuf', x
720         x = s("${_concat(PRE, LIST, SUF, __env__)}")
721         assert x == 'preasuf prebsuf', x
722
723
724
725     def test_Append(self):
726         """Test appending to construction variables in an Environment
727         """
728
729         b1 = Environment()['BUILDERS']
730         b2 = Environment()['BUILDERS']
731         assert b1 == b2, diff_dict(b1, b2)
732
733         import UserList
734         UL = UserList.UserList
735         env1 = Environment(AAA = 'a',
736                            AAA1 = 'a1', AAA2 = 'a2', AAA3 = 'a3',
737                            EEE = ['e'],
738                            EEE1 = ['e1'], EEE2 = ['e2'], EEE3 = ['e3'],
739                            III = UL(['i']),
740                            III1 = UL(['i1']), III2 = UL(['i2']), III3 = UL(['i3']),
741                            MMM = '',
742                            MMM1 = '', MMM2 = '', MMM3 = '',
743                            NNN = [],
744                            NNN1 = [], NNN2 = [], NNN3 = [],
745                            OOO = UL([]),
746                            OOO1 = UL([]), OOO2 = UL([]), OOO3 = UL([]),
747                            PPP = [''],
748                            PPP1 = [''], PPP2 = [''], PPP3 = [''],
749                            QQQ = UL(['']),
750                            QQQ1 = UL(['']), QQQ2 = UL(['']), QQQ3 = UL(['']))
751         env1.Append(AAA1 = 'A1', AAA2 = ['A2'], AAA3 = UL(['A3']),
752                     EEE1 = 'E1', EEE2 = ['E2'], EEE3 = UL(['E3']),
753                     III1 = 'I1', III2 = ['I2'], III3 = UL(['I3']),
754                     MMM1 = 'M1', MMM2 = ['M2'], MMM3 = UL(['M3']),
755                     NNN1 = 'N1', NNN2 = ['N2'], NNN3 = UL(['N3']),
756                     OOO1 = 'O1', OOO2 = ['O2'], OOO3 = UL(['O3']),
757                     PPP1 = 'P1', PPP2 = ['P2'], PPP3 = UL(['P3']),
758                     QQQ1 = 'Q1', QQQ2 = ['Q2'], QQQ3 = UL(['Q3']))
759         assert env1['AAA'] == 'a', env1['AAA']
760         assert env1['AAA1'] == 'a1A1', env1['AAA1']
761         assert env1['AAA2'] == ['a2', 'A2'], env1['AAA2']
762         assert env1['AAA3'] == UL(['a3', 'A3']), env1['AAA3']
763         assert env1['EEE'] == ['e'], env1['EEE']
764         assert env1['EEE1'] == ['e1', 'E1'], env1['EEE1']
765         assert env1['EEE2'] == ['e2', 'E2'], env1['EEE2']
766         assert env1['EEE3'] == UL(['e3', 'E3']), env1['EEE3']
767         assert env1['III'] == UL(['i']), env1['III']
768         assert env1['III1'] == UL(['i1', 'I1']), env1['III1']
769         assert env1['III2'] == UL(['i2', 'I2']), env1['III2']
770         assert env1['III3'] == UL(['i3', 'I3']), env1['III3']
771         assert env1['MMM'] == '', env1['MMM']
772         assert env1['MMM1'] == 'M1', env1['MMM1']
773         assert env1['MMM2'] == ['M2'], env1['MMM2']
774         assert env1['MMM3'] == UL(['M3']), env1['MMM3']
775         assert env1['NNN1'] == ['N1'], env1['NNN1']
776         assert env1['NNN2'] == ['N2'], env1['NNN2']
777         assert env1['NNN3'] == UL(['N3']), env1['NNN3']
778         assert env1['OOO1'] == ['O1'], env1['OOO1']
779         assert env1['OOO2'] == ['O2'], env1['OOO2']
780         assert env1['OOO3'] == UL(['O3']), env1['OOO3']
781         assert env1['PPP1'] == ['', 'P1'], env1['PPP1']
782         assert env1['PPP2'] == ['', 'P2'], env1['PPP2']
783         assert env1['PPP3'] == UL(['', 'P3']), env1['PPP3']
784         assert env1['QQQ1'] == UL(['', 'Q1']), env1['QQQ1']
785         assert env1['QQQ2'] == UL(['', 'Q2']), env1['QQQ2']
786         assert env1['QQQ3'] == UL(['', 'Q3']), env1['QQQ3']
787
788         class C:
789             def __init__(self, name):
790                 self.name = name
791             def __str__(self):
792                 return self.name
793             def __cmp__(self, other):
794                 raise "should not compare"
795
796         ccc = C('ccc')
797
798         env2 = Environment(CCC1 = ['c1'], CCC2 = ccc)
799         env2.Append(CCC1 = ccc, CCC2 = ['c2'])
800         assert env2['CCC1'][0] == 'c1', env2['CCC1']
801         assert env2['CCC1'][1] is ccc, env2['CCC1']
802         assert env2['CCC2'][0] is ccc, env2['CCC2']
803         assert env2['CCC2'][1] == 'c2', env2['CCC2']
804
805         env3 = Environment(X = {'x1' : 7})
806         env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
807         assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X']
808         assert env3['Y'] == {'y1': 10}, env3['Y']
809
810         env4 = Environment(BUILDERS = {'z1' : 11})
811         env4.Append(BUILDERS = {'z2' : 12})
812         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
813         assert hasattr(env4, 'z1')
814         assert hasattr(env4, 'z2')
815
816     def test_AppendENVPath(self):
817         """Test appending to an ENV path."""
818         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
819                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
820         # have to include the pathsep here so that the test will work on UNIX too.
821         env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
822         env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
823         env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
824         env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
825         assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
826         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
827
828     def test_Copy(self):
829         """Test construction Environment copying
830
831         Update the copy independently afterwards and check that
832         the original remains intact (that is, no dangling
833         references point to objects in the copied environment).
834         Copy the original with some construction variable
835         updates and check that the original remains intact
836         and the copy has the updated values.
837         """
838         env1 = Environment(XXX = 'x', YYY = 'y')
839         env2 = env1.Copy()
840         env1copy = env1.Copy()
841         env2.Replace(YYY = 'yyy')
842         assert env1 != env2
843         assert env1 == env1copy
844
845         env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
846         assert env3.Dictionary('XXX') == 'x3'
847         assert env3.Dictionary('YYY') == 'y'
848         assert env3.Dictionary('ZZZ') == 'z3'
849         assert env1 == env1copy
850
851         # Ensure that lists and dictionaries are
852         # deep copied, but not instances.
853         class TestA:
854             pass
855         env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
856                            ZZZ = { 1:2, 3:4 })
857         env2=env1.Copy()
858         env2.Dictionary('YYY').append(4)
859         env2.Dictionary('ZZZ')[5] = 6
860         assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
861         assert 4 in env2.Dictionary('YYY')
862         assert not 4 in env1.Dictionary('YYY')
863         assert env2.Dictionary('ZZZ').has_key(5)
864         assert not env1.Dictionary('ZZZ').has_key(5)
865
866         #
867         env1 = Environment(BUILDERS = {'b1' : 1})
868         assert hasattr(env1, 'b1'), "env1.b1 was not set"
869         assert env1.b1.env == env1, "b1.env doesn't point to env1"
870         env2 = env1.Copy(BUILDERS = {'b2' : 2})
871         assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
872         assert env1.b1.env == env1, "b1.env was changed"
873         assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
874         assert hasattr(env2, 'b2'), "env2.b2 was not set"
875         assert env2.b2.env == env2, "b2.env doesn't point to env2"
876
877         # Ensure that specifying new tools in a copied environment
878         # works.
879         def foo(env): env['FOO'] = 1
880         def bar(env): env['BAR'] = 2
881         def baz(env): env['BAZ'] = 3
882         env1 = Environment(tools=[foo])
883         env2 = env1.Copy()
884         env3 = env1.Copy(tools=[bar, baz])
885
886         assert env1.get('FOO') is 1
887         assert env1.get('BAR') is None
888         assert env1.get('BAZ') is None
889         assert env2.get('FOO') is 1
890         assert env2.get('BAR') is None
891         assert env2.get('BAZ') is None
892         assert env3.get('FOO') is 1
893         assert env3.get('BAR') is 2
894         assert env3.get('BAZ') is 3
895
896     def test_Detect(self):
897         """Test Detect()ing tools"""
898         test = TestCmd.TestCmd(workdir = '')
899         test.subdir('sub1', 'sub2')
900         sub1 = test.workpath('sub1')
901         sub2 = test.workpath('sub2')
902
903         if sys.platform == 'win32':
904             test.write(['sub1', 'xxx'], "sub1/xxx\n")
905             test.write(['sub2', 'xxx'], "sub2/xxx\n")
906
907             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
908
909             x = env.Detect('xxx.exe')
910             assert x is None, x
911
912             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
913
914             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
915
916             x = env.Detect('xxx.exe')
917             assert x == 'xxx.exe', x
918
919             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
920
921             x = env.Detect('xxx.exe')
922             assert x == 'xxx.exe', x
923
924         else:
925             test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n")
926             test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n")
927
928             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
929
930             x = env.Detect('xxx.exe')
931             assert x is None, x
932
933             sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
934             os.chmod(sub2_xxx_exe, 0755)
935
936             env = Environment(ENV = { 'PATH' : [sub1, sub2] })
937
938             x = env.Detect('xxx.exe')
939             assert x == 'xxx.exe', x
940
941             sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
942             os.chmod(sub1_xxx_exe, 0755)
943
944             x = env.Detect('xxx.exe')
945             assert x == 'xxx.exe', x
946
947         env = Environment(ENV = { 'PATH' : [] })
948         x = env.Detect('xxx.exe')
949         assert x is None, x
950
951     def test_Dictionary(self):
952         """Test retrieval of known construction variables
953
954         Fetch them from the Dictionary and check for well-known
955         defaults that get inserted.
956         """
957         env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z')
958         assert env.Dictionary('XXX') == 'x'
959         assert env.Dictionary('YYY') == 'y'
960         assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
961         xxx, zzz = env.Dictionary('XXX', 'ZZZ')
962         assert xxx == 'x'
963         assert zzz == 'z'
964         assert env.Dictionary().has_key('BUILDERS')
965         assert env.Dictionary().has_key('CC')
966         assert env.Dictionary().has_key('CCFLAGS')
967         assert env.Dictionary().has_key('ENV')
968
969         assert env['XXX'] == 'x'
970         env['XXX'] = 'foo'
971         assert env.Dictionary('XXX') == 'foo'
972         del env['XXX']
973         assert not env.Dictionary().has_key('XXX')
974
975     def test_FindIxes(self):
976         "Test FindIxes()"
977         env = Environment(LIBPREFIX='lib',
978                           LIBSUFFIX='.a',
979                           SHLIBPREFIX='lib',
980                           SHLIBSUFFIX='.so',
981                           PREFIX='pre',
982                           SUFFIX='post')
983
984         paths = [os.path.join('dir', 'libfoo.a'),
985                  os.path.join('dir', 'libfoo.so')]
986
987         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
988         assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
989         assert None == env.FindIxes(paths, 'PREFIX', 'POST')
990
991         paths = ['libfoo.a', 'prefoopost']
992
993         assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
994         assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
995         assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
996
997     def test_Override(self):
998         "Test overriding construction variables"
999         env = Environment(ONE=1, TWO=2)
1000         assert env['ONE'] == 1
1001         assert env['TWO'] == 2
1002         env2 = env.Override({'TWO':'10'})
1003         assert env2['ONE'] == 1
1004         assert env2['TWO'] == '10'
1005         assert env['TWO'] == 2
1006         env2.Replace(ONE = "won")
1007         assert env2['ONE'] == "won"
1008         assert env['ONE'] == 1
1009
1010     def test_ParseConfig(self):
1011         """Test the ParseConfig() method"""
1012         env = Environment(COMMAND='command',
1013                           CPPPATH='string',
1014                           LIBPATH=['list'],
1015                           LIBS='',
1016                           CCFLAGS=[''])
1017         save_command = []
1018         orig_popen = os.popen
1019         def my_popen(command, save_command=save_command):
1020             save_command.append(command)
1021             class fake_file:
1022                 def read(self):
1023                     return "-I/usr/include/fum -Ibar -X\n" + \
1024                            "-L/usr/fax -Lfoo -lxxx abc"
1025             return fake_file()
1026         try:
1027             os.popen = my_popen
1028             libs = env.ParseConfig("fake $COMMAND")
1029             assert save_command == ['fake command'], save_command
1030             assert libs == ['abc'], libs
1031             assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
1032             assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
1033             assert env['LIBS'] == ['xxx'], env['LIBS']
1034             assert env['CCFLAGS'] == ['', '-X'], env['CCFLAGS']
1035         finally:
1036             os.popen = orig_popen
1037
1038     def test_Platform(self):
1039         """Test the Platform() method"""
1040         env = Environment(WIN32='win32', NONE='no-such-platform')
1041
1042         exc_caught = None
1043         try:
1044             env.Platform('does_not_exist')
1045         except SCons.Errors.UserError:
1046             exc_caught = 1
1047         assert exc_caught, "did not catch expected UserError"
1048
1049         exc_caught = None
1050         try:
1051             env.Platform('$NONE')
1052         except SCons.Errors.UserError:
1053             exc_caught = 1
1054         assert exc_caught, "did not catch expected UserError"
1055
1056         env.Platform('posix')
1057         assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX']
1058
1059         env.Platform('$WIN32')
1060         assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX']
1061
1062     def test_Prepend(self):
1063         """Test prepending to construction variables in an Environment
1064         """
1065         import UserList
1066         UL = UserList.UserList
1067         env1 = Environment(AAA = 'a', BBB = 'b', CCC = 'c', DDD = 'd',
1068                            EEE = ['e'], FFF = ['f'], GGG = ['g'], HHH = ['h'],
1069                            III = UL(['i']), JJJ = UL(['j']),
1070                            KKK = UL(['k']), LLL = UL(['l']))
1071         env1.Prepend(BBB = 'B', CCC = ['C'], DDD = UL(['D']),
1072                     FFF = 'F', GGG = ['G'], HHH = UL(['H']),
1073                     JJJ = 'J', KKK = ['K'], LLL = UL(['L']))
1074         env2 = Environment(AAA = 'a', BBB = 'Bb',
1075                            CCC = ['C', 'c'], DDD = UL(['D', 'd']),
1076                            EEE = ['e'], FFF = ['F', 'f'],
1077                            GGG = ['G', 'g'], HHH = UL(['H', 'h']),
1078                            III = UL(['i']), JJJ = UL(['J', 'j']),
1079                            KKK = UL(['K', 'k']), LLL = UL(['L', 'l']))
1080         assert env1 == env2, diff_env(env1, env2)
1081
1082         env3 = Environment(X = {'x1' : 7})
1083         env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
1084         assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
1085         assert env3['Y'] == {'y1': 10}, env3['Y']
1086
1087         env4 = Environment(BUILDERS = {'z1' : 11})
1088         env4.Prepend(BUILDERS = {'z2' : 12})
1089         assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
1090         assert hasattr(env4, 'z1')
1091         assert hasattr(env4, 'z2')
1092
1093     def test_PrependENVPath(self):
1094         """Test prepending to an ENV path."""
1095         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1096                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1097         # have to include the pathsep here so that the test will work on UNIX too.
1098         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
1099         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
1100         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
1101         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
1102         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
1103         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
1104
1105     def test_PrependENVPath(self):
1106         """Test prepending to an ENV path."""
1107         env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
1108                            MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
1109         # have to include the pathsep here so that the test will work on UNIX too.
1110         env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
1111         env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
1112         env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
1113         env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
1114         assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
1115         assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
1116
1117     def test_Replace(self):
1118         """Test replacing construction variables in an Environment
1119
1120         After creation of the Environment, of course.
1121         """
1122         env1 = Environment(AAA = 'a', BBB = 'b')
1123         env1.Replace(BBB = 'bbb', CCC = 'ccc')
1124
1125         env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
1126         assert env1 == env2, diff_env(env1, env2)
1127
1128         env3 = Environment(BUILDERS = {'b1' : 1})
1129         assert hasattr(env3, 'b1'), "b1 was not set"
1130         env3.Replace(BUILDERS = {'b2' : 2})
1131         assert not hasattr(env3, 'b1'), "b1 was not cleared"
1132         assert hasattr(env3, 'b2'), "b2 was not set"
1133
1134     def test_ReplaceIxes(self):
1135         "Test ReplaceIxes()"
1136         env = Environment(LIBPREFIX='lib',
1137                           LIBSUFFIX='.a',
1138                           SHLIBPREFIX='lib',
1139                           SHLIBSUFFIX='.so',
1140                           PREFIX='pre',
1141                           SUFFIX='post')
1142
1143         assert 'libfoo.a' == env.ReplaceIxes('libfoo.so',
1144                                              'SHLIBPREFIX', 'SHLIBSUFFIX',
1145                                              'LIBPREFIX', 'LIBSUFFIX')
1146
1147         assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'),
1148                                                                    'SHLIBPREFIX', 'SHLIBSUFFIX',
1149                                                                    'LIBPREFIX', 'LIBSUFFIX')
1150
1151         assert 'libfoo.a' == env.ReplaceIxes('prefoopost',
1152                                              'PREFIX', 'SUFFIX',
1153                                              'LIBPREFIX', 'LIBSUFFIX')
1154
1155     def test_Tool(self):
1156         """Test the Tool() method"""
1157         env = Environment(LINK='link', NONE='no-such-tool')
1158
1159         exc_caught = None
1160         try:
1161             env.Tool('does_not_exist')
1162         except SCons.Errors.UserError:
1163             exc_caught = 1
1164         assert exc_caught, "did not catch expected UserError"
1165
1166         exc_caught = None
1167         try:
1168             env.Tool('$NONE')
1169         except SCons.Errors.UserError:
1170             exc_caught = 1
1171         assert exc_caught, "did not catch expected UserError"
1172
1173         # Use a non-existent toolpath directory just to make sure we
1174         # can call Tool() with the keyword argument.
1175         env.Tool('cc', toolpath=['/no/such/directory'])
1176         assert env['CC'] == 'cc', env['CC']
1177
1178         env.Tool('$LINK')
1179         assert env['LINK'] == '$SMARTLINK', env['LINK']
1180
1181     def test_WhereIs(self):
1182         """Test the WhereIs() method"""
1183         test = TestCmd.TestCmd(workdir = '')
1184
1185         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
1186         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
1187         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
1188         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
1189
1190         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
1191
1192         if sys.platform != 'win32':
1193             test.write(sub1_xxx_exe, "\n")
1194
1195         os.mkdir(sub2_xxx_exe)
1196
1197         test.write(sub3_xxx_exe, "\n")
1198         os.chmod(sub3_xxx_exe, 0777)
1199
1200         test.write(sub4_xxx_exe, "\n")
1201         os.chmod(sub4_xxx_exe, 0777)
1202
1203         env_path = os.environ['PATH']
1204
1205         pathdirs_1234 = [ test.workpath('sub1'),
1206                           test.workpath('sub2'),
1207                           test.workpath('sub3'),
1208                           test.workpath('sub4'),
1209                         ] + string.split(env_path, os.pathsep)
1210
1211         pathdirs_1243 = [ test.workpath('sub1'),
1212                           test.workpath('sub2'),
1213                           test.workpath('sub4'),
1214                           test.workpath('sub3'),
1215                         ] + string.split(env_path, os.pathsep)
1216
1217         path = string.join(pathdirs_1234, os.pathsep)
1218         env = Environment(ENV = {'PATH' : path})
1219         wi = env.WhereIs('xxx.exe')
1220         assert wi == test.workpath(sub3_xxx_exe), wi
1221         wi = env.WhereIs('xxx.exe', pathdirs_1243)
1222         assert wi == test.workpath(sub4_xxx_exe), wi
1223         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
1224         assert wi == test.workpath(sub4_xxx_exe), wi
1225
1226         path = string.join(pathdirs_1243, os.pathsep)
1227         env = Environment(ENV = {'PATH' : path})
1228         wi = env.WhereIs('xxx.exe')
1229         assert wi == test.workpath(sub4_xxx_exe), wi
1230         wi = env.WhereIs('xxx.exe', pathdirs_1234)
1231         assert wi == test.workpath(sub3_xxx_exe), wi
1232         wi = env.WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
1233         assert wi == test.workpath(sub3_xxx_exe), wi
1234
1235         if sys.platform == 'win32':
1236             wi = env.WhereIs('xxx', pathext = '')
1237             assert wi is None, wi
1238
1239             wi = env.WhereIs('xxx', pathext = '.exe')
1240             assert wi == test.workpath(sub4_xxx_exe), wi
1241
1242             wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
1243             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
1244
1245             # Test that we return a normalized path even when
1246             # the path contains forward slashes.
1247             forward_slash = test.workpath('') + '/sub3'
1248             wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE')
1249             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
1250
1251
1252
1253     def test_Action(self):
1254         """Test the Action() method"""
1255         import SCons.Action
1256
1257         env = Environment(FOO = 'xyzzy')
1258
1259         a = env.Action('foo')
1260         assert a, a
1261         assert a.__class__ is SCons.Action.CommandAction, a
1262
1263         a = env.Action('$FOO')
1264         assert a, a
1265         assert a.__class__ is SCons.Action.CommandGeneratorAction, a
1266
1267         a = env.Action(['$FOO', 'foo'])
1268         assert a, a
1269         assert a.__class__ is SCons.Action.ListAction, a
1270
1271         def func(arg):
1272             pass
1273         a = env.Action(func)
1274         assert a, a
1275         assert a.__class__ is SCons.Action.FunctionAction, a
1276
1277     def test_AddPostAction(self):
1278         """Test the AddPostAction() method"""
1279         env = Environment(FOO='fff', BAR='bbb')
1280
1281         n = env.AddPostAction('$FOO', lambda x: x)
1282         assert str(n[0]) == 'fff', n[0]
1283
1284         n = env.AddPostAction(['ggg', '$BAR'], lambda x: x)
1285         assert str(n[0]) == 'ggg', n[0]
1286         assert str(n[1]) == 'bbb', n[1]
1287
1288     def test_AddPreAction(self):
1289         """Test the AddPreAction() method"""
1290         env = Environment(FOO='fff', BAR='bbb')
1291
1292         n = env.AddPreAction('$FOO', lambda x: x)
1293         assert str(n[0]) == 'fff', n[0]
1294
1295         n = env.AddPreAction(['ggg', '$BAR'], lambda x: x)
1296         assert str(n[0]) == 'ggg', n[0]
1297         assert str(n[1]) == 'bbb', n[1]
1298
1299     def test_Alias(self):
1300         """Test the Alias() method"""
1301         env = Environment(FOO='kkk', BAR='lll', EA='export_alias')
1302
1303         tgt = env.Alias('new_alias')
1304         assert str(tgt) == 'new_alias', tgt
1305         assert tgt.sources == [], tgt.sources
1306
1307         tgt = env.Alias('None_alias', None)
1308         assert str(tgt) == 'None_alias', tgt
1309         assert tgt.sources == [], tgt.sources
1310
1311         tgt = env.Alias('empty_list', [])
1312         assert str(tgt) == 'empty_list', tgt
1313         assert tgt.sources == [], tgt.sources
1314
1315         tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])
1316         assert str(tgt) == 'export_alias', tgt
1317         assert len(tgt.sources) == 2, map(str, tgt.sources)
1318         assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources)
1319         assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources)
1320
1321         n = env.Alias(tgt, source = ['$BAR', 'asrc4'])
1322         assert n is tgt, n
1323         assert len(tgt.sources) == 4, map(str, tgt.sources)
1324         assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources)
1325         assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources)
1326
1327         n = env.Alias('$EA', 'asrc5')
1328         assert n is tgt, n
1329         assert len(tgt.sources) == 5, map(str, tgt.sources)
1330         assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources)
1331
1332         t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
1333         assert str(t1) == 't1', t1
1334         assert str(t2) == 't2', t2
1335         assert len(t1.sources) == 2, map(str, t1.sources)
1336         assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources)
1337         assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources)
1338         assert len(t2.sources) == 2, map(str, t2.sources)
1339         assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources)
1340         assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources)
1341
1342     def test_AlwaysBuild(self):
1343         """Test the AlwaysBuild() method"""
1344         env = Environment(FOO='fff', BAR='bbb')
1345         t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR')
1346         assert t[0].__class__.__name__ == 'File'
1347         assert t[0].path == 'a'
1348         assert t[0].always_build
1349         assert t[1].__class__.__name__ == 'File'
1350         assert t[1].path == 'bfff'
1351         assert t[1].always_build
1352         assert t[2].__class__.__name__ == 'File'
1353         assert t[2].path == 'c'
1354         assert t[2].always_build
1355         assert t[3].__class__.__name__ == 'File'
1356         assert t[3].path == 'd'
1357         assert t[3].always_build
1358         assert t[4].__class__.__name__ == 'File'
1359         assert t[4].path == 'bbb'
1360         assert t[4].always_build
1361
1362     def test_BuildDir(self):
1363         """Test the BuildDir() method"""
1364         class MyFS:
1365              def Dir(self, name):
1366                  return name
1367              def BuildDir(self, build_dir, src_dir, duplicate):
1368                  self.build_dir = build_dir
1369                  self.src_dir = src_dir
1370                  self.duplicate = duplicate
1371
1372         env = Environment(FOO = 'fff', BAR = 'bbb')
1373         env.fs = MyFS()
1374
1375         env.BuildDir('build', 'src')
1376         assert env.fs.build_dir == 'build', env.fs.build_dir
1377         assert env.fs.src_dir == 'src', env.fs.src_dir
1378         assert env.fs.duplicate == 1, env.fs.duplicate
1379
1380         env.BuildDir('build${FOO}', '${BAR}src', 0)
1381         assert env.fs.build_dir == 'buildfff', env.fs.build_dir
1382         assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir
1383         assert env.fs.duplicate == 0, env.fs.duplicate
1384
1385     def test_Builder(self):
1386         """Test the Builder() method"""
1387         env = Environment(FOO = 'xyzzy')
1388
1389         b = env.Builder(action = 'foo')
1390         assert not b is None, b
1391
1392         b = env.Builder(action = '$FOO')
1393         assert not b is None, b
1394
1395         b = env.Builder(action = ['$FOO', 'foo'])
1396         assert not b is None, b
1397
1398         def func(arg):
1399             pass
1400         b = env.Builder(action = func)
1401         assert not b is None, b
1402         b = env.Builder(generator = func)
1403         assert not b is None, b
1404
1405     def test_CacheDir(self):
1406         """Test the CacheDir() method"""
1407         class MyFS:
1408             def CacheDir(self, path):
1409                 self.CD = path
1410
1411         env = Environment(CD = 'CacheDir')
1412         env.fs = MyFS()
1413
1414         env.CacheDir('foo')
1415         assert env.fs.CD == 'foo', env.fs.CD
1416
1417         env.CacheDir('$CD')
1418         assert env.fs.CD == 'CacheDir', env.fs.CD
1419
1420     def test_Clean(self):
1421         """Test the Clean() method"""
1422         env = Environment(FOO = 'fff', BAR = 'bbb')
1423
1424         CT = SCons.Environment.CleanTargets
1425
1426         foo = env.arg2nodes('foo')[0]
1427         fff = env.arg2nodes('fff')[0]
1428
1429         t = env.Clean('foo', 'aaa')
1430         l = map(str, CT[foo])
1431         assert l == ['aaa'], l
1432
1433         t = env.Clean(foo, ['$BAR', 'ccc'])
1434         l = map(str, CT[foo])
1435         assert l == ['aaa', 'bbb', 'ccc'], l
1436
1437         eee = env.arg2nodes('eee')[0]
1438
1439         t = env.Clean('$FOO', 'ddd')
1440         l = map(str, CT[fff])
1441         assert l == ['ddd'], l
1442         t = env.Clean(fff, [eee, 'fff'])
1443         l = map(str, CT[fff])
1444         assert l == ['ddd', 'eee', 'fff'], l
1445
1446     def test_Command(self):
1447         """Test the Command() method."""
1448         env = Environment()
1449         t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
1450                         action='buildfoo $target $source')
1451         assert not t.builder is None
1452         assert t.builder.action.__class__.__name__ == 'CommandAction'
1453         assert t.builder.action.cmd_list == 'buildfoo $target $source'
1454         assert 'foo1.in' in map(lambda x: x.path, t.sources)
1455         assert 'foo2.in' in map(lambda x: x.path, t.sources)
1456
1457         sub = SCons.Node.FS.default_fs.Dir('sub')
1458         t = env.Command(target='bar.out', source='sub',
1459                         action='buildbar $target $source')
1460         assert 'sub' in map(lambda x: x.path, t.sources)
1461
1462         def testFunc(env, target, source):
1463             assert str(target[0]) == 'foo.out'
1464             assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
1465             return 0
1466         t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
1467                         action=testFunc)
1468         assert not t.builder is None
1469         assert t.builder.action.__class__.__name__ == 'FunctionAction'
1470         t.build()
1471         assert 'foo1.in' in map(lambda x: x.path, t.sources)
1472         assert 'foo2.in' in map(lambda x: x.path, t.sources)
1473
1474     def test_Configure(self):
1475         """Test the Configure() method"""
1476         # Configure() will write to a local temporary file.
1477         test = TestCmd.TestCmd(workdir = '')
1478         save = os.getcwd()
1479         # Configure() will test, if we are reading a SConscript file
1480         import SCons.Script.SConscript
1481         SCons.Script.SConscript.sconscript_reading = 1
1482
1483         try:
1484             os.chdir(test.workpath())
1485
1486             env = Environment(FOO = 'xyzzy')
1487
1488             def func(arg):
1489                 pass
1490
1491             c = env.Configure()
1492             assert not c is None, c
1493             c.Finish()
1494
1495             c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
1496             assert not c is None, c
1497             assert hasattr(c, 'foo')
1498             assert hasattr(c, 'xyzzy')
1499             c.Finish()
1500         finally:
1501             os.chdir(save)
1502
1503     def test_Depends(self):
1504         """Test the explicit Depends method."""
1505         env = Environment(FOO = 'xxx', BAR='yyy')
1506         env.Dir('dir1')
1507         env.Dir('dir2')
1508         env.File('xxx.py')
1509         env.File('yyy.py')
1510         t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py')
1511         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
1512         assert t.path == 'EnvironmentTest.py'
1513         assert len(t.depends) == 1
1514         d = t.depends[0]
1515         assert d.__class__.__name__ == 'Entry', d.__class__.__name__
1516         assert d.path == 'Environment.py'
1517
1518         t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')
1519         assert t.__class__.__name__ == 'File', t.__class__.__name__
1520         assert t.path == 'xxx.py'
1521         assert len(t.depends) == 1
1522         d = t.depends[0]
1523         assert d.__class__.__name__ == 'File', d.__class__.__name__
1524         assert d.path == 'yyy.py'
1525
1526         t = env.Depends(target='dir1', dependency='dir2')
1527         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
1528         assert t.path == 'dir1'
1529         assert len(t.depends) == 1
1530         d = t.depends[0]
1531         assert d.__class__.__name__ == 'Dir', d.__class__.__name__
1532         assert d.path == 'dir2'
1533
1534     def test_Dir(self):
1535         """Test the Dir() method"""
1536         class MyFS:
1537             def Dir(self, name):
1538                 return 'Dir(%s)' % name
1539
1540         env = Environment(FOO = 'foodir', BAR = 'bardir')
1541         env.fs = MyFS()
1542
1543         d = env.Dir('d')
1544         assert d == 'Dir(d)', d
1545
1546         d = env.Dir('$FOO')
1547         assert d == 'Dir(foodir)', d
1548
1549         d = env.Dir('${BAR}_$BAR')
1550         assert d == 'Dir(bardir_bardir)', d
1551
1552     def test_Environment(self):
1553         """Test the Environment() method"""
1554         env = Environment(FOO = 'xxx', BAR = 'yyy')
1555
1556         e2 = env.Environment(X = '$FOO', Y = '$BAR')
1557         assert e2['X'] == 'xxx', e2['X']
1558         assert e2['Y'] == 'yyy', e2['Y']
1559
1560     def test_File(self):
1561         """Test the File() method"""
1562         class MyFS:
1563             def File(self, name):
1564                 return 'File(%s)' % name
1565
1566         env = Environment(FOO = 'foofile', BAR = 'barfile')
1567         env.fs = MyFS()
1568
1569         f = env.File('f')
1570         assert f == 'File(f)', f
1571
1572         f = env.File('$FOO')
1573         assert f == 'File(foofile)', f
1574
1575         f = env.File('${BAR}_$BAR')
1576         assert f == 'File(barfile_barfile)', f
1577
1578     def test_FindFile(self):
1579         """Test the FindFile() method"""
1580         env = Environment(FOO = 'fff', BAR = 'bbb')
1581
1582         r = env.FindFile('foo', ['no_such_directory'])
1583         assert r is None, r
1584
1585         # XXX
1586
1587     def test_GetBuildPath(self):
1588         """Test the GetBuildPath() method."""
1589         env = Environment(MAGIC = 'xyzzy')
1590
1591         p = env.GetBuildPath('foo')
1592         assert p == 'foo', p
1593
1594         p = env.GetBuildPath('$MAGIC')
1595         assert p == 'xyzzy', p
1596
1597     def test_Ignore(self):
1598         """Test the explicit Ignore method."""
1599         env = Environment(FOO='yyy', BAR='zzz')
1600         env.Dir('dir1')
1601         env.Dir('dir2')
1602         env.File('yyyzzz')
1603         env.File('zzzyyy')
1604
1605         t = env.Ignore(target='targ.py', dependency='dep.py')
1606         assert t.__class__.__name__ == 'Entry', t.__class__.__name__
1607         assert t.path == 'targ.py'
1608         assert len(t.ignore) == 1
1609         i = t.ignore[0]
1610         assert i.__class__.__name__ == 'Entry', i.__class__.__name__
1611         assert i.path == 'dep.py'
1612
1613         t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')
1614         assert t.__class__.__name__ == 'File', t.__class__.__name__
1615         assert t.path == 'yyyzzz'
1616         assert len(t.ignore) == 1
1617         i = t.ignore[0]
1618         assert i.__class__.__name__ == 'File', i.__class__.__name__
1619         assert i.path == 'zzzyyy'
1620
1621         t = env.Ignore(target='dir1', dependency='dir2')
1622         assert t.__class__.__name__ == 'Dir', t.__class__.__name__
1623         assert t.path == 'dir1'
1624         assert len(t.ignore) == 1
1625         i = t.ignore[0]
1626         assert i.__class__.__name__ == 'Dir', i.__class__.__name__
1627         assert i.path == 'dir2'
1628
1629     def test_Install(self):
1630         """Test the Install method"""
1631         env = Environment(FOO='iii', BAR='jjj')
1632
1633         tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
1634         paths = map(str, tgt)
1635         paths.sort()
1636         expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
1637         assert paths == expect, paths
1638         for tnode in tgt:
1639             assert tnode.builder == InstallBuilder
1640
1641         tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
1642         paths = map(str, tgt)
1643         paths.sort()
1644         expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
1645         assert paths == expect, paths
1646         for tnode in tgt:
1647             assert tnode.builder == InstallBuilder
1648
1649         exc_caught = None
1650         try:
1651             tgt = env.Install('export', 'export')
1652         except SCons.Errors.UserError, e:
1653             exc_caught = 1
1654         assert exc_caught, "UserError should be thrown when Install() target is not a file."
1655         match = str(e) == "Source `export' of Install() is not a file.  Install() source must be one or more files."
1656         assert match, e
1657
1658         exc_caught = None
1659         try:
1660             tgt = env.Install('export', ['export', 'build/foo1'])
1661         except SCons.Errors.UserError, e:
1662             exc_caught = 1
1663         assert exc_caught, "UserError should be thrown when Install() target containins non-files."
1664         match = str(e) == "Source `['export', 'build/foo1']' of Install() contains one or more non-files.  Install() source must be one or more files."
1665         assert match, e
1666
1667         exc_caught = None
1668         try:
1669             tgt = env.Install('export/foo1', 'build/foo1')
1670         except SCons.Errors.UserError, e:
1671             exc_caught = 1
1672         assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
1673         match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?"
1674         assert match, e
1675
1676     def test_InstallAs(self):
1677         """Test the InstallAs method"""
1678         env = Environment(FOO='iii', BAR='jjj')
1679
1680         tgt = env.InstallAs(target=string.split('foo1 foo2'),
1681                             source=string.split('bar1 bar2'))
1682         assert len(tgt) == 2, len(tgt)
1683         paths = map(lambda x: str(x.sources[0]), tgt)
1684         paths.sort()
1685         expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
1686         assert paths == expect, paths
1687         for tnode in tgt:
1688             assert tnode.builder == InstallBuilder
1689
1690         tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')
1691         assert tgt.path == 'iii.t'
1692         assert tgt.sources[0].path == 'jjj.s'
1693         assert tgt.builder == InstallBuilder
1694
1695     def test_Literal(self):
1696         """Test the Literal() method"""
1697         env = Environment(FOO='fff', BAR='bbb')
1698         list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0]
1699         assert list == ['$FOO', 'bbb'], list
1700         list = env.subst_list(['$FOO', env.Literal('$BAR')])[0]
1701         assert list == ['fff', '$BAR'], list
1702
1703     def test_Local(self):
1704         """Test the Local() method."""
1705         env = Environment(FOO='lll')
1706
1707         l = env.Local(env.fs.File('fff'))
1708         assert str(l[0]) == 'fff', l[0]
1709
1710         l = env.Local('ggg', '$FOO')
1711         assert str(l[0]) == 'ggg', l[0]
1712         assert str(l[1]) == 'lll', l[1]
1713
1714     def test_Precious(self):
1715         """Test the Precious() method"""
1716         env = Environment(FOO='ggg', BAR='hhh')
1717         env.Dir('p_hhhb')
1718         env.File('p_d')
1719         t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO')
1720
1721         assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__
1722         assert t[0].path == 'p_a'
1723         assert t[0].precious
1724         assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__
1725         assert t[1].path == 'p_hhhb'
1726         assert t[1].precious
1727         assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__
1728         assert t[2].path == 'p_c'
1729         assert t[2].precious
1730         assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__
1731         assert t[3].path == 'p_d'
1732         assert t[3].precious
1733         assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__
1734         assert t[4].path == 'p_ggg'
1735         assert t[4].precious
1736
1737     def test_Repository(self):
1738         """Test the Repository() method."""
1739         class MyFS:
1740             def __init__(self):
1741                 self.list = []
1742             def Repository(self, *dirs):
1743                 self.list.extend(list(dirs))
1744             def Dir(self, name):
1745                 return name
1746         env = Environment(FOO='rrr', BAR='sss')
1747         env.fs = MyFS()
1748         env.Repository('/tmp/foo')
1749         env.Repository('/tmp/$FOO', '/tmp/$BAR/foo')
1750         expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
1751         assert env.fs.list == expect, env.fs.list
1752
1753     def test_Scanner(self):
1754         """Test the Scanner() method"""
1755         def scan(node, env, target, arg):
1756             pass
1757
1758         env = Environment(FOO = scan)
1759
1760         s = env.Scanner('foo')
1761         assert not s is None, s
1762
1763         s = env.Scanner(function = 'foo')
1764         assert not s is None, s
1765
1766         if 0:
1767             s = env.Scanner('$FOO')
1768             assert not s is None, s
1769
1770             s = env.Scanner(function = '$FOO')
1771             assert not s is None, s
1772
1773     def test_SConsignFile(self):
1774         """Test the SConsignFile() method"""
1775         import SCons.Sig
1776
1777         class MyFS:
1778             SConstruct_dir = os.sep + 'dir'
1779
1780         env = Environment(FOO = 'SConsign',
1781                           BAR = os.path.join(os.sep, 'File'))
1782         env.fs = MyFS()
1783
1784         try:
1785             fnames = []
1786             dbms = []
1787             def capture(name, dbm_module, fnames=fnames, dbms=dbms):
1788                 fnames.append(name)
1789                 dbms.append(dbm_module)
1790
1791             save_Sig_SConsignFile = SCons.Sig.SConsignFile
1792             SCons.Sig.SConsignFile = capture
1793
1794             env.SConsignFile('foo')
1795             assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames
1796             assert dbms[0] == None, dbms
1797
1798             env.SConsignFile('$FOO')
1799             assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
1800             assert dbms[1] == None, dbms
1801
1802             env.SConsignFile('/$FOO')
1803             assert fnames[2] == '/SConsign', fnames
1804             assert dbms[2] == None, dbms
1805
1806             env.SConsignFile('$BAR', 'x')
1807             assert fnames[3] == os.path.join(os.sep, 'File'), fnames
1808             assert dbms[3] == 'x', dbms
1809
1810             env.SConsignFile('__$BAR', 7)
1811             assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
1812             assert dbms[4] == 7, dbms
1813         finally:
1814             SCons.Sig.SConsignFile = save_Sig_SConsignFile
1815
1816     def test_SideEffect(self):
1817         """Test the SideEffect() method"""
1818         env = Environment(LIB='lll', FOO='fff', BAR='bbb')
1819         env.File('mylll.pdb')
1820         env.Dir('mymmm.pdb')
1821
1822         foo = env.Object('foo.obj', 'foo.cpp')
1823         bar = env.Object('bar.obj', 'bar.cpp')
1824         s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])
1825         assert s.__class__.__name__ == 'Entry', s.__class__.__name__
1826         assert s.path == 'mylib.pdb'
1827         assert s.side_effect
1828         assert foo.side_effects == [s]
1829         assert bar.side_effects == [s]
1830         assert s.depends_on([bar])
1831         assert s.depends_on([foo])
1832
1833         fff = env.Object('fff.obj', 'fff.cpp')
1834         bbb = env.Object('bbb.obj', 'bbb.cpp')
1835         s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])
1836         assert s.__class__.__name__ == 'File', s.__class__.__name__
1837         assert s.path == 'mylll.pdb'
1838         assert s.side_effect
1839         assert fff.side_effects == [s], fff.side_effects
1840         assert bbb.side_effects == [s], bbb.side_effects
1841         assert s.depends_on([bbb])
1842         assert s.depends_on([fff])
1843
1844         ggg = env.Object('ggg.obj', 'ggg.cpp')
1845         ccc = env.Object('ccc.obj', 'ccc.cpp')
1846         s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])
1847         assert s.__class__.__name__ == 'Dir', s.__class__.__name__
1848         assert s.path == 'mymmm.pdb'
1849         assert s.side_effect
1850         assert ggg.side_effects == [s], ggg.side_effects
1851         assert ccc.side_effects == [s], ccc.side_effects
1852         assert s.depends_on([ccc])
1853         assert s.depends_on([ggg])
1854
1855     def test_SourceCode(self):
1856         """Test the SourceCode() method."""
1857         env = Environment(FOO='mmm', BAR='nnn')
1858         e = env.SourceCode('foo', None)
1859         assert e.path == 'foo'
1860         s = e.src_builder()
1861         assert s is None, s
1862
1863         b = Builder()
1864         e = env.SourceCode(e, b)
1865         assert e.path == 'foo'
1866         s = e.src_builder()
1867         assert s is b, s
1868
1869         e = env.SourceCode('$BAR$FOO', None)
1870         assert e.path == 'nnnmmm'
1871         s = e.src_builder()
1872         assert s is None, s
1873
1874     def test_SourceSignatures(type):
1875         """Test the SourceSignatures() method"""
1876         env = Environment(M = 'MD5', T = 'timestamp')
1877
1878         exc_caught = None
1879         try:
1880             env.SourceSignatures('invalid_type')
1881         except SCons.Errors.UserError:
1882             exc_caught = 1
1883         assert exc_caught, "did not catch expected UserError"
1884         assert not hasattr(env, '_calc_module')
1885
1886         env.SourceSignatures('MD5')
1887         m = env._calc_module
1888
1889         env.SourceSignatures('$M')
1890         assert env._calc_module is m
1891
1892         env.SourceSignatures('timestamp')
1893         t = env._calc_module
1894
1895         env.SourceSignatures('$T')
1896         assert env._calc_module is t
1897
1898     def test_Split(self):
1899         """Test the Split() method"""
1900         env = Environment(FOO='fff', BAR='bbb')
1901         s = env.Split("foo bar")
1902         assert s == ["foo", "bar"], s
1903         s = env.Split("$FOO bar")
1904         assert s == ["fff", "bar"], s
1905         s = env.Split(["foo", "bar"])
1906         assert s == ["foo", "bar"], s
1907         s = env.Split(["foo", "${BAR}-bbb"])
1908         assert s == ["foo", "bbb-bbb"], s
1909         s = env.Split("foo")
1910         assert s == ["foo"], s
1911         s = env.Split("$FOO$BAR")
1912         assert s == ["fffbbb"], s
1913
1914     def test_TargetSignatures(type):
1915         """Test the TargetSignatures() method"""
1916         env = Environment(B = 'build', C = 'content')
1917
1918         exc_caught = None
1919         try:
1920             env.TargetSignatures('invalid_type')
1921         except SCons.Errors.UserError:
1922             exc_caught = 1
1923         assert exc_caught, "did not catch expected UserError"
1924         assert not hasattr(env, '_build_signature')
1925
1926         env.TargetSignatures('build')
1927         assert env._build_signature == 1, env._build_signature
1928
1929         env.TargetSignatures('content')
1930         assert env._build_signature == 0, env._build_signature
1931
1932         env.TargetSignatures('$B')
1933         assert env._build_signature == 1, env._build_signature
1934
1935         env.TargetSignatures('$C')
1936         assert env._build_signature == 0, env._build_signature
1937
1938     def test_Value(self):
1939         """Test creating a Value() object
1940         """
1941         env = Environment()
1942         v1 = env.Value('a')
1943         assert v1.value == 'a', v1.value
1944
1945         value2 = 'a'
1946         v2 = env.Value(value2)
1947         assert v2.value == value2, v2.value
1948         assert v2.value is value2, v2.value
1949
1950         assert not v1 is v2
1951         assert v1.value == v2.value
1952
1953
1954
1955     def test_Environment_global_variable(type):
1956         """Test setting Environment variable to an Environment.Base subclass"""
1957         class MyEnv(SCons.Environment.Base):
1958             def xxx(self, string):
1959                 return self.subst(string)
1960
1961         SCons.Environment.Environment = MyEnv
1962
1963         env = SCons.Environment.Environment(FOO = 'foo')
1964
1965         f = env.subst('$FOO')
1966         assert f == 'foo', f
1967
1968         f = env.xxx('$FOO')
1969         assert f == 'foo', f
1970
1971
1972 if __name__ == "__main__":
1973     suite = unittest.makeSuite(EnvironmentTestCase, 'test_')
1974     if not unittest.TextTestRunner().run(suite).wasSuccessful():
1975         sys.exit(1)