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 def test_is_Dict(self):
313 assert is_Dict(UserDict.UserDict())
314 assert not is_Dict([])
315 assert not is_Dict("")
316 if hasattr(types, 'UnicodeType'):
317 exec "assert not is_Dict(u'')"
319 def test_is_List(self):
322 assert is_List(UserList.UserList())
323 assert not is_List({})
324 assert not is_List("")
325 if hasattr(types, 'UnicodeType'):
326 exec "assert not is_List(u'')"
328 def test_Split(self):
329 assert Split("foo bar") == ["foo", "bar"]
330 assert Split(["foo", "bar"]) == ["foo", "bar"]
331 assert Split("foo") == ["foo"]
333 def test_is_String(self):
335 if hasattr(types, 'UnicodeType'):
336 exec "assert is_String(u'')"
342 assert is_String(UserString.UserString(''))
343 assert not is_String({})
344 assert not is_String([])
346 def test_to_String(self):
347 """Test the to_String() method."""
348 assert to_String(1) == "1", to_String(1)
349 assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
350 assert to_String("foo") == "foo", to_String("foo")
355 s1=UserString.UserString('blah')
356 assert to_String(s1) == s1, s1
357 assert to_String(s1) == 'blah', s1
359 class Derived(UserString.UserString):
362 assert to_String(s2) == s2, s2
363 assert to_String(s2) == 'foo', s2
365 if hasattr(types, 'UnicodeType'):
366 s3=UserString.UserString(unicode('bar'))
367 assert to_String(s3) == s3, s3
368 assert to_String(s3) == unicode('bar'), s3
369 assert type(to_String(s3)) is types.UnicodeType, \
374 if hasattr(types, 'UnicodeType'):
376 assert to_String(s4) == unicode('baz'), to_String(s4)
377 assert type(to_String(s4)) is types.UnicodeType, \
380 def test_WhereIs(self):
381 test = TestCmd.TestCmd(workdir = '')
383 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
384 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
385 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
386 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
388 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
390 if sys.platform != 'win32':
391 test.write(sub1_xxx_exe, "\n")
393 os.mkdir(sub2_xxx_exe)
395 test.write(sub3_xxx_exe, "\n")
396 os.chmod(sub3_xxx_exe, 0777)
398 test.write(sub4_xxx_exe, "\n")
399 os.chmod(sub4_xxx_exe, 0777)
401 env_path = os.environ['PATH']
403 pathdirs_1234 = [ test.workpath('sub1'),
404 test.workpath('sub2'),
405 test.workpath('sub3'),
406 test.workpath('sub4'),
407 ] + string.split(env_path, os.pathsep)
409 pathdirs_1243 = [ test.workpath('sub1'),
410 test.workpath('sub2'),
411 test.workpath('sub4'),
412 test.workpath('sub3'),
413 ] + string.split(env_path, os.pathsep)
415 os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
416 wi = WhereIs('xxx.exe')
417 assert wi == test.workpath(sub3_xxx_exe), wi
418 wi = WhereIs('xxx.exe', pathdirs_1243)
419 assert wi == test.workpath(sub4_xxx_exe), wi
420 wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
421 assert wi == test.workpath(sub4_xxx_exe), wi
423 os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
424 wi = WhereIs('xxx.exe')
425 assert wi == test.workpath(sub4_xxx_exe), wi
426 wi = WhereIs('xxx.exe', pathdirs_1234)
427 assert wi == test.workpath(sub3_xxx_exe), wi
428 wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
429 assert wi == test.workpath(sub3_xxx_exe), wi
431 if sys.platform == 'win32':
432 wi = WhereIs('xxx', pathext = '')
433 assert wi is None, wi
435 wi = WhereIs('xxx', pathext = '.exe')
436 assert wi == test.workpath(sub4_xxx_exe), wi
438 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
439 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
441 def test_get_env_var(self):
442 """Testing get_environment_var()."""
443 assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
444 assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
445 assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
446 assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
447 assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
449 def test_Proxy(self):
450 """Test generic Proxy class."""
460 class ProxyTest(Proxy):
466 assert p.foo() == 1, p.foo()
467 assert p.bar() == 4, p.bar()
468 assert p.baz == 3, p.baz
473 assert p.baz == 5, p.baz
475 def test_Literal(self):
476 """Test the Literal() function."""
477 cmd_list = [ '$FOO', Literal('$BAR') ]
478 cmd_list = scons_subst_list(cmd_list,
480 'BAR' : 'BLAT' }, {})
481 def escape_func(cmd):
482 return '**' + cmd + '**'
484 map(lambda x, e=escape_func: x.escape(e), cmd_list[0])
485 cmd_list = map(str, cmd_list[0])
486 assert cmd_list[0] == 'BAZ', cmd_list[0]
487 assert cmd_list[1] == '**$BAR**', cmd_list[1]
489 def test_mapPaths(self):
490 """Test the mapPaths function"""
491 fs = SCons.Node.FS.FS()
493 file=fs.File('bar/file')
496 def subst(self, arg):
499 res = mapPaths([ file, 'baz', 'blat/boo', '#test' ], dir)
500 assert res[0] == file, res[0]
501 assert res[1] == os.path.join('foo', 'baz'), res[1]
502 assert res[2] == os.path.join('foo', 'blat/boo'), res[2]
503 assert res[3] == '#test', res[3]
506 res=mapPaths('bleh', dir, env)
507 assert res[0] == os.path.normpath('foo/bar'), res[1]
509 def test_display(self):
510 old_stdout = sys.stdout
511 sys.stdout = OutBuffer()
512 SCons.Util.display("line1")
514 SCons.Util.display("line2")
516 SCons.Util.display("line3")
518 assert sys.stdout.buffer == "line1\nline3\n"
519 sys.stdout = old_stdout
521 def test_fs_delete(self):
522 test = TestCmd.TestCmd(workdir = '')
523 base = test.workpath('')
524 xxx = test.workpath('xxx.xxx')
525 sub1_yyy = test.workpath('sub1', 'yyy.yyy')
527 test.write(xxx, "\n")
528 test.write(sub1_yyy, "\n")
530 old_stdout = sys.stdout
531 sys.stdout = OutBuffer()
533 exp = "Removed " + os.path.join(base, sub1_yyy) + '\n' + \
534 "Removed directory " + os.path.join(base, 'sub1') + '\n' + \
535 "Removed " + os.path.join(base, xxx) + '\n' + \
536 "Removed directory " + base + '\n'
538 SCons.Util.fs_delete(base, remove=0)
539 assert sys.stdout.buffer == exp
540 assert os.path.exists(sub1_yyy)
542 sys.stdout.buffer = ""
543 SCons.Util.fs_delete(base, remove=1)
544 assert sys.stdout.buffer == exp
545 assert not os.path.exists(base)
548 sys.stdout = old_stdout
551 if __name__ == "__main__":
552 suite = unittest.makeSuite(UtilTestCase, 'test_')
553 if not unittest.TextTestRunner().run(suite).wasSuccessful():