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__"
34 from UserDict import UserDict
40 from SCons.Util import *
47 self.buffer = self.buffer + str
49 class UtilTestCase(unittest.TestCase):
50 def test_splitext(self):
51 assert splitext('foo') == ('foo','')
52 assert splitext('foo.bar') == ('foo','.bar')
53 assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
56 def __init__(self, name, children=[]):
57 self.children = children
65 def has_builder(self):
67 def has_explicit_builder(self):
69 def side_effect(self):
73 def always_build(self):
80 def tree_case_1(self):
81 """Fixture for the render_tree() and print_tree() tests."""
82 windows_h = self.Node("windows.h")
83 stdlib_h = self.Node("stdlib.h")
84 stdio_h = self.Node("stdio.h")
85 bar_c = self.Node("bar.c", [stdlib_h, windows_h])
86 bar_o = self.Node("bar.o", [bar_c])
87 foo_c = self.Node("foo.c", [stdio_h])
88 foo_o = self.Node("foo.o", [foo_c])
89 foo = self.Node("foo", [foo_o, bar_o])
102 lines = string.split(expect, '\n')[:-1]
103 lines = map(lambda l: '[E BSPACN]'+l, lines)
104 withtags = string.join(lines, '\n') + '\n'
106 return foo, expect, withtags
108 def tree_case_2(self):
109 """Fixture for the render_tree() and print_tree() tests."""
111 stdlib_h = self.Node("stdlib.h")
112 bar_h = self.Node('bar.h', [stdlib_h])
113 blat_h = self.Node('blat.h', [stdlib_h])
114 blat_c = self.Node('blat.c', [blat_h, bar_h])
115 blat_o = self.Node('blat.o', [blat_c])
125 lines = string.split(expect, '\n')[:-1]
126 lines = map(lambda l: '[E BSPACN]'+l, lines)
127 withtags = string.join(lines, '\n') + '\n'
129 return blat_o, expect, withtags
131 def test_render_tree(self):
132 """Test the render_tree() function"""
133 def get_children(node):
136 node, expect, withtags = self.tree_case_1()
137 actual = render_tree(node, get_children)
138 assert expect == actual, (expect, actual)
140 node, expect, withtags = self.tree_case_2()
141 actual = render_tree(node, get_children, 1)
142 assert expect == actual, (expect, actual)
144 def test_print_tree(self):
145 """Test the print_tree() function"""
146 def get_children(node):
149 save_stdout = sys.stdout
152 node, expect, withtags = self.tree_case_1()
154 sys.stdout = StringIO.StringIO()
155 print_tree(node, get_children)
156 actual = sys.stdout.getvalue()
157 assert expect == actual, (expect, actual)
159 sys.stdout = StringIO.StringIO()
160 print_tree(node, get_children, showtags=1)
161 actual = sys.stdout.getvalue()
162 assert withtags == actual, (withtags, actual)
164 node, expect, withtags = self.tree_case_2()
166 sys.stdout = StringIO.StringIO()
167 print_tree(node, get_children, 1)
168 actual = sys.stdout.getvalue()
169 assert expect == actual, (expect, actual)
171 sys.stdout = StringIO.StringIO()
172 # The following call should work here:
173 # print_tree(node, get_children, 1, showtags=1)
174 # For some reason I don't understand, though, *this*
175 # time that we call print_tree, the visited dictionary
176 # is still populated with the values from the last call!
177 # I can't see why this would be, short of a bug in Python,
178 # and rather than continue banging my head against the
179 # brick wall for a *test*, we're going to going with
180 # the cheap, easy workaround:
181 print_tree(node, get_children, 1, showtags=1, visited={})
182 actual = sys.stdout.getvalue()
183 assert withtags == actual, (withtags, actual)
185 sys.stdout = save_stdout
187 def test_is_Dict(self):
189 assert is_Dict(UserDict())
190 assert not is_Dict([])
191 assert not is_Dict("")
192 if hasattr(types, 'UnicodeType'):
193 exec "assert not is_Dict(u'')"
195 def test_is_List(self):
198 assert is_List(UserList.UserList())
199 assert not is_List({})
200 assert not is_List("")
201 if hasattr(types, 'UnicodeType'):
202 exec "assert not is_List(u'')"
204 def test_is_String(self):
206 if hasattr(types, 'UnicodeType'):
207 exec "assert is_String(u'')"
213 assert is_String(UserString.UserString(''))
214 assert not is_String({})
215 assert not is_String([])
217 def test_to_String(self):
218 """Test the to_String() method."""
219 assert to_String(1) == "1", to_String(1)
220 assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
221 assert to_String("foo") == "foo", to_String("foo")
226 s1=UserString.UserString('blah')
227 assert to_String(s1) == s1, s1
228 assert to_String(s1) == 'blah', s1
230 class Derived(UserString.UserString):
233 assert to_String(s2) == s2, s2
234 assert to_String(s2) == 'foo', s2
236 if hasattr(types, 'UnicodeType'):
237 s3=UserString.UserString(unicode('bar'))
238 assert to_String(s3) == s3, s3
239 assert to_String(s3) == unicode('bar'), s3
240 assert type(to_String(s3)) is types.UnicodeType, \
245 if hasattr(types, 'UnicodeType'):
247 assert to_String(s4) == unicode('baz'), to_String(s4)
248 assert type(to_String(s4)) is types.UnicodeType, \
251 def test_WhereIs(self):
252 test = TestCmd.TestCmd(workdir = '')
254 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
255 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
256 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
257 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
259 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
261 if sys.platform != 'win32':
262 test.write(sub1_xxx_exe, "\n")
264 os.mkdir(sub2_xxx_exe)
266 test.write(sub3_xxx_exe, "\n")
267 os.chmod(sub3_xxx_exe, 0777)
269 test.write(sub4_xxx_exe, "\n")
270 os.chmod(sub4_xxx_exe, 0777)
272 env_path = os.environ['PATH']
275 pathdirs_1234 = [ test.workpath('sub1'),
276 test.workpath('sub2'),
277 test.workpath('sub3'),
278 test.workpath('sub4'),
279 ] + string.split(env_path, os.pathsep)
281 pathdirs_1243 = [ test.workpath('sub1'),
282 test.workpath('sub2'),
283 test.workpath('sub4'),
284 test.workpath('sub3'),
285 ] + string.split(env_path, os.pathsep)
287 os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
288 wi = WhereIs('xxx.exe')
289 assert wi == test.workpath(sub3_xxx_exe), wi
290 wi = WhereIs('xxx.exe', pathdirs_1243)
291 assert wi == test.workpath(sub4_xxx_exe), wi
292 wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
293 assert wi == test.workpath(sub4_xxx_exe), wi
295 wi = WhereIs('xxx.exe',reject = sub3_xxx_exe)
296 assert wi == test.workpath(sub4_xxx_exe), wi
297 wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
298 assert wi == test.workpath(sub4_xxx_exe), wi
300 os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
301 wi = WhereIs('xxx.exe')
302 assert wi == test.workpath(sub4_xxx_exe), wi
303 wi = WhereIs('xxx.exe', pathdirs_1234)
304 assert wi == test.workpath(sub3_xxx_exe), wi
305 wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
306 assert wi == test.workpath(sub3_xxx_exe), wi
308 if sys.platform == 'win32':
309 wi = WhereIs('xxx', pathext = '')
310 assert wi is None, wi
312 wi = WhereIs('xxx', pathext = '.exe')
313 assert wi == test.workpath(sub4_xxx_exe), wi
315 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
316 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
318 # Test that we return a normalized path even when
319 # the path contains forward slashes.
320 forward_slash = test.workpath('') + '/sub3'
321 wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
322 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
324 del os.environ['PATH']
325 wi = WhereIs('xxx.exe')
326 assert wi is None, wi
329 os.environ['PATH'] = env_path
332 def test_is_valid_construction_var(self):
333 """Testing is_valid_construction_var()"""
334 r = is_valid_construction_var("_a")
335 assert not r is None, r
336 r = is_valid_construction_var("z_")
337 assert not r is None, r
338 r = is_valid_construction_var("X_")
339 assert not r is None, r
340 r = is_valid_construction_var("2a")
342 r = is_valid_construction_var("a2_")
343 assert not r is None, r
344 r = is_valid_construction_var("/")
346 r = is_valid_construction_var("_/")
348 r = is_valid_construction_var("a/")
350 r = is_valid_construction_var(".b")
352 r = is_valid_construction_var("_.b")
354 r = is_valid_construction_var("b1._")
356 r = is_valid_construction_var("-b")
358 r = is_valid_construction_var("_-b")
360 r = is_valid_construction_var("b1-_")
363 def test_get_env_var(self):
364 """Testing get_environment_var()."""
365 assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
366 assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
367 assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
368 assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
369 assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
370 assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
371 assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
372 assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
373 assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
375 def test_Proxy(self):
376 """Test generic Proxy class."""
386 class ProxyTest(Proxy):
392 assert p.foo() == 1, p.foo()
393 assert p.bar() == 4, p.bar()
394 assert p.baz == 3, p.baz
399 assert p.baz == 5, p.baz
400 assert p.get() == s, p.get()
402 def test_display(self):
403 old_stdout = sys.stdout
404 sys.stdout = OutBuffer()
410 display("line4\n", append_newline=0)
412 display("dont print1")
413 display("dont print2\n", append_newline=0)
415 assert sys.stdout.buffer == "line1\nline3\nline4\n"
416 sys.stdout = old_stdout
418 def test_get_native_path(self):
419 """Test the get_native_path() function."""
421 filename = tempfile.mktemp()
422 str = '1234567890 ' + filename
424 open(filename, 'w').write(str)
425 assert open(get_native_path(filename)).read() == str
432 def test_PrependPath(self):
433 """Test prepending to a path"""
434 p1 = r'C:\dir\num\one;C:\dir\num\two'
435 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
436 # have to include the pathsep here so that the test will work on UNIX too.
437 p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';')
438 p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
439 p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';')
440 p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';')
441 assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
442 assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
444 def test_AppendPath(self):
445 """Test appending to a path."""
446 p1 = r'C:\dir\num\one;C:\dir\num\two'
447 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
448 # have to include the pathsep here so that the test will work on UNIX too.
449 p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';')
450 p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
451 p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';')
452 p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';')
453 assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
454 assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
456 def test_NodeList(self):
457 """Test NodeList class"""
459 def __init__(self, name, child=None):
463 return self.bar + "foo"
467 t1 = TestClass('t1', TestClass('t1child'))
468 t2 = TestClass('t2', TestClass('t2child'))
471 nl = NodeList([t1, t2, t3])
472 assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo()
473 assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
474 assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar
475 assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \
477 assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
480 def test_CLVar(self):
481 """Test the command-line construction variable class"""
482 f = SCons.Util.CLVar('a b')
485 assert isinstance(r, SCons.Util.CLVar), type(r)
486 assert r.data == ['a', 'b', 'c', 'd'], r.data
487 assert str(r) == 'a b c d', str(r)
490 assert isinstance(r, SCons.Util.CLVar), type(r)
491 assert r.data == ['a', 'b', 'c', 'd'], r.data
492 assert str(r) == 'a b c d', str(r)
495 assert isinstance(r, SCons.Util.CLVar), type(r)
496 assert r.data == ['a', 'b', 'c d'], r.data
497 assert str(r) == 'a b c d', str(r)
500 assert isinstance(r, SCons.Util.CLVar), type(r)
501 assert r.data == ['a', 'b', ' c d'], r.data
502 assert str(r) == 'a b c d', str(r)
505 assert isinstance(r, SCons.Util.CLVar), type(r)
506 assert r.data == ['a', 'b', 'c', 'd'], r.data
507 assert str(r) == 'a b c d', str(r)
510 assert isinstance(r, SCons.Util.CLVar), type(r)
511 assert r.data == ['a', 'b', ' c', 'd'], r.data
512 assert str(r) == 'a b c d', str(r)
514 f = SCons.Util.CLVar(['a b'])
517 assert isinstance(r, SCons.Util.CLVar), type(r)
518 assert r.data == ['a b', 'c', 'd'], r.data
519 assert str(r) == 'a b c d', str(r)
522 assert isinstance(r, SCons.Util.CLVar), type(r)
523 assert r.data == ['a b', 'c', 'd'], r.data
524 assert str(r) == 'a b c d', str(r)
527 assert isinstance(r, SCons.Util.CLVar), type(r)
528 assert r.data == ['a b', 'c d'], r.data
529 assert str(r) == 'a b c d', str(r)
532 assert isinstance(r, SCons.Util.CLVar), type(r)
533 assert r.data == ['a b', ' c d'], r.data
534 assert str(r) == 'a b c d', str(r)
537 assert isinstance(r, SCons.Util.CLVar), type(r)
538 assert r.data == ['a b', 'c', 'd'], r.data
539 assert str(r) == 'a b c d', str(r)
542 assert isinstance(r, SCons.Util.CLVar), type(r)
543 assert r.data == ['a b', ' c', 'd'], r.data
544 assert str(r) == 'a b c d', str(r)
546 f = SCons.Util.CLVar(['a', 'b'])
549 assert isinstance(r, SCons.Util.CLVar), type(r)
550 assert r.data == ['a', 'b', 'c', 'd'], r.data
551 assert str(r) == 'a b c d', str(r)
554 assert isinstance(r, SCons.Util.CLVar), type(r)
555 assert r.data == ['a', 'b', 'c', 'd'], r.data
556 assert str(r) == 'a b c d', str(r)
559 assert isinstance(r, SCons.Util.CLVar), type(r)
560 assert r.data == ['a', 'b', 'c d'], r.data
561 assert str(r) == 'a b c d', str(r)
564 assert isinstance(r, SCons.Util.CLVar), type(r)
565 assert r.data == ['a', 'b', ' c d'], r.data
566 assert str(r) == 'a b c d', str(r)
569 assert isinstance(r, SCons.Util.CLVar), type(r)
570 assert r.data == ['a', 'b', 'c', 'd'], r.data
571 assert str(r) == 'a b c d', str(r)
574 assert isinstance(r, SCons.Util.CLVar), type(r)
575 assert r.data == ['a', 'b', ' c', 'd'], r.data
576 assert str(r) == 'a b c d', str(r)
578 def test_Selector(self):
579 """Test the Selector class"""
581 s = Selector({'a' : 'AAA', 'b' : 'BBB'})
582 assert s['a'] == 'AAA', s['a']
583 assert s['b'] == 'BBB', s['b']
589 assert exc_caught, "should have caught a KeyError"
591 assert s['c'] == 'CCC', s['c']
593 class DummyEnv(UserDict):
594 def subst(self, key):
601 s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
603 assert ret == None, ret
604 ret = s(env, ['foo.d'])
605 assert ret == 'DDD', ret
606 ret = s(env, ['bar.e'])
607 assert ret == 'EEE', ret
608 ret = s(env, ['bar.x'])
609 assert ret == None, ret
611 ret = s(env, ['bar.x'])
612 assert ret == 'XXX', ret
614 env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
616 s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'})
617 ret = s(env, ['foo.f'])
618 assert ret == 'FFF', ret
619 ret = s(env, ['bar.g'])
620 assert ret == 'GGG', ret
622 def test_adjustixes(self):
623 """Test the adjustixes() function"""
624 r = adjustixes('file', 'pre-', '-suf')
625 assert r == 'pre-file-suf', r
626 r = adjustixes('pre-file', 'pre-', '-suf')
627 assert r == 'pre-file-suf', r
628 r = adjustixes('file-suf', 'pre-', '-suf')
629 assert r == 'pre-file-suf', r
630 r = adjustixes('pre-file-suf', 'pre-', '-suf')
631 assert r == 'pre-file-suf', r
632 r = adjustixes('pre-file.xxx', 'pre-', '-suf')
633 assert r == 'pre-file.xxx', r
634 r = adjustixes('dir/file', 'pre-', '-suf')
635 assert r == os.path.join('dir', 'pre-file-suf'), r
637 def test_containsAny(self):
638 """Test the containsAny() function"""
639 assert containsAny('*.py', '*?[]')
640 assert not containsAny('file.txt', '*?[]')
642 def test_containsAll(self):
643 """Test the containsAll() function"""
644 assert containsAll('43221', '123')
645 assert not containsAll('134', '123')
647 def test_containsOnly(self):
648 """Test the containsOnly() function"""
649 assert containsOnly('.83', '0123456789.')
650 assert not containsOnly('43221', '123')
652 def test_LogicalLines(self):
653 """Test the LogicalLines class"""
654 fobj = StringIO.StringIO(r"""
664 lines = LogicalLines(fobj).readlines()
669 'bling bling \\ bling\n',
673 if __name__ == "__main__":
674 suite = unittest.makeSuite(UtilTestCase, 'test_')
675 if not unittest.TextTestRunner().run(suite).wasSuccessful():