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