Merged revisions 2302-2362,2364-2452 via svnmerge from
[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 string
29 import StringIO
30 import sys
31 import types
32 import unittest
33
34 from UserDict import UserDict
35
36 import TestCmd
37
38 import SCons.Errors
39
40 from SCons.Util import *
41
42 class OutBuffer:
43     def __init__(self):
44         self.buffer = ""
45
46     def write(self, str):
47         self.buffer = self.buffer + str
48
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
54
55         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
60
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'),'')
66
67     class Node:
68         def __init__(self, name, children=[]):
69             self.children = children
70             self.name = name
71             self.nocache = None
72         def __str__(self):
73             return self.name
74         def exists(self):
75             return 1
76         def rexists(self):
77             return 1
78         def has_builder(self):
79             return 1
80         def has_explicit_builder(self):
81             return 1
82         def side_effect(self):
83             return 1
84         def precious(self):
85             return 1
86         def always_build(self):
87             return 1
88         def is_up_to_date(self):
89             return 1
90         def noclean(self):
91             return 1
92
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])
103
104         expect = """\
105 +-foo
106   +-foo.o
107   | +-foo.c
108   |   +-stdio.h
109   +-bar.o
110     +-bar.c
111       +-stdlib.h
112       +-windows.h
113 """
114
115         lines = string.split(expect, '\n')[:-1]
116         lines = map(lambda l: '[E BSPACN ]'+l, lines)
117         withtags = string.join(lines, '\n') + '\n'
118
119         return foo, expect, withtags
120
121     def tree_case_2(self, prune=1):
122         """Fixture for the render_tree() and print_tree() tests."""
123
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])
129
130         expect = """\
131 +-blat.o
132   +-blat.c
133     +-blat.h
134     | +-stdlib.h
135     +-bar.h
136       +-[stdlib.h]
137 """
138
139         if not prune:
140             expect = string.replace(expect, '[', '')
141             expect = string.replace(expect, ']', '')
142
143         lines = string.split(expect, '\n')[:-1]
144         lines = map(lambda l: '[E BSPACN ]'+l, lines)
145         withtags = string.join(lines, '\n') + '\n'
146
147         return blat_o, expect, withtags
148
149     def test_render_tree(self):
150         """Test the render_tree() function"""
151         def get_children(node):
152             return node.children
153
154         node, expect, withtags = self.tree_case_1()
155         actual = render_tree(node, get_children)
156         assert expect == actual, (expect, actual)
157
158         node, expect, withtags = self.tree_case_2()
159         actual = render_tree(node, get_children, 1)
160         assert expect == actual, (expect, actual)
161
162     def test_print_tree(self):
163         """Test the print_tree() function"""
164         def get_children(node):
165             return node.children
166
167         save_stdout = sys.stdout
168
169         try:
170             node, expect, withtags = self.tree_case_1()
171
172             sys.stdout = StringIO.StringIO()
173             print_tree(node, get_children)
174             actual = sys.stdout.getvalue()
175             assert expect == actual, (expect, actual)
176
177             sys.stdout = StringIO.StringIO()
178             print_tree(node, get_children, showtags=1)
179             actual = sys.stdout.getvalue()
180             assert withtags == actual, (withtags, actual)
181
182             node, expect, withtags = self.tree_case_2(prune=0)
183
184             sys.stdout = StringIO.StringIO()
185             print_tree(node, get_children, 1)
186             actual = sys.stdout.getvalue()
187             assert expect == actual, (expect, actual)
188
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)
202         finally:
203             sys.stdout = save_stdout
204
205     def test_is_Dict(self):
206         assert is_Dict({})
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'')"
213
214     def test_is_List(self):
215         assert is_List([])
216         import UserList
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'')"
223
224     def test_is_String(self):
225         assert is_String("")
226         if hasattr(types, 'UnicodeType'):
227             exec "assert is_String(u'')"
228         try:
229             import UserString
230         except:
231             pass
232         else:
233             assert is_String(UserString.UserString(''))
234         assert not is_String({})
235         assert not is_String([])
236         assert not is_String(())
237
238     def test_is_Tuple(self):
239         assert is_Tuple(())
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'')"
245
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")
251
252         try:
253             import UserString
254
255             s1=UserString.UserString('blah')
256             assert to_String(s1) == s1, s1
257             assert to_String(s1) == 'blah', s1
258
259             class Derived(UserString.UserString):
260                 pass
261             s2 = Derived('foo')
262             assert to_String(s2) == s2, s2
263             assert to_String(s2) == 'foo', s2
264
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, \
270                        type(to_String(s3))
271         except ImportError:
272             pass
273
274         if hasattr(types, 'UnicodeType'):
275             s4 = unicode('baz')
276             assert to_String(s4) == unicode('baz'), to_String(s4)
277             assert type(to_String(s4)) is types.UnicodeType, \
278                    type(to_String(s4))
279
280     def test_WhereIs(self):
281         test = TestCmd.TestCmd(workdir = '')
282
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')
287
288         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
289
290         if sys.platform != 'win32':
291             test.write(sub1_xxx_exe, "\n")
292
293         os.mkdir(sub2_xxx_exe)
294
295         test.write(sub3_xxx_exe, "\n")
296         os.chmod(sub3_xxx_exe, 0777)
297
298         test.write(sub4_xxx_exe, "\n")
299         os.chmod(sub4_xxx_exe, 0777)
300
301         env_path = os.environ['PATH']
302
303         try:
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)
309
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)
315
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
323
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
328
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
336
337             if sys.platform == 'win32':
338                 wi = WhereIs('xxx', pathext = '')
339                 assert wi is None, wi
340
341                 wi = WhereIs('xxx', pathext = '.exe')
342                 assert wi == test.workpath(sub4_xxx_exe), wi
343
344                 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
345                 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
346
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
352
353             del os.environ['PATH']
354             wi = WhereIs('xxx.exe')
355             assert wi is None, wi
356
357         finally:
358             os.environ['PATH'] = env_path
359             
360
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")
370         assert r is None, r
371         r = is_valid_construction_var("a2_")
372         assert not r is None, r
373         r = is_valid_construction_var("/")
374         assert r is None, r
375         r = is_valid_construction_var("_/")
376         assert r is None, r
377         r = is_valid_construction_var("a/")
378         assert r is None, r
379         r = is_valid_construction_var(".b")
380         assert r is None, r
381         r = is_valid_construction_var("_.b")
382         assert r is None, r
383         r = is_valid_construction_var("b1._")
384         assert r is None, r
385         r = is_valid_construction_var("-b")
386         assert r is None, r
387         r = is_valid_construction_var("_-b")
388         assert r is None, r
389         r = is_valid_construction_var("b1-_")
390         assert r is None, r
391
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')}")
403
404     def test_Proxy(self):
405         """Test generic Proxy class."""
406         class Subject:
407             def foo(self):
408                 return 1
409             def bar(self):
410                 return 2
411
412         s=Subject()
413         s.baz = 3
414
415         class ProxyTest(Proxy):
416             def bar(self):
417                 return 4
418
419         p=ProxyTest(s)
420
421         assert p.foo() == 1, p.foo()
422         assert p.bar() == 4, p.bar()
423         assert p.baz == 3, p.baz
424
425         p.baz = 5
426         s.baz = 6
427
428         assert p.baz == 5, p.baz
429         assert p.get() == s, p.get()
430
431     def test_display(self):
432         old_stdout = sys.stdout
433         sys.stdout = OutBuffer()
434         display("line1")
435         display.set_mode(0)
436         display("line2")
437         display.set_mode(1)
438         display("line3")
439         display("line4\n", append_newline=0)
440         display.set_mode(0)
441         display("dont print1")
442         display("dont print2\n", append_newline=0)
443         display.set_mode(1)
444         assert sys.stdout.buffer == "line1\nline3\nline4\n"
445         sys.stdout = old_stdout
446
447     def test_get_native_path(self):
448         """Test the get_native_path() function."""
449         import tempfile
450         filename = tempfile.mktemp()
451         str = '1234567890 ' + filename
452         try:
453             open(filename, 'w').write(str)
454             assert open(get_native_path(filename)).read() == str
455         finally:
456             try:
457                 os.unlink(filename)
458             except OSError:
459                 pass
460
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')
472
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')
484
485     def test_NodeList(self):
486         """Test NodeList class"""
487         class TestClass:
488             def __init__(self, name, child=None):
489                 self.child = child
490                 self.bar = name
491             def foo(self):
492                 return self.bar + "foo"
493             def getself(self):
494                 return self
495
496         t1 = TestClass('t1', TestClass('t1child'))
497         t2 = TestClass('t2', TestClass('t2child'))
498         t3 = TestClass('t3')
499
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' ], \
505                nl[0:2].child.foo()
506         assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
507                nl[0:2].child.bar
508
509     def test_CLVar(self):
510         """Test the command-line construction variable class"""
511         f = SCons.Util.CLVar('a b')
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         r = f + ['c', 'd']
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)
537
538         r = f + [' c', 'd']
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)
542
543         f = SCons.Util.CLVar(['a b'])
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         r = f + ['c', 'd']
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)
569
570         r = f + [' c', 'd']
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)
574
575         f = SCons.Util.CLVar(['a', 'b'])
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         r = f + ['c', 'd']
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)
601
602         r = f + [' c', 'd']
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)
606
607     def test_Selector(self):
608         """Test the Selector class"""
609
610         s = Selector({'a' : 'AAA', 'b' : 'BBB'})
611         assert s['a'] == 'AAA', s['a']
612         assert s['b'] == 'BBB', s['b']
613         exc_caught = None
614         try:
615             x = s['c']
616         except KeyError:
617             exc_caught = 1
618         assert exc_caught, "should have caught a KeyError"
619         s['c'] = 'CCC'
620         assert s['c'] == 'CCC', s['c']
621
622         class DummyEnv(UserDict):
623             def subst(self, key):
624                 if key[0] == '$':
625                     return self[key[1:]]
626                 return key
627
628         env = DummyEnv()
629
630         s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
631         ret = s(env, [])
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
639         s[None] = 'XXX'
640         ret = s(env, ['bar.x'])
641         assert ret == 'XXX', ret
642
643         env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
644
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
650
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
665
666     def test_containsAny(self):
667         """Test the containsAny() function"""
668         assert containsAny('*.py', '*?[]')
669         assert not containsAny('file.txt', '*?[]')
670
671     def test_containsAll(self):
672         """Test the containsAll() function"""
673         assert containsAll('43221', '123')
674         assert not containsAll('134', '123')
675
676     def test_containsOnly(self):
677         """Test the containsOnly() function"""
678         assert containsOnly('.83', '0123456789.')
679         assert not containsOnly('43221', '123')
680
681     def test_LogicalLines(self):
682         """Test the LogicalLines class"""
683         fobj = StringIO.StringIO(r"""
684 foo \
685 bar \
686 baz
687 foo
688 bling \
689 bling \ bling
690 bling
691 """)
692
693         lines = LogicalLines(fobj).readlines()
694         assert lines == [
695             '\n',
696             'foo bar baz\n',
697             'foo\n',
698             'bling bling \\ bling\n',
699             'bling\n',
700         ], lines
701
702 class MD5TestCase(unittest.TestCase):
703
704     def test_collect(self):
705         """Test collecting a list of signatures into a new signature value
706         """
707         s = map(MD5signature, ('111', '222', '333'))
708         
709         assert '698d51a19d8a121ce581499d7b701668' == MD5collect(s[0:1])
710         assert '8980c988edc2c78cc43ccb718c06efd5' == MD5collect(s[0:2])
711         assert '53fd88c84ff8a285eb6e0a687e55b8c7' == MD5collect(s)
712
713     def test_MD5signature(self):
714         """Test generating a signature"""
715         s = MD5signature('111')
716         assert '698d51a19d8a121ce581499d7b701668' == s, s
717
718         s = MD5signature('222')
719         assert 'bcbe3365e6ac95ea2c0343a2395834dd' == s, s
720
721 if __name__ == "__main__":
722     suite = unittest.TestSuite()
723     tclasses = [ dictifyTestCase,
724                  MD5TestCase,
725                  UtilTestCase,
726                ]
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():
731         sys.exit(1)