Add a NoClean() function. (Steven Johnson)
[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 UtilTestCase(unittest.TestCase):
50     def test_splitext(self):
51         assert splitext('foo') == ('foo','')
52         assert splitext('foo.bar') == ('foo','.bar')
53         assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
54
55     class Node:
56         def __init__(self, name, children=[]):
57             self.children = children
58             self.name = name
59         def __str__(self):
60             return self.name
61         def exists(self):
62             return 1
63         def rexists(self):
64             return 1
65         def has_builder(self):
66             return 1
67         def has_explicit_builder(self):
68             return 1
69         def side_effect(self):
70             return 1
71         def precious(self):
72             return 1
73         def always_build(self):
74             return 1
75         def current(self):
76             return 1
77         def noclean(self):
78             return 1
79
80     def tree_case_1(self):
81         """Fixture for the render_tree() and print_tree() tests."""
82         windows_h = self.Node("windows.h")
83         stdlib_h = self.Node("stdlib.h")
84         stdio_h = self.Node("stdio.h")
85         bar_c = self.Node("bar.c", [stdlib_h, windows_h])
86         bar_o = self.Node("bar.o", [bar_c])
87         foo_c = self.Node("foo.c", [stdio_h])
88         foo_o = self.Node("foo.o", [foo_c])
89         foo = self.Node("foo", [foo_o, bar_o])
90
91         expect = """\
92 +-foo
93   +-foo.o
94   | +-foo.c
95   |   +-stdio.h
96   +-bar.o
97     +-bar.c
98       +-stdlib.h
99       +-windows.h
100 """
101
102         lines = string.split(expect, '\n')[:-1]
103         lines = map(lambda l: '[E BSPACN]'+l, lines)
104         withtags = string.join(lines, '\n') + '\n'
105
106         return foo, expect, withtags
107
108     def tree_case_2(self):
109         """Fixture for the render_tree() and print_tree() tests."""
110
111         stdlib_h = self.Node("stdlib.h")
112         bar_h = self.Node('bar.h', [stdlib_h])
113         blat_h = self.Node('blat.h', [stdlib_h])
114         blat_c = self.Node('blat.c', [blat_h, bar_h])
115         blat_o = self.Node('blat.o', [blat_c])
116
117         expect = """\
118 +-blat.o
119   +-blat.c
120     +-blat.h
121     | +-stdlib.h
122     +-bar.h
123 """
124
125         lines = string.split(expect, '\n')[:-1]
126         lines = map(lambda l: '[E BSPACN]'+l, lines)
127         withtags = string.join(lines, '\n') + '\n'
128
129         return blat_o, expect, withtags
130
131     def test_render_tree(self):
132         """Test the render_tree() function"""
133         def get_children(node):
134             return node.children
135
136         node, expect, withtags = self.tree_case_1()
137         actual = render_tree(node, get_children)
138         assert expect == actual, (expect, actual)
139
140         node, expect, withtags = self.tree_case_2()
141         actual = render_tree(node, get_children, 1)
142         assert expect == actual, (expect, actual)
143
144     def test_print_tree(self):
145         """Test the print_tree() function"""
146         def get_children(node):
147             return node.children
148
149         save_stdout = sys.stdout
150
151         try:
152             node, expect, withtags = self.tree_case_1()
153
154             sys.stdout = StringIO.StringIO()
155             print_tree(node, get_children)
156             actual = sys.stdout.getvalue()
157             assert expect == actual, (expect, actual)
158
159             sys.stdout = StringIO.StringIO()
160             print_tree(node, get_children, showtags=1)
161             actual = sys.stdout.getvalue()
162             assert withtags == actual, (withtags, actual)
163
164             node, expect, withtags = self.tree_case_2()
165
166             sys.stdout = StringIO.StringIO()
167             print_tree(node, get_children, 1)
168             actual = sys.stdout.getvalue()
169             assert expect == actual, (expect, actual)
170
171             sys.stdout = StringIO.StringIO()
172             # The following call should work here:
173             #    print_tree(node, get_children, 1, showtags=1)
174             # For some reason I don't understand, though, *this*
175             # time that we call print_tree, the visited dictionary
176             # is still populated with the values from the last call!
177             # I can't see why this would be, short of a bug in Python,
178             # and rather than continue banging my head against the
179             # brick wall for a *test*, we're going to going with
180             # the cheap, easy workaround:
181             print_tree(node, get_children, 1, showtags=1, visited={})
182             actual = sys.stdout.getvalue()
183             assert withtags == actual, (withtags, actual)
184         finally:
185             sys.stdout = save_stdout
186
187     def test_is_Dict(self):
188         assert is_Dict({})
189         assert is_Dict(UserDict())
190         assert not is_Dict([])
191         assert not is_Dict("")
192         if hasattr(types, 'UnicodeType'):
193             exec "assert not is_Dict(u'')"
194
195     def test_is_List(self):
196         assert is_List([])
197         import UserList
198         assert is_List(UserList.UserList())
199         assert not is_List({})
200         assert not is_List("")
201         if hasattr(types, 'UnicodeType'):
202             exec "assert not is_List(u'')"
203
204     def test_is_String(self):
205         assert is_String("")
206         if hasattr(types, 'UnicodeType'):
207             exec "assert is_String(u'')"
208         try:
209             import UserString
210         except:
211             pass
212         else:
213             assert is_String(UserString.UserString(''))
214         assert not is_String({})
215         assert not is_String([])
216
217     def test_to_String(self):
218         """Test the to_String() method."""
219         assert to_String(1) == "1", to_String(1)
220         assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3])
221         assert to_String("foo") == "foo", to_String("foo")
222
223         try:
224             import UserString
225
226             s1=UserString.UserString('blah')
227             assert to_String(s1) == s1, s1
228             assert to_String(s1) == 'blah', s1
229
230             class Derived(UserString.UserString):
231                 pass
232             s2 = Derived('foo')
233             assert to_String(s2) == s2, s2
234             assert to_String(s2) == 'foo', s2
235
236             if hasattr(types, 'UnicodeType'):
237                 s3=UserString.UserString(unicode('bar'))
238                 assert to_String(s3) == s3, s3
239                 assert to_String(s3) == unicode('bar'), s3
240                 assert type(to_String(s3)) is types.UnicodeType, \
241                        type(to_String(s3))
242         except ImportError:
243             pass
244
245         if hasattr(types, 'UnicodeType'):
246             s4 = unicode('baz')
247             assert to_String(s4) == unicode('baz'), to_String(s4)
248             assert type(to_String(s4)) is types.UnicodeType, \
249                    type(to_String(s4))
250
251     def test_WhereIs(self):
252         test = TestCmd.TestCmd(workdir = '')
253
254         sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
255         sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
256         sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
257         sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
258
259         test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
260
261         if sys.platform != 'win32':
262             test.write(sub1_xxx_exe, "\n")
263
264         os.mkdir(sub2_xxx_exe)
265
266         test.write(sub3_xxx_exe, "\n")
267         os.chmod(sub3_xxx_exe, 0777)
268
269         test.write(sub4_xxx_exe, "\n")
270         os.chmod(sub4_xxx_exe, 0777)
271
272         env_path = os.environ['PATH']
273
274         try:
275             pathdirs_1234 = [ test.workpath('sub1'),
276                               test.workpath('sub2'),
277                               test.workpath('sub3'),
278                               test.workpath('sub4'),
279                             ] + string.split(env_path, os.pathsep)
280
281             pathdirs_1243 = [ test.workpath('sub1'),
282                               test.workpath('sub2'),
283                               test.workpath('sub4'),
284                               test.workpath('sub3'),
285                             ] + string.split(env_path, os.pathsep)
286
287             os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
288             wi = WhereIs('xxx.exe')
289             assert wi == test.workpath(sub3_xxx_exe), wi
290             wi = WhereIs('xxx.exe', pathdirs_1243)
291             assert wi == test.workpath(sub4_xxx_exe), wi
292             wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
293             assert wi == test.workpath(sub4_xxx_exe), wi
294
295             wi = WhereIs('xxx.exe',reject = sub3_xxx_exe)
296             assert wi == test.workpath(sub4_xxx_exe), wi
297             wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe)
298             assert wi == test.workpath(sub4_xxx_exe), wi
299
300             os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
301             wi = WhereIs('xxx.exe')
302             assert wi == test.workpath(sub4_xxx_exe), wi
303             wi = WhereIs('xxx.exe', pathdirs_1234)
304             assert wi == test.workpath(sub3_xxx_exe), wi
305             wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
306             assert wi == test.workpath(sub3_xxx_exe), wi
307
308             if sys.platform == 'win32':
309                 wi = WhereIs('xxx', pathext = '')
310                 assert wi is None, wi
311
312                 wi = WhereIs('xxx', pathext = '.exe')
313                 assert wi == test.workpath(sub4_xxx_exe), wi
314
315                 wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
316                 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
317
318                 # Test that we return a normalized path even when
319                 # the path contains forward slashes.
320                 forward_slash = test.workpath('') + '/sub3'
321                 wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE')
322                 assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
323
324             del os.environ['PATH']
325             wi = WhereIs('xxx.exe')
326             assert wi is None, wi
327
328         finally:
329             os.environ['PATH'] = env_path
330             
331
332     def test_is_valid_construction_var(self):
333         """Testing is_valid_construction_var()"""
334         r = is_valid_construction_var("_a")
335         assert not r is None, r
336         r = is_valid_construction_var("z_")
337         assert not r is None, r
338         r = is_valid_construction_var("X_")
339         assert not r is None, r
340         r = is_valid_construction_var("2a")
341         assert r is None, r
342         r = is_valid_construction_var("a2_")
343         assert not r is None, r
344         r = is_valid_construction_var("/")
345         assert r is None, r
346         r = is_valid_construction_var("_/")
347         assert r is None, r
348         r = is_valid_construction_var("a/")
349         assert r is None, r
350         r = is_valid_construction_var(".b")
351         assert r is None, r
352         r = is_valid_construction_var("_.b")
353         assert r is None, r
354         r = is_valid_construction_var("b1._")
355         assert r is None, r
356         r = is_valid_construction_var("-b")
357         assert r is None, r
358         r = is_valid_construction_var("_-b")
359         assert r is None, r
360         r = is_valid_construction_var("b1-_")
361         assert r is None, r
362
363     def test_get_env_var(self):
364         """Testing get_environment_var()."""
365         assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO")
366         assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}")
367         assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234")
368         assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}")
369         assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO")
370         assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ")
371         assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR")
372         assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]")
373         assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}")
374
375     def test_Proxy(self):
376         """Test generic Proxy class."""
377         class Subject:
378             def foo(self):
379                 return 1
380             def bar(self):
381                 return 2
382
383         s=Subject()
384         s.baz = 3
385
386         class ProxyTest(Proxy):
387             def bar(self):
388                 return 4
389
390         p=ProxyTest(s)
391
392         assert p.foo() == 1, p.foo()
393         assert p.bar() == 4, p.bar()
394         assert p.baz == 3, p.baz
395
396         p.baz = 5
397         s.baz = 6
398
399         assert p.baz == 5, p.baz
400         assert p.get() == s, p.get()
401
402     def test_display(self):
403         old_stdout = sys.stdout
404         sys.stdout = OutBuffer()
405         display("line1")
406         display.set_mode(0)
407         display("line2")
408         display.set_mode(1)
409         display("line3")
410         display("line4\n", append_newline=0)
411         display.set_mode(0)
412         display("dont print1")
413         display("dont print2\n", append_newline=0)
414         display.set_mode(1)
415         assert sys.stdout.buffer == "line1\nline3\nline4\n"
416         sys.stdout = old_stdout
417
418     def test_get_native_path(self):
419         """Test the get_native_path() function."""
420         import tempfile
421         filename = tempfile.mktemp()
422         str = '1234567890 ' + filename
423         try:
424             open(filename, 'w').write(str)
425             assert open(get_native_path(filename)).read() == str
426         finally:
427             try:
428                 os.unlink(filename)
429             except OSError:
430                 pass
431
432     def test_PrependPath(self):
433         """Test prepending to a path"""
434         p1 = r'C:\dir\num\one;C:\dir\num\two'
435         p2 = r'C:\mydir\num\one;C:\mydir\num\two'
436         # have to include the pathsep here so that the test will work on UNIX too.
437         p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';')
438         p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
439         p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';')
440         p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';')
441         assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
442         assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
443
444     def test_AppendPath(self):
445         """Test appending to a path."""
446         p1 = r'C:\dir\num\one;C:\dir\num\two'
447         p2 = r'C:\mydir\num\one;C:\mydir\num\two'
448         # have to include the pathsep here so that the test will work on UNIX too.
449         p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';')
450         p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
451         p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';')
452         p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';')
453         assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
454         assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
455
456     def test_NodeList(self):
457         """Test NodeList class"""
458         class TestClass:
459             def __init__(self, name, child=None):
460                 self.child = child
461                 self.bar = name
462             def foo(self):
463                 return self.bar + "foo"
464             def getself(self):
465                 return self
466
467         t1 = TestClass('t1', TestClass('t1child'))
468         t2 = TestClass('t2', TestClass('t2child'))
469         t3 = TestClass('t3')
470
471         nl = NodeList([t1, t2, t3])
472         assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo()
473         assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
474         assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar
475         assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \
476                nl[0:2].child.foo()
477         assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
478                nl[0:2].child.bar
479
480     def test_CLVar(self):
481         """Test the command-line construction variable class"""
482         f = SCons.Util.CLVar('a b')
483
484         r = f + 'c d'
485         assert isinstance(r, SCons.Util.CLVar), type(r)
486         assert r.data == ['a', 'b', 'c', 'd'], r.data
487         assert str(r) == 'a b c d', str(r)
488
489         r = f + ' c d'
490         assert isinstance(r, SCons.Util.CLVar), type(r)
491         assert r.data == ['a', 'b', 'c', 'd'], r.data
492         assert str(r) == 'a b c d', str(r)
493
494         r = f + ['c d']
495         assert isinstance(r, SCons.Util.CLVar), type(r)
496         assert r.data == ['a', 'b', 'c d'], r.data
497         assert str(r) == 'a b c d', str(r)
498
499         r = f + [' c d']
500         assert isinstance(r, SCons.Util.CLVar), type(r)
501         assert r.data == ['a', 'b', ' c d'], r.data
502         assert str(r) == 'a b  c d', str(r)
503
504         r = f + ['c', 'd']
505         assert isinstance(r, SCons.Util.CLVar), type(r)
506         assert r.data == ['a', 'b', 'c', 'd'], r.data
507         assert str(r) == 'a b c d', str(r)
508
509         r = f + [' c', 'd']
510         assert isinstance(r, SCons.Util.CLVar), type(r)
511         assert r.data == ['a', 'b', ' c', 'd'], r.data
512         assert str(r) == 'a b  c d', str(r)
513
514         f = SCons.Util.CLVar(['a b'])
515
516         r = f + 'c d'
517         assert isinstance(r, SCons.Util.CLVar), type(r)
518         assert r.data == ['a b', 'c', 'd'], r.data
519         assert str(r) == 'a b c d', str(r)
520
521         r = f + ' c d'
522         assert isinstance(r, SCons.Util.CLVar), type(r)
523         assert r.data == ['a b', 'c', 'd'], r.data
524         assert str(r) == 'a b c d', str(r)
525
526         r = f + ['c d']
527         assert isinstance(r, SCons.Util.CLVar), type(r)
528         assert r.data == ['a b', 'c d'], r.data
529         assert str(r) == 'a b c d', str(r)
530
531         r = f + [' c d']
532         assert isinstance(r, SCons.Util.CLVar), type(r)
533         assert r.data == ['a b', ' c d'], r.data
534         assert str(r) == 'a b  c d', str(r)
535
536         r = f + ['c', 'd']
537         assert isinstance(r, SCons.Util.CLVar), type(r)
538         assert r.data == ['a b', 'c', 'd'], r.data
539         assert str(r) == 'a b c d', str(r)
540
541         r = f + [' c', 'd']
542         assert isinstance(r, SCons.Util.CLVar), type(r)
543         assert r.data == ['a b', ' c', 'd'], r.data
544         assert str(r) == 'a b  c d', str(r)
545
546         f = SCons.Util.CLVar(['a', 'b'])
547
548         r = f + 'c d'
549         assert isinstance(r, SCons.Util.CLVar), type(r)
550         assert r.data == ['a', 'b', 'c', 'd'], r.data
551         assert str(r) == 'a b c d', str(r)
552
553         r = f + ' c d'
554         assert isinstance(r, SCons.Util.CLVar), type(r)
555         assert r.data == ['a', 'b', 'c', 'd'], r.data
556         assert str(r) == 'a b c d', str(r)
557
558         r = f + ['c d']
559         assert isinstance(r, SCons.Util.CLVar), type(r)
560         assert r.data == ['a', 'b', 'c d'], r.data
561         assert str(r) == 'a b c d', str(r)
562
563         r = f + [' c d']
564         assert isinstance(r, SCons.Util.CLVar), type(r)
565         assert r.data == ['a', 'b', ' c d'], r.data
566         assert str(r) == 'a b  c d', str(r)
567
568         r = f + ['c', 'd']
569         assert isinstance(r, SCons.Util.CLVar), type(r)
570         assert r.data == ['a', 'b', 'c', 'd'], r.data
571         assert str(r) == 'a b c d', str(r)
572
573         r = f + [' c', 'd']
574         assert isinstance(r, SCons.Util.CLVar), type(r)
575         assert r.data == ['a', 'b', ' c', 'd'], r.data
576         assert str(r) == 'a b  c d', str(r)
577
578     def test_Selector(self):
579         """Test the Selector class"""
580
581         s = Selector({'a' : 'AAA', 'b' : 'BBB'})
582         assert s['a'] == 'AAA', s['a']
583         assert s['b'] == 'BBB', s['b']
584         exc_caught = None
585         try:
586             x = s['c']
587         except KeyError:
588             exc_caught = 1
589         assert exc_caught, "should have caught a KeyError"
590         s['c'] = 'CCC'
591         assert s['c'] == 'CCC', s['c']
592
593         class DummyEnv(UserDict):
594             def subst(self, key):
595                 if key[0] == '$':
596                     return self[key[1:]]
597                 return key
598
599         env = DummyEnv()
600
601         s = Selector({'.d' : 'DDD', '.e' : 'EEE'})
602         ret = s(env, [])
603         assert ret == None, ret
604         ret = s(env, ['foo.d'])
605         assert ret == 'DDD', ret
606         ret = s(env, ['bar.e'])
607         assert ret == 'EEE', ret
608         ret = s(env, ['bar.x'])
609         assert ret == None, ret
610         s[None] = 'XXX'
611         ret = s(env, ['bar.x'])
612         assert ret == 'XXX', ret
613
614         env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'})
615
616         s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'})
617         ret = s(env, ['foo.f'])
618         assert ret == 'FFF', ret
619         ret = s(env, ['bar.g'])
620         assert ret == 'GGG', ret
621
622     def test_adjustixes(self):
623         """Test the adjustixes() function"""
624         r = adjustixes('file', 'pre-', '-suf')
625         assert r == 'pre-file-suf', r
626         r = adjustixes('pre-file', 'pre-', '-suf')
627         assert r == 'pre-file-suf', r
628         r = adjustixes('file-suf', 'pre-', '-suf')
629         assert r == 'pre-file-suf', r
630         r = adjustixes('pre-file-suf', 'pre-', '-suf')
631         assert r == 'pre-file-suf', r
632         r = adjustixes('pre-file.xxx', 'pre-', '-suf')
633         assert r == 'pre-file.xxx', r
634         r = adjustixes('dir/file', 'pre-', '-suf')
635         assert r == os.path.join('dir', 'pre-file-suf'), r
636
637     def test_containsAny(self):
638         """Test the containsAny() function"""
639         assert containsAny('*.py', '*?[]')
640         assert not containsAny('file.txt', '*?[]')
641
642     def test_containsAll(self):
643         """Test the containsAll() function"""
644         assert containsAll('43221', '123')
645         assert not containsAll('134', '123')
646
647     def test_containsOnly(self):
648         """Test the containsOnly() function"""
649         assert containsOnly('.83', '0123456789.')
650         assert not containsOnly('43221', '123')
651
652     def test_LogicalLines(self):
653         """Test the LogicalLines class"""
654         fobj = StringIO.StringIO(r"""
655 foo \
656 bar \
657 baz
658 foo
659 bling \
660 bling \ bling
661 bling
662 """)
663
664         lines = LogicalLines(fobj).readlines()
665         assert lines == [
666             '\n',
667             'foo bar baz\n',
668             'foo\n',
669             'bling bling \\ bling\n',
670             'bling\n',
671         ], lines
672
673 if __name__ == "__main__":
674     suite = unittest.makeSuite(UtilTestCase, 'test_')
675     if not unittest.TextTestRunner().run(suite).wasSuccessful():
676         sys.exit(1)