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 dictifyTestCase(unittest.TestCase):
50 def test_dictify(self):
51 """Test the dictify() function"""
52 r = SCons.Util.dictify(['a', 'b', 'c'], [1, 2, 3])
53 assert r == {'a':1, 'b':2, 'c':3}, r
56 SCons.Util.dictify(['a'], [1], r)
57 SCons.Util.dictify(['b'], [2], r)
58 SCons.Util.dictify(['c'], [3], r)
59 assert r == {'a':1, 'b':2, 'c':3}, r
61 class UtilTestCase(unittest.TestCase):
62 def test_splitext(self):
63 assert splitext('foo') == ('foo','')
64 assert splitext('foo.bar') == ('foo','.bar')
65 assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
68 def __init__(self, name, children=[]):
69 self.children = children
78 def has_builder(self):
80 def has_explicit_builder(self):
82 def side_effect(self):
86 def always_build(self):
88 def is_up_to_date(self):
93 def tree_case_1(self):
94 """Fixture for the render_tree() and print_tree() tests."""
95 windows_h = self.Node("windows.h")
96 stdlib_h = self.Node("stdlib.h")
97 stdio_h = self.Node("stdio.h")
98 bar_c = self.Node("bar.c", [stdlib_h, windows_h])
99 bar_o = self.Node("bar.o", [bar_c])
100 foo_c = self.Node("foo.c", [stdio_h])
101 foo_o = self.Node("foo.o", [foo_c])
102 foo = self.Node("foo", [foo_o, bar_o])
115 lines = string.split(expect, '\n')[:-1]
116 lines = map(lambda l: '[E BSPACN ]'+l, lines)
117 withtags = string.join(lines, '\n') + '\n'
119 return foo, expect, withtags
121 def tree_case_2(self, prune=1):
122 """Fixture for the render_tree() and print_tree() tests."""
124 stdlib_h = self.Node("stdlib.h")
125 bar_h = self.Node('bar.h', [stdlib_h])
126 blat_h = self.Node('blat.h', [stdlib_h])
127 blat_c = self.Node('blat.c', [blat_h, bar_h])
128 blat_o = self.Node('blat.o', [blat_c])
140 expect = string.replace(expect, '[', '')
141 expect = string.replace(expect, ']', '')
143 lines = string.split(expect, '\n')[:-1]
144 lines = map(lambda l: '[E BSPACN ]'+l, lines)
145 withtags = string.join(lines, '\n') + '\n'
147 return blat_o, expect, withtags
149 def test_render_tree(self):
150 """Test the render_tree() function"""
151 def get_children(node):
154 node, expect, withtags = self.tree_case_1()
155 actual = render_tree(node, get_children)
156 assert expect == actual, (expect, actual)
158 node, expect, withtags = self.tree_case_2()
159 actual = render_tree(node, get_children, 1)
160 assert expect == actual, (expect, actual)
162 def test_print_tree(self):
163 """Test the print_tree() function"""
164 def get_children(node):
167 save_stdout = sys.stdout
170 node, expect, withtags = self.tree_case_1()
172 sys.stdout = StringIO.StringIO()
173 print_tree(node, get_children)
174 actual = sys.stdout.getvalue()
175 assert expect == actual, (expect, actual)
177 sys.stdout = StringIO.StringIO()
178 print_tree(node, get_children, showtags=1)
179 actual = sys.stdout.getvalue()
180 assert withtags == actual, (withtags, actual)
182 node, expect, withtags = self.tree_case_2(prune=0)
184 sys.stdout = StringIO.StringIO()
185 print_tree(node, get_children, 1)
186 actual = sys.stdout.getvalue()
187 assert expect == actual, (expect, actual)
189 sys.stdout = StringIO.StringIO()
190 # The following call should work here:
191 # print_tree(node, get_children, 1, showtags=1)
192 # For some reason I don't understand, though, *this*
193 # time that we call print_tree, the visited dictionary
194 # is still populated with the values from the last call!
195 # I can't see why this would be, short of a bug in Python,
196 # and rather than continue banging my head against the
197 # brick wall for a *test*, we're going to going with
198 # the cheap, easy workaround:
199 print_tree(node, get_children, 1, showtags=1, visited={})
200 actual = sys.stdout.getvalue()
201 assert withtags == actual, (withtags, actual)
203 sys.stdout = save_stdout
205 def test_is_Dict(self):
207 assert is_Dict(UserDict())
208 assert not is_Dict([])
209 assert not is_Dict(())
210 assert not is_Dict("")
211 if hasattr(types, 'UnicodeType'):
212 exec "assert not is_Dict(u'')"
214 def test_is_List(self):
217 assert is_List(UserList.UserList())
218 assert not is_List(())
219 assert not is_List({})
220 assert not is_List("")
221 if hasattr(types, 'UnicodeType'):
222 exec "assert not is_List(u'')"
224 def test_is_String(self):
226 if hasattr(types, 'UnicodeType'):
227 exec "assert is_String(u'')"
233 assert is_String(UserString.UserString(''))
234 assert not is_String({})
235 assert not is_String([])
236 assert not is_String(())
238 def test_is_Tuple(self):
240 assert not is_Tuple([])
241 assert not is_Tuple({})
242 assert not is_Tuple("")
243 if hasattr(types, 'UnicodeType'):
244 exec "assert not is_Tuple(u'')"
246 def test_to_String(self):
247 """Test the to_String() method."""
248 assert to_String(1) == "1", to_String(1)
249 assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
250 assert to_String("foo") == "foo", to_String("foo")
255 s1=UserString.UserString('blah')
256 assert to_String(s1) == s1, s1
257 assert to_String(s1) == 'blah', s1
259 class Derived(UserString.UserString):
262 assert to_String(s2) == s2, s2
263 assert to_String(s2) == 'foo', s2
265 if hasattr(types, 'UnicodeType'):
266 s3=UserString.UserString(unicode('bar'))
267 assert to_String(s3) == s3, s3
268 assert to_String(s3) == unicode('bar'), s3
269 assert type(to_String(s3)) is types.UnicodeType, \
274 if hasattr(types, 'UnicodeType'):
276 assert to_String(s4) == unicode('baz'), to_String(s4)
277 assert type(to_String(s4)) is types.UnicodeType, \
280 def test_WhereIs(self):
281 test = TestCmd.TestCmd(workdir = '')
283 sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
284 sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
285 sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
286 sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
288 test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
290 if sys.platform != 'win32':
291 test.write(sub1_xxx_exe, "\n")
293 os.mkdir(sub2_xxx_exe)
295 test.write(sub3_xxx_exe, "\n")
296 os.chmod(sub3_xxx_exe, 0777)
298 test.write(sub4_xxx_exe, "\n")
299 os.chmod(sub4_xxx_exe, 0777)
301 env_path = os.environ['PATH']
304 pathdirs_1234 = [ test.workpath('sub1'),
305 test.workpath('sub2'),
306 test.workpath('sub3'),
307 test.workpath('sub4'),
308 ] + string.split(env_path, os.pathsep)
310 pathdirs_1243 = [ test.workpath('sub1'),
311 test.workpath('sub2'),
312 test.workpath('sub4'),
313 test.workpath('sub3'),
314 ] + string.split(env_path, os.pathsep)
316 os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
317 wi = WhereIs('xxx.exe')
318 assert wi == test.workpath(sub3_xxx_exe), wi
319 wi = WhereIs('xxx.exe', pathdirs_1243)
320 assert wi == test.workpath(sub4_xxx_exe), wi
321 wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
322 assert wi == test.workpath(sub4_xxx_exe), wi
324 wi = WhereIs('xxx.exe',reject = sub3_xxx_exe)
325 assert wi == test.workpath(sub4_xxx_exe), wi
326 wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
327 assert wi == test.workpath(sub4_xxx_exe), wi
329 os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
330 wi = WhereIs('xxx.exe')
331 assert wi == test.workpath(sub4_xxx_exe), wi
332 wi = WhereIs('xxx.exe', pathdirs_1234)
333 assert wi == test.workpath(sub3_xxx_exe), wi
334 wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
335 assert wi == test.workpath(sub3_xxx_exe), wi
337 if sys.platform == 'win32':
338 wi = WhereIs('xxx', pathext = '')
339 assert wi is None, wi
341 wi = WhereIs('xxx', pathext = '.exe')
342 assert wi == test.workpath(sub4_xxx_exe), wi
344 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
345 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
347 # Test that we return a normalized path even when
348 # the path contains forward slashes.
349 forward_slash = test.workpath('') + '/sub3'
350 wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
351 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
353 del os.environ['PATH']
354 wi = WhereIs('xxx.exe')
355 assert wi is None, wi
358 os.environ['PATH'] = env_path
361 def test_is_valid_construction_var(self):
362 """Testing is_valid_construction_var()"""
363 r = is_valid_construction_var("_a")
364 assert not r is None, r
365 r = is_valid_construction_var("z_")
366 assert not r is None, r
367 r = is_valid_construction_var("X_")
368 assert not r is None, r
369 r = is_valid_construction_var("2a")
371 r = is_valid_construction_var("a2_")
372 assert not r is None, r
373 r = is_valid_construction_var("/")
375 r = is_valid_construction_var("_/")
377 r = is_valid_construction_var("a/")
379 r = is_valid_construction_var(".b")
381 r = is_valid_construction_var("_.b")
383 r = is_valid_construction_var("b1._")
385 r = is_valid_construction_var("-b")
387 r = is_valid_construction_var("_-b")
389 r = is_valid_construction_var("b1-_")
392 def test_get_env_var(self):
393 """Testing get_environment_var()."""
394 assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
395 assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
396 assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
397 assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
398 assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
399 assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
400 assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
401 assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
402 assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
404 def test_Proxy(self):
405 """Test generic Proxy class."""
415 class ProxyTest(Proxy):
421 assert p.foo() == 1, p.foo()
422 assert p.bar() == 4, p.bar()
423 assert p.baz == 3, p.baz
428 assert p.baz == 5, p.baz
429 assert p.get() == s, p.get()
431 def test_display(self):
432 old_stdout = sys.stdout
433 sys.stdout = OutBuffer()
439 display("line4\n", append_newline=0)
441 display("dont print1")
442 display("dont print2\n", append_newline=0)
444 assert sys.stdout.buffer == "line1\nline3\nline4\n"
445 sys.stdout = old_stdout
447 def test_get_native_path(self):
448 """Test the get_native_path() function."""
450 filename = tempfile.mktemp()
451 str = '1234567890 ' + filename
453 open(filename, 'w').write(str)
454 assert open(get_native_path(filename)).read() == str
461 def test_PrependPath(self):
462 """Test prepending to a path"""
463 p1 = r'C:\dir\num\one;C:\dir\num\two'
464 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
465 # have to include the pathsep here so that the test will work on UNIX too.
466 p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';')
467 p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
468 p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';')
469 p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';')
470 assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
471 assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
473 def test_AppendPath(self):
474 """Test appending to a path."""
475 p1 = r'C:\dir\num\one;C:\dir\num\two'
476 p2 = r'C:\mydir\num\one;C:\mydir\num\two'
477 # have to include the pathsep here so that the test will work on UNIX too.
478 p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';')
479 p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
480 p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';')
481 p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';')
482 assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
483 assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
485 def test_NodeList(self):
486 """Test NodeList class"""
488 def __init__(self, name, child=None):
492 return self.bar + "foo"
496 t1 = TestClass('t1', TestClass('t1child'))
497 t2 = TestClass('t2', TestClass('t2child'))
500 nl = NodeList([t1, t2, t3])
501 assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo()
502 assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
503 assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar
504 assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \
506 assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
509 def test_CLVar(self):
510 """Test the command-line construction variable class"""
511 f = SCons.Util.CLVar('a b')
514 assert isinstance(r, SCons.Util.CLVar), type(r)
515 assert r.data == ['a', 'b', 'c', 'd'], r.data
516 assert str(r) == 'a b c d', str(r)
519 assert isinstance(r, SCons.Util.CLVar), type(r)
520 assert r.data == ['a', 'b', 'c', 'd'], r.data
521 assert str(r) == 'a b c d', str(r)
524 assert isinstance(r, SCons.Util.CLVar), type(r)
525 assert r.data == ['a', 'b', 'c d'], r.data
526 assert str(r) == 'a b c d', str(r)
529 assert isinstance(r, SCons.Util.CLVar), type(r)
530 assert r.data == ['a', 'b', ' c d'], r.data
531 assert str(r) == 'a b c d', str(r)
534 assert isinstance(r, SCons.Util.CLVar), type(r)
535 assert r.data == ['a', 'b', 'c', 'd'], r.data
536 assert str(r) == 'a b c d', str(r)
539 assert isinstance(r, SCons.Util.CLVar), type(r)
540 assert r.data == ['a', 'b', ' c', 'd'], r.data
541 assert str(r) == 'a b c d', str(r)
543 f = SCons.Util.CLVar(['a b'])
546 assert isinstance(r, SCons.Util.CLVar), type(r)
547 assert r.data == ['a b', 'c', 'd'], r.data
548 assert str(r) == 'a b c d', str(r)
551 assert isinstance(r, SCons.Util.CLVar), type(r)
552 assert r.data == ['a b', 'c', 'd'], r.data
553 assert str(r) == 'a b c d', str(r)
556 assert isinstance(r, SCons.Util.CLVar), type(r)
557 assert r.data == ['a b', 'c d'], r.data
558 assert str(r) == 'a b c d', str(r)
561 assert isinstance(r, SCons.Util.CLVar), type(r)
562 assert r.data == ['a b', ' c d'], r.data
563 assert str(r) == 'a b c d', str(r)
566 assert isinstance(r, SCons.Util.CLVar), type(r)
567 assert r.data == ['a b', 'c', 'd'], r.data
568 assert str(r) == 'a b c d', str(r)
571 assert isinstance(r, SCons.Util.CLVar), type(r)
572 assert r.data == ['a b', ' c', 'd'], r.data
573 assert str(r) == 'a b c d', str(r)
575 f = SCons.Util.CLVar(['a', 'b'])
578 assert isinstance(r, SCons.Util.CLVar), type(r)
579 assert r.data == ['a', 'b', 'c', 'd'], r.data
580 assert str(r) == 'a b c d', str(r)
583 assert isinstance(r, SCons.Util.CLVar), type(r)
584 assert r.data == ['a', 'b', 'c', 'd'], r.data
585 assert str(r) == 'a b c d', str(r)
588 assert isinstance(r, SCons.Util.CLVar), type(r)
589 assert r.data == ['a', 'b', 'c d'], r.data
590 assert str(r) == 'a b c d', str(r)
593 assert isinstance(r, SCons.Util.CLVar), type(r)
594 assert r.data == ['a', 'b', ' c d'], r.data
595 assert str(r) == 'a b c d', str(r)
598 assert isinstance(r, SCons.Util.CLVar), type(r)
599 assert r.data == ['a', 'b', 'c', 'd'], r.data
600 assert str(r) == 'a b c d', str(r)
603 assert isinstance(r, SCons.Util.CLVar), type(r)
604 assert r.data == ['a', 'b', ' c', 'd'], r.data
605 assert str(r) == 'a b c d', str(r)
607 def test_Selector(self):
608 """Test the Selector class"""
610 s = Selector({'a' : 'AAA', 'b' : 'BBB'})
611 assert s['a'] == 'AAA', s['a']
612 assert s['b'] == 'BBB', s['b']
618 assert exc_caught, "should have caught a KeyError"
620 assert s['c'] == 'CCC', s['c']
622 class DummyEnv(UserDict):
623 def subst(self, key):
630 s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
632 assert ret == None, ret
633 ret = s(env, ['foo.d'])
634 assert ret == 'DDD', ret
635 ret = s(env, ['bar.e'])
636 assert ret == 'EEE', ret
637 ret = s(env, ['bar.x'])
638 assert ret == None, ret
640 ret = s(env, ['bar.x'])
641 assert ret == 'XXX', ret
643 env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
645 s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'})
646 ret = s(env, ['foo.f'])
647 assert ret == 'FFF', ret
648 ret = s(env, ['bar.g'])
649 assert ret == 'GGG', ret
651 def test_adjustixes(self):
652 """Test the adjustixes() function"""
653 r = adjustixes('file', 'pre-', '-suf')
654 assert r == 'pre-file-suf', r
655 r = adjustixes('pre-file', 'pre-', '-suf')
656 assert r == 'pre-file-suf', r
657 r = adjustixes('file-suf', 'pre-', '-suf')
658 assert r == 'pre-file-suf', r
659 r = adjustixes('pre-file-suf', 'pre-', '-suf')
660 assert r == 'pre-file-suf', r
661 r = adjustixes('pre-file.xxx', 'pre-', '-suf')
662 assert r == 'pre-file.xxx', r
663 r = adjustixes('dir/file', 'pre-', '-suf')
664 assert r == os.path.join('dir', 'pre-file-suf'), r
666 def test_containsAny(self):
667 """Test the containsAny() function"""
668 assert containsAny('*.py', '*?[]')
669 assert not containsAny('file.txt', '*?[]')
671 def test_containsAll(self):
672 """Test the containsAll() function"""
673 assert containsAll('43221', '123')
674 assert not containsAll('134', '123')
676 def test_containsOnly(self):
677 """Test the containsOnly() function"""
678 assert containsOnly('.83', '0123456789.')
679 assert not containsOnly('43221', '123')
681 def test_LogicalLines(self):
682 """Test the LogicalLines class"""
683 fobj = StringIO.StringIO(r"""
693 lines = LogicalLines(fobj).readlines()
698 'bling bling \\ bling\n',
702 class MD5TestCase(unittest.TestCase):
704 def test_collect(self):
705 """Test collecting a list of signatures into a new signature value
707 s = map(MD5signature, ('111', '222', '333'))
709 assert '698d51a19d8a121ce581499d7b701668' == MD5collect(s[0:1])
710 assert '8980c988edc2c78cc43ccb718c06efd5' == MD5collect(s[0:2])
711 assert '53fd88c84ff8a285eb6e0a687e55b8c7' == MD5collect(s)
713 def test_MD5signature(self):
714 """Test generating a signature"""
715 s = MD5signature('111')
716 assert '698d51a19d8a121ce581499d7b701668' == s, s
718 s = MD5signature('222')
719 assert 'bcbe3365e6ac95ea2c0343a2395834dd' == s, s
721 if __name__ == "__main__":
722 suite = unittest.TestSuite()
723 tclasses = [ dictifyTestCase,
727 for tclass in tclasses:
728 names = unittest.getTestCaseNames(tclass, 'test_')
729 suite.addTests(map(tclass, names))
730 if not unittest.TextTestRunner().run(suite).wasSuccessful():