670fc83c1173ddbf24b51acdfe4abbe381005567
[scons.git] / src / engine / SCons / UtilTests.py
1 #
2 # __COPYRIGHT__
3 #
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:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
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.
22 #
23
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25
26 import os
27 import os.path
28 import StringIO
29 import sys
30 import types
31 import unittest
32
33 from UserDict import UserDict
34
35 import TestCmd
36
37 import SCons.Errors
38
39 from SCons.Util import *
40
41 class OutBuffer:
42     def __init__(self):
43         self.buffer = ""
44
45     def write(self, str):
46         self.buffer = self.buffer + str
47
48 class dictifyTestCase(unittest.TestCase):
49     def test_dictify(self):
50         """Test the dictify() function"""
51         r = SCons.Util.dictify(['a', 'b', 'c'], [1, 2, 3])
52         assert r == {'a':1, 'b':2, 'c':3}, r
53
54         r = {}
55         SCons.Util.dictify(['a'], [1], r)
56         SCons.Util.dictify(['b'], [2], r)
57         SCons.Util.dictify(['c'], [3], r)
58         assert r == {'a':1, 'b':2, 'c':3}, r
59
60 class UtilTestCase(unittest.TestCase):
61     def test_splitext(self):
62         assert splitext('foo') == ('foo','')
63         assert splitext('foo.bar') == ('foo','.bar')
64         assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
65
66     class Node:
67         def __init__(self, name, children=[]):
68             self.children = children
69             self.name = name
70             self.nocache = None
71         def __str__(self):
72             return self.name
73         def exists(self):
74             return 1
75         def rexists(self):
76             return 1
77         def has_builder(self):
78             return 1
79         def has_explicit_builder(self):
80             return 1
81         def side_effect(self):
82             return 1
83         def precious(self):
84             return 1
85         def always_build(self):
86             return 1
87         def is_up_to_date(self):
88             return 1
89         def noclean(self):
90             return 1
91
92     def tree_case_1(self):
93         """Fixture for the render_tree() and print_tree() tests."""
94         windows_h = self.Node("windows.h")
95         stdlib_h = self.Node("stdlib.h")
96         stdio_h = self.Node("stdio.h")
97         bar_c = self.Node("bar.c", [stdlib_h, windows_h])
98         bar_o = self.Node("bar.o", [bar_c])
99         foo_c = self.Node("foo.c", [stdio_h])
100         foo_o = self.Node("foo.o", [foo_c])
101         foo = self.Node("foo", [foo_o, bar_o])
102
103         expect = """\
104 +-foo
105   +-foo.o
106   | +-foo.c
107   |   +-stdio.h
108   +-bar.o
109     +-bar.c
110       +-stdlib.h
111       +-windows.h
112 """
113
114         lines = expect.split('\n')[:-1]
115         lines = ['[E BSPACN ]'+l for l in lines]
116         withtags = '\n'.join(lines) + '\n'
117
118         return foo, expect, withtags
119
120     def tree_case_2(self, prune=1):
121         """Fixture for the render_tree() and print_tree() tests."""
122
123         stdlib_h = self.Node("stdlib.h")
124         bar_h = self.Node('bar.h', [stdlib_h])
125         blat_h = self.Node('blat.h', [stdlib_h])
126         blat_c = self.Node('blat.c', [blat_h, bar_h])
127         blat_o = self.Node('blat.o', [blat_c])
128
129         expect = """\
130 +-blat.o
131   +-blat.c
132     +-blat.h
133     | +-stdlib.h
134     +-bar.h
135       +-[stdlib.h]
136 """
137
138         if not prune:
139             expect = expect.replace('[', '')
140             expect = expect.replace(']', '')
141
142         lines = expect.split('\n')[:-1]
143         lines = ['[E BSPACN ]'+l for l in lines]
144         withtags = '\n'.join(lines) + '\n'
145
146         return blat_o, expect, withtags
147
148     def test_render_tree(self):
149         """Test the render_tree() function"""
150         def get_children(node):
151             return node.children
152
153         node, expect, withtags = self.tree_case_1()
154         actual = render_tree(node, get_children)
155         assert expect == actual, (expect, actual)
156
157         node, expect, withtags = self.tree_case_2()
158         actual = render_tree(node, get_children, 1)
159         assert expect == actual, (expect, actual)
160
161     def test_print_tree(self):
162         """Test the print_tree() function"""
163         def get_children(node):
164             return node.children
165
166         save_stdout = sys.stdout
167
168         try:
169             node, expect, withtags = self.tree_case_1()
170
171             sys.stdout = StringIO.StringIO()
172             print_tree(node, get_children)
173             actual = sys.stdout.getvalue()
174             assert expect == actual, (expect, actual)
175
176             sys.stdout = StringIO.StringIO()
177             print_tree(node, get_children, showtags=1)
178             actual = sys.stdout.getvalue()
179             assert withtags == actual, (withtags, actual)
180
181             node, expect, withtags = self.tree_case_2(prune=0)
182
183             sys.stdout = StringIO.StringIO()
184             print_tree(node, get_children, 1)
185             actual = sys.stdout.getvalue()
186             assert expect == actual, (expect, actual)
187
188             sys.stdout = StringIO.StringIO()
189             # The following call should work here:
190             #    print_tree(node, get_children, 1, showtags=1)
191             # For some reason I don't understand, though, *this*
192             # time that we call print_tree, the visited dictionary
193             # is still populated with the values from the last call!
194             # I can't see why this would be, short of a bug in Python,
195             # and rather than continue banging my head against the
196             # brick wall for a *test*, we're going to going with
197             # the cheap, easy workaround:
198             print_tree(node, get_children, 1, showtags=1, visited={})
199             actual = sys.stdout.getvalue()
200             assert withtags == actual, (withtags, actual)
201         finally:
202             sys.stdout = save_stdout
203
204     def test_is_Dict(self):
205         assert is_Dict({})
206         assert is_Dict(UserDict())
207         try:
208             class mydict(dict):
209                 pass
210         except TypeError:
211             pass
212         else:
213             assert is_Dict(mydict({}))
214         assert not is_Dict([])
215         assert not is_Dict(())
216         assert not is_Dict("")
217         if hasattr(types, 'UnicodeType'):
218             exec "assert not is_Dict(u'')"
219
220     def test_is_List(self):
221         assert is_List([])
222         import UserList
223         assert is_List(UserList.UserList())
224         try:
225             class mylist(list):
226                 pass
227         except TypeError:
228             pass
229         else:
230             assert is_List(mylist([]))
231         assert not is_List(())
232         assert not is_List({})
233         assert not is_List("")
234         if hasattr(types, 'UnicodeType'):
235             exec "assert not is_List(u'')"
236
237     def test_is_String(self):
238         assert is_String("")
239         if hasattr(types, 'UnicodeType'):
240             exec "assert is_String(u'')"
241         try:
242             import UserString
243         except:
244             pass
245         else:
246             assert is_String(UserString.UserString(''))
247         try:
248             class mystr(str):
249                 pass
250         except TypeError:
251             pass
252         else:
253             assert is_String(mystr(''))
254         assert not is_String({})
255         assert not is_String([])
256         assert not is_String(())
257
258     def test_is_Tuple(self):
259         assert is_Tuple(())
260         try:
261             class mytuple(tuple):
262                 pass
263         except TypeError:
264             pass
265         else:
266             assert is_Tuple(mytuple(()))
267         assert not is_Tuple([])
268         assert not is_Tuple({})
269         assert not is_Tuple("")
270         if hasattr(types, 'UnicodeType'):
271             exec "assert not is_Tuple(u'')"
272
273     def test_to_String(self):
274         """Test the to_String() method."""
275         assert to_String(1) == "1", to_String(1)
276         assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
277         assert to_String("foo") == "foo", to_String("foo")
278
279         try:
280             import UserString
281
282             s1=UserString.UserString('blah')
283             assert to_String(s1) == s1, s1
284             assert to_String(s1) == 'blah', s1
285
286             class Derived(UserString.UserString):
287                 pass
288             s2 = Derived('foo')
289             assert to_String(s2) == s2, s2
290             assert to_String(s2) == 'foo', s2
291
292             if hasattr(types, 'UnicodeType'):
293                 s3=UserString.UserString(unicode('bar'))
294                 assert to_String(s3) == s3, s3
295                 assert to_String(s3) == unicode('bar'), s3
296                 assert type(to_String(s3)) is types.UnicodeType, \
297                        type(to_String(s3))
298         except ImportError:
299             pass
300
301         if hasattr(types, 'UnicodeType'):
302             s4 = unicode('baz')
303             assert to_String(s4) == unicode('baz'), to_String(s4)
304             assert type(to_String(s4)) is types.UnicodeType, \
305                    type(to_String(s4))
306
307     def test_WhereIs(self):
308         test = TestCmd.TestCmd(workdir = '')
309
310         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
311         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
312         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
313         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
314
315         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
316
317         if sys.platform != 'win32':
318             test.write(sub1_xxx_exe, "\n")
319
320         os.mkdir(sub2_xxx_exe)
321
322         test.write(sub3_xxx_exe, "\n")
323         os.chmod(sub3_xxx_exe, 0777)
324
325         test.write(sub4_xxx_exe, "\n")
326         os.chmod(sub4_xxx_exe, 0777)
327
328         env_path = os.environ['PATH']
329
330         try:
331             pathdirs_1234 = [ test.workpath('sub1'),
332                               test.workpath('sub2'),
333                               test.workpath('sub3'),
334                               test.workpath('sub4'),
335                             ] + env_path.split(os.pathsep)
336
337             pathdirs_1243 = [ test.workpath('sub1'),
338                               test.workpath('sub2'),
339                               test.workpath('sub4'),
340                               test.workpath('sub3'),
341                             ] + env_path.split(os.pathsep)
342
343             os.environ['PATH'] = os.pathsep.join(pathdirs_1234)
344             wi = WhereIs('xxx.exe')
345             assert wi == test.workpath(sub3_xxx_exe), wi
346             wi = WhereIs('xxx.exe', pathdirs_1243)
347             assert wi == test.workpath(sub4_xxx_exe), wi
348             wi = WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243))
349             assert wi == test.workpath(sub4_xxx_exe), wi
350
351             wi = WhereIs('xxx.exe',reject = sub3_xxx_exe)
352             assert wi == test.workpath(sub4_xxx_exe), wi
353             wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
354             assert wi == test.workpath(sub4_xxx_exe), wi
355
356             os.environ['PATH'] = os.pathsep.join(pathdirs_1243)
357             wi = WhereIs('xxx.exe')
358             assert wi == test.workpath(sub4_xxx_exe), wi
359             wi = WhereIs('xxx.exe', pathdirs_1234)
360             assert wi == test.workpath(sub3_xxx_exe), wi
361             wi = WhereIs('xxx.exe', os.pathsep.join(pathdirs_1234))
362             assert wi == test.workpath(sub3_xxx_exe), wi
363
364             if sys.platform == 'win32':
365                 wi = WhereIs('xxx', pathext = '')
366                 assert wi is None, wi
367
368                 wi = WhereIs('xxx', pathext = '.exe')
369                 assert wi == test.workpath(sub4_xxx_exe), wi
370
371                 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
372                 assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi
373
374                 # Test that we return a normalized path even when
375                 # the path contains forward slashes.
376                 forward_slash = test.workpath('') + '/sub3'
377                 wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
378                 assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi
379
380             del os.environ['PATH']
381             wi = WhereIs('xxx.exe')
382             assert wi is None, wi
383
384         finally:
385             os.environ['PATH'] = env_path
386
387     def test_get_env_var(self):
388         """Testing get_environment_var()."""
389         assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
390         assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
391         assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
392         assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
393         assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
394         assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
395         assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
396         assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
397         assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
398
399     def test_Proxy(self):
400         """Test generic Proxy class."""
401         class Subject:
402             def foo(self):
403                 return 1
404             def bar(self):
405                 return 2
406
407         s=Subject()
408         s.baz = 3
409
410         class ProxyTest(Proxy):
411             def bar(self):
412                 return 4
413
414         p=ProxyTest(s)
415
416         assert p.foo() == 1, p.foo()
417         assert p.bar() == 4, p.bar()
418         assert p.baz == 3, p.baz
419
420         p.baz = 5
421         s.baz = 6
422
423         assert p.baz == 5, p.baz
424         assert p.get() == s, p.get()
425
426     def test_display(self):
427         old_stdout = sys.stdout
428         sys.stdout = OutBuffer()
429         display("line1")
430         display.set_mode(0)
431         display("line2")
432         display.set_mode(1)
433         display("line3")
434         display("line4\n", append_newline=0)
435         display.set_mode(0)
436         display("dont print1")
437         display("dont print2\n", append_newline=0)
438         display.set_mode(1)
439         assert sys.stdout.buffer == "line1\nline3\nline4\n"
440         sys.stdout = old_stdout
441
442     def test_get_native_path(self):
443         """Test the get_native_path() function."""
444         import tempfile
445         filename = tempfile.mktemp()
446         str = '1234567890 ' + filename
447         try:
448             open(filename, 'w').write(str)
449             assert open(get_native_path(filename)).read() == str
450         finally:
451             try:
452                 os.unlink(filename)
453             except OSError:
454                 pass
455
456     def test_PrependPath(self):
457         """Test prepending to a path"""
458         p1 = r'C:\dir\num\one;C:\dir\num\two'
459         p2 = r'C:\mydir\num\one;C:\mydir\num\two'
460         # have to include the pathsep here so that the test will work on UNIX too.
461         p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';')
462         p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
463         p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';')
464         p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';')
465         assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
466         assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
467
468     def test_AppendPath(self):
469         """Test appending to a path."""
470         p1 = r'C:\dir\num\one;C:\dir\num\two'
471         p2 = r'C:\mydir\num\one;C:\mydir\num\two'
472         # have to include the pathsep here so that the test will work on UNIX too.
473         p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';')
474         p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
475         p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';')
476         p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';')
477         assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
478         assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
479
480     def test_PrependPathPreserveOld(self):
481         """Test prepending to a path while preserving old paths"""
482         p1 = r'C:\dir\num\one;C:\dir\num\two'
483         # have to include the pathsep here so that the test will work on UNIX too.
484         p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';', delete_existing=0)
485         p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
486         assert(p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two')
487
488     def test_AppendPathPreserveOld(self):
489         """Test appending to a path while preserving old paths"""
490         p1 = r'C:\dir\num\one;C:\dir\num\two'
491         # have to include the pathsep here so that the test will work on UNIX too.
492         p1 = AppendPath(p1,r'C:\dir\num\one',sep = ';', delete_existing=0)
493         p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
494         assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
495
496     def test_CLVar(self):
497         """Test the command-line construction variable class"""
498         f = SCons.Util.CLVar('a b')
499
500         r = f + 'c d'
501         assert isinstance(r, SCons.Util.CLVar), type(r)
502         assert r.data == ['a', 'b', 'c', 'd'], r.data
503         assert str(r) == 'a b c d', str(r)
504
505         r = f + ' c d'
506         assert isinstance(r, SCons.Util.CLVar), type(r)
507         assert r.data == ['a', 'b', 'c', 'd'], r.data
508         assert str(r) == 'a b c d', str(r)
509
510         r = f + ['c d']
511         assert isinstance(r, SCons.Util.CLVar), type(r)
512         assert r.data == ['a', 'b', 'c d'], r.data
513         assert str(r) == 'a b c d', str(r)
514
515         r = f + [' c d']
516         assert isinstance(r, SCons.Util.CLVar), type(r)
517         assert r.data == ['a', 'b', ' c d'], r.data
518         assert str(r) == 'a b  c d', str(r)
519
520         r = f + ['c', 'd']
521         assert isinstance(r, SCons.Util.CLVar), type(r)
522         assert r.data == ['a', 'b', 'c', 'd'], r.data
523         assert str(r) == 'a b c d', str(r)
524
525         r = f + [' c', 'd']
526         assert isinstance(r, SCons.Util.CLVar), type(r)
527         assert r.data == ['a', 'b', ' c', 'd'], r.data
528         assert str(r) == 'a b  c d', str(r)
529
530         f = SCons.Util.CLVar(['a b'])
531
532         r = f + 'c d'
533         assert isinstance(r, SCons.Util.CLVar), type(r)
534         assert r.data == ['a b', 'c', 'd'], r.data
535         assert str(r) == 'a b c d', str(r)
536
537         r = f + ' c d'
538         assert isinstance(r, SCons.Util.CLVar), type(r)
539         assert r.data == ['a b', 'c', 'd'], r.data
540         assert str(r) == 'a b c d', str(r)
541
542         r = f + ['c d']
543         assert isinstance(r, SCons.Util.CLVar), type(r)
544         assert r.data == ['a b', 'c d'], r.data
545         assert str(r) == 'a b c d', str(r)
546
547         r = f + [' c d']
548         assert isinstance(r, SCons.Util.CLVar), type(r)
549         assert r.data == ['a b', ' c d'], r.data
550         assert str(r) == 'a b  c d', str(r)
551
552         r = f + ['c', 'd']
553         assert isinstance(r, SCons.Util.CLVar), type(r)
554         assert r.data == ['a b', 'c', 'd'], r.data
555         assert str(r) == 'a b c d', str(r)
556
557         r = f + [' c', 'd']
558         assert isinstance(r, SCons.Util.CLVar), type(r)
559         assert r.data == ['a b', ' c', 'd'], r.data
560         assert str(r) == 'a b  c d', str(r)
561
562         f = SCons.Util.CLVar(['a', 'b'])
563
564         r = f + 'c d'
565         assert isinstance(r, SCons.Util.CLVar), type(r)
566         assert r.data == ['a', 'b', 'c', 'd'], r.data
567         assert str(r) == 'a b c d', str(r)
568
569         r = f + ' c d'
570         assert isinstance(r, SCons.Util.CLVar), type(r)
571         assert r.data == ['a', 'b', 'c', 'd'], r.data
572         assert str(r) == 'a b c d', str(r)
573
574         r = f + ['c d']
575         assert isinstance(r, SCons.Util.CLVar), type(r)
576         assert r.data == ['a', 'b', 'c d'], r.data
577         assert str(r) == 'a b c d', str(r)
578
579         r = f + [' c d']
580         assert isinstance(r, SCons.Util.CLVar), type(r)
581         assert r.data == ['a', 'b', ' c d'], r.data
582         assert str(r) == 'a b  c d', str(r)
583
584         r = f + ['c', 'd']
585         assert isinstance(r, SCons.Util.CLVar), type(r)
586         assert r.data == ['a', 'b', 'c', 'd'], r.data
587         assert str(r) == 'a b c d', str(r)
588
589         r = f + [' c', 'd']
590         assert isinstance(r, SCons.Util.CLVar), type(r)
591         assert r.data == ['a', 'b', ' c', 'd'], r.data
592         assert str(r) == 'a b  c d', str(r)
593
594     def test_Selector(self):
595         """Test the Selector class"""
596
597         class MyNode:
598             def __init__(self, name):
599                 self.name = name
600                 self.suffix = os.path.splitext(name)[1]
601
602             def __str__(self):
603                 return self.name
604
605         s = Selector({'a' : 'AAA', 'b' : 'BBB'})
606         assert s['a'] == 'AAA', s['a']
607         assert s['b'] == 'BBB', s['b']
608         exc_caught = None
609         try:
610             x = s['c']
611         except KeyError:
612             exc_caught = 1
613         assert exc_caught, "should have caught a KeyError"
614         s['c'] = 'CCC'
615         assert s['c'] == 'CCC', s['c']
616
617         class DummyEnv(UserDict):
618             def subst(self, key):
619                 if key[0] == '$':
620                     return self[key[1:]]
621                 return key
622
623         env = DummyEnv()
624
625         s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
626         ret = s(env, [])
627         assert ret is None, ret
628         ret = s(env, [MyNode('foo.d')])
629         assert ret == 'DDD', ret
630         ret = s(env, [MyNode('bar.e')])
631         assert ret == 'EEE', ret
632         ret = s(env, [MyNode('bar.x')])
633         assert ret is None, ret
634         s[None] = 'XXX'
635         ret = s(env, [MyNode('bar.x')])
636         assert ret == 'XXX', ret
637
638         env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
639
640         s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'})
641         ret = s(env, [MyNode('foo.f')])
642         assert ret == 'FFF', ret
643         ret = s(env, [MyNode('bar.g')])
644         assert ret == 'GGG', ret
645
646     def test_adjustixes(self):
647         """Test the adjustixes() function"""
648         r = adjustixes('file', 'pre-', '-suf')
649         assert r == 'pre-file-suf', r
650         r = adjustixes('pre-file', 'pre-', '-suf')
651         assert r == 'pre-file-suf', r
652         r = adjustixes('file-suf', 'pre-', '-suf')
653         assert r == 'pre-file-suf', r
654         r = adjustixes('pre-file-suf', 'pre-', '-suf')
655         assert r == 'pre-file-suf', r
656         r = adjustixes('pre-file.xxx', 'pre-', '-suf')
657         assert r == 'pre-file.xxx', r
658         r = adjustixes('dir/file', 'pre-', '-suf')
659         assert r == os.path.join('dir', 'pre-file-suf'), r
660
661     def test_containsAny(self):
662         """Test the containsAny() function"""
663         assert containsAny('*.py', '*?[]')
664         assert not containsAny('file.txt', '*?[]')
665
666     def test_containsAll(self):
667         """Test the containsAll() function"""
668         assert containsAll('43221', '123')
669         assert not containsAll('134', '123')
670
671     def test_containsOnly(self):
672         """Test the containsOnly() function"""
673         assert containsOnly('.83', '0123456789.')
674         assert not containsOnly('43221', '123')
675
676     def test_LogicalLines(self):
677         """Test the LogicalLines class"""
678         fobj = StringIO.StringIO(r"""
679 foo \
680 bar \
681 baz
682 foo
683 bling \
684 bling \ bling
685 bling
686 """)
687
688         lines = LogicalLines(fobj).readlines()
689         assert lines == [
690             '\n',
691             'foo bar baz\n',
692             'foo\n',
693             'bling bling \\ bling\n',
694             'bling\n',
695         ], lines
696
697     def test_intern(self):
698         s1 = silent_intern("spam")
699         # Python 1.5 and 3.x do not have a unicode() built-in
700         if sys.version[0] == '2': 
701             s2 = silent_intern(unicode("unicode spam"))
702         s3 = silent_intern(42)
703         s4 = silent_intern("spam")
704         assert id(s1) == id(s4)
705
706
707 class MD5TestCase(unittest.TestCase):
708
709     def test_collect(self):
710         """Test collecting a list of signatures into a new signature value
711         """
712         s = list(map(MD5signature, ('111', '222', '333')))
713         
714         assert '698d51a19d8a121ce581499d7b701668' == MD5collect(s[0:1])
715         assert '8980c988edc2c78cc43ccb718c06efd5' == MD5collect(s[0:2])
716         assert '53fd88c84ff8a285eb6e0a687e55b8c7' == MD5collect(s)
717
718     def test_MD5signature(self):
719         """Test generating a signature"""
720         s = MD5signature('111')
721         assert '698d51a19d8a121ce581499d7b701668' == s, s
722
723         s = MD5signature('222')
724         assert 'bcbe3365e6ac95ea2c0343a2395834dd' == s, s
725
726 class NodeListTestCase(unittest.TestCase):
727     def test_simple_attributes(self):
728         """Test simple attributes of a NodeList class"""
729         class TestClass:
730             def __init__(self, name, child=None):
731                 self.child = child
732                 self.bar = name
733
734         t1 = TestClass('t1', TestClass('t1child'))
735         t2 = TestClass('t2', TestClass('t2child'))
736         t3 = TestClass('t3')
737
738         nl = NodeList([t1, t2, t3])
739         assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
740         assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
741                nl[0:2].child.bar
742
743     def test_callable_attributes(self):
744         """Test callable attributes of a NodeList class"""
745         class TestClass:
746             def __init__(self, name, child=None):
747                 self.child = child
748                 self.bar = name
749             def foo(self):
750                 return self.bar + "foo"
751             def getself(self):
752                 return self
753
754         t1 = TestClass('t1', TestClass('t1child'))
755         t2 = TestClass('t2', TestClass('t2child'))
756         t3 = TestClass('t3')
757
758         nl = NodeList([t1, t2, t3])
759         assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo()
760         assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
761         assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar
762         assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \
763                nl[0:2].child.foo()
764         assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
765                nl[0:2].child.bar
766
767     def test_null(self):
768         """Test a null NodeList"""
769         nl = NodeList([])
770         r = str(nl)
771         assert r == '', r
772         for node in nl:
773             raise Exception, "should not enter this loop"
774
775
776 class flattenTestCase(unittest.TestCase):
777
778     def test_scalar(self):
779         """Test flattening a scalar"""
780         result = flatten('xyz')
781         assert result == ['xyz'], result
782
783 if __name__ == "__main__":
784     suite = unittest.TestSuite()
785     tclasses = [ dictifyTestCase,
786                  flattenTestCase,
787                  MD5TestCase,
788                  NodeListTestCase,
789                  UtilTestCase,
790                ]
791     for tclass in tclasses:
792         names = unittest.getTestCaseNames(tclass, 'test_')
793         suite.addTests(list(map(tclass, names)))
794     if not unittest.TextTestRunner().run(suite).wasSuccessful():
795         sys.exit(1)
796
797 # Local Variables:
798 # tab-width:4
799 # indent-tabs-mode:nil
800 # End:
801 # vim: set expandtab tabstop=4 shiftwidth=4: