2 # Copyright (c) 2001 Steven Knight
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:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
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.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26 # Define a null function for use as a builder action.
27 # Where this is defined in the file seems to affect its
28 # byte-code contents, so try to minimize changes by
29 # defining it here, before we even import anything.
39 # Initial setup of the common environment for all tests,
40 # a temporary working directory containing a
41 # script for writing arguments to an output file.
43 # We don't do this as a setUp() method because it's
44 # unnecessary to create a separate directory and script
45 # for each test, they can just use the one.
46 test = TestCmd.TestCmd(workdir = '')
48 test.write('act.py', """import os, string, sys
49 f = open(sys.argv[1], 'w')
50 f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n")
53 f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n")
60 act_py = test.workpath('act.py')
61 outfile = test.workpath('outfile')
71 class BuilderTestCase(unittest.TestCase):
73 def test__call__(self):
74 """Test calling a builder to establish source dependencies
77 def __init__(self, name):
83 def builder_set(self, builder):
84 self.builder = builder
85 def env_set(self, env, safe=0):
87 def add_source(self, source):
88 self.sources.extend(source)
89 builder = SCons.Builder.Builder(action = "foo")
92 builder(env, target = n1, source = n2)
94 assert n1.builder == builder
95 assert n1.sources == [n2]
98 def test_action(self):
99 """Test Builder creation
101 Verify that we can retrieve the supplied action attribute.
103 builder = SCons.Builder.Builder(action = "foo")
104 assert builder.action.command == "foo"
107 """Test simple comparisons of Builder objects
109 b1 = SCons.Builder.Builder(src_suffix = '.o')
110 b2 = SCons.Builder.Builder(src_suffix = '.o')
112 b3 = SCons.Builder.Builder(src_suffix = '.x')
116 def test_execute(self):
117 """Test execution of simple Builder objects
119 One Builder is a string that executes an external command,
120 one is an internal Python function, one is a list
121 containing one of each.
124 python = sys.executable
126 cmd1 = r'%s %s %s xyzzy' % (python, act_py, outfile)
128 builder = SCons.Builder.Builder(action = cmd1)
129 r = builder.execute()
131 c = test.read(outfile, 'r')
132 assert c == "act.py: 'xyzzy'\n", c
134 cmd2 = r'%s %s %s $TARGET' % (python, act_py, outfile)
136 builder = SCons.Builder.Builder(action = cmd2)
137 r = builder.execute(target = 'foo')
139 c = test.read(outfile, 'r')
140 assert c == "act.py: 'foo'\n", c
142 cmd3 = r'%s %s %s ${TARGETS}' % (python, act_py, outfile)
144 builder = SCons.Builder.Builder(action = cmd3)
145 r = builder.execute(target = ['aaa', 'bbb'])
147 c = test.read(outfile, 'r')
148 assert c == "act.py: 'aaa' 'bbb'\n", c
150 cmd4 = r'%s %s %s $SOURCES' % (python, act_py, outfile)
152 builder = SCons.Builder.Builder(action = cmd4)
153 r = builder.execute(source = ['one', 'two'])
155 c = test.read(outfile, 'r')
156 assert c == "act.py: 'one' 'two'\n", c
158 cmd4 = r'%s %s %s ${SOURCES[:2]}' % (python, act_py, outfile)
160 builder = SCons.Builder.Builder(action = cmd4)
161 r = builder.execute(source = ['three', 'four', 'five'])
163 c = test.read(outfile, 'r')
164 assert c == "act.py: 'three' 'four'\n", c
166 cmd5 = r'%s %s %s $TARGET XYZZY' % (python, act_py, outfile)
168 builder = SCons.Builder.Builder(action = cmd5)
169 r = builder.execute(target = 'out5', env = {'ENV' : {'XYZZY' : 'xyzzy'}})
171 c = test.read(outfile, 'r')
172 assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy'\n", c
174 cmd7 = '%s %s %s one\n\n%s %s %s two' % (python, act_py, outfile,
175 python, act_py, outfile)
176 expect7 = '%s %s %s one\n%s %s %s two\n' % (python, act_py, outfile,
177 python, act_py, outfile)
179 builder = SCons.Builder.Builder(action = cmd7)
185 show_string = show_string + string + "\n"
186 builder.action.show = my_show
188 r = builder.execute()
190 assert show_string == expect7, show_string
193 open(kw['out'], 'w').write("function1\n")
196 builder = SCons.Builder.Builder(action = function1)
197 r = builder.execute(out = outfile)
199 c = test.read(outfile, 'r')
200 assert c == "function1\n", c
203 def __init__(self, **kw):
204 open(kw['out'], 'w').write("class1a\n")
206 builder = SCons.Builder.Builder(action = class1a)
207 r = builder.execute(out = outfile)
208 assert r.__class__ == class1a
209 c = test.read(outfile, 'r')
210 assert c == "class1a\n", c
213 def __call__(self, **kw):
214 open(kw['out'], 'w').write("class1b\n")
217 builder = SCons.Builder.Builder(action = class1b())
218 r = builder.execute(out = outfile)
220 c = test.read(outfile, 'r')
221 assert c == "class1b\n", c
223 cmd2 = r'%s %s %s syzygy' % (python, act_py, outfile)
226 open(kw['out'], 'a').write("function2\n")
230 def __call__(self, **kw):
231 open(kw['out'], 'a').write("class2a\n")
235 def __init__(self, **kw):
236 open(kw['out'], 'a').write("class2b\n")
238 builder = SCons.Builder.Builder(action = [cmd2, function2, class2a(), class2b])
239 r = builder.execute(out = outfile)
240 assert r.__class__ == class2b
241 c = test.read(outfile, 'r')
242 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
244 def test_get_contents(self):
245 """Test returning the signature contents of a Builder
248 b1 = SCons.Builder.Builder(action = "foo")
249 contents = b1.get_contents()
250 assert contents == "foo", contents
252 b2 = SCons.Builder.Builder(action = Func)
253 contents = b2.get_contents()
254 assert contents == "\177\036\000\177\037\000d\000\000S", repr(contents)
256 b3 = SCons.Builder.Builder(action = ["foo", Func, "bar"])
257 contents = b3.get_contents()
258 assert contents == "foo\177\036\000\177\037\000d\000\000Sbar", repr(contents)
261 """Test Builder creation with a specified name
263 builder = SCons.Builder.Builder(name = 'foo')
264 assert builder.name == 'foo'
266 def test_node_factory(self):
267 """Test a Builder that creates nodes of a specified class
271 def FooFactory(target):
274 builder = SCons.Builder.Builder(node_factory = FooFactory)
275 assert builder.node_factory is FooFactory
277 def test_prefix(self):
278 """Test Builder creation with a specified target prefix
280 Make sure that there is no '.' separator appended.
282 builder = SCons.Builder.Builder(prefix = 'lib.')
283 assert builder.prefix == 'lib.'
284 builder = SCons.Builder.Builder(prefix = 'lib')
285 assert builder.prefix == 'lib'
286 tgt = builder(env, target = 'tgt1', source = 'src1')
287 assert tgt.path == 'libtgt1', \
288 "Target has unexpected name: %s" % tgt.path
290 def test_src_suffix(self):
291 """Test Builder creation with a specified source file suffix
293 Make sure that the '.' separator is appended to the
294 beginning if it isn't already present.
296 builder = SCons.Builder.Builder(src_suffix = '.c')
297 assert builder.src_suffix == '.c'
298 builder = SCons.Builder.Builder(src_suffix = 'c')
299 assert builder.src_suffix == '.c'
300 tgt = builder(env, target = 'tgt2', source = 'src2')
301 assert tgt.sources[0].path == 'src2.c', \
302 "Source has unexpected name: %s" % tgt.sources[0].path
304 def test_suffix(self):
305 """Test Builder creation with a specified target suffix
307 Make sure that the '.' separator is appended to the
308 beginning if it isn't already present.
310 builder = SCons.Builder.Builder(suffix = '.o')
311 assert builder.suffix == '.o'
312 builder = SCons.Builder.Builder(suffix = 'o')
313 assert builder.suffix == '.o'
314 tgt = builder(env, target = 'tgt3', source = 'src3')
315 assert tgt.path == 'tgt3.o', \
316 "Target has unexpected name: %s" % tgt[0].path
318 def test_MultiStepBuilder(self):
319 """Testing MultiStepBuilder class."""
320 builder1 = SCons.Builder.Builder(action='foo',
323 builder2 = SCons.Builder.MultiStepBuilder(action='foo',
324 src_builder = builder1)
325 tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt')
327 for snode in tgt.sources:
328 if snode.path == 'test.foo':
330 assert snode.sources[0].path == 'test.bar'
333 def test_CompositeBuilder(self):
334 """Testing CompositeBuilder class."""
335 builder = SCons.Builder.Builder(action={ '.foo' : 'foo',
338 assert isinstance(builder, SCons.Builder.CompositeBuilder)
339 tgt = builder(env, target='test1', source='test1.foo')
340 assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
341 assert tgt.builder.action.command == 'foo'
342 tgt = builder(env, target='test2', source='test2.bar')
343 assert tgt.builder.action.command == 'bar'
346 tgt = builder(env, target='test2', source='test2.bar test1.foo')
347 except SCons.Errors.UserError:
349 assert flag, "UserError should be thrown when we build targets with files of different suffixes."
351 def test_build_scanner(self):
352 """Testing ability to set a target scanner through a builder."""
355 def instance(self, env):
360 builder=SCons.Builder.Builder(scanner=scn)
361 tgt = builder(env, target='foo', source='bar')
362 assert tgt.scanner == scn, tgt.scanner
366 builder1 = SCons.Builder.Builder(action='foo',
369 builder2 = SCons.Builder.Builder(action='foo',
370 src_builder = builder1,
372 tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt')
373 assert tgt.scanner == scn, tgt.scanner
376 if __name__ == "__main__":
377 suite = unittest.makeSuite(BuilderTestCase, 'test_')
378 if not unittest.TextTestRunner().run(suite).wasSuccessful():