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.
42 import SCons.Environment
47 # Initial setup of the common environment for all tests,
48 # a temporary working directory containing a
49 # script for writing arguments to an output file.
51 # We don't do this as a setUp() method because it's
52 # unnecessary to create a separate directory and script
53 # for each test, they can just use the one.
54 test = TestCmd.TestCmd(workdir = '')
56 test.write('act.py', """import os, string, sys
57 f = open(sys.argv[1], 'w')
58 f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n")
61 f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n")
65 if os.environ.has_key( 'ACTPY_PIPE' ):
66 sys.stdout.write( 'act.py: stdout: executed act.py\\n' )
67 sys.stderr.write( 'act.py: stderr: executed act.py\\n' )
71 act_py = test.workpath('act.py')
73 outfile = test.workpath('outfile')
74 outfile2 = test.workpath('outfile2')
76 scons_env = SCons.Environment.Environment()
78 # Capture all the stuff the Actions will print,
79 # so it doesn't clutter the output.
80 sys.stdout = StringIO.StringIO()
83 def __init__(self, **kw):
85 self.d['SHELL'] = scons_env['SHELL']
86 self.d['SPAWN'] = scons_env['SPAWN']
87 self.d['PSPAWN'] = scons_env['PSPAWN']
88 self.d['ESCAPE'] = scons_env['ESCAPE']
89 for k, v in kw.items():
92 if not SCons.Util.is_String(s):
97 return self.d.get(s[2:-1], '')
99 return self.d.get(s[1:], '')
102 return self.d.get(s, s)
103 def __getitem__(self, item):
105 def __setitem__(self, item, value):
107 def has_key(self, item):
108 return self.d.has_key(item)
109 def get(self, key, value):
110 return self.d.get(key, value)
112 return self.d.items()
113 def Dictionary(self):
115 def Copy(self, **kw):
117 res.d = SCons.Environment.our_deepcopy(self.d)
118 for k, v in kw.items():
123 for k,v in self.items(): d[k] = v
124 d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__']
125 d['TARGET'] = d['TARGETS'][0]
126 d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__']
127 d['SOURCE'] = d['SOURCES'][0]
131 def __init__(self, name):
137 def get_subst_proxy(self):
140 if os.name == 'java':
141 python = os.path.join(sys.prefix, 'jython')
143 python = sys.executable
145 class ActionTestCase(unittest.TestCase):
147 def test_factory(self):
148 """Test the Action factory
154 a1 = SCons.Action.Action(foo)
155 assert isinstance(a1, SCons.Action.FunctionAction), a1
156 assert a1.execfunction == foo, a1.execfunction
158 a2 = SCons.Action.Action("string")
159 assert isinstance(a2, SCons.Action.CommandAction), a2
160 assert a2.cmd_list == "string", a2.cmd_list
162 if hasattr(types, 'UnicodeType'):
163 exec "a3 = SCons.Action.Action(u'string')"
164 exec "assert isinstance(a3, SCons.Action.CommandAction), a3"
166 a4 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]])
167 assert isinstance(a4, SCons.Action.ListAction), a4
168 assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0]
169 assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list
170 assert isinstance(a4.list[1], SCons.Action.CommandAction), a4.list[1]
171 assert a4.list[1].cmd_list == "y", a4.list[1].cmd_list
172 assert isinstance(a4.list[2], SCons.Action.CommandAction), a4.list[2]
173 assert a4.list[2].cmd_list == "z", a4.list[2].cmd_list
174 assert isinstance(a4.list[3], SCons.Action.CommandAction), a4.list[3]
175 assert a4.list[3].cmd_list == [ "a", "b", "c" ], a4.list[3].cmd_list
177 a5 = SCons.Action.Action(1)
178 assert a5 is None, a5
180 a6 = SCons.Action.Action(a1)
183 a7 = SCons.Action.Action([[ "explicit", "command", "line" ]])
184 assert isinstance(a7, SCons.Action.CommandAction), a7
185 assert a7.cmd_list == [ "explicit", "command", "line" ], a7.cmd_list
187 a8 = SCons.Action.Action(["a8"])
188 assert isinstance(a8, SCons.Action.CommandAction), a8
189 assert a8.cmd_list == "a8", a8.cmd_list
191 a9 = SCons.Action.Action("x\ny\nz")
192 assert isinstance(a9, SCons.Action.ListAction), a9
193 assert isinstance(a9.list[0], SCons.Action.CommandAction), a9.list[0]
194 assert a9.list[0].cmd_list == "x", a9.list[0].cmd_list
195 assert isinstance(a9.list[1], SCons.Action.CommandAction), a9.list[1]
196 assert a9.list[1].cmd_list == "y", a9.list[1].cmd_list
197 assert isinstance(a9.list[2], SCons.Action.CommandAction), a9.list[2]
198 assert a9.list[2].cmd_list == "z", a9.list[2].cmd_list
200 a10 = SCons.Action.Action(["x", foo, "z"])
201 assert isinstance(a10, SCons.Action.ListAction), a10
202 assert isinstance(a10.list[0], SCons.Action.CommandAction), a10.list[0]
203 assert a10.list[0].cmd_list == "x", a10.list[0].cmd_list
204 assert isinstance(a10.list[1], SCons.Action.FunctionAction), a10.list[1]
205 assert a10.list[1].execfunction == foo, a10.list[1].execfunction
206 assert isinstance(a10.list[2], SCons.Action.CommandAction), a10.list[2]
207 assert a10.list[2].cmd_list == "z", a10.list[2].cmd_list
209 a11 = SCons.Action.Action(foo, strfunction=bar)
210 assert isinstance(a11, SCons.Action.FunctionAction), a11
211 assert a11.execfunction == foo, a11.execfunction
212 assert a11.strfunction == bar, a11.strfunction
214 class ActionBaseTestCase(unittest.TestCase):
217 """Test Action comparison
219 a1 = SCons.Action.Action("x")
220 a2 = SCons.Action.Action("x")
222 a3 = SCons.Action.Action("y")
227 """Test the show() method
229 save_stdout = sys.stdout
231 save = SCons.Action.print_actions
232 SCons.Action.print_actions = 0
234 sio = StringIO.StringIO()
236 a = SCons.Action.Action("x")
241 SCons.Action.print_actions = 1
243 sio = StringIO.StringIO()
247 assert s == "foobar\n", s
249 SCons.Action.print_actions = save
250 sys.stdout = save_stdout
252 def test_get_actions(self):
253 """Test the get_actions() method
255 a = SCons.Action.Action("x")
260 """Test adding Actions to stuff."""
261 # Adding actions to other Actions or to stuff that can
262 # be converted into an Action should produce a ListAction
263 # containing all the Actions.
266 baz = SCons.Action.CommandGenerator(bar)
267 act1 = SCons.Action.Action('foo bar')
268 act2 = SCons.Action.Action([ 'foo', bar ])
271 assert isinstance(sum, SCons.Action.ListAction), str(sum)
272 assert len(sum.list) == 3, len(sum.list)
273 assert map(lambda x: isinstance(x, SCons.Action.ActionBase),
274 sum.list) == [ 1, 1, 1 ]
277 assert isinstance(sum, SCons.Action.ListAction), str(sum)
278 assert len(sum.list) == 2, len(sum.list)
281 assert isinstance(sum, SCons.Action.ListAction), str(sum)
282 assert len(sum.list) == 4, len(sum.list)
284 # Should also be able to add command generators to each other
287 assert isinstance(sum, SCons.Action.ListAction), str(sum)
288 assert len(sum.list) == 2, len(sum.list)
291 assert isinstance(sum, SCons.Action.ListAction), str(sum)
292 assert len(sum.list) == 2, len(sum.list)
295 assert isinstance(sum, SCons.Action.ListAction), str(sum)
296 assert len(sum.list) == 3, len(sum.list)
298 # Also should be able to add Actions to anything that can
299 # be converted into an action.
301 assert isinstance(sum, SCons.Action.ListAction), str(sum)
302 assert len(sum.list) == 2, len(sum.list)
303 assert isinstance(sum.list[1], SCons.Action.FunctionAction)
305 sum = 'foo bar' + act2
306 assert isinstance(sum, SCons.Action.ListAction), str(sum)
307 assert len(sum.list) == 3, len(sum.list)
308 assert isinstance(sum.list[0], SCons.Action.CommandAction)
310 sum = [ 'foo', 'bar' ] + act1
311 assert isinstance(sum, SCons.Action.ListAction), str(sum)
312 assert len(sum.list) == 3, sum.list
313 assert isinstance(sum.list[0], SCons.Action.CommandAction)
314 assert isinstance(sum.list[1], SCons.Action.CommandAction)
316 sum = act2 + [ baz, bar ]
317 assert isinstance(sum, SCons.Action.ListAction), str(sum)
318 assert len(sum.list) == 4, len(sum.list)
319 assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction)
320 assert isinstance(sum.list[3], SCons.Action.FunctionAction)
327 assert 0, "Should have thrown a TypeError adding to an int."
334 assert 0, "Should have thrown a TypeError adding to an int."
336 class CommandActionTestCase(unittest.TestCase):
339 """Test creation of a command Action
341 a = SCons.Action.CommandAction(["xyzzy"])
342 assert a.cmd_list == [ "xyzzy" ], a.cmd_list
344 def test_strfunction(self):
345 """Test fetching the string representation of command Actions
348 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
349 s = act.strfunction([], [], Environment())
350 assert s == ['xyzzy'], s
351 s = act.strfunction([DummyNode('target')], [DummyNode('source')], Environment())
352 assert s == ['xyzzy target source'], s
353 s = act.strfunction([DummyNode('t1'), DummyNode('t2')],
354 [DummyNode('s1'), DummyNode('s2')], Environment())
355 assert s == ['xyzzy t1 s1'], s
357 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
358 s = act.strfunction([], [], Environment())
359 assert s == ['xyzzy'], s
360 s = act.strfunction([DummyNode('target')], [DummyNode('source')], Environment())
361 assert s == ['xyzzy target source'], s
362 s = act.strfunction([DummyNode('t1'), DummyNode('t2')],
363 [DummyNode('s1'), DummyNode('s2')], Environment())
364 assert s == ['xyzzy t1 t2 s1 s2'], s
366 act = SCons.Action.CommandAction(['xyzzy',
367 '$TARGET', '$SOURCE',
368 '$TARGETS', '$SOURCES'])
369 s = act.strfunction([], [], Environment())
370 assert s == ['xyzzy'], s
371 s = act.strfunction([DummyNode('target')], [DummyNode('source')], Environment())
372 assert s == ['xyzzy target source target source'], s
373 s = act.strfunction([DummyNode('t1'), DummyNode('t2')],
374 [DummyNode('s1'), DummyNode('s2')], Environment())
375 assert s == ['xyzzy t1 s1 t1 t2 s1 s2'], s
377 def test_execute(self):
378 """Test execution of command Actions
383 except AttributeError:
386 cmd1 = r'%s %s %s xyzzy' % (python, act_py, outfile)
388 act = SCons.Action.CommandAction(cmd1)
389 r = act([], [], env.Copy())
391 c = test.read(outfile, 'r')
392 assert c == "act.py: 'xyzzy'\n", c
394 cmd2 = r'%s %s %s $TARGET' % (python, act_py, outfile)
396 act = SCons.Action.CommandAction(cmd2)
397 r = act(DummyNode('foo'), [], env.Copy())
399 c = test.read(outfile, 'r')
400 assert c == "act.py: 'foo'\n", c
402 cmd3 = r'%s %s %s ${TARGETS}' % (python, act_py, outfile)
404 act = SCons.Action.CommandAction(cmd3)
405 r = act(map(DummyNode, ['aaa', 'bbb']), [], env.Copy())
407 c = test.read(outfile, 'r')
408 assert c == "act.py: 'aaa' 'bbb'\n", c
410 cmd4 = r'%s %s %s $SOURCES' % (python, act_py, outfile)
412 act = SCons.Action.CommandAction(cmd4)
413 r = act([], [DummyNode('one'), DummyNode('two')], env.Copy())
415 c = test.read(outfile, 'r')
416 assert c == "act.py: 'one' 'two'\n", c
418 cmd4 = r'%s %s %s ${SOURCES[:2]}' % (python, act_py, outfile)
420 act = SCons.Action.CommandAction(cmd4)
422 source = [DummyNode('three'),
427 c = test.read(outfile, 'r')
428 assert c == "act.py: 'three' 'four'\n", c
430 cmd5 = r'%s %s %s $TARGET XYZZY' % (python, act_py, outfile)
432 act = SCons.Action.CommandAction(cmd5)
434 if scons_env.has_key('ENV'):
435 env5['ENV'] = scons_env['ENV']
436 PATH = scons_env['ENV'].get('PATH', '')
441 env5['ENV']['XYZZY'] = 'xyzzy'
442 r = act(target = DummyNode('out5'), source = [], env = env5)
444 act = SCons.Action.CommandAction(cmd5)
445 r = act(target = DummyNode('out5'),
447 env = env.Copy(ENV = {'XYZZY' : 'xyzzy',
450 c = test.read(outfile, 'r')
451 assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy'\n", c
454 def __init__(self, str):
460 def get_subst_proxy(self):
463 cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (python, act_py, outfile)
465 act = SCons.Action.CommandAction(cmd6)
466 r = act(target = [Obj('111'), Obj('222')],
467 source = [Obj('333'), Obj('444'), Obj('555')],
470 c = test.read(outfile, 'r')
471 assert c == "act.py: '222' '111' '333' '444'\n", c
473 cmd7 = '%s %s %s one\n\n%s %s %s two' % (python, act_py, outfile,
474 python, act_py, outfile)
475 expect7 = '%s %s %s one\n%s %s %s two\n' % (python, act_py, outfile,
476 python, act_py, outfile)
478 act = SCons.Action.CommandAction(cmd7)
484 show_string = show_string + string + "\n"
487 r = act([], [], env.Copy())
489 assert show_string == expect7, show_string
492 # NT treats execs of directories and non-executable files
493 # as "file not found" errors
494 expect_nonexistent = 1
495 expect_nonexecutable = 1
496 elif sys.platform == 'cygwin':
497 expect_nonexistent = 127
498 expect_nonexecutable = 127
500 expect_nonexistent = 127
501 expect_nonexecutable = 126
503 # Test that a nonexistent command returns 127
504 act = SCons.Action.CommandAction(python + "_XyZzY_")
505 r = act([], [], env.Copy(out = outfile))
506 assert r == expect_nonexistent, "r == %d" % r
508 # Test that trying to execute a directory returns 126
509 dir, tail = os.path.split(python)
510 act = SCons.Action.CommandAction(dir)
511 r = act([], [], env.Copy(out = outfile))
512 assert r == expect_nonexecutable, "r == %d" % r
514 # Test that trying to execute a non-executable file returns 126
515 act = SCons.Action.CommandAction(outfile)
516 r = act([], [], env.Copy(out = outfile))
517 assert r == expect_nonexecutable, "r == %d" % r
520 def test_pipe_execute(self):
521 """Test capturing piped output from an action
523 pipe_file = open( test.workpath('pipe.out'), "w" )
524 self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1,
525 PSTDOUT = pipe_file, PSTDERR = pipe_file)
526 # everything should also work when piping output
528 self.env['PSTDOUT'].close()
529 pipe_out = test.read( test.workpath('pipe.out') )
530 if sys.platform == 'win32':
534 found = re.findall( "act.py: stdout: executed act.py%s\nact.py: stderr: executed act.py%s\n" % (cr, cr), pipe_out )
535 assert len(found) == 8, found
537 def test_set_handler(self):
538 """Test setting the command handler...
544 def func(sh, escape, cmd, args, env, test=t):
548 def escape_func(cmd):
549 return '**' + cmd + '**'
552 def __init__(self, x):
556 def is_literal(self):
560 SCons.Action.SetCommandHandler(func)
561 except SCons.Errors.UserError:
564 assert 0, "should have gotten user error"
566 a = SCons.Action.CommandAction(["xyzzy"])
567 a([], [], Environment(SPAWN = func))
568 assert t.executed == [ 'xyzzy' ]
570 a = SCons.Action.CommandAction(["xyzzy"])
571 a([], [], Environment(SPAWN = func, SHELL = 'fake shell'))
572 assert t.executed == [ 'xyzzy' ]
573 assert t.shell == 'fake shell'
575 a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ])
576 a([], [], Environment(SPAWN = func, ESCAPE = escape_func))
577 assert t.executed == [ '**xyzzy**' ], t.executed
579 def test_get_raw_contents(self):
580 """Test fetching the contents of a command Action
582 def CmdGen(target, source, env, for_signature):
585 (env["foo"], env["bar"])
587 # The number 1 is there to make sure all args get converted to strings.
588 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
589 "$)", "|", "$baz", 1])
590 c = a.get_raw_contents(target=[], source=[],
591 env=Environment(foo = 'FFF', bar = 'BBB',
593 assert c == "| $( FFF | BBB $) | FFF BBB 1", c
595 # We've discusssed using the real target and source names in a
596 # CommandAction's signature contents. This would have have the
597 # advantage of recompiling when a file's name changes (keeping
598 # debug info current), but it would currently break repository
599 # logic that will change the file name based on whether the
600 # files come from a repository or locally. If we ever move to
601 # that scheme, then all of the '__t1__' and '__s6__' file names
602 # in the asserts below would change to 't1' and 's6' and the
604 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
605 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
608 a = SCons.Action.CommandAction(["$TARGET"])
609 c = a.get_raw_contents(target=t, source=s, env=env)
612 a = SCons.Action.CommandAction(["$TARGETS"])
613 c = a.get_raw_contents(target=t, source=s, env=env)
614 assert c == "t1 t2 t3 t4 t5 t6", c
616 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
617 c = a.get_raw_contents(target=t, source=s, env=env)
620 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
621 c = a.get_raw_contents(target=t, source=s, env=env)
622 assert c == "t4 t5", c
624 a = SCons.Action.CommandAction(["$SOURCE"])
625 c = a.get_raw_contents(target=t, source=s, env=env)
628 a = SCons.Action.CommandAction(["$SOURCES"])
629 c = a.get_raw_contents(target=t, source=s, env=env)
630 assert c == "s1 s2 s3 s4 s5 s6", c
632 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
633 c = a.get_raw_contents(target=t, source=s, env=env)
636 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
637 c = a.get_raw_contents(target=t, source=s, env=env)
638 assert c == "s4 s5", c
640 def test_get_contents(self):
641 """Test fetching the contents of a command Action
643 def CmdGen(target, source, env, for_signature):
646 (env["foo"], env["bar"])
648 # The number 1 is there to make sure all args get converted to strings.
649 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
650 "$)", "|", "$baz", 1])
651 c = a.get_contents(target=[], source=[],
652 env=Environment(foo = 'FFF', bar = 'BBB',
654 assert c == "| | FFF BBB 1", c
656 # We've discusssed using the real target and source names in a
657 # CommandAction's signature contents. This would have have the
658 # advantage of recompiling when a file's name changes (keeping
659 # debug info current), but it would currently break repository
660 # logic that will change the file name based on whether the
661 # files come from a repository or locally. If we ever move to
662 # that scheme, then all of the '__t1__' and '__s6__' file names
663 # in the asserts below would change to 't1' and 's6' and the
665 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
666 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
669 a = SCons.Action.CommandAction(["$TARGET"])
670 c = a.get_contents(target=t, source=s, env=env)
673 a = SCons.Action.CommandAction(["$TARGETS"])
674 c = a.get_contents(target=t, source=s, env=env)
675 assert c == "t1 t2 t3 t4 t5 t6", c
677 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
678 c = a.get_contents(target=t, source=s, env=env)
681 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
682 c = a.get_contents(target=t, source=s, env=env)
683 assert c == "t4 t5", c
685 a = SCons.Action.CommandAction(["$SOURCE"])
686 c = a.get_contents(target=t, source=s, env=env)
689 a = SCons.Action.CommandAction(["$SOURCES"])
690 c = a.get_contents(target=t, source=s, env=env)
691 assert c == "s1 s2 s3 s4 s5 s6", c
693 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
694 c = a.get_contents(target=t, source=s, env=env)
697 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
698 c = a.get_contents(target=t, source=s, env=env)
699 assert c == "s4 s5", c
701 class CommandGeneratorActionTestCase(unittest.TestCase):
704 """Test creation of a command generator Action
706 def f(target, source, env):
708 a = SCons.Action.CommandGeneratorAction(f)
709 assert a.generator == f
711 def test_execute(self):
712 """Test executing a command generator Action
715 def f(target, source, env, for_signature, self=self):
718 s = env.subst("$FOO")
719 assert s == 'foo baz\nbar ack', s
721 def func_action(target, source, env, self=self):
723 s = env.subst('$foo')
726 def f2(target, source, env, for_signature, f=func_action):
728 def ch(sh, escape, cmd, args, env, self=self):
730 self.args.append(args)
732 a = SCons.Action.CommandGeneratorAction(f)
736 a([], [], env=Environment(FOO = 'foo baz\nbar ack',
739 assert self.dummy == 1, self.dummy
740 assert self.cmd == ['foo', 'bar'], self.cmd
741 assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args
743 b = SCons.Action.CommandGeneratorAction(f2)
745 b(target=[], source=[], env=Environment(foo = 'bar',
747 assert self.dummy==2, self.dummy
751 def __init__(self, t):
754 self.t.rfile_called = 1
756 def get_subst_proxy(self):
758 def f3(target, source, env, for_signature):
760 c = SCons.Action.CommandGeneratorAction(f3)
761 c(target=[], source=DummyFile(self), env=Environment())
762 assert self.rfile_called
764 def test_get_contents(self):
765 """Test fetching the contents of a command generator Action
767 def f(target, source, env, for_signature):
770 assert for_signature, for_signature
771 return [["guux", foo, "$(", "$ignore", "$)", bar,
772 '${test("$( foo $bar $)")}' ]]
775 assert mystr == "$( foo $bar $)", mystr
778 a = SCons.Action.CommandGeneratorAction(f)
779 c = a.get_contents(target=[], source=[],
780 env=Environment(foo = 'FFF', bar = 'BBB',
781 ignore = 'foo', test=test))
782 assert c == "guux FFF BBB test", c
785 class FunctionActionTestCase(unittest.TestCase):
788 """Test creation of a function Action
799 a = SCons.Action.FunctionAction(func1)
800 assert a.execfunction == func1, a.execfunction
801 assert isinstance(a.strfunction, types.FunctionType)
803 a = SCons.Action.FunctionAction(func2, strfunction=func3)
804 assert a.execfunction == func2, a.execfunction
805 assert a.strfunction == func3, a.strfunction
807 a = SCons.Action.FunctionAction(func3, func4)
808 assert a.execfunction == func3, a.execfunction
809 assert a.strfunction == func4, a.strfunction
811 a = SCons.Action.FunctionAction(func4, None)
812 assert a.execfunction == func4, a.execfunction
813 assert a.strfunction is None, a.strfunction
815 def test_execute(self):
816 """Test executing a function Action
819 def f(target, source, env):
824 assert env.subst("$BAR") == 'foo bar', env.subst("$BAR")
826 a = SCons.Action.FunctionAction(f)
827 a(target=1, source=2, env=Environment(BAR = 'foo bar',
829 assert self.inc == 1, self.inc
830 assert self.source == [2], self.source
831 assert self.target == [1], self.target
835 def function1(target, source, env):
839 open(t, 'w').write("function1\n")
842 act = SCons.Action.FunctionAction(function1)
845 r = act(target = [outfile, outfile2], source=[], env=Environment())
846 except SCons.Errors.BuildError:
850 c = test.read(outfile, 'r')
851 assert c == "function1\n", c
852 c = test.read(outfile2, 'r')
853 assert c == "function1\n", c
856 def __init__(self, target, source, env):
857 open(env['out'], 'w').write("class1a\n")
859 act = SCons.Action.FunctionAction(class1a)
860 r = act([], [], Environment(out = outfile))
861 assert r.__class__ == class1a
862 c = test.read(outfile, 'r')
863 assert c == "class1a\n", c
866 def __call__(self, target, source, env):
867 open(env['out'], 'w').write("class1b\n")
870 act = SCons.Action.FunctionAction(class1b())
871 r = act([], [], Environment(out = outfile))
873 c = test.read(outfile, 'r')
874 assert c == "class1b\n", c
876 def build_it(target, source, env, self=self):
879 def string_it(target, source, env, self=self):
882 act = SCons.Action.FunctionAction(build_it, string_it)
883 r = act([], [], Environment())
886 assert self.string_it
888 def test_get_contents(self):
889 """Test fetching the contents of a function Action
891 a = SCons.Action.FunctionAction(Func)
892 c = a.get_contents(target=[], source=[], env=Environment())
893 assert c == "\177\036\000\177\037\000d\000\000S", repr(c)
895 a = SCons.Action.FunctionAction(Func, varlist=['XYZ'])
896 c = a.get_contents(target=[], source=[], env=Environment())
897 assert c == "\177\036\000\177\037\000d\000\000S", repr(c)
898 c = a.get_contents(target=[], source=[], env=Environment(XYZ = 'foo'))
899 assert c == "\177\036\000\177\037\000d\000\000Sfoo", repr(c)
901 class ListActionTestCase(unittest.TestCase):
904 """Test creation of a list of subsidiary Actions
908 a = SCons.Action.ListAction(["x", func, ["y", "z"]])
909 assert isinstance(a.list[0], SCons.Action.CommandAction)
910 assert isinstance(a.list[1], SCons.Action.FunctionAction)
911 assert isinstance(a.list[2], SCons.Action.ListAction)
912 assert a.list[2].list[0].cmd_list == 'y'
914 def test_get_actions(self):
915 """Test the get_actions() method for ListActions
917 a = SCons.Action.ListAction(["x", "y"])
919 assert len(l) == 2, l
920 assert isinstance(l[0], SCons.Action.CommandAction), l[0]
921 g = l[0].get_actions()
922 assert g == [l[0]], g
923 assert isinstance(l[1], SCons.Action.CommandAction), l[1]
924 g = l[1].get_actions()
925 assert g == [l[1]], g
927 def test_execute(self):
928 """Test executing a list of subsidiary Actions
931 def f(target,source,env):
934 a = SCons.Action.ListAction([f, f, f])
935 a([], [], Environment(s = self))
936 assert self.inc == 3, self.inc
938 cmd2 = r'%s %s %s syzygy' % (python, act_py, outfile)
940 def function2(target, source, env):
941 open(env['out'], 'a').write("function2\n")
945 def __call__(self, target, source, env):
946 open(env['out'], 'a').write("class2a\n")
950 def __init__(self, target, source, env):
951 open(env['out'], 'a').write("class2b\n")
952 act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
953 r = act([], [], Environment(out = outfile))
954 assert r.__class__ == class2b
955 c = test.read(outfile, 'r')
956 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
958 def test_get_contents(self):
959 """Test fetching the contents of a list of subsidiary Actions
962 def gen(target, source, env, for_signature):
966 a = SCons.Action.ListAction(["x",
967 SCons.Action.CommandGenerator(gen),
969 c = a.get_contents(target=[], source=[], env=Environment(s = self))
970 assert self.foo==1, self.foo
973 class LazyActionTestCase(unittest.TestCase):
975 """Test creation of a lazy-evaluation Action
977 # Environment variable references should create a special
978 # type of CommandGeneratorAction that lazily evaluates the
980 a9 = SCons.Action.Action('$FOO')
981 assert isinstance(a9, SCons.Action.CommandGeneratorAction), a9
982 assert a9.generator.var == 'FOO', a9.generator.var
984 a10 = SCons.Action.Action('${FOO}')
985 assert isinstance(a9, SCons.Action.CommandGeneratorAction), a10
986 assert a10.generator.var == 'FOO', a10.generator.var
988 def test_execute(self):
989 """Test executing a lazy-evaluation Action
991 def f(target, source, env):
995 a = SCons.Action.Action('$BAR')
996 a([], [], env=Environment(BAR = f, s = self))
997 assert self.test == 1, self.test
999 def test_get_contents(self):
1000 """Test fetching the contents of a lazy-evaluation Action
1002 a = SCons.Action.Action("${FOO}")
1003 c = a.get_contents(target=[], source=[],
1004 env = Environment(FOO = [["This", "is", "$(", "$a", "$)", "test"]]))
1005 assert c == "This is test", c
1008 if __name__ == "__main__":
1009 suite = unittest.TestSuite()
1010 tclasses = [ ActionTestCase,
1012 CommandActionTestCase,
1013 CommandGeneratorActionTestCase,
1014 FunctionActionTestCase,
1016 LazyActionTestCase ]
1017 for tclass in tclasses:
1018 names = unittest.getTestCaseNames(tclass, 'test_')
1019 suite.addTests(map(tclass, names))
1020 if not unittest.TextTestRunner().run(suite).wasSuccessful():