2 # Copyright (c) 2001, 2002 Steven Knight
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
35 from SCons.Util import *
44 self.buffer = self.buffer + str
47 class UtilTestCase(unittest.TestCase):
49 """Test the subst function."""
51 loc['TARGETS'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
54 loc['TARGET'] = loc['TARGETS'][0]
55 loc['SOURCES'] = PathList(map(os.path.normpath, [ "./foo/blah.cpp",
58 loc['SOURCE'] = loc['SOURCES'][0]
68 return string.replace(str, '/', os.sep)
70 newcom = scons_subst("test $TARGETS $SOURCES", loc, {})
71 assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp /bar/ack.cpp ../foo/ack.c")
73 newcom = scons_subst("test ${TARGETS[:]} ${SOURCES[0]}", loc, {})
74 assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp")
76 newcom = scons_subst("test ${TARGETS[1:]}v", loc, {})
77 assert newcom == cvt("test /bar/baz.obj ../foo/baz.objv")
79 newcom = scons_subst("test $TARGET", loc, {})
80 assert newcom == cvt("test foo/bar.exe")
82 newcom = scons_subst("test $TARGET$FOO[0]", loc, {})
83 assert newcom == cvt("test foo/bar.exe[0]")
85 newcom = scons_subst("test ${TARGET.file}", loc, {})
86 assert newcom == cvt("test bar.exe")
88 newcom = scons_subst("test ${TARGET.filebase}", loc, {})
89 assert newcom == cvt("test bar")
91 newcom = scons_subst("test ${TARGET.suffix}", loc, {})
92 assert newcom == cvt("test .exe")
94 newcom = scons_subst("test ${TARGET.base}", loc, {})
95 assert newcom == cvt("test foo/bar")
97 newcom = scons_subst("test ${TARGET.dir}", loc, {})
98 assert newcom == cvt("test foo")
100 newcom = scons_subst("test ${TARGET.abspath}", loc, {})
101 assert newcom == cvt("test %s/foo/bar.exe"%SCons.Util.updrive(os.getcwd())), newcom
103 newcom = scons_subst("test ${SOURCES.abspath}", loc, {})
104 assert newcom == cvt("test %s/foo/blah.cpp %s %s/foo/ack.c"%(SCons.Util.updrive(os.getcwd()),
105 SCons.Util.updrive(os.path.abspath(os.path.normpath("/bar/ack.cpp"))),
106 SCons.Util.updrive(os.path.normpath(os.getcwd()+"/..")))), newcom
108 newcom = scons_subst("test ${SOURCE.abspath}", loc, {})
109 assert newcom == cvt("test %s/foo/blah.cpp"%SCons.Util.updrive(os.getcwd())), newcom
111 newcom = scons_subst("test $xxx", loc, {})
112 assert newcom == cvt("test"), newcom
114 newcom = scons_subst("test $($xxx$)", loc, {})
115 assert newcom == cvt("test $($)"), newcom
117 newcom = scons_subst("test $( $xxx $)", loc, {})
118 assert newcom == cvt("test $( $)"), newcom
120 newcom = scons_subst("test $($xxx$)", loc, {}, re.compile('\$[()]'))
121 assert newcom == cvt("test"), newcom
123 newcom = scons_subst("test $( $xxx $)", loc, {}, re.compile('\$[()]'))
124 assert newcom == cvt("test"), newcom
126 newcom = scons_subst("test $zero", loc, {})
127 assert newcom == cvt("test 0"), newcom
129 newcom = scons_subst("test $one", loc, {})
130 assert newcom == cvt("test 1"), newcom
132 newcom = scons_subst("test aXbXcXd", loc, {}, re.compile('X'))
133 assert newcom == cvt("test abcd"), newcom
135 glob = { 'a' : 1, 'b' : 2 }
136 loc = {'a' : 3, 'c' : 4 }
137 newcom = scons_subst("test $a $b $c $d test", glob, loc)
138 assert newcom == "test 3 2 4 test", newcom
140 # Test against a former bug in scons_subst_list()
141 glob = { "FOO" : "$BAR",
144 "BARXYX" : "BADNEWS" }
145 newcom = scons_subst("$FOO$BLAT", glob, {})
146 assert newcom == "BAZXYX", newcom
148 # Test for double-dollar-sign behavior
149 glob = { "FOO" : "BAR",
151 newcom = scons_subst("$$FOO$BAZ", glob, {})
152 assert newcom == "$FOOBLAT", newcom
154 def test_splitext(self):
155 assert splitext('foo') == ('foo','')
156 assert splitext('foo.bar') == ('foo','.bar')
157 assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
159 def test_subst_list(self):
160 """Testing the scons_subst_list() method..."""
163 def __init__(self, name):
167 def is_literal(self):
171 loc['TARGETS'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
172 "/bar/baz with spaces.obj",
174 loc['TARGET'] = loc['TARGETS'][0]
175 loc['SOURCES'] = PathList(map(os.path.normpath, [ "./foo/blah with spaces.cpp",
179 loc['NEWLINE'] = 'before\nafter'
181 loc['DO'] = Node('do something')
182 loc['FOO'] = Node('foo.in')
183 loc['BAR'] = Node('bar with spaces.out')
184 loc['CRAZY'] = Node('crazy\nfile.in')
191 return string.replace(str, '/', os.sep)
193 cmd_list = scons_subst_list("$TARGETS", loc, {})
194 assert cmd_list[0][1] == cvt("/bar/baz with spaces.obj"), cmd_list[0][1]
196 cmd_list = scons_subst_list("$SOURCES $NEWLINE $TARGETS", loc, {})
197 assert len(cmd_list) == 2, cmd_list
198 assert cmd_list[0][0] == cvt('foo/blah with spaces.cpp'), cmd_list[0][0]
199 assert cmd_list[1][2] == cvt("/bar/baz with spaces.obj"), cmd_list[1]
201 cmd_list = scons_subst_list("$SOURCES$NEWLINE", loc, {})
202 assert len(cmd_list) == 2, cmd_list
203 assert cmd_list[1][0] == 'after', cmd_list[1][0]
204 assert cmd_list[0][2] == cvt('../foo/ack.cbefore'), cmd_list[0][2]
206 cmd_list = scons_subst_list("$DO --in=$FOO --out=$BAR", loc, {})
207 assert len(cmd_list) == 1, cmd_list
208 assert len(cmd_list[0]) == 3, cmd_list
209 assert cmd_list[0][0] == 'do something', cmd_list[0][0]
210 assert cmd_list[0][1] == '--in=foo.in', cmd_list[0][1]
211 assert cmd_list[0][2] == '--out=bar with spaces.out', cmd_list[0][2]
213 # This test is now fixed, and works like it should.
214 cmd_list = scons_subst_list("$DO --in=$CRAZY --out=$BAR", loc, {})
215 assert len(cmd_list) == 1, map(str, cmd_list[0])
216 assert len(cmd_list[0]) == 3, cmd_list
217 assert cmd_list[0][0] == 'do something', cmd_list[0][0]
218 assert cmd_list[0][1] == '--in=crazy\nfile.in', cmd_list[0][1]
219 assert cmd_list[0][2] == '--out=bar with spaces.out', cmd_list[0][2]
221 # Test inputting a list to scons_subst_list()
222 cmd_list = scons_subst_list([ "$SOURCES$NEWLINE", "$TARGETS",
225 assert len(cmd_list) == 2, len(cmd_list)
226 assert cmd_list[0][0] == cvt('foo/blah with spaces.cpp'), cmd_list[0][0]
227 assert cmd_list[1][0] == cvt("after"), cmd_list[1]
228 assert cmd_list[1][4] == "This is a test", cmd_list[1]
230 glob = { 'a' : 1, 'b' : 2 }
231 loc = {'a' : 3, 'c' : 4 }
232 cmd_list = scons_subst_list("test $a $b $c $d test", glob, loc)
233 assert len(cmd_list) == 1, cmd_list
234 assert map(str, cmd_list[0]) == ['test', '3', '2', '4', 'test'], map(str, cmd_list[0])
236 # Test against a former bug in scons_subst_list()
237 glob = { "FOO" : "$BAR",
240 "BARXYX" : "BADNEWS" }
241 cmd_list = scons_subst_list("$FOO$BLAT", glob, {})
242 assert cmd_list[0][0] == "BAZXYX", cmd_list[0][0]
244 # Test for double-dollar-sign behavior
245 glob = { "FOO" : "BAR",
247 cmd_list = scons_subst_list("$$FOO$BAZ", glob, {})
248 assert cmd_list[0][0] == "$FOOBLAT", cmd_list[0][0]
250 # Now test escape functionality
251 def escape_func(foo):
252 return '**' + foo + '**'
255 glob = { "FOO" : PathList([ 'foo\nwith\nnewlines',
256 'bar\nwith\nnewlines' ]) }
257 cmd_list = scons_subst_list("$FOO", glob, {})
258 assert cmd_list[0][0] == 'foo\nwith\nnewlines', cmd_list[0][0]
259 cmd_list[0][0].escape(escape_func)
260 assert cmd_list[0][0] == '**foo\nwith\nnewlines**', cmd_list[0][0]
261 assert cmd_list[0][1] == 'bar\nwith\nnewlines', cmd_list[0][0]
262 cmd_list[0][1].escape(escape_func)
263 assert cmd_list[0][1] == '**bar\nwith\nnewlines**', cmd_list[0][0]
265 def test_quote_spaces(self):
266 """Testing the quote_spaces() method..."""
267 q = quote_spaces('x')
270 q = quote_spaces('x x')
271 assert q == '"x x"', q
273 q = quote_spaces('x\tx')
274 assert q == '"x\tx"', q
276 def test_render_tree(self):
278 def __init__(self, name, children=[]):
279 self.children = children
284 def get_children(node):
287 windows_h = Node("windows.h")
288 stdlib_h = Node("stdlib.h")
289 stdio_h = Node("stdio.h")
290 bar_c = Node("bar.c", [stdlib_h, windows_h])
291 bar_o = Node("bar.o", [bar_c])
292 foo_c = Node("foo.c", [stdio_h])
293 foo_o = Node("foo.o", [foo_c])
294 foo = Node("foo", [foo_o, bar_o])
307 actual = render_tree(foo, get_children)
308 assert expect == actual, (expect, actual)
310 bar_h = Node('bar.h', [stdlib_h])
311 blat_h = Node('blat.h', [stdlib_h])
312 blat_c = Node('blat.c', [blat_h, bar_h])
313 blat_o = Node('blat.o', [blat_c])
323 actual = render_tree(blat_o, get_children, 1)
324 assert expect == actual, (expect, actual)
326 def test_is_Dict(self):
329 assert is_Dict(UserDict.UserDict())
330 assert not is_Dict([])
331 assert not is_Dict("")
332 if hasattr(types, 'UnicodeType'):
333 exec "assert not is_Dict(u'')"
335 def test_is_List(self):
338 assert is_List(UserList.UserList())
339 assert not is_List({})
340 assert not is_List("")
341 if hasattr(types, 'UnicodeType'):
342 exec "assert not is_List(u'')"
344 def test_Split(self):
345 assert Split("foo bar") == ["foo", "bar"]
346 assert Split(["foo", "bar"]) == ["foo", "bar"]
347 assert Split("foo") == ["foo"]
349 def test_is_String(self):
351 if hasattr(types, 'UnicodeType'):
352 exec "assert is_String(u'')"
358 assert is_String(UserString.UserString(''))
359 assert not is_String({})
360 assert not is_String([])
362 def test_to_String(self):
363 """Test the to_String() method."""
364 assert to_String(1) == "1", to_String(1)
365 assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
366 assert to_String("foo") == "foo", to_String("foo")
371 s1=UserString.UserString('blah')
372 assert to_String(s1) == s1, s1
373 assert to_String(s1) == 'blah', s1
375 class Derived(UserString.UserString):
378 assert to_String(s2) == s2, s2
379 assert to_String(s2) == 'foo', s2
381 if hasattr(types, 'UnicodeType'):
382 s3=UserString.UserString(unicode('bar'))
383 assert to_String(s3) == s3, s3
384 assert to_String(s3) == unicode('bar'), s3
385 assert type(to_String(s3)) is types.UnicodeType, \
390 if hasattr(types, 'UnicodeType'):
392 assert to_String(s4) == unicode('baz'), to_String(s4)
393 assert type(to_String(s4)) is types.UnicodeType, \
396 def test_WhereIs(self):
397 test = TestCmd.TestCmd(workdir = '')
399 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
400 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
401 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
402 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
404 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
406 if sys.platform != 'win32':
407 test.write(sub1_xxx_exe, "\n")
409 os.mkdir(sub2_xxx_exe)
411 test.write(sub3_xxx_exe, "\n")
412 os.chmod(sub3_xxx_exe, 0777)
414 test.write(sub4_xxx_exe, "\n")
415 os.chmod(sub4_xxx_exe, 0777)
417 env_path = os.environ['PATH']
419 pathdirs_1234 = [ test.workpath('sub1'),
420 test.workpath('sub2'),
421 test.workpath('sub3'),
422 test.workpath('sub4'),
423 ] + string.split(env_path, os.pathsep)
425 pathdirs_1243 = [ test.workpath('sub1'),
426 test.workpath('sub2'),
427 test.workpath('sub4'),
428 test.workpath('sub3'),
429 ] + string.split(env_path, os.pathsep)
431 os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
432 wi = WhereIs('xxx.exe')
433 assert wi == test.workpath(sub3_xxx_exe), wi
434 wi = WhereIs('xxx.exe', pathdirs_1243)
435 assert wi == test.workpath(sub4_xxx_exe), wi
436 wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
437 assert wi == test.workpath(sub4_xxx_exe), wi
439 os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
440 wi = WhereIs('xxx.exe')
441 assert wi == test.workpath(sub4_xxx_exe), wi
442 wi = WhereIs('xxx.exe', pathdirs_1234)
443 assert wi == test.workpath(sub3_xxx_exe), wi
444 wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
445 assert wi == test.workpath(sub3_xxx_exe), wi
447 if sys.platform == 'win32':
448 wi = WhereIs('xxx', pathext = '')
449 assert wi is None, wi
451 wi = WhereIs('xxx', pathext = '.exe')
452 assert wi == test.workpath(sub4_xxx_exe), wi
454 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
455 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
457 def test_get_env_var(self):
458 """Testing get_environment_var()."""
459 assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
460 assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
461 assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
462 assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
463 assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
465 def test_Proxy(self):
466 """Test generic Proxy class."""
476 class ProxyTest(Proxy):
482 assert p.foo() == 1, p.foo()
483 assert p.bar() == 4, p.bar()
484 assert p.baz == 3, p.baz
489 assert p.baz == 5, p.baz
491 def test_Literal(self):
492 """Test the Literal() function."""
493 cmd_list = [ '$FOO', Literal('$BAR') ]
494 cmd_list = scons_subst_list(cmd_list,
496 'BAR' : 'BLAT' }, {})
497 def escape_func(cmd):
498 return '**' + cmd + '**'
500 map(lambda x, e=escape_func: x.escape(e), cmd_list[0])
501 cmd_list = map(str, cmd_list[0])
502 assert cmd_list[0] == 'BAZ', cmd_list[0]
503 assert cmd_list[1] == '**$BAR**', cmd_list[1]
505 def test_mapPaths(self):
506 """Test the mapPaths function"""
507 fs = SCons.Node.FS.FS()
509 file=fs.File('bar/file')
512 def subst(self, arg):
515 res = mapPaths([ file, 'baz', 'blat/boo', '#test' ], dir)
516 assert res[0] == file, res[0]
517 assert res[1] == os.path.join('foo', 'baz'), res[1]
518 assert res[2] == os.path.join('foo', 'blat/boo'), res[2]
519 assert res[3] == '#test', res[3]
522 res=mapPaths('bleh', dir, env)
523 assert res[0] == os.path.normpath('foo/bar'), res[1]
525 def test_display(self):
526 old_stdout = sys.stdout
527 sys.stdout = OutBuffer()
528 SCons.Util.display("line1")
530 SCons.Util.display("line2")
532 SCons.Util.display("line3")
534 assert sys.stdout.buffer == "line1\nline3\n"
535 sys.stdout = old_stdout
537 def test_fs_delete(self):
538 test = TestCmd.TestCmd(workdir = '')
539 base = test.workpath('')
540 xxx = test.workpath('xxx.xxx')
541 sub1_yyy = test.workpath('sub1', 'yyy.yyy')
543 test.write(xxx, "\n")
544 test.write(sub1_yyy, "\n")
546 old_stdout = sys.stdout
547 sys.stdout = OutBuffer()
549 exp = "Removed " + os.path.join(base, sub1_yyy) + '\n' + \
550 "Removed directory " + os.path.join(base, 'sub1') + '\n' + \
551 "Removed " + os.path.join(base, xxx) + '\n' + \
552 "Removed directory " + base + '\n'
554 SCons.Util.fs_delete(base, remove=0)
555 assert sys.stdout.buffer == exp
556 assert os.path.exists(sub1_yyy)
558 sys.stdout.buffer = ""
559 SCons.Util.fs_delete(base, remove=1)
560 assert sys.stdout.buffer == exp
561 assert not os.path.exists(base)
564 sys.stdout = old_stdout
567 if __name__ == "__main__":
568 suite = unittest.makeSuite(UtilTestCase, 'test_')
569 if not unittest.TextTestRunner().run(suite).wasSuccessful():