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):
78 def tree_case_1(self):
79 """Fixture for the render_tree() and print_tree() tests."""
80 windows_h = self.Node("windows.h")
81 stdlib_h = self.Node("stdlib.h")
82 stdio_h = self.Node("stdio.h")
83 bar_c = self.Node("bar.c", [stdlib_h, windows_h])
84 bar_o = self.Node("bar.o", [bar_c])
85 foo_c = self.Node("foo.c", [stdio_h])
86 foo_o = self.Node("foo.o", [foo_c])
87 foo = self.Node("foo", [foo_o, bar_o])
100 lines = string.split(expect, '\n')[:-1]
101 lines = map(lambda l: '[E BSPAC]'+l, lines)
102 withtags = string.join(lines, '\n') + '\n'
104 return foo, expect, withtags
106 def tree_case_2(self):
107 """Fixture for the render_tree() and print_tree() tests."""
109 stdlib_h = self.Node("stdlib.h")
110 bar_h = self.Node('bar.h', [stdlib_h])
111 blat_h = self.Node('blat.h', [stdlib_h])
112 blat_c = self.Node('blat.c', [blat_h, bar_h])
113 blat_o = self.Node('blat.o', [blat_c])
123 lines = string.split(expect, '\n')[:-1]
124 lines = map(lambda l: '[E BSPAC]'+l, lines)
125 withtags = string.join(lines, '\n') + '\n'
127 return blat_o, expect, withtags
129 def test_render_tree(self):
130 """Test the render_tree() function"""
131 def get_children(node):
134 node, expect, withtags = self.tree_case_1()
135 actual = render_tree(node, get_children)
136 assert expect == actual, (expect, actual)
138 node, expect, withtags = self.tree_case_2()
139 actual = render_tree(node, get_children, 1)
140 assert expect == actual, (expect, actual)
142 def test_print_tree(self):
143 """Test the print_tree() function"""
144 def get_children(node):
147 save_stdout = sys.stdout
150 node, expect, withtags = self.tree_case_1()
152 sys.stdout = StringIO.StringIO()
153 print_tree(node, get_children)
154 actual = sys.stdout.getvalue()
155 assert expect == actual, (expect, actual)
157 sys.stdout = StringIO.StringIO()
158 print_tree(node, get_children, showtags=1)
159 actual = sys.stdout.getvalue()
160 assert withtags == actual, (withtags, actual)
162 node, expect, withtags = self.tree_case_2()
164 sys.stdout = StringIO.StringIO()
165 print_tree(node, get_children, 1)
166 actual = sys.stdout.getvalue()
167 assert expect == actual, (expect, actual)
169 sys.stdout = StringIO.StringIO()
170 # The following call should work here:
171 # print_tree(node, get_children, 1, showtags=1)
172 # For some reason I don't understand, though, *this*
173 # time that we call print_tree, the visited dictionary
174 # is still populated with the values from the last call!
175 # I can't see why this would be, short of a bug in Python,
176 # and rather than continue banging my head against the
177 # brick wall for a *test*, we're going to going with
178 # the cheap, easy workaround:
179 print_tree(node, get_children, 1, showtags=1, visited={})
180 actual = sys.stdout.getvalue()
181 assert withtags == actual, (withtags, actual)
183 sys.stdout = save_stdout
185 def test_is_Dict(self):
187 assert is_Dict(UserDict())
188 assert not is_Dict([])
189 assert not is_Dict("")
190 if hasattr(types, 'UnicodeType'):
191 exec "assert not is_Dict(u'')"
193 def test_is_List(self):
196 assert is_List(UserList.UserList())
197 assert not is_List({})
198 assert not is_List("")
199 if hasattr(types, 'UnicodeType'):
200 exec "assert not is_List(u'')"
202 def test_is_String(self):
204 if hasattr(types, 'UnicodeType'):
205 exec "assert is_String(u'')"
211 assert is_String(UserString.UserString(''))
212 assert not is_String({})
213 assert not is_String([])
215 def test_to_String(self):
216 """Test the to_String() method."""
217 assert to_String(1) == "1", to_String(1)
218 assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
219 assert to_String("foo") == "foo", to_String("foo")
224 s1=UserString.UserString('blah')
225 assert to_String(s1) == s1, s1
226 assert to_String(s1) == 'blah', s1
228 class Derived(UserString.UserString):
231 assert to_String(s2) == s2, s2
232 assert to_String(s2) == 'foo', s2
234 if hasattr(types, 'UnicodeType'):
235 s3=UserString.UserString(unicode('bar'))
236 assert to_String(s3) == s3, s3
237 assert to_String(s3) == unicode('bar'), s3
238 assert type(to_String(s3)) is types.UnicodeType, \
243 if hasattr(types, 'UnicodeType'):
245 assert to_String(s4) == unicode('baz'), to_String(s4)
246 assert type(to_String(s4)) is types.UnicodeType, \
249 def test_WhereIs(self):
250 test = TestCmd.TestCmd(workdir = '')
252 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
253 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
254 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
255 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
257 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
259 if sys.platform != 'win32':
260 test.write(sub1_xxx_exe, "\n")
262 os.mkdir(sub2_xxx_exe)
264 test.write(sub3_xxx_exe, "\n")
265 os.chmod(sub3_xxx_exe, 0777)
267 test.write(sub4_xxx_exe, "\n")
268 os.chmod(sub4_xxx_exe, 0777)
270 env_path = os.environ['PATH']
273 pathdirs_1234 = [ test.workpath('sub1'),
274 test.workpath('sub2'),
275 test.workpath('sub3'),
276 test.workpath('sub4'),
277 ] + string.split(env_path, os.pathsep)
279 pathdirs_1243 = [ test.workpath('sub1'),
280 test.workpath('sub2'),
281 test.workpath('sub4'),
282 test.workpath('sub3'),
283 ] + string.split(env_path, os.pathsep)
285 os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
286 wi = WhereIs('xxx.exe')
287 assert wi == test.workpath(sub3_xxx_exe), wi
288 wi = WhereIs('xxx.exe', pathdirs_1243)
289 assert wi == test.workpath(sub4_xxx_exe), wi
290 wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
291 assert wi == test.workpath(sub4_xxx_exe), wi
293 wi = WhereIs('xxx.exe',reject = sub3_xxx_exe)
294 assert wi == test.workpath(sub4_xxx_exe), wi
295 wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
296 assert wi == test.workpath(sub4_xxx_exe), wi
298 os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
299 wi = WhereIs('xxx.exe')
300 assert wi == test.workpath(sub4_xxx_exe), wi
301 wi = WhereIs('xxx.exe', pathdirs_1234)
302 assert wi == test.workpath(sub3_xxx_exe), wi
303 wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
304 assert wi == test.workpath(sub3_xxx_exe), wi
306 if sys.platform == 'win32':
307 wi = WhereIs('xxx', pathext = '')
308 assert wi is None, wi
310 wi = WhereIs('xxx', pathext = '.exe')
311 assert wi == test.workpath(sub4_xxx_exe), wi
313 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
314 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
316 # Test that we return a normalized path even when
317 # the path contains forward slashes.
318 forward_slash = test.workpath('') + '/sub3'
319 wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
320 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
322 del os.environ['PATH']
323 wi = WhereIs('xxx.exe')
324 assert wi is None, wi
327 os.environ['PATH'] = env_path
330 def test_is_valid_construction_var(self):
331 """Testing is_valid_construction_var()"""
332 r = is_valid_construction_var("_a")
333 assert not r is None, r
334 r = is_valid_construction_var("z_")
335 assert not r is None, r
336 r = is_valid_construction_var("X_")
337 assert not r is None, r
338 r = is_valid_construction_var("2a")
340 r = is_valid_construction_var("a2_")
341 assert not r is None, r
342 r = is_valid_construction_var("/")
344 r = is_valid_construction_var("_/")
346 r = is_valid_construction_var("a/")
348 r = is_valid_construction_var(".b")
350 r = is_valid_construction_var("_.b")
352 r = is_valid_construction_var("b1._")
354 r = is_valid_construction_var("-b")
356 r = is_valid_construction_var("_-b")
358 r = is_valid_construction_var("b1-_")
361 def test_get_env_var(self):
362 """Testing get_environment_var()."""
363 assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
364 assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
365 assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
366 assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
367 assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
368 assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
369 assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
370 assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
371 assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
373 def test_Proxy(self):
374 """Test generic Proxy class."""
384 class ProxyTest(Proxy):
390 assert p.foo() == 1, p.foo()
391 assert p.bar() == 4, p.bar()
392 assert p.baz == 3, p.baz
397 assert p.baz == 5, p.baz
398 assert p.get() == s, p.get()
400 def test_display(self):
401 old_stdout = sys.stdout
402 sys.stdout = OutBuffer()
408 display("line4\n", append_newline=0)
410 display("dont print1")
411 display("dont print2\n", append_newline=0)
413 assert sys.stdout.buffer == "line1\nline3\nline4\n"
414 sys.stdout = old_stdout
416 def test_get_native_path(self):
417 """Test the get_native_path() function."""
419 filename = tempfile.mktemp()
420 str = '1234567890 ' + filename
422 open(filename, 'w').write(str)
423 assert open(get_native_path(filename)).read() == str
430 def test_PrependPath(self):
431 """Test prepending to a path"""
432 p1 = r'C:\dir\num\one;C:\dir\num\two'
433 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
434 # have to include the pathsep here so that the test will work on UNIX too.
435 p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';')
436 p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
437 p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';')
438 p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';')
439 assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
440 assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
442 def test_AppendPath(self):
443 """Test appending to a path."""
444 p1 = r'C:\dir\num\one;C:\dir\num\two'
445 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
446 # have to include the pathsep here so that the test will work on UNIX too.
447 p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';')
448 p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
449 p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';')
450 p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';')
451 assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
452 assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
454 def test_NodeList(self):
455 """Test NodeList class"""
457 def __init__(self, name, child=None):
461 return self.bar + "foo"
465 t1 = TestClass('t1', TestClass('t1child'))
466 t2 = TestClass('t2', TestClass('t2child'))
469 nl = NodeList([t1, t2, t3])
470 assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo()
471 assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
472 assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar
473 assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \
475 assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
478 def test_CLVar(self):
479 """Test the command-line construction variable class"""
480 f = SCons.Util.CLVar('a b')
483 assert isinstance(r, SCons.Util.CLVar), type(r)
484 assert r.data == ['a', 'b', 'c', 'd'], r.data
485 assert str(r) == 'a b c d', str(r)
488 assert isinstance(r, SCons.Util.CLVar), type(r)
489 assert r.data == ['a', 'b', 'c', 'd'], r.data
490 assert str(r) == 'a b c d', str(r)
493 assert isinstance(r, SCons.Util.CLVar), type(r)
494 assert r.data == ['a', 'b', 'c d'], r.data
495 assert str(r) == 'a b c d', str(r)
498 assert isinstance(r, SCons.Util.CLVar), type(r)
499 assert r.data == ['a', 'b', ' c d'], r.data
500 assert str(r) == 'a b c d', str(r)
503 assert isinstance(r, SCons.Util.CLVar), type(r)
504 assert r.data == ['a', 'b', 'c', 'd'], r.data
505 assert str(r) == 'a b c d', str(r)
508 assert isinstance(r, SCons.Util.CLVar), type(r)
509 assert r.data == ['a', 'b', ' c', 'd'], r.data
510 assert str(r) == 'a b c d', str(r)
512 f = SCons.Util.CLVar(['a b'])
515 assert isinstance(r, SCons.Util.CLVar), type(r)
516 assert r.data == ['a b', 'c', 'd'], r.data
517 assert str(r) == 'a b c d', str(r)
520 assert isinstance(r, SCons.Util.CLVar), type(r)
521 assert r.data == ['a b', 'c', 'd'], r.data
522 assert str(r) == 'a b c d', str(r)
525 assert isinstance(r, SCons.Util.CLVar), type(r)
526 assert r.data == ['a b', 'c d'], r.data
527 assert str(r) == 'a b c d', str(r)
530 assert isinstance(r, SCons.Util.CLVar), type(r)
531 assert r.data == ['a b', ' c d'], r.data
532 assert str(r) == 'a b c d', str(r)
535 assert isinstance(r, SCons.Util.CLVar), type(r)
536 assert r.data == ['a b', 'c', 'd'], r.data
537 assert str(r) == 'a b c d', str(r)
540 assert isinstance(r, SCons.Util.CLVar), type(r)
541 assert r.data == ['a b', ' c', 'd'], r.data
542 assert str(r) == 'a b c d', str(r)
544 f = SCons.Util.CLVar(['a', 'b'])
547 assert isinstance(r, SCons.Util.CLVar), type(r)
548 assert r.data == ['a', 'b', 'c', 'd'], r.data
549 assert str(r) == 'a b c d', str(r)
552 assert isinstance(r, SCons.Util.CLVar), type(r)
553 assert r.data == ['a', 'b', 'c', 'd'], r.data
554 assert str(r) == 'a b c d', str(r)
557 assert isinstance(r, SCons.Util.CLVar), type(r)
558 assert r.data == ['a', 'b', 'c d'], r.data
559 assert str(r) == 'a b c d', str(r)
562 assert isinstance(r, SCons.Util.CLVar), type(r)
563 assert r.data == ['a', 'b', ' c d'], r.data
564 assert str(r) == 'a b c d', str(r)
567 assert isinstance(r, SCons.Util.CLVar), type(r)
568 assert r.data == ['a', 'b', 'c', 'd'], r.data
569 assert str(r) == 'a b c d', str(r)
572 assert isinstance(r, SCons.Util.CLVar), type(r)
573 assert r.data == ['a', 'b', ' c', 'd'], r.data
574 assert str(r) == 'a b c d', str(r)
576 def test_Selector(self):
577 """Test the Selector class"""
579 s = Selector({'a' : 'AAA', 'b' : 'BBB'})
580 assert s['a'] == 'AAA', s['a']
581 assert s['b'] == 'BBB', s['b']
587 assert exc_caught, "should have caught a KeyError"
589 assert s['c'] == 'CCC', s['c']
591 class DummyEnv(UserDict):
592 def subst(self, key):
599 s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
601 assert ret == None, ret
602 ret = s(env, ['foo.d'])
603 assert ret == 'DDD', ret
604 ret = s(env, ['bar.e'])
605 assert ret == 'EEE', ret
606 ret = s(env, ['bar.x'])
607 assert ret == None, ret
609 ret = s(env, ['bar.x'])
610 assert ret == 'XXX', ret
612 env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
614 s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'})
615 ret = s(env, ['foo.f'])
616 assert ret == 'FFF', ret
617 ret = s(env, ['bar.g'])
618 assert ret == 'GGG', ret
620 def test_adjustixes(self):
621 """Test the adjustixes() function"""
622 r = adjustixes('file', 'pre-', '-suf')
623 assert r == 'pre-file-suf', r
624 r = adjustixes('pre-file', 'pre-', '-suf')
625 assert r == 'pre-file-suf', r
626 r = adjustixes('file-suf', 'pre-', '-suf')
627 assert r == 'pre-file-suf', r
628 r = adjustixes('pre-file-suf', 'pre-', '-suf')
629 assert r == 'pre-file-suf', r
630 r = adjustixes('pre-file.xxx', 'pre-', '-suf')
631 assert r == 'pre-file.xxx', r
632 r = adjustixes('dir/file', 'pre-', '-suf')
633 assert r == os.path.join('dir', 'pre-file-suf'), r
635 def test_containsAny(self):
636 """Test the containsAny() function"""
637 assert containsAny('*.py', '*?[]')
638 assert not containsAny('file.txt', '*?[]')
640 def test_containsAll(self):
641 """Test the containsAll() function"""
642 assert containsAll('43221', '123')
643 assert not containsAll('134', '123')
645 def test_containsOnly(self):
646 """Test the containsOnly() function"""
647 assert containsOnly('.83', '0123456789.')
648 assert not containsOnly('43221', '123')
650 def test_LogicalLines(self):
651 """Test the LogicalLines class"""
652 fobj = StringIO.StringIO(r"""
662 lines = LogicalLines(fobj).readlines()
667 'bling bling \\ bling\n',
671 if __name__ == "__main__":
672 suite = unittest.makeSuite(UtilTestCase, 'test_')
673 if not unittest.TextTestRunner().run(suite).wasSuccessful():