Follow-up test portability fixes for IRIX. (Chad Austin)
[scons.git] / src / engine / SCons / UtilTests.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 os.path
28 import re
29 import string
30 import sys
31 import types
32 import unittest
33 import SCons.Node
34 import SCons.Node.FS
35 from SCons.Util import *
36 import TestCmd
37
38
39 class OutBuffer:
40     def __init__(self):
41         self.buffer = ""
42
43     def write(self, str):
44         self.buffer = self.buffer + str
45
46 class DummyEnv:
47     def __init__(self, dict={}):
48         self.dict = dict
49
50     def Dictionary(self, key = None):
51         if not key:
52             return self.dict
53         return self.dict[key]
54
55     def sig_dict(self):
56         dict = self.dict.copy()
57         dict["TARGETS"] = 'tsig'
58         dict["SOURCES"] = 'ssig'
59         return dict
60
61 def CmdGen1(target, source, env):
62     # Nifty trick...since Environment references are interpolated,
63     # instantiate an instance of a callable class with this one,
64     # which will then get evaluated.
65     assert target == 't', target
66     assert source == 's', source
67     return "${CMDGEN2('foo')}"
68
69 class CmdGen2:
70     def __init__(self, mystr):
71         self.mystr = mystr
72
73     def __call__(self, target, source, env):
74         assert target == 't', target
75         assert source == 's', source
76         return [ self.mystr, env.Dictionary('BAR') ]
77
78 class UtilTestCase(unittest.TestCase):
79     def test_subst(self):
80         """Test the subst function"""
81         loc = {}
82         target = [ "./foo/bar.exe",
83                    "/bar/baz.obj",
84                    "../foo/baz.obj" ]
85         source = [ "./foo/blah.cpp",
86                    "/bar/ack.cpp",
87                    "../foo/ack.c" ]
88         loc['xxx'] = None
89         loc['zero'] = 0
90         loc['one'] = 1
91         loc['BAR'] = 'baz'
92
93         loc['CMDGEN1'] = CmdGen1
94         loc['CMDGEN2'] = CmdGen2
95
96         env = DummyEnv(loc)
97
98         if os.sep == '/':
99             def cvt(str):
100                 return str
101         else:
102             def cvt(str):
103                 return string.replace(str, '/', os.sep)
104
105         newcom = scons_subst("test $TARGETS $SOURCES", env,
106                              target=target, source=source)
107         assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp /bar/ack.cpp ../foo/ack.c")
108
109         newcom = scons_subst("test ${TARGETS[:]} ${SOURCES[0]}", env,
110                              target=target, source=source)
111         assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp")
112
113         newcom = scons_subst("test ${TARGETS[1:]}v", env,
114                              target=target, source=source)
115         assert newcom == cvt("test /bar/baz.obj ../foo/baz.objv")
116
117         newcom = scons_subst("test $TARGET", env,
118                              target=target, source=source)
119         assert newcom == cvt("test foo/bar.exe")
120
121         newcom = scons_subst("test $TARGET$FOO[0]", env,
122                              target=target, source=source)
123         assert newcom == cvt("test foo/bar.exe[0]")
124
125         newcom = scons_subst("test ${TARGET.file}", env,
126                              target=target, source=source)
127         assert newcom == cvt("test bar.exe")
128
129         newcom = scons_subst("test ${TARGET.filebase}", env,
130                              target=target, source=source)
131         assert newcom == cvt("test bar")
132
133         newcom = scons_subst("test ${TARGET.suffix}", env,
134                              target=target, source=source)
135         assert newcom == cvt("test .exe")
136
137         newcom = scons_subst("test ${TARGET.base}", env,
138                              target=target, source=source)
139         assert newcom == cvt("test foo/bar")
140
141         newcom = scons_subst("test ${TARGET.dir}", env,
142                              target=target, source=source)
143         assert newcom == cvt("test foo")
144
145         newcom = scons_subst("test ${TARGET.abspath}", env,
146                              target=target, source=source)
147         assert newcom == cvt("test %s/foo/bar.exe"%SCons.Util.updrive(os.getcwd())), newcom
148
149         newcom = scons_subst("test ${SOURCES.abspath}", env,
150                              target=target, source=source)
151         assert newcom == cvt("test %s/foo/blah.cpp %s %s/foo/ack.c"%(SCons.Util.updrive(os.getcwd()),
152                                                                      SCons.Util.updrive(os.path.abspath(os.path.normpath("/bar/ack.cpp"))),
153                                                                      SCons.Util.updrive(os.path.normpath(os.getcwd()+"/..")))), newcom
154
155         newcom = scons_subst("test ${SOURCE.abspath}", env,
156                              target=target, source=source)
157         assert newcom == cvt("test %s/foo/blah.cpp"%SCons.Util.updrive(os.getcwd())), newcom
158
159         # Note that we don't use the cvt() helper function here,
160         # because we're testing that the .posix attribute does its own
161         # conversion of the path name backslashes to slashes.
162         newcom = scons_subst("test ${TARGET.posix} ${SOURCE.posix}", env,
163                              target=target, source=source)
164         assert newcom == "test foo/bar.exe foo/blah.cpp", newcom
165
166         SCons.Node.FS.default_fs.BuildDir("#baz","#foo")
167
168         newcom = scons_subst("test ${SOURCE.srcdir}", env,
169                              target=target, source=['baz/bar.c'])
170
171         assert newcom == cvt("test foo"), newcom
172
173         newcom = scons_subst("test ${SOURCE.srcpath}", env,
174                              target=target, source=['baz/bar.c'])
175
176         assert newcom == cvt("test foo/bar.c"), newcom
177
178         newcom = scons_subst("test $xxx", env)
179         assert newcom == cvt("test"), newcom
180
181         newcom = scons_subst("test $($xxx$)", env)
182         assert newcom == cvt("test $($)"), newcom
183
184         newcom = scons_subst("test $( $xxx $)", env)
185         assert newcom == cvt("test $( $)"), newcom
186
187         newcom = scons_subst("test $($xxx$)", env, re.compile('\$[()]'))
188         assert newcom == cvt("test"), newcom
189
190         newcom = scons_subst("test $( $xxx $)", env, re.compile('\$[()]'))
191         assert newcom == cvt("test"), newcom
192
193         newcom = scons_subst("test $zero", env)
194         assert newcom == cvt("test 0"), newcom
195
196         newcom = scons_subst("test $one", env)
197         assert newcom == cvt("test 1"), newcom
198
199         newcom = scons_subst("test aXbXcXd", env, re.compile('X'))
200         assert newcom == cvt("test abcd"), newcom
201
202         newcom = scons_subst("test $CMDGEN1 $SOURCES $TARGETS",
203                              env, target='t', source='s')
204         assert newcom == cvt("test foo baz s t"), newcom
205
206         # Test against a former bug in scons_subst_list()
207         glob = { "FOO" : "$BAR",
208                  "BAR" : "BAZ",
209                  "BLAT" : "XYX",
210                  "BARXYX" : "BADNEWS" }
211         newcom = scons_subst("$FOO$BLAT", DummyEnv(glob))
212         assert newcom == "BAZXYX", newcom
213
214         # Test for double-dollar-sign behavior
215         glob = { "FOO" : "BAR",
216                  "BAZ" : "BLAT" }
217         newcom = scons_subst("$$FOO$BAZ", DummyEnv(glob))
218         assert newcom == "$FOOBLAT", newcom
219
220     def test_splitext(self):
221         assert splitext('foo') == ('foo','')
222         assert splitext('foo.bar') == ('foo','.bar')
223         assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
224
225     def test_subst_list(self):
226         """Testing the scons_subst_list() method..."""
227
228         class Node:
229             def __init__(self, name):
230                 self.name = name
231             def __str__(self):
232                 return self.name
233             def is_literal(self):
234                 return 1
235         
236         loc = {}
237         target = [ "./foo/bar.exe",
238                    "/bar/baz with spaces.obj",
239                    "../foo/baz.obj" ]
240         source = [ "./foo/blah with spaces.cpp",
241                    "/bar/ack.cpp",
242                    "../foo/ack.c" ]
243         loc['xxx'] = None
244         loc['NEWLINE'] = 'before\nafter'
245
246         loc['DO'] = Node('do something')
247         loc['FOO'] = Node('foo.in')
248         loc['BAR'] = Node('bar with spaces.out')
249         loc['CRAZY'] = Node('crazy\nfile.in')
250
251         loc['CMDGEN1'] = CmdGen1
252         loc['CMDGEN2'] = CmdGen2
253
254         env = DummyEnv(loc)
255
256         if os.sep == '/':
257             def cvt(str):
258                 return str
259         else:
260             def cvt(str):
261                 return string.replace(str, '/', os.sep)
262
263         cmd_list = scons_subst_list("$TARGETS", env,
264                                     target=target,
265                                     source=source)
266         assert cmd_list[0][1] == cvt("/bar/baz with spaces.obj"), cmd_list[0][1]
267
268         cmd_list = scons_subst_list("$SOURCES $NEWLINE $TARGETS", env,
269                                     target=target,
270                                     source=source)
271         assert len(cmd_list) == 2, cmd_list
272         assert cmd_list[0][0] == cvt('foo/blah with spaces.cpp'), cmd_list[0][0]
273         assert cmd_list[1][2] == cvt("/bar/baz with spaces.obj"), cmd_list[1]
274
275         cmd_list = scons_subst_list("$SOURCES$NEWLINE", env,
276                                     target=target,
277                                     source=source)
278         assert len(cmd_list) == 2, cmd_list
279         assert cmd_list[1][0] == 'after', cmd_list[1][0]
280         assert cmd_list[0][2] == cvt('../foo/ack.cbefore'), cmd_list[0][2]
281
282         cmd_list = scons_subst_list("$DO --in=$FOO --out=$BAR", env)
283         assert len(cmd_list) == 1, cmd_list
284         assert len(cmd_list[0]) == 3, cmd_list
285         assert cmd_list[0][0] == 'do something', cmd_list[0][0]
286         assert cmd_list[0][1] == '--in=foo.in', cmd_list[0][1]
287         assert cmd_list[0][2] == '--out=bar with spaces.out', cmd_list[0][2]
288
289         # This test is now fixed, and works like it should.
290         cmd_list = scons_subst_list("$DO --in=$CRAZY --out=$BAR", env)
291         assert len(cmd_list) == 1, map(str, cmd_list[0])
292         assert len(cmd_list[0]) == 3, cmd_list
293         assert cmd_list[0][0] == 'do something', cmd_list[0][0]
294         assert cmd_list[0][1] == '--in=crazy\nfile.in', cmd_list[0][1]
295         assert cmd_list[0][2] == '--out=bar with spaces.out', cmd_list[0][2]
296         
297         # Test inputting a list to scons_subst_list()
298         cmd_list = scons_subst_list([ "$SOURCES$NEWLINE", "$TARGETS",
299                                         "This is a test" ],
300                                     env,
301                                     target=target,
302                                     source=source)
303         assert len(cmd_list) == 2, len(cmd_list)
304         assert cmd_list[0][0] == cvt('foo/blah with spaces.cpp'), cmd_list[0][0]
305         assert cmd_list[1][0] == cvt("after"), cmd_list[1]
306         assert cmd_list[1][4] == "This is a test", cmd_list[1]
307
308         # Test interpolating a callable.
309         cmd_list = scons_subst_list("testing $CMDGEN1 $TARGETS $SOURCES", env,
310                                     target='t', source='s')
311         assert len(cmd_list) == 1, len(cmd_list)
312         assert cmd_list[0][0] == 'testing', cmd_list[0][0]
313         assert cmd_list[0][1] == 'foo', cmd_list[0][1]
314         assert cmd_list[0][2] == 'bar with spaces.out', cmd_list[0][2]
315         assert cmd_list[0][3] == 't', cmd_list[0][3]
316         assert cmd_list[0][4] == 's', cmd_list[0][4]
317
318
319         # Test against a former bug in scons_subst_list()
320         glob = { "FOO" : "$BAR",
321                  "BAR" : "BAZ",
322                  "BLAT" : "XYX",
323                  "BARXYX" : "BADNEWS" }
324         cmd_list = scons_subst_list("$FOO$BLAT", DummyEnv(glob))
325         assert cmd_list[0][0] == "BAZXYX", cmd_list[0][0]
326
327         # Test for double-dollar-sign behavior
328         glob = { "FOO" : "BAR",
329                  "BAZ" : "BLAT" }
330         cmd_list = scons_subst_list("$$FOO$BAZ", DummyEnv(glob))
331         assert cmd_list[0][0] == "$FOOBLAT", cmd_list[0][0]
332
333         # Now test escape functionality
334         def escape_func(foo):
335             return '**' + foo + '**'
336         def quote_func(foo):
337             return foo
338         glob = { "FOO" : PathList([ 'foo\nwith\nnewlines',
339                                     'bar\nwith\nnewlines' ]) }
340         cmd_list = scons_subst_list("$FOO", DummyEnv(glob))
341         assert cmd_list[0][0] == 'foo\nwith\nnewlines', cmd_list[0][0]
342         cmd_list[0][0].escape(escape_func)
343         assert cmd_list[0][0] == '**foo\nwith\nnewlines**', cmd_list[0][0]
344         assert cmd_list[0][1] == 'bar\nwith\nnewlines', cmd_list[0][0]
345         cmd_list[0][1].escape(escape_func)
346         assert cmd_list[0][1] == '**bar\nwith\nnewlines**', cmd_list[0][0]
347
348     def test_quote_spaces(self):
349         """Testing the quote_spaces() method..."""
350         q = quote_spaces('x')
351         assert q == 'x', q
352
353         q = quote_spaces('x x')
354         assert q == '"x x"', q
355
356         q = quote_spaces('x\tx')
357         assert q == '"x\tx"', q
358
359     def test_render_tree(self):
360         class Node:
361             def __init__(self, name, children=[]):
362                 self.children = children
363                 self.name = name
364             def __str__(self):
365                 return self.name
366
367         def get_children(node):
368             return node.children
369
370         windows_h = Node("windows.h")
371         stdlib_h = Node("stdlib.h")
372         stdio_h = Node("stdio.h")
373         bar_c = Node("bar.c", [stdlib_h, windows_h])
374         bar_o = Node("bar.o", [bar_c])
375         foo_c = Node("foo.c", [stdio_h])
376         foo_o = Node("foo.o", [foo_c])
377         foo = Node("foo", [foo_o, bar_o])
378
379         expect = """\
380 +-foo
381   +-foo.o
382   | +-foo.c
383   |   +-stdio.h
384   +-bar.o
385     +-bar.c
386       +-stdlib.h
387       +-windows.h
388 """
389
390         actual = render_tree(foo, get_children)
391         assert expect == actual, (expect, actual)
392         
393         bar_h = Node('bar.h', [stdlib_h])
394         blat_h = Node('blat.h', [stdlib_h])
395         blat_c = Node('blat.c', [blat_h, bar_h])
396         blat_o = Node('blat.o', [blat_c])
397
398         expect = """\
399 +-blat.o
400   +-blat.c
401     +-blat.h
402     | +-stdlib.h
403     +-bar.h
404 """
405
406         actual = render_tree(blat_o, get_children, 1)
407         assert expect == actual, (expect, actual)        
408
409     def test_is_Dict(self):
410         assert is_Dict({})
411         import UserDict
412         assert is_Dict(UserDict.UserDict())
413         assert not is_Dict([])
414         assert not is_Dict("")
415         if hasattr(types, 'UnicodeType'):
416             exec "assert not is_Dict(u'')"
417
418     def test_is_List(self):
419         assert is_List([])
420         import UserList
421         assert is_List(UserList.UserList())
422         assert not is_List({})
423         assert not is_List("")
424         if hasattr(types, 'UnicodeType'):
425             exec "assert not is_List(u'')"
426
427     def test_Split(self):
428         assert Split("foo bar") == ["foo", "bar"]
429         assert Split(["foo", "bar"]) == ["foo", "bar"]
430         assert Split("foo") == ["foo"]
431
432     def test_is_String(self):
433         assert is_String("")
434         if hasattr(types, 'UnicodeType'):
435             exec "assert is_String(u'')"
436         try:
437             import UserString
438         except:
439             pass
440         else:
441             assert is_String(UserString.UserString(''))
442         assert not is_String({})
443         assert not is_String([])
444
445     def test_to_String(self):
446         """Test the to_String() method."""
447         assert to_String(1) == "1", to_String(1)
448         assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
449         assert to_String("foo") == "foo", to_String("foo")
450
451         try:
452             import UserString
453
454             s1=UserString.UserString('blah')
455             assert to_String(s1) == s1, s1
456             assert to_String(s1) == 'blah', s1
457
458             class Derived(UserString.UserString):
459                 pass
460             s2 = Derived('foo')
461             assert to_String(s2) == s2, s2
462             assert to_String(s2) == 'foo', s2
463
464             if hasattr(types, 'UnicodeType'):
465                 s3=UserString.UserString(unicode('bar'))
466                 assert to_String(s3) == s3, s3
467                 assert to_String(s3) == unicode('bar'), s3
468                 assert type(to_String(s3)) is types.UnicodeType, \
469                        type(to_String(s3))
470         except ImportError:
471             pass
472
473         if hasattr(types, 'UnicodeType'):
474             s4 = unicode('baz')
475             assert to_String(s4) == unicode('baz'), to_String(s4)
476             assert type(to_String(s4)) is types.UnicodeType, \
477                    type(to_String(s4))
478
479     def test_WhereIs(self):
480         test = TestCmd.TestCmd(workdir = '')
481
482         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
483         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
484         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
485         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
486
487         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
488
489         if sys.platform != 'win32':
490             test.write(sub1_xxx_exe, "\n")
491
492         os.mkdir(sub2_xxx_exe)
493
494         test.write(sub3_xxx_exe, "\n")
495         os.chmod(sub3_xxx_exe, 0777)
496
497         test.write(sub4_xxx_exe, "\n")
498         os.chmod(sub4_xxx_exe, 0777)
499
500         env_path = os.environ['PATH']
501
502         pathdirs_1234 = [ test.workpath('sub1'),
503                           test.workpath('sub2'),
504                           test.workpath('sub3'),
505                           test.workpath('sub4'),
506                         ] + string.split(env_path, os.pathsep)
507
508         pathdirs_1243 = [ test.workpath('sub1'),
509                           test.workpath('sub2'),
510                           test.workpath('sub4'),
511                           test.workpath('sub3'),
512                         ] + string.split(env_path, os.pathsep)
513
514         os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
515         wi = WhereIs('xxx.exe')
516         assert wi == test.workpath(sub3_xxx_exe), wi
517         wi = WhereIs('xxx.exe', pathdirs_1243)
518         assert wi == test.workpath(sub4_xxx_exe), wi
519         wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
520         assert wi == test.workpath(sub4_xxx_exe), wi
521
522         os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
523         wi = WhereIs('xxx.exe')
524         assert wi == test.workpath(sub4_xxx_exe), wi
525         wi = WhereIs('xxx.exe', pathdirs_1234)
526         assert wi == test.workpath(sub3_xxx_exe), wi
527         wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
528         assert wi == test.workpath(sub3_xxx_exe), wi
529
530         if sys.platform == 'win32':
531             wi = WhereIs('xxx', pathext = '')
532             assert wi is None, wi
533
534             wi = WhereIs('xxx', pathext = '.exe')
535             assert wi == test.workpath(sub4_xxx_exe), wi
536
537             wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
538             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
539
540             # Test that we return a normalized path even when
541             # the path contains forward slashes.
542             forward_slash = test.workpath('') + '/sub3'
543             wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
544             assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
545
546     def test_get_env_var(self):
547         """Testing get_environment_var()."""
548         assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
549         assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
550         assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
551         assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
552         assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
553         assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
554         assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
555         assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
556         assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
557
558     def test_Proxy(self):
559         """Test generic Proxy class."""
560         class Subject:
561             def foo(self):
562                 return 1
563             def bar(self):
564                 return 2
565
566         s=Subject()
567         s.baz = 3
568
569         class ProxyTest(Proxy):
570             def bar(self):
571                 return 4
572
573         p=ProxyTest(s)
574
575         assert p.foo() == 1, p.foo()
576         assert p.bar() == 4, p.bar()
577         assert p.baz == 3, p.baz
578
579         p.baz = 5
580         s.baz = 6
581
582         assert p.baz == 5, p.baz
583
584     def test_Literal(self):
585         """Test the Literal() function."""
586         cmd_list = [ '$FOO', Literal('$BAR') ]
587         cmd_list = scons_subst_list(cmd_list,
588                                     DummyEnv({ 'FOO' : 'BAZ',
589                                                'BAR' : 'BLAT' }))
590         def escape_func(cmd):
591             return '**' + cmd + '**'
592
593         map(lambda x, e=escape_func: x.escape(e), cmd_list[0])
594         cmd_list = map(str, cmd_list[0])
595         assert cmd_list[0] == 'BAZ', cmd_list[0]
596         assert cmd_list[1] == '**$BAR**', cmd_list[1]
597
598     def test_mapPaths(self):
599         """Test the mapPaths function"""
600         fs = SCons.Node.FS.FS()
601         dir=fs.Dir('foo')
602         file=fs.File('bar/file')
603         
604         class DummyEnv:
605             def subst(self, arg):
606                 return 'bar'
607
608         res = mapPaths([ file, 'baz', 'blat/boo', '#test' ], dir)
609         assert res[0] == file, res[0]
610         assert res[1] == os.path.join('foo', 'baz'), res[1]
611         assert res[2] == os.path.join('foo', 'blat/boo'), res[2]
612         assert res[3] == '#test', res[3]
613
614         env=DummyEnv()
615         res=mapPaths('bleh', dir, env)
616         assert res[0] == os.path.normpath('foo/bar'), res[1]
617
618     def test_display(self):
619         old_stdout = sys.stdout
620         sys.stdout = OutBuffer()
621         SCons.Util.display("line1")
622         display.set_mode(0)
623         SCons.Util.display("line2")
624         display.set_mode(1)
625         SCons.Util.display("line3")
626
627         assert sys.stdout.buffer == "line1\nline3\n"
628         sys.stdout = old_stdout
629
630     def test_fs_delete(self):
631         test = TestCmd.TestCmd(workdir = '')
632         base = test.workpath('')
633         xxx = test.workpath('xxx.xxx')
634         ZZZ = test.workpath('ZZZ.ZZZ')
635         sub1_yyy = test.workpath('sub1', 'yyy.yyy')
636         
637         test.subdir('sub1')
638         test.write(xxx, "\n")
639         test.write(ZZZ, "\n")
640         test.write(sub1_yyy, "\n")
641
642         old_stdout = sys.stdout
643         sys.stdout = OutBuffer()
644
645         exp = "Removed " + os.path.join(base, ZZZ) + "\n" + \
646               "Removed " + os.path.join(base, sub1_yyy) + '\n' + \
647               "Removed directory " + os.path.join(base, 'sub1') + '\n' + \
648               "Removed " + os.path.join(base, xxx) + '\n' + \
649               "Removed directory " + base + '\n'
650
651         SCons.Util.fs_delete(base, remove=0)
652         assert sys.stdout.buffer == exp, sys.stdout.buffer
653         assert os.path.exists(sub1_yyy)
654
655         sys.stdout.buffer = ""
656         SCons.Util.fs_delete(base, remove=1)
657         assert sys.stdout.buffer == exp
658         assert not os.path.exists(base)
659
660         test._dirlist = None
661         sys.stdout = old_stdout
662
663     def test_get_native_path(self):
664         """Test the get_native_path() function."""
665         import tempfile
666         filename = tempfile.mktemp()
667         str = '1234567890 ' + filename
668         open(filename, 'w').write(str)
669         assert open(SCons.Util.get_native_path(filename)).read() == str
670
671     def test_subst_dict(self):
672         """Test substituting dictionary values in an Action
673         """
674         d = subst_dict([], [], DummyEnv({'a' : 'A', 'b' : 'B'}))
675         assert d['a'] == 'A', d
676         assert d['b'] == 'B', d
677
678         d = subst_dict(target = 't', source = 's', env=DummyEnv())
679         assert str(d['TARGETS']) == 't', d['TARGETS']
680         assert str(d['TARGET']) == 't', d['TARGET']
681         assert str(d['SOURCES']) == 's', d['SOURCES']
682         assert str(d['SOURCE']) == 's', d['SOURCE']
683
684         d = subst_dict(target = ['t1', 't2'],
685                        source = ['s1', 's2'],
686                        env = DummyEnv())
687         TARGETS = map(lambda x: str(x), d['TARGETS'])
688         TARGETS.sort()
689         assert TARGETS == ['t1', 't2'], d['TARGETS']
690         assert str(d['TARGET']) == 't1', d['TARGET']
691         SOURCES = map(lambda x: str(x), d['SOURCES'])
692         SOURCES.sort()
693         assert SOURCES == ['s1', 's2'], d['SOURCES']
694         assert str(d['SOURCE']) == 's1', d['SOURCE']
695
696         class N:
697             def __init__(self, name):
698                 self.name = name
699             def __str__(self):
700                 return self.name
701             def rstr(self):
702                 return 'rstr-' + self.name
703
704         d = subst_dict(target = [N('t3'), 't4'],
705                        source = ['s3', N('s4')],
706                        env = DummyEnv())
707         TARGETS = map(lambda x: str(x), d['TARGETS'])
708         TARGETS.sort()
709         assert TARGETS == ['t3', 't4'], d['TARGETS']
710         SOURCES = map(lambda x: str(x), d['SOURCES'])
711         SOURCES.sort()
712         assert SOURCES == ['rstr-s4', 's3'], d['SOURCES']
713
714
715 if __name__ == "__main__":
716     suite = unittest.makeSuite(UtilTestCase, 'test_')
717     if not unittest.TextTestRunner().run(suite).wasSuccessful():
718         sys.exit(1)