bb698341268a920fc1cb9f6cde8cf2c525785d20
[scons.git] / src / engine / SCons / UtilTests.py
1 #
2 # Copyright (c) 2001, 2002 Steven Knight
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 re
29 import string
30 import sys
31 import unittest
32 import SCons.Node
33 import SCons.Node.FS
34 from SCons.Util import *
35 import TestCmd
36
37 class UtilTestCase(unittest.TestCase):
38     def test_str2nodes(self):
39         """Test the str2nodes function."""
40         nodes = scons_str2nodes("Util.py UtilTests.py")
41         assert len(nodes) == 2
42         assert isinstance(nodes[0], SCons.Node.FS.File)
43         assert isinstance(nodes[1], SCons.Node.FS.File)
44         assert nodes[0].path == "Util.py"
45         assert nodes[1].path == "UtilTests.py"
46
47         nodes = scons_str2nodes("Util.py UtilTests.py", SCons.Node.FS.FS().File)
48         assert len(nodes) == 2
49         assert isinstance(nodes[0], SCons.Node.FS.File)
50         assert isinstance(nodes[1], SCons.Node.FS.File)
51         assert nodes[0].path == "Util.py"
52         assert nodes[1].path == "UtilTests.py"
53
54         nodes = scons_str2nodes(["Util.py", "UtilTests.py"])
55         assert len(nodes) == 2
56         assert isinstance(nodes[0], SCons.Node.FS.File)
57         assert isinstance(nodes[1], SCons.Node.FS.File)
58         assert nodes[0].path == "Util.py"
59         assert nodes[1].path == "UtilTests.py"
60
61         n1 = SCons.Node.FS.default_fs.File("Util.py")
62         nodes = scons_str2nodes([n1, "UtilTests.py"])
63         assert len(nodes) == 2
64         assert isinstance(nodes[0], SCons.Node.FS.File)
65         assert isinstance(nodes[1], SCons.Node.FS.File)
66         assert nodes[0].path == "Util.py"
67         assert nodes[1].path == "UtilTests.py"
68
69         class SConsNode(SCons.Node.Node):
70             pass
71         node = scons_str2nodes(SConsNode())
72
73         class OtherNode:
74             pass
75         node = scons_str2nodes(OtherNode())
76
77
78     def test_subst(self):
79         """Test the subst function."""
80         loc = {}
81         loc['TARGETS'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
82                                                           "/bar/baz.obj",
83                                                           "../foo/baz.obj" ]))
84         loc['TARGET'] = loc['TARGETS'][0]
85         loc['SOURCES'] = PathList(map(os.path.normpath, [ "./foo/blah.cpp",
86                                                           "/bar/ack.cpp",
87                                                           "../foo/ack.c" ]))
88         loc['xxx'] = None
89
90         if os.sep == '/':
91             def cvt(str):
92                 return str
93         else:
94             def cvt(str):
95                 return string.replace(str, '/', os.sep)
96
97
98         newcom = scons_subst("test $TARGETS $SOURCES", loc, {})
99         assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp /bar/ack.cpp ../foo/ack.c")
100
101         newcom = scons_subst("test ${TARGETS[:]} ${SOURCES[0]}", loc, {})
102         assert newcom == cvt("test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp")
103
104         newcom = scons_subst("test ${TARGETS[1:]}v", loc, {})
105         assert newcom == cvt("test /bar/baz.obj ../foo/baz.objv")
106
107         newcom = scons_subst("test $TARGET", loc, {})
108         assert newcom == cvt("test foo/bar.exe")
109
110         newcom = scons_subst("test $TARGET$SOURCE[0]", loc, {})
111         assert newcom == cvt("test foo/bar.exe[0]")
112
113         newcom = scons_subst("test ${TARGET.file}", loc, {})
114         assert newcom == cvt("test bar.exe")
115
116         newcom = scons_subst("test ${TARGET.filebase}", loc, {})
117         assert newcom == cvt("test bar")
118
119         newcom = scons_subst("test ${TARGET.suffix}", loc, {})
120         assert newcom == cvt("test .exe")
121
122         newcom = scons_subst("test ${TARGET.base}", loc, {})
123         assert newcom == cvt("test foo/bar")
124
125         newcom = scons_subst("test ${TARGET.dir}", loc, {})
126         assert newcom == cvt("test foo")
127
128         newcom = scons_subst("test $xxx", loc, {})
129         assert newcom == cvt("test"), newcom
130
131         newcom = scons_subst("test $($xxx$)", loc, {})
132         assert newcom == cvt("test $($)"), newcom
133
134         newcom = scons_subst("test $( $xxx $)", loc, {})
135         assert newcom == cvt("test $( $)"), newcom
136
137         newcom = scons_subst("test $($xxx$)", loc, {}, re.compile('\$[()]'))
138         assert newcom == cvt("test"), newcom
139
140         newcom = scons_subst("test $( $xxx $)", loc, {}, re.compile('\$[()]'))
141         assert newcom == cvt("test"), newcom
142
143         newcom = scons_subst("test aXbXcXd", loc, {}, re.compile('X'))
144         assert newcom == cvt("test abcd"), newcom
145
146     def test_subst_list(self):
147         """Testing the scons_subst_list() method..."""
148         loc = {}
149         loc['TARGETS'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
150                                                           "/bar/baz with spaces.obj",
151                                                           "../foo/baz.obj" ]))
152         loc['TARGET'] = loc['TARGETS'][0]
153         loc['SOURCES'] = PathList(map(os.path.normpath, [ "./foo/blah with spaces.cpp",
154                                                           "/bar/ack.cpp",
155                                                           "../foo/ack.c" ]))
156         loc['xxx'] = None
157         loc['NEWLINE'] = 'before\nafter'
158
159         if os.sep == '/':
160             def cvt(str):
161                 return str
162         else:
163             def cvt(str):
164                 return string.replace(str, '/', os.sep)
165
166         cmd_list = scons_subst_list("$TARGETS", loc, {})
167         assert cmd_list[0][1] == cvt("/bar/baz with spaces.obj"), cmd_list[0][1]
168
169         cmd_list = scons_subst_list("$SOURCES $NEWLINE $TARGETS", loc, {})
170         assert len(cmd_list) == 2, cmd_list
171         assert cmd_list[0][0] == cvt('foo/blah with spaces.cpp'), cmd_list[0][0]
172         assert cmd_list[1][2] == cvt("/bar/baz with spaces.obj"), cmd_list[1]
173
174         cmd_list = scons_subst_list("$SOURCES$NEWLINE", loc, {})
175         assert len(cmd_list) == 2, cmd_list
176         assert cmd_list[1][0] == 'after', cmd_list[1][0]
177         assert cmd_list[0][2] == cvt('../foo/ack.cbefore'), cmd_list[0][2]
178
179     def test_find_file(self):
180         """Testing find_file function."""
181         test = TestCmd.TestCmd(workdir = '')
182         test.write('./foo', 'Some file\n')
183         fs = SCons.Node.FS.FS(test.workpath(""))
184         os.chdir(test.workpath("")) # FS doesn't like the cwd to be something other than it's root
185         node_derived = fs.File(test.workpath('bar/baz'))
186         node_derived.builder_set(1) # Any non-zero value.
187         paths = map(fs.Dir, ['.', './bar'])
188         nodes = [find_file('foo', paths, fs.File), 
189                  find_file('baz', paths, fs.File)] 
190         file_names = map(str, nodes)
191         file_names = map(os.path.normpath, file_names)
192         assert os.path.normpath('./foo') in file_names, file_names
193         assert os.path.normpath('./bar/baz') in file_names, file_names
194
195     def test_autogenerate(dict):
196         """Test autogenerating variables in a dictionary."""
197         dict = {'LIBS'          : [ 'foo', 'bar', 'baz' ],
198                 'LIBLINKPREFIX' : 'foo',
199                 'LIBLINKSUFFIX' : 'bar'}
200         autogenerate(dict, dir = SCons.Node.FS.default_fs.Dir('/xx'))
201         assert len(dict['_LIBFLAGS']) == 3, dict('_LIBFLAGS')
202         assert dict['_LIBFLAGS'][0] == 'foofoobar', \
203                dict['_LIBFLAGS'][0]
204         assert dict['_LIBFLAGS'][1] == 'foobarbar', \
205                dict['_LIBFLAGS'][1]
206         assert dict['_LIBFLAGS'][2] == 'foobazbar', \
207                dict['_LIBFLAGS'][2]
208
209         blat = SCons.Node.FS.default_fs.File('blat')
210         dict = {'CPPPATH'   : [ 'foo', 'bar', 'baz', '$FOO/bar', blat],
211                 'INCPREFIX' : 'foo',
212                 'INCSUFFIX' : 'bar',
213                 'FOO'       : 'baz' }
214         autogenerate(dict, dir = SCons.Node.FS.default_fs.Dir('/xx'))
215         assert len(dict['_INCFLAGS']) == 7, dict['_INCFLAGS']
216         assert dict['_INCFLAGS'][0] == '$(', \
217                dict['_INCFLAGS'][0]
218         assert dict['_INCFLAGS'][1] == os.path.normpath('foo/xx/foobar'), \
219                dict['_INCFLAGS'][1]
220         assert dict['_INCFLAGS'][2] == os.path.normpath('foo/xx/barbar'), \
221                dict['_INCFLAGS'][2]
222         assert dict['_INCFLAGS'][3] == os.path.normpath('foo/xx/bazbar'), \
223                dict['_INCFLAGS'][3]
224         assert dict['_INCFLAGS'][4] == os.path.normpath('foo/xx/baz/barbar'), \
225                dict['_INCFLAGS'][4]
226         
227         assert dict['_INCFLAGS'][5] == os.path.normpath('fooblatbar'), \
228                dict['_INCFLAGS'][5]
229         assert dict['_INCFLAGS'][6] == '$)', \
230                dict['_INCFLAGS'][6]
231
232     def test_render_tree(self):
233         class Node:
234             def __init__(self, name, children=[]):
235                 self.children = children
236                 self.name = name
237             def __str__(self):
238                 return self.name
239
240         def get_children(node):
241             return node.children
242
243         windows_h = Node("windows.h")
244         stdlib_h = Node("stdlib.h")
245         stdio_h = Node("stdio.h")
246         bar_c = Node("bar.c", [stdlib_h, windows_h])
247         bar_o = Node("bar.o", [bar_c])
248         foo_c = Node("foo.c", [stdio_h])
249         foo_o = Node("foo.o", [foo_c])
250         foo = Node("foo", [foo_o, bar_o])
251
252         expect = """\
253 +-foo
254   +-foo.o
255   | +-foo.c
256   |   +-stdio.h
257   +-bar.o
258     +-bar.c
259       +-stdlib.h
260       +-windows.h
261 """
262
263         actual = render_tree(foo, get_children)
264         assert expect == actual, (expect, actual)
265
266     def test_is_Dict(self):
267         assert is_Dict({})
268         import UserDict
269         assert is_Dict(UserDict.UserDict())
270         assert not is_Dict([])
271         assert not is_Dict("")
272
273     def test_is_List(self):
274         assert is_List([])
275         import UserList
276         assert is_List(UserList.UserList())
277         assert not is_List({})
278         assert not is_List("")
279
280     def test_is_String(self):
281         assert is_String("")
282         try:
283             import UserString
284         except:
285             pass
286         else:
287             assert is_String(UserString.UserString(''))
288         assert not is_String({})
289         assert not is_String([])
290
291 if __name__ == "__main__":
292     suite = unittest.makeSuite(UtilTestCase, 'test_')
293     if not unittest.TextTestRunner().run(suite).wasSuccessful():
294         sys.exit(1)