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 and a null class for use as builder actions.
27 # Where these are defined in the file seems to affect their byte-code
28 # contents, so try to minimize changes by defining them here, before we
29 # even import anything.
47 import SCons.Environment
52 # Initial setup of the common environment for all tests,
53 # a temporary working directory containing a
54 # script for writing arguments to an output file.
56 # We don't do this as a setUp() method because it's
57 # unnecessary to create a separate directory and script
58 # for each test, they can just use the one.
59 test = TestCmd.TestCmd(workdir = '')
61 test.write('act.py', """\
62 import os, string, sys
63 f = open(sys.argv[1], 'w')
64 f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n")
67 f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n")
71 if os.environ.has_key( 'ACTPY_PIPE' ):
72 if os.environ.has_key( 'PIPE_STDOUT_FILE' ):
73 stdout_msg = open(os.environ['PIPE_STDOUT_FILE'], 'r').read()
75 stdout_msg = "act.py: stdout: executed act.py %s\\n" % string.join(sys.argv[1:])
76 sys.stdout.write( stdout_msg )
77 if os.environ.has_key( 'PIPE_STDERR_FILE' ):
78 stderr_msg = open(os.environ['PIPE_STDERR_FILE'], 'r').read()
80 stderr_msg = "act.py: stderr: executed act.py %s\\n" % string.join(sys.argv[1:])
81 sys.stderr.write( stderr_msg )
85 test.write('exit.py', """\
87 sys.exit(int(sys.argv[1]))
90 act_py = test.workpath('act.py')
91 exit_py = test.workpath('exit.py')
93 outfile = test.workpath('outfile')
94 outfile2 = test.workpath('outfile2')
95 pipe_file = test.workpath('pipe.out')
97 scons_env = SCons.Environment.Environment()
99 # Capture all the stuff the Actions will print,
100 # so it doesn't clutter the output.
101 sys.stdout = StringIO.StringIO()
103 class CmdStringHolder:
104 def __init__(self, cmd, literal=None):
106 self.literal = literal
108 def is_literal(self):
111 def escape(self, escape_func):
112 """Escape the string with the supplied function. The
113 function is expected to take an arbitrary string, then
114 return it with all special characters escaped and ready
115 for passing to the command interpreter.
117 After calling this function, the next call to str() will
118 return the escaped string.
121 if self.is_literal():
122 return escape_func(self.data)
123 elif ' ' in self.data or '\t' in self.data:
124 return '"%s"' % self.data
129 def __init__(self, **kw):
131 self.d['SHELL'] = scons_env['SHELL']
132 self.d['SPAWN'] = scons_env['SPAWN']
133 self.d['PSPAWN'] = scons_env['PSPAWN']
134 self.d['ESCAPE'] = scons_env['ESCAPE']
135 for k, v in kw.items():
137 # Just use the underlying scons_subst*() utility methods.
138 def subst(self, strSubst, raw=0, target=[], source=[], conv=None):
139 return SCons.Subst.scons_subst(strSubst, self, raw,
140 target, source, self.d, conv=conv)
141 subst_target_source = subst
142 def subst_list(self, strSubst, raw=0, target=[], source=[], conv=None):
143 return SCons.Subst.scons_subst_list(strSubst, self, raw,
144 target, source, self.d, conv=conv)
145 def __getitem__(self, item):
147 def __setitem__(self, item, value):
149 def has_key(self, item):
150 return self.d.has_key(item)
151 def get(self, key, value=None):
152 return self.d.get(key, value)
154 return self.d.items()
155 def Dictionary(self):
157 def Clone(self, **kw):
159 res.d = SCons.Util.semi_deepcopy(self.d)
160 for k, v in kw.items():
165 for k,v in self.items(): d[k] = v
166 d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__']
167 d['TARGET'] = d['TARGETS'][0]
168 d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__']
169 d['SOURCE'] = d['SOURCES'][0]
173 def __init__(self, name):
175 def str_for_display(self):
176 return '"' + self.name + '"'
181 def get_subst_proxy(self):
184 if os.name == 'java':
185 python = os.path.join(sys.prefix, 'jython')
187 python = sys.executable
189 _python_ = '"' + python + '"'
191 _null = SCons.Action._null
193 def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw):
194 def call_action(a, pos_call=pos_call, str_call=str_call, kw=kw):
195 #FUTURE a = SCons.Action.Action(*a, **kw)
196 a = apply(SCons.Action.Action, a, kw)
197 # returned object must provide these entry points
198 assert hasattr(a, '__call__')
199 assert hasattr(a, 'get_contents')
200 assert hasattr(a, 'genstring')
205 a = call_action((cmd, cmdstrfunc))
206 assert a.varlist == (), a.varlist
208 a = call_action((cmd, cmdstrfunc, 'foo'))
209 assert a.varlist == ('foo',), a.varlist
211 a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c'))
212 assert a.varlist == ('a', 'b', 'c'), a.varlist
214 kw['varlist'] = 'foo'
215 a = call_action((cmd, cmdstrfunc))
216 assert a.varlist == ('foo',), a.varlist
218 kw['varlist'] = ['x', 'y', 'z']
219 a = call_action((cmd, cmdstrfunc))
220 assert a.varlist == ('x', 'y', 'z'), a.varlist
222 a = call_action((cmd, cmdstrfunc, 'foo'))
223 assert a.varlist == ('foo', 'x', 'y', 'z'), a.varlist
225 a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c'))
226 assert a.varlist == ('a', 'b', 'c', 'x', 'y', 'z'), a.varlist
228 def test_positional_args(pos_callback, cmd, **kw):
229 """Test that Action() returns the expected type and that positional args work.
231 #FUTURE act = SCons.Action.Action(cmd, **kw)
232 act = apply(SCons.Action.Action, (cmd,), kw)
234 assert act.varlist is (), act.varlist
236 if not isinstance(act, SCons.Action._ActionAction):
237 # only valid cmdstrfunc is None
239 #FUTURE test_varlist(pos_callback, none, cmd, None, **kw)
240 apply(test_varlist, (pos_callback, none, cmd, None), kw)
242 # _ActionAction should have set these
243 assert hasattr(act, 'strfunction')
244 assert act.cmdstr is _null, act.cmdstr
245 assert act.presub is _null, act.presub
246 assert act.chdir is None, act.chdir
247 assert act.exitstatfunc is SCons.Action.default_exitstatfunc, \
251 assert hasattr(a, 'strfunction')
252 assert a.cmdstr == 'cmdstr', a.cmdstr
253 #FUTURE test_varlist(pos_callback, cmdstr, cmd, 'cmdstr', **kw)
254 apply(test_varlist, (pos_callback, cmdstr, cmd, 'cmdstr'), kw)
257 def strfun(a, fun=fun):
258 assert a.strfunction is fun, a.strfunction
259 assert a.cmdstr == _null, a.cmdstr
260 #FUTURE test_varlist(pos_callback, strfun, cmd, fun, **kw)
261 apply(test_varlist, (pos_callback, strfun, cmd, fun), kw)
264 assert hasattr(a, 'strfunction')
265 assert a.cmdstr is None, a.cmdstr
266 #FUTURE test_varlist(pos_callback, none, cmd, None, **kw)
267 apply(test_varlist, (pos_callback, none, cmd, None), kw)
269 """Test handling of bad cmdstrfunc arguments """
271 #FUTURE a = SCons.Action.Action(cmd, [], **kw)
272 a = apply(SCons.Action.Action, (cmd, []), kw)
273 except SCons.Errors.UserError, e:
275 m = 'Invalid command display variable'
276 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
278 raise Exception, "did not catch expected UserError"
282 class ActionTestCase(unittest.TestCase):
283 """Test the Action() factory function"""
285 def test_FunctionAction(self):
286 """Test the Action() factory's creation of FunctionAction objects
291 def func_action(a, foo=foo):
292 assert isinstance(a, SCons.Action.FunctionAction), a
293 assert a.execfunction == foo, a.execfunction
294 test_positional_args(func_action, foo)
295 # a singleton list returns the contained action
296 test_positional_args(func_action, [foo])
298 def test_CommandAction(self):
299 """Test the Action() factory's creation of CommandAction objects
302 assert isinstance(a, SCons.Action.CommandAction), a
303 assert a.cmd_list == "string", a.cmd_list
304 test_positional_args(cmd_action, "string")
305 # a singleton list returns the contained action
306 test_positional_args(cmd_action, ["string"])
308 if hasattr(types, 'UnicodeType'):
309 a2 = eval("SCons.Action.Action(u'string')")
310 assert isinstance(a2, SCons.Action.CommandAction), a2
313 assert isinstance(a, SCons.Action.CommandAction), a
314 assert a.cmd_list == [ "explicit", "command", "line" ], a.cmd_list
315 test_positional_args(line_action, [[ "explicit", "command", "line" ]])
317 def test_ListAction(self):
318 """Test the Action() factory's creation of ListAction objects
320 a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]])
321 assert isinstance(a1, SCons.Action.ListAction), a1
322 assert a1.varlist is (), a1.varlist
323 assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0]
324 assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list
325 assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1]
326 assert a1.list[1].cmd_list == "y", a1.list[1].cmd_list
327 assert isinstance(a1.list[2], SCons.Action.CommandAction), a1.list[2]
328 assert a1.list[2].cmd_list == "z", a1.list[2].cmd_list
329 assert isinstance(a1.list[3], SCons.Action.CommandAction), a1.list[3]
330 assert a1.list[3].cmd_list == [ "a", "b", "c" ], a1.list[3].cmd_list
332 a2 = SCons.Action.Action("x\ny\nz")
333 assert isinstance(a2, SCons.Action.ListAction), a2
334 assert a2.varlist is (), a2.varlist
335 assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0]
336 assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list
337 assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1]
338 assert a2.list[1].cmd_list == "y", a2.list[1].cmd_list
339 assert isinstance(a2.list[2], SCons.Action.CommandAction), a2.list[2]
340 assert a2.list[2].cmd_list == "z", a2.list[2].cmd_list
345 a3 = SCons.Action.Action(["x", foo, "z"])
346 assert isinstance(a3, SCons.Action.ListAction), a3
347 assert a3.varlist is (), a3.varlist
348 assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0]
349 assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list
350 assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1]
351 assert a3.list[1].execfunction == foo, a3.list[1].execfunction
352 assert isinstance(a3.list[2], SCons.Action.CommandAction), a3.list[2]
353 assert a3.list[2].cmd_list == "z", a3.list[2].cmd_list
355 a4 = SCons.Action.Action(["x", "y"], strfunction=foo)
356 assert isinstance(a4, SCons.Action.ListAction), a4
357 assert a4.varlist is (), a4.varlist
358 assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0]
359 assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list
360 assert a4.list[0].strfunction == foo, a4.list[0].strfunction
361 assert isinstance(a4.list[1], SCons.Action.CommandAction), a4.list[1]
362 assert a4.list[1].cmd_list == "y", a4.list[1].cmd_list
363 assert a4.list[1].strfunction == foo, a4.list[1].strfunction
365 a5 = SCons.Action.Action("x\ny", strfunction=foo)
366 assert isinstance(a5, SCons.Action.ListAction), a5
367 assert a5.varlist is (), a5.varlist
368 assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0]
369 assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list
370 assert a5.list[0].strfunction == foo, a5.list[0].strfunction
371 assert isinstance(a5.list[1], SCons.Action.CommandAction), a5.list[1]
372 assert a5.list[1].cmd_list == "y", a5.list[1].cmd_list
373 assert a5.list[1].strfunction == foo, a5.list[1].strfunction
375 def test_CommandGeneratorAction(self):
376 """Test the Action() factory's creation of CommandGeneratorAction objects
380 def gen_action(a, foo=foo):
381 assert isinstance(a, SCons.Action.CommandGeneratorAction), a
382 assert a.generator is foo, a.generator
383 test_positional_args(gen_action, foo, generator=1)
385 def test_LazyCmdGeneratorAction(self):
386 """Test the Action() factory's creation of lazy CommandGeneratorAction objects
389 assert isinstance(a, SCons.Action.LazyAction), a
390 assert a.var == "FOO", a.var
391 assert a.cmd_list == "${FOO}", a.cmd_list
392 test_positional_args(lazy_action, "$FOO")
393 test_positional_args(lazy_action, "${FOO}")
395 def test_no_action(self):
396 """Test when the Action() factory can't create an action object
398 a5 = SCons.Action.Action(1)
399 assert a5 is None, a5
401 def test_reentrance(self):
402 """Test the Action() factory when the action is already an Action object
404 a1 = SCons.Action.Action("foo")
405 a2 = SCons.Action.Action(a1)
408 class _ActionActionTestCase(unittest.TestCase):
410 def test__init__(self):
411 """Test creation of _ActionAction objects
423 a = SCons.Action._ActionAction()
424 assert not hasattr(a, 'strfunction')
425 assert a.cmdstr is _null, a.cmdstr
426 assert a.varlist == (), a.varlist
427 assert a.presub is _null, a.presub
428 assert a.chdir is None, a.chdir
429 assert a.exitstatfunc is SCons.Action.default_exitstatfunc, a.exitstatfunc
431 assert SCons.Action._ActionAction(kwarg = 1)
432 assert not hasattr(a, 'kwarg')
433 assert not hasattr(a, 'strfunction')
434 assert a.cmdstr is _null, a.cmdstr
435 assert a.varlist == (), a.varlist
436 assert a.presub is _null, a.presub
437 assert a.chdir is None, a.chdir
438 assert a.exitstatfunc is SCons.Action.default_exitstatfunc, a.exitstatfunc
440 a = SCons.Action._ActionAction(strfunction=func1)
441 assert a.strfunction is func1, a.strfunction
443 a = SCons.Action._ActionAction(strfunction=None)
444 assert not hasattr(a, 'strfunction')
445 assert a.cmdstr is None, a.cmdstr
447 a = SCons.Action._ActionAction(cmdstr='cmdstr')
448 assert not hasattr(a, 'strfunction')
449 assert a.cmdstr is 'cmdstr', a.cmdstr
451 a = SCons.Action._ActionAction(cmdstr=None)
452 assert not hasattr(a, 'strfunction')
453 assert a.cmdstr is None, a.cmdstr
456 a = SCons.Action._ActionAction(varlist=t)
457 assert a.varlist == t, a.varlist
459 a = SCons.Action._ActionAction(presub=func1)
460 assert a.presub is func1, a.presub
462 a = SCons.Action._ActionAction(chdir=1)
463 assert a.chdir is 1, a.chdir
465 a = SCons.Action._ActionAction(exitstatfunc=func1)
466 assert a.exitstatfunc is func1, a.exitstatfunc
468 a = SCons.Action._ActionAction(
469 # alphabetical order ...
477 assert a.chdir is 'x', a.chdir
478 assert a.cmdstr is 'cmdstr', a.cmdstr
479 assert a.exitstatfunc is func3, a.exitstatfunc
480 assert a.presub is func2, a.presub
481 assert a.strfunction is func1, a.strfunction
482 assert a.varlist is t, a.varlist
484 def test_dup_keywords(self):
485 """Test handling of both cmdstr and strfunction arguments
489 a = SCons.Action.Action('foo', cmdstr='string', strfunction=func)
490 except SCons.Errors.UserError, e:
492 m = 'Cannot have both strfunction and cmdstr args to Action()'
493 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
495 raise Exception, "did not catch expected UserError"
497 def test___cmp__(self):
498 """Test Action comparison
500 a1 = SCons.Action.Action("x")
501 a2 = SCons.Action.Action("x")
503 a3 = SCons.Action.Action("y")
507 def test_print_cmd_lines(self):
508 """Test the print_cmd_lines() method
510 save_stdout = sys.stdout
513 def execfunc(target, source, env):
515 a = SCons.Action.Action(execfunc)
517 sio = StringIO.StringIO()
519 a.print_cmd_line("foo bar", None, None, None)
521 assert s == "foo bar\n", s
524 sys.stdout = save_stdout
526 def test___call__(self):
527 """Test calling an Action
529 save_stdout = sys.stdout
531 save_print_actions = SCons.Action.print_actions
532 save_print_actions_presub = SCons.Action.print_actions_presub
533 save_execute_actions = SCons.Action.execute_actions
534 #SCons.Action.print_actions = 0
536 test = TestCmd.TestCmd(workdir = '')
537 test.subdir('sub', 'xyz')
538 os.chdir(test.workpath())
543 def execfunc(target, source, env):
544 assert type(target) is type([]), type(target)
545 assert type(source) is type([]), type(source)
547 a = SCons.Action.Action(execfunc)
549 def firstfunc(target, source, env):
550 assert type(target) is type([]), type(target)
551 assert type(source) is type([]), type(source)
553 def lastfunc(target, source, env):
554 assert type(target) is type([]), type(target)
555 assert type(source) is type([]), type(source)
557 b = SCons.Action.Action([firstfunc, execfunc, lastfunc])
559 sio = StringIO.StringIO()
561 result = a("out", "in", env)
562 assert result.status == 7, result
564 assert s == "execfunc(['out'], ['in'])\n", s
567 expect = "os.chdir(%s)\nexecfunc(['out'], ['in'])\nos.chdir(%s)\n"
569 sio = StringIO.StringIO()
571 result = a("out", "in", env)
572 assert result.status == 7, result.status
574 assert s == expect % (repr('xyz'), repr(test.workpath())), s
576 sio = StringIO.StringIO()
578 result = a("out", "in", env, chdir='sub')
579 assert result.status == 7, result.status
581 assert s == expect % (repr('sub'), repr(test.workpath())), s
585 sio = StringIO.StringIO()
587 result = b("out", "in", env)
588 assert result.status == 7, result.status
590 assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\n", s
592 SCons.Action.execute_actions = 0
594 sio = StringIO.StringIO()
596 result = a("out", "in", env)
597 assert result == 0, result
599 assert s == "execfunc(['out'], ['in'])\n", s
601 sio = StringIO.StringIO()
603 result = b("out", "in", env)
604 assert result == 0, result
606 assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\nlastfunc(['out'], ['in'])\n", s
608 SCons.Action.print_actions_presub = 1
609 SCons.Action.execute_actions = 1
611 sio = StringIO.StringIO()
613 result = a("out", "in", env)
614 assert result.status == 7, result.status
616 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
618 sio = StringIO.StringIO()
620 result = a("out", "in", env, presub=0)
621 assert result.status == 7, result.status
623 assert s == "execfunc(['out'], ['in'])\n", s
625 sio = StringIO.StringIO()
627 result = a("out", "in", env, presub=1)
628 assert result.status == 7, result.status
630 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
632 sio = StringIO.StringIO()
634 result = b(["out"], "in", env, presub=1)
635 assert result.status == 7, result.status
637 assert s == "Building out with action:\n firstfunc(target, source, env)\nfirstfunc(['out'], ['in'])\nBuilding out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
639 sio = StringIO.StringIO()
641 result = b(["out", "list"], "in", env, presub=1)
642 assert result.status == 7, result.status
644 assert s == "Building out and list with action:\n firstfunc(target, source, env)\nfirstfunc(['out', 'list'], ['in'])\nBuilding out and list with action:\n execfunc(target, source, env)\nexecfunc(['out', 'list'], ['in'])\n", s
646 a2 = SCons.Action.Action(execfunc)
648 sio = StringIO.StringIO()
650 result = a2("out", "in", env)
651 assert result.status == 7, result.status
653 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
655 sio = StringIO.StringIO()
657 result = a2("out", "in", env, presub=0)
658 assert result.status == 7, result.status
660 assert s == "execfunc(['out'], ['in'])\n", s
662 SCons.Action.execute_actions = 0
664 sio = StringIO.StringIO()
666 result = a2("out", "in", env, presub=0)
667 assert result == 0, result
669 assert s == "execfunc(['out'], ['in'])\n", s
671 sio = StringIO.StringIO()
673 result = a("out", "in", env, presub=0, execute=1, show=0)
674 assert result.status == 7, result.status
678 sys.stdout = save_stdout
679 exitstatfunc_result = []
681 def exitstatfunc(stat, result=exitstatfunc_result):
685 result = a("out", "in", env, exitstatfunc=exitstatfunc)
686 assert result == 0, result
687 assert exitstatfunc_result == [], exitstatfunc_result
689 result = a("out", "in", env, execute=1, exitstatfunc=exitstatfunc)
690 assert result.status == 7, result.status
691 assert exitstatfunc_result == [7], exitstatfunc_result
693 SCons.Action.execute_actions = 1
696 def my_print_cmd_line(s, target, source, env, result=result):
698 env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line
699 a("output", "input", env)
700 assert result == ["execfunc(['output'], ['input'])"], result
704 sys.stdout = save_stdout
705 SCons.Action.print_actions = save_print_actions
706 SCons.Action.print_actions_presub = save_print_actions_presub
707 SCons.Action.execute_actions = save_execute_actions
709 def test_presub_lines(self):
710 """Test the presub_lines() method
713 a = SCons.Action.Action("x")
714 s = a.presub_lines(env)
717 a = SCons.Action.Action(["y", "z"])
718 s = a.presub_lines(env)
719 assert s == ['y', 'z'], s
723 a = SCons.Action.Action(func)
724 s = a.presub_lines(env)
725 assert s == ["func(target, source, env)"], s
727 def gen(target, source, env, for_signature):
728 return 'generat' + env.get('GEN', 'or')
729 a = SCons.Action.Action(gen, generator=1)
730 s = a.presub_lines(env)
731 assert s == ["generator"], s
732 s = a.presub_lines(Environment(GEN = 'ed'))
733 assert s == ["generated"], s
735 a = SCons.Action.Action("$ACT")
736 s = a.presub_lines(env)
738 s = a.presub_lines(Environment(ACT = 'expanded action'))
739 assert s == ['expanded action'], s
742 """Test adding Actions to stuff."""
743 # Adding actions to other Actions or to stuff that can
744 # be converted into an Action should produce a ListAction
745 # containing all the Actions.
748 baz = SCons.Action.Action(bar, generator=1)
749 act1 = SCons.Action.Action('foo bar')
750 act2 = SCons.Action.Action([ 'foo', bar ])
753 assert isinstance(sum, SCons.Action.ListAction), str(sum)
754 assert len(sum.list) == 3, len(sum.list)
755 assert map(lambda x: isinstance(x, SCons.Action.ActionBase),
756 sum.list) == [ 1, 1, 1 ]
759 assert isinstance(sum, SCons.Action.ListAction), str(sum)
760 assert len(sum.list) == 2, len(sum.list)
763 assert isinstance(sum, SCons.Action.ListAction), str(sum)
764 assert len(sum.list) == 4, len(sum.list)
766 # Should also be able to add command generators to each other
769 assert isinstance(sum, SCons.Action.ListAction), str(sum)
770 assert len(sum.list) == 2, len(sum.list)
773 assert isinstance(sum, SCons.Action.ListAction), str(sum)
774 assert len(sum.list) == 2, len(sum.list)
777 assert isinstance(sum, SCons.Action.ListAction), str(sum)
778 assert len(sum.list) == 3, len(sum.list)
780 # Also should be able to add Actions to anything that can
781 # be converted into an action.
783 assert isinstance(sum, SCons.Action.ListAction), str(sum)
784 assert len(sum.list) == 2, len(sum.list)
785 assert isinstance(sum.list[1], SCons.Action.FunctionAction)
787 sum = 'foo bar' + act2
788 assert isinstance(sum, SCons.Action.ListAction), str(sum)
789 assert len(sum.list) == 3, len(sum.list)
790 assert isinstance(sum.list[0], SCons.Action.CommandAction)
792 sum = [ 'foo', 'bar' ] + act1
793 assert isinstance(sum, SCons.Action.ListAction), str(sum)
794 assert len(sum.list) == 3, sum.list
795 assert isinstance(sum.list[0], SCons.Action.CommandAction)
796 assert isinstance(sum.list[1], SCons.Action.CommandAction)
798 sum = act2 + [ baz, bar ]
799 assert isinstance(sum, SCons.Action.ListAction), str(sum)
800 assert len(sum.list) == 4, len(sum.list)
801 assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction)
802 assert isinstance(sum.list[3], SCons.Action.FunctionAction)
809 assert 0, "Should have thrown a TypeError adding to an int."
816 assert 0, "Should have thrown a TypeError adding to an int."
818 class CommandActionTestCase(unittest.TestCase):
820 def test___init__(self):
821 """Test creation of a command Action
823 a = SCons.Action.CommandAction(["xyzzy"])
824 assert a.cmd_list == [ "xyzzy" ], a.cmd_list
825 assert a.cmdstr is _null, a.cmdstr
827 a = SCons.Action.CommandAction(["abra"], cmdstr="cadabra")
828 assert a.cmd_list == [ "abra" ], a.cmd_list
829 assert a.cmdstr == "cadabra", a.cmdstr
831 def test___str__(self):
832 """Test fetching the pre-substitution string for command Actions
835 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
837 assert s == 'xyzzy $TARGET $SOURCE', s
839 act = SCons.Action.CommandAction(['xyzzy',
840 '$TARGET', '$SOURCE',
841 '$TARGETS', '$SOURCES'])
843 assert s == "xyzzy $TARGET $SOURCE $TARGETS $SOURCES", s
845 def test_genstring(self):
846 """Test the genstring() method for command Actions
854 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
855 expect = 'xyzzy $TARGET $SOURCE'
856 s = act.genstring([], [], env)
857 assert s == expect, s
858 s = act.genstring([t1], [s1], env)
859 assert s == expect, s
860 s = act.genstring([t1, t2], [s1, s2], env)
861 assert s == expect, s
863 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
864 expect = 'xyzzy $TARGETS $SOURCES'
865 s = act.genstring([], [], env)
866 assert s == expect, s
867 s = act.genstring([t1], [s1], env)
868 assert s == expect, s
869 s = act.genstring([t1, t2], [s1, s2], env)
870 assert s == expect, s
872 act = SCons.Action.CommandAction(['xyzzy',
873 '$TARGET', '$SOURCE',
874 '$TARGETS', '$SOURCES'])
875 expect = "xyzzy $TARGET $SOURCE $TARGETS $SOURCES"
876 s = act.genstring([], [], env)
877 assert s == expect, s
878 s = act.genstring([t1], [s1], env)
879 assert s == expect, s
880 s = act.genstring([t1, t2], [s1, s2], env)
881 assert s == expect, s
883 def test_strfunction(self):
884 """Test fetching the string representation of command Actions
892 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
893 s = act.strfunction([], [], env)
894 assert s == 'xyzzy', s
895 s = act.strfunction([t1], [s1], env)
896 assert s == 'xyzzy t1 s1', s
897 s = act.strfunction([t1, t2], [s1, s2], env)
898 assert s == 'xyzzy t1 s1', s
900 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE',
901 cmdstr='cmdstr - $SOURCE - $TARGET -')
902 s = act.strfunction([], [], env)
903 assert s == 'cmdstr - - -', s
904 s = act.strfunction([t1], [s1], env)
905 assert s == 'cmdstr - s1 - t1 -', s
906 s = act.strfunction([t1, t2], [s1, s2], env)
907 assert s == 'cmdstr - s1 - t1 -', s
909 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
910 s = act.strfunction([], [], env)
911 assert s == 'xyzzy', s
912 s = act.strfunction([t1], [s1], env)
913 assert s == 'xyzzy t1 s1', s
914 s = act.strfunction([t1, t2], [s1, s2], env)
915 assert s == 'xyzzy t1 t2 s1 s2', s
917 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
918 cmdstr='cmdstr = $SOURCES = $TARGETS =')
919 s = act.strfunction([], [], env)
920 assert s == 'cmdstr = = =', s
921 s = act.strfunction([t1], [s1], env)
922 assert s == 'cmdstr = s1 = t1 =', s
923 s = act.strfunction([t1, t2], [s1, s2], env)
924 assert s == 'cmdstr = s1 s2 = t1 t2 =', s
926 act = SCons.Action.CommandAction(['xyzzy',
927 '$TARGET', '$SOURCE',
928 '$TARGETS', '$SOURCES'])
929 s = act.strfunction([], [], env)
930 assert s == 'xyzzy', s
931 s = act.strfunction([t1], [s1], env)
932 assert s == 'xyzzy t1 s1 t1 s1', s
933 s = act.strfunction([t1, t2], [s1, s2], env)
934 assert s == 'xyzzy t1 s1 t1 t2 s1 s2', s
936 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
937 cmdstr='cmdstr\t$TARGETS\n$SOURCES ')
939 s = act.strfunction([], [], env)
940 assert s == 'cmdstr\t\n ', s
941 s = act.strfunction([t1], [s1], env)
942 assert s == 'cmdstr\tt1\ns1 ', s
943 s = act.strfunction([t1, t2], [s1, s2], env)
944 assert s == 'cmdstr\tt1 t2\ns1 s2 ', s
946 def sf(target, source, env):
947 return "sf was called"
948 act = SCons.Action.CommandAction('foo', strfunction=sf)
949 s = act.strfunction([], [], env)
950 assert s == "sf was called", s
953 def __init__(self, targets, sources, env):
958 def __init__(self, targets, sources, env):
963 def __init__(self, targets, sources, env):
967 def strfunction(self, targets, sources, env):
968 return 'actclass3 on %s to get %s'%(str(sources[0]),
971 def __init__(self, targets, sources, env):
977 act1 = SCons.Action.Action(actclass1([t1], [s1], env))
978 s = act1.strfunction([t1], [s1], env)
979 assert s == 'actclass1(["t1"], ["s1"])', s
981 act2 = SCons.Action.Action(actclass2([t1], [s1], env))
982 s = act2.strfunction([t1], [s1], env)
983 assert s == 'actclass2(["t1"], ["s1"])', s
985 act3 = SCons.Action.Action(actclass3([t1], [s1], env))
986 s = act3.strfunction([t1], [s1], env)
987 assert s == 'actclass3 on s1 to get t1', s
989 act4 = SCons.Action.Action(actclass4([t1], [s1], env))
990 s = act4.strfunction([t1], [s1], env)
993 act = SCons.Action.CommandAction("@foo bar")
994 s = act.strfunction([], [], env)
997 act = SCons.Action.CommandAction("@-foo bar")
998 s = act.strfunction([], [], env)
1001 act = SCons.Action.CommandAction("-@foo bar")
1002 s = act.strfunction([], [], env)
1005 act = SCons.Action.CommandAction("-foo bar")
1006 s = act.strfunction([], [], env)
1007 assert s == "foo bar", s
1009 act = SCons.Action.CommandAction("@ foo bar")
1010 s = act.strfunction([], [], env)
1013 act = SCons.Action.CommandAction("@- foo bar")
1014 s = act.strfunction([], [], env)
1017 act = SCons.Action.CommandAction("-@ foo bar")
1018 s = act.strfunction([], [], env)
1021 act = SCons.Action.CommandAction("- foo bar")
1022 s = act.strfunction([], [], env)
1023 assert s == "foo bar", s
1025 def test_execute(self):
1026 """Test execution of command Actions
1031 except AttributeError:
1034 cmd1 = r'%s %s %s xyzzy' % (_python_, act_py, outfile)
1036 act = SCons.Action.CommandAction(cmd1)
1037 r = act([], [], env.Clone())
1039 c = test.read(outfile, 'r')
1040 assert c == "act.py: 'xyzzy'\n", c
1042 cmd2 = r'%s %s %s $TARGET' % (_python_, act_py, outfile)
1044 act = SCons.Action.CommandAction(cmd2)
1045 r = act(DummyNode('foo'), [], env.Clone())
1047 c = test.read(outfile, 'r')
1048 assert c == "act.py: 'foo'\n", c
1050 cmd3 = r'%s %s %s ${TARGETS}' % (_python_, act_py, outfile)
1052 act = SCons.Action.CommandAction(cmd3)
1053 r = act(map(DummyNode, ['aaa', 'bbb']), [], env.Clone())
1055 c = test.read(outfile, 'r')
1056 assert c == "act.py: 'aaa' 'bbb'\n", c
1058 cmd4 = r'%s %s %s $SOURCES' % (_python_, act_py, outfile)
1060 act = SCons.Action.CommandAction(cmd4)
1061 r = act([], [DummyNode('one'), DummyNode('two')], env.Clone())
1063 c = test.read(outfile, 'r')
1064 assert c == "act.py: 'one' 'two'\n", c
1066 cmd4 = r'%s %s %s ${SOURCES[:2]}' % (_python_, act_py, outfile)
1068 act = SCons.Action.CommandAction(cmd4)
1069 sources = [DummyNode('three'), DummyNode('four'), DummyNode('five')]
1071 r = act([], source = sources, env = env2)
1073 c = test.read(outfile, 'r')
1074 assert c == "act.py: 'three' 'four'\n", c
1076 cmd5 = r'%s %s %s $TARGET XYZZY' % (_python_, act_py, outfile)
1078 act = SCons.Action.CommandAction(cmd5)
1079 env5 = Environment()
1080 if scons_env.has_key('ENV'):
1081 env5['ENV'] = scons_env['ENV']
1082 PATH = scons_env['ENV'].get('PATH', '')
1087 env5['ENV']['XYZZY'] = 'xyzzy'
1088 r = act(target = DummyNode('out5'), source = [], env = env5)
1090 act = SCons.Action.CommandAction(cmd5)
1091 r = act(target = DummyNode('out5'),
1093 env = env.Clone(ENV = {'XYZZY' : 'xyzzy5',
1096 c = test.read(outfile, 'r')
1097 assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy5'\n", c
1100 def __init__(self, str):
1106 def get_subst_proxy(self):
1109 cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (_python_, act_py, outfile)
1111 act = SCons.Action.CommandAction(cmd6)
1112 r = act(target = [Obj('111'), Obj('222')],
1113 source = [Obj('333'), Obj('444'), Obj('555')],
1116 c = test.read(outfile, 'r')
1117 assert c == "act.py: '222' '111' '333' '444'\n", c
1120 # NT treats execs of directories and non-executable files
1121 # as "file not found" errors
1122 expect_nonexistent = 1
1123 expect_nonexecutable_file = 1
1124 expect_nonexecutable_dir = 1
1125 elif sys.platform == 'cygwin':
1126 expect_nonexistent = 127
1127 # Newer cygwin seems to return 126 for following
1128 expect_nonexecutable_file = 126
1129 expect_nonexecutable_dir = 127
1131 expect_nonexistent = 127
1132 expect_nonexecutable_file = 126
1133 expect_nonexecutable_dir = 126
1135 # Test that a nonexistent command returns 127
1136 act = SCons.Action.CommandAction(python + "_no_such_command_")
1137 r = act([], [], env.Clone(out = outfile))
1138 assert r.status == expect_nonexistent, r.status
1140 # Test that trying to execute a directory returns 126
1141 dir, tail = os.path.split(python)
1142 act = SCons.Action.CommandAction(dir)
1143 r = act([], [], env.Clone(out = outfile))
1144 assert r.status == expect_nonexecutable_file, r.status
1146 # Test that trying to execute a non-executable file returns 126
1147 act = SCons.Action.CommandAction(outfile)
1148 r = act([], [], env.Clone(out = outfile))
1149 assert r.status == expect_nonexecutable_dir, r.status
1151 act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py))
1152 r = act([], [], env)
1153 assert r.status == 1, r.status
1155 act = SCons.Action.CommandAction('@%s %s 1' % (_python_, exit_py))
1156 r = act([], [], env)
1157 assert r.status == 1, r.status
1159 act = SCons.Action.CommandAction('@-%s %s 1' % (_python_, exit_py))
1160 r = act([], [], env)
1163 act = SCons.Action.CommandAction('-%s %s 1' % (_python_, exit_py))
1164 r = act([], [], env)
1167 act = SCons.Action.CommandAction('@ %s %s 1' % (_python_, exit_py))
1168 r = act([], [], env)
1169 assert r.status == 1, r.status
1171 act = SCons.Action.CommandAction('@- %s %s 1' % (_python_, exit_py))
1172 r = act([], [], env)
1175 act = SCons.Action.CommandAction('- %s %s 1' % (_python_, exit_py))
1176 r = act([], [], env)
1179 def _DO_NOT_EXECUTE_test_pipe_execute(self):
1180 """Test capturing piped output from an action
1182 We used to have PIPE_BUILD support built right into
1183 Action.execute() for the benefit of the SConf subsystem, but we've
1184 moved that logic back into SConf itself. We'll leave this code
1185 here, just in case we ever want to resurrect this functionality
1186 in the future, but change the name of the test so it doesn't
1187 get executed as part of the normal test suite.
1189 pipe = open( pipe_file, "w" )
1190 self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1,
1191 PSTDOUT = pipe, PSTDERR = pipe)
1192 # everything should also work when piping output
1194 self.env['PSTDOUT'].close()
1195 pipe_out = test.read( pipe_file )
1197 act_out = "act.py: stdout: executed act.py"
1198 act_err = "act.py: stderr: executed act.py"
1200 # Since we are now using select(), stdout and stderr can be
1201 # intermixed, so count the lines separately.
1202 outlines = re.findall(act_out, pipe_out)
1203 errlines = re.findall(act_err, pipe_out)
1204 assert len(outlines) == 6, pipe_out + repr(outlines)
1205 assert len(errlines) == 6, pipe_out + repr(errlines)
1207 # test redirection operators
1208 def test_redirect(self, redir, stdout_msg, stderr_msg):
1209 cmd = r'%s %s %s xyzzy %s' % (_python_, act_py, outfile, redir)
1210 # Write the output and error messages to files because
1211 # Windows can't handle strings that are too big in its
1212 # external environment (os.spawnve() returns EINVAL,
1213 # "Invalid argument").
1214 stdout_file = test.workpath('stdout_msg')
1215 stderr_file = test.workpath('stderr_msg')
1216 open(stdout_file, 'w').write(stdout_msg)
1217 open(stderr_file, 'w').write(stderr_msg)
1218 pipe = open( pipe_file, "w" )
1219 act = SCons.Action.CommandAction(cmd)
1220 env = Environment( ENV = {'ACTPY_PIPE' : '1',
1221 'PIPE_STDOUT_FILE' : stdout_file,
1222 'PIPE_STDERR_FILE' : stderr_file},
1224 PSTDOUT = pipe, PSTDERR = pipe )
1225 r = act([], [], env)
1228 return (test.read(outfile2, 'r'), test.read(pipe_file, 'r'))
1230 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1232 assert redirected == act_out
1233 assert pipe_out == act_err
1235 (redirected, pipe_out) = test_redirect(self,'2> %s' % outfile2,
1237 assert redirected == act_err
1238 assert pipe_out == act_out
1240 (redirected, pipe_out) = test_redirect(self,'> %s 2>&1' % outfile2,
1242 assert (redirected == act_out + act_err or
1243 redirected == act_err + act_out)
1244 assert pipe_out == ""
1246 act_err = "Long Command Output\n"*3000
1247 # the size of the string should exceed the system's default block size
1249 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1251 assert (redirected == act_out)
1252 assert (pipe_out == act_err)
1254 def test_set_handler(self):
1255 """Test setting the command handler...
1261 def func(sh, escape, cmd, args, env, test=t):
1262 test.executed = args
1265 def escape_func(cmd):
1266 return '**' + cmd + '**'
1269 def __init__(self, x):
1273 def escape(self, escape_func):
1274 return escape_func(self.data)
1275 def is_literal(self):
1278 a = SCons.Action.CommandAction(["xyzzy"])
1279 e = Environment(SPAWN = func)
1281 assert t.executed == [ 'xyzzy' ], t.executed
1283 a = SCons.Action.CommandAction(["xyzzy"])
1284 e = Environment(SPAWN = '$FUNC', FUNC = func)
1286 assert t.executed == [ 'xyzzy' ], t.executed
1288 a = SCons.Action.CommandAction(["xyzzy"])
1289 e = Environment(SPAWN = func, SHELL = 'fake shell')
1291 assert t.executed == [ 'xyzzy' ], t.executed
1292 assert t.shell == 'fake shell', t.shell
1294 a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ])
1295 e = Environment(SPAWN = func, ESCAPE = escape_func)
1297 assert t.executed == [ '**xyzzy**' ], t.executed
1299 def test_get_contents(self):
1300 """Test fetching the contents of a command Action
1302 def CmdGen(target, source, env, for_signature):
1303 assert for_signature
1305 (env["foo"], env["bar"])
1307 # The number 1 is there to make sure all args get converted to strings.
1308 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
1309 "$)", "|", "$baz", 1])
1310 c = a.get_contents(target=[], source=[],
1311 env=Environment(foo = 'FFF', bar = 'BBB',
1313 assert c == "| | FFF BBB 1", c
1315 # Make sure that CommandActions use an Environment's
1316 # subst_target_source() method for substitution.
1317 class SpecialEnvironment(Environment):
1318 def subst_target_source(self, strSubst, raw=0, target=[], source=[]):
1319 return 'subst_target_source: ' + strSubst
1321 c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'),
1322 env=SpecialEnvironment(foo = 'GGG', bar = 'CCC',
1324 assert c == 'subst_target_source: | $( $foo | $bar $) | $baz 1', c
1326 # We've discussed using the real target and source names in a
1327 # CommandAction's signature contents. This would have have the
1328 # advantage of recompiling when a file's name changes (keeping
1329 # debug info current), but it would currently break repository
1330 # logic that will change the file name based on whether the
1331 # files come from a repository or locally. If we ever move to
1332 # that scheme, then all of the '__t1__' and '__s6__' file names
1333 # in the asserts below would change to 't1' and 's6' and the
1335 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
1336 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
1339 a = SCons.Action.CommandAction(["$TARGET"])
1340 c = a.get_contents(target=t, source=s, env=env)
1343 a = SCons.Action.CommandAction(["$TARGETS"])
1344 c = a.get_contents(target=t, source=s, env=env)
1345 assert c == "t1 t2 t3 t4 t5 t6", c
1347 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
1348 c = a.get_contents(target=t, source=s, env=env)
1351 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
1352 c = a.get_contents(target=t, source=s, env=env)
1353 assert c == "t4 t5", c
1355 a = SCons.Action.CommandAction(["$SOURCE"])
1356 c = a.get_contents(target=t, source=s, env=env)
1359 a = SCons.Action.CommandAction(["$SOURCES"])
1360 c = a.get_contents(target=t, source=s, env=env)
1361 assert c == "s1 s2 s3 s4 s5 s6", c
1363 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
1364 c = a.get_contents(target=t, source=s, env=env)
1367 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
1368 c = a.get_contents(target=t, source=s, env=env)
1369 assert c == "s4 s5", c
1371 class CommandGeneratorActionTestCase(unittest.TestCase):
1373 def factory(self, act, **kw):
1374 """Pass any keywords as a dict"""
1375 return SCons.Action.CommandGeneratorAction(act, kw)
1377 def test___init__(self):
1378 """Test creation of a command generator Action
1380 def f(target, source, env):
1383 assert a.generator == f
1385 def test___str__(self):
1386 """Test the pre-substitution strings for command generator Actions
1388 def f(target, source, env, for_signature, self=self):
1390 # See if "env" is really a construction environment (or
1391 # looks like one) by accessing the FindIxes attribute.
1392 # (The Tool/mingw.py module has a generator that uses this,
1393 # and the __str__() method used to cause problems by passing
1394 # us a regular dictionary as a fallback.)
1400 assert s == 'FOO', s
1402 def test_genstring(self):
1403 """Test the command generator Action genstring() method
1405 def f(target, source, env, for_signature, self=self):
1406 dummy = env['dummy']
1408 return "$FOO $TARGET $SOURCE $TARGETS $SOURCES"
1411 s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1))
1412 assert self.dummy == 1, self.dummy
1413 assert s == "$FOO $TARGET $SOURCE $TARGETS $SOURCES", s
1415 def test_execute(self):
1416 """Test executing a command generator Action
1419 def f(target, source, env, for_signature, self=self):
1420 dummy = env['dummy']
1422 s = env.subst("$FOO")
1423 assert s == 'foo baz\nbar ack', s
1425 def func_action(target, source, env, self=self):
1427 s = env.subst('$foo')
1428 assert s == 'bar', s
1430 def f2(target, source, env, for_signature, f=func_action):
1432 def ch(sh, escape, cmd, args, env, self=self):
1433 self.cmd.append(cmd)
1434 self.args.append(args)
1440 a([], [], env=Environment(FOO = 'foo baz\nbar ack',
1443 assert self.dummy == 1, self.dummy
1444 assert self.cmd == ['foo', 'bar'], self.cmd
1445 assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args
1447 b = self.factory(f2)
1449 b(target=[], source=[], env=Environment(foo = 'bar',
1451 assert self.dummy==2, self.dummy
1455 def __init__(self, t):
1458 self.t.rfile_called = 1
1460 def get_subst_proxy(self):
1462 def f3(target, source, env, for_signature):
1464 c = self.factory(f3)
1465 c(target=[], source=DummyFile(self), env=Environment())
1466 assert self.rfile_called
1468 def test_get_contents(self):
1469 """Test fetching the contents of a command generator Action
1471 def f(target, source, env, for_signature):
1474 assert for_signature, for_signature
1475 return [["guux", foo, "$(", "$ignore", "$)", bar,
1476 '${test("$( foo $bar $)")}' ]]
1479 assert mystr == "$( foo $bar $)", mystr
1482 env = Environment(foo = 'FFF', bar = 'BBB',
1483 ignore = 'foo', test=test)
1485 c = a.get_contents(target=[], source=[], env=env)
1486 assert c == "guux FFF BBB test", c
1488 def test_get_contents_of_function_action(self):
1489 """Test contents of a CommandGeneratorAction-generated FunctionAction
1496 "0,0,0,0,(),(),(d\000\000S),(),()",
1497 "0,0,0,0,(),(),(d\x00\x00S),(),()",
1501 "1,1,0,0,(),(),(d\000\000S),(),()",
1502 "1,1,0,0,(),(),(d\x00\x00S),(),()",
1505 def f_global(target, source, env, for_signature):
1506 return SCons.Action.Action(GlobalFunc)
1509 #def f_local(target, source, env, for_signature):
1510 def f_local(target, source, env, for_signature, LocalFunc=LocalFunc):
1511 return SCons.Action.Action(LocalFunc)
1513 env = Environment(XYZ = 'foo')
1515 a = self.factory(f_global)
1516 c = a.get_contents(target=[], source=[], env=env)
1517 assert c in func_matches, repr(c)
1519 a = self.factory(f_local)
1520 c = a.get_contents(target=[], source=[], env=env)
1521 assert c in func_matches, repr(c)
1523 def f_global(target, source, env, for_signature):
1524 return SCons.Action.Action(GlobalFunc, varlist=['XYZ'])
1527 #def f_local(target, source, env, for_signature):
1528 def f_local(target, source, env, for_signature, LocalFunc=LocalFunc):
1529 return SCons.Action.Action(LocalFunc, varlist=['XYZ'])
1531 matches_foo = map(lambda x: x + "foo", func_matches)
1533 a = self.factory(f_global)
1534 c = a.get_contents(target=[], source=[], env=env)
1535 assert c in matches_foo, repr(c)
1537 a = self.factory(f_local)
1538 c = a.get_contents(target=[], source=[], env=env)
1539 assert c in matches_foo, repr(c)
1542 class FunctionActionTestCase(unittest.TestCase):
1544 def test___init__(self):
1545 """Test creation of a function Action
1556 a = SCons.Action.FunctionAction(func1, {})
1557 assert a.execfunction == func1, a.execfunction
1558 assert isinstance(a.strfunction, types.MethodType), type(a.strfunction)
1560 a = SCons.Action.FunctionAction(func2, { 'strfunction' : func3 })
1561 assert a.execfunction == func2, a.execfunction
1562 assert a.strfunction == func3, a.strfunction
1564 def test___str__(self):
1565 """Test the __str__() method for function Actions
1569 a = SCons.Action.FunctionAction(func1, {})
1571 assert s == "func1(target, source, env)", s
1576 a = SCons.Action.FunctionAction(class1(), {})
1578 assert s == "class1(target, source, env)", s
1580 def test_execute(self):
1581 """Test executing a function Action
1584 def f(target, source, env):
1589 assert env.subst("$BAR") == 'foo bar', env.subst("$BAR")
1591 a = SCons.Action.FunctionAction(f, {})
1592 a(target=1, source=2, env=Environment(BAR = 'foo bar',
1594 assert self.inc == 1, self.inc
1595 assert self.source == [2], self.source
1596 assert self.target == [1], self.target
1600 def function1(target, source, env):
1604 open(t, 'w').write("function1\n")
1607 act = SCons.Action.FunctionAction(function1, {})
1608 r = act(target = [outfile, outfile2], source=[], env=Environment())
1609 assert r.status == 1, r.status
1611 assert count == 1, count
1612 c = test.read(outfile, 'r')
1613 assert c == "function1\n", c
1614 c = test.read(outfile2, 'r')
1615 assert c == "function1\n", c
1618 def __init__(self, target, source, env):
1619 open(env['out'], 'w').write("class1a\n")
1621 act = SCons.Action.FunctionAction(class1a, {})
1622 r = act([], [], Environment(out = outfile))
1623 assert isinstance(r.status, class1a), r.status
1624 c = test.read(outfile, 'r')
1625 assert c == "class1a\n", c
1628 def __call__(self, target, source, env):
1629 open(env['out'], 'w').write("class1b\n")
1632 act = SCons.Action.FunctionAction(class1b(), {})
1633 r = act([], [], Environment(out = outfile))
1634 assert r.status == 2, r.status
1635 c = test.read(outfile, 'r')
1636 assert c == "class1b\n", c
1638 def build_it(target, source, env, executor=None, self=self):
1641 def string_it(target, source, env, executor=None, self=self):
1644 act = SCons.Action.FunctionAction(build_it,
1645 { 'strfunction' : string_it })
1646 r = act([], [], Environment())
1648 assert self.build_it
1649 assert self.string_it
1651 def test_get_contents(self):
1652 """Test fetching the contents of a function Action
1659 "0,0,0,0,(),(),(d\000\000S),(),()",
1660 "0,0,0,0,(),(),(d\x00\x00S),(),()",
1664 "1,1,0,0,(),(),(d\000\000S),(),()",
1665 "1,1,0,0,(),(),(d\x00\x00S),(),()",
1668 def factory(act, **kw):
1669 return SCons.Action.FunctionAction(act, kw)
1671 a = factory(GlobalFunc)
1672 c = a.get_contents(target=[], source=[], env=Environment())
1673 assert c in func_matches, repr(c)
1675 a = factory(LocalFunc)
1676 c = a.get_contents(target=[], source=[], env=Environment())
1677 assert c in func_matches, repr(c)
1679 matches_foo = map(lambda x: x + "foo", func_matches)
1681 a = factory(GlobalFunc, varlist=['XYZ'])
1682 c = a.get_contents(target=[], source=[], env=Environment())
1683 assert c in func_matches, repr(c)
1684 c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo'))
1685 assert c in matches_foo, repr(c)
1687 ##TODO: is this set of tests still needed?
1688 # Make sure a bare string varlist works
1689 a = factory(GlobalFunc, varlist='XYZ')
1690 c = a.get_contents(target=[], source=[], env=Environment())
1691 assert c in func_matches, repr(c)
1692 c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo'))
1693 assert c in matches_foo, repr(c)
1696 def get_contents(self, target, source, env):
1699 c = a.get_contents(target=[], source=[], env=Environment())
1700 assert c == 'xyzzy', repr(c)
1703 def LocalMethod(self):
1706 a = factory(lc.LocalMethod)
1707 c = a.get_contents(target=[], source=[], env=Environment())
1708 assert c in meth_matches, repr(c)
1710 def test_strfunction(self):
1711 """Test the FunctionAction.strfunction() method
1716 def factory(act, **kw):
1717 return SCons.Action.FunctionAction(act, kw)
1720 s = a.strfunction(target=[], source=[], env=Environment())
1721 assert s == 'func([], [])', s
1723 a = factory(func, strfunction=None)
1724 s = a.strfunction(target=[], source=[], env=Environment())
1727 a = factory(func, cmdstr='function')
1728 s = a.strfunction(target=[], source=[], env=Environment())
1729 assert s == 'function', s
1731 class ListActionTestCase(unittest.TestCase):
1733 def test___init__(self):
1734 """Test creation of a list of subsidiary Actions
1738 a = SCons.Action.ListAction(["x", func, ["y", "z"]])
1739 assert isinstance(a.list[0], SCons.Action.CommandAction)
1740 assert isinstance(a.list[1], SCons.Action.FunctionAction)
1741 assert isinstance(a.list[2], SCons.Action.ListAction)
1742 assert a.list[2].list[0].cmd_list == 'y'
1744 def test___str__(self):
1745 """Test the __str__() method for a list of subsidiary Actions
1747 def f(target,source,env):
1749 def g(target,source,env):
1751 a = SCons.Action.ListAction([f, g, "XXX", f])
1753 assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s
1755 def test_genstring(self):
1756 """Test the genstring() method for a list of subsidiary Actions
1758 def f(target,source,env):
1760 def g(target,source,env,for_signature):
1761 return 'generated %s %s' % (target[0], source[0])
1762 g = SCons.Action.Action(g, generator=1)
1763 a = SCons.Action.ListAction([f, g, "XXX", f])
1764 s = a.genstring(['foo.x'], ['bar.y'], Environment())
1765 assert s == "f(target, source, env)\ngenerated foo.x bar.y\nXXX\nf(target, source, env)", s
1767 def test_execute(self):
1768 """Test executing a list of subsidiary Actions
1771 def f(target,source,env):
1774 a = SCons.Action.ListAction([f, f, f])
1775 a([], [], Environment(s = self))
1776 assert self.inc == 3, self.inc
1778 cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile)
1780 def function2(target, source, env):
1781 open(env['out'], 'a').write("function2\n")
1785 def __call__(self, target, source, env):
1786 open(env['out'], 'a').write("class2a\n")
1790 def __init__(self, target, source, env):
1791 open(env['out'], 'a').write("class2b\n")
1792 act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
1793 r = act([], [], Environment(out = outfile))
1794 assert isinstance(r.status, class2b), r.status
1795 c = test.read(outfile, 'r')
1796 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
1798 def test_get_contents(self):
1799 """Test fetching the contents of a list of subsidiary Actions
1802 def gen(target, source, env, for_signature):
1806 a = SCons.Action.ListAction(["x",
1807 SCons.Action.Action(gen, generator=1),
1809 c = a.get_contents(target=[], source=[], env=Environment(s = self))
1810 assert self.foo==1, self.foo
1811 assert c == "xyz", c
1813 class LazyActionTestCase(unittest.TestCase):
1814 def test___init__(self):
1815 """Test creation of a lazy-evaluation Action
1817 # Environment variable references should create a special type
1818 # of LazyAction that lazily evaluates the variable for whether
1819 # it's a string or something else before doing anything.
1820 a9 = SCons.Action.Action('$FOO')
1821 assert isinstance(a9, SCons.Action.LazyAction), a9
1822 assert a9.var == 'FOO', a9.var
1824 a10 = SCons.Action.Action('${FOO}')
1825 assert isinstance(a10, SCons.Action.LazyAction), a10
1826 assert a10.var == 'FOO', a10.var
1828 def test_genstring(self):
1829 """Test the lazy-evaluation Action genstring() method
1831 def f(target, source, env):
1833 a = SCons.Action.Action('$BAR')
1834 env1 = Environment(BAR=f, s=self)
1835 env2 = Environment(BAR='xxx', s=self)
1836 s = a.genstring([], [], env=env1)
1837 assert s == "f(target, source, env)", s
1838 s = a.genstring([], [], env=env2)
1839 assert s == 'xxx', s
1841 def test_execute(self):
1842 """Test executing a lazy-evaluation Action
1844 def f(target, source, env):
1848 a = SCons.Action.Action('$BAR')
1849 a([], [], env=Environment(BAR = f, s = self))
1850 assert self.test == 1, self.test
1851 cmd = r'%s %s %s lazy' % (_python_, act_py, outfile)
1852 a([], [], env=Environment(BAR = cmd, s = self))
1853 c = test.read(outfile, 'r')
1854 assert c == "act.py: 'lazy'\n", c
1856 def test_get_contents(self):
1857 """Test fetching the contents of a lazy-evaluation Action
1859 a = SCons.Action.Action("${FOO}")
1860 env = Environment(FOO = [["This", "is", "a", "test"]])
1861 c = a.get_contents(target=[], source=[], env=env)
1862 assert c == "This is a test", c
1864 def test_get_contents_of_function_action(self):
1865 """Test fetching the contents of a lazy-evaluation FunctionAction
1872 "0,0,0,0,(),(),(d\000\000S),(),()",
1873 "0,0,0,0,(),(),(d\x00\x00S),(),()",
1877 "1,1,0,0,(),(),(d\000\000S),(),()",
1878 "1,1,0,0,(),(),(d\x00\x00S),(),()",
1881 def factory(act, **kw):
1882 return SCons.Action.FunctionAction(act, kw)
1885 a = SCons.Action.Action("${FOO}")
1887 env = Environment(FOO = factory(GlobalFunc))
1888 c = a.get_contents(target=[], source=[], env=env)
1889 assert c in func_matches, repr(c)
1891 env = Environment(FOO = factory(LocalFunc))
1892 c = a.get_contents(target=[], source=[], env=env)
1893 assert c in func_matches, repr(c)
1895 matches_foo = map(lambda x: x + "foo", func_matches)
1897 env = Environment(FOO = factory(GlobalFunc, varlist=['XYZ']))
1898 c = a.get_contents(target=[], source=[], env=env)
1899 assert c in func_matches, repr(c)
1902 c = a.get_contents(target=[], source=[], env=env)
1903 assert c in matches_foo, repr(c)
1905 class ActionCallerTestCase(unittest.TestCase):
1906 def test___init__(self):
1907 """Test creation of an ActionCaller"""
1908 ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO' : 4, 'BAR' : 5})
1909 assert ac.parent == 1, ac.parent
1910 assert ac.args == [2, 3], ac.args
1911 assert ac.kw == {'FOO' : 4, 'BAR' : 5}, ac.kw
1913 def test_get_contents(self):
1914 """Test fetching the contents of an ActionCaller"""
1926 af = SCons.Action.ActionFactory(GlobalFunc, strfunc)
1927 ac = SCons.Action.ActionCaller(af, [], {})
1928 c = ac.get_contents([], [], Environment())
1929 assert c in matches, repr(c)
1931 af = SCons.Action.ActionFactory(LocalFunc, strfunc)
1932 ac = SCons.Action.ActionCaller(af, [], {})
1933 c = ac.get_contents([], [], Environment())
1934 assert c in matches, repr(c)
1945 af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc)
1946 ac = SCons.Action.ActionCaller(af, [], {})
1947 c = ac.get_contents([], [], Environment())
1948 assert c in matches, repr(c)
1950 af = SCons.Action.ActionFactory(LocalActFunc(), strfunc)
1951 ac = SCons.Action.ActionCaller(af, [], {})
1952 c = ac.get_contents([], [], Environment())
1953 assert c in matches, repr(c)
1956 "<built-in function str>",
1960 af = SCons.Action.ActionFactory(str, strfunc)
1961 ac = SCons.Action.ActionCaller(af, [], {})
1962 c = ac.get_contents([], [], Environment())
1963 assert c == "<built-in function str>" or \
1964 c == "<type 'str'>", repr(c)
1966 def test___call__(self):
1967 """Test calling an ActionCaller"""
1969 def actfunc(a1, a2, a3, args=actfunc_args):
1970 args.extend([a1, a2, a3])
1971 def strfunc(a1, a2, a3):
1974 e = Environment(FOO = 2, BAR = 5)
1976 af = SCons.Action.ActionFactory(actfunc, strfunc)
1977 ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {})
1979 assert actfunc_args[0] is e, actfunc_args
1980 assert actfunc_args[1] == '2', actfunc_args
1981 assert actfunc_args[2] == 3, actfunc_args
1984 ac = SCons.Action.ActionCaller(af, [], {'a3' : '$__env__', 'a2' : '$BAR', 'a1' : 4})
1986 assert actfunc_args[0] == 4, actfunc_args
1987 assert actfunc_args[1] == '5', actfunc_args
1988 assert actfunc_args[2] is e, actfunc_args
1991 def test_strfunction(self):
1992 """Test calling the ActionCaller strfunction() method"""
1994 def actfunc(a1, a2, a3, a4):
1996 def strfunc(a1, a2, a3, a4, args=strfunc_args):
1997 args.extend([a1, a2, a3, a4])
1999 af = SCons.Action.ActionFactory(actfunc, strfunc)
2000 ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3, '$WS'], {})
2001 ac.strfunction([], [], Environment(FOO = 2, WS='white space'))
2002 assert strfunc_args == [1, '2', 3, 'white space'], strfunc_args
2005 d = {'a3' : 6, 'a2' : '$BAR', 'a1' : 4, 'a4' : '$WS'}
2006 ac = SCons.Action.ActionCaller(af, [], d)
2007 ac.strfunction([], [], Environment(BAR = 5, WS='w s'))
2008 assert strfunc_args == [4, '5', 6, 'w s'], strfunc_args
2010 class ActionFactoryTestCase(unittest.TestCase):
2011 def test___init__(self):
2012 """Test creation of an ActionFactory"""
2017 ac = SCons.Action.ActionFactory(actfunc, strfunc)
2018 assert ac.actfunc is actfunc, ac.actfunc
2019 assert ac.strfunc is strfunc, ac.strfunc
2021 def test___call__(self):
2022 """Test calling whatever's returned from an ActionFactory"""
2025 def actfunc(a1, a2, a3, args=actfunc_args):
2026 args.extend([a1, a2, a3])
2027 def strfunc(a1, a2, a3, args=strfunc_args):
2028 args.extend([a1, a2, a3])
2029 af = SCons.Action.ActionFactory(actfunc, strfunc)
2030 af(3, 6, 9)([], [], Environment())
2031 assert actfunc_args == [3, 6, 9], actfunc_args
2032 assert strfunc_args == [3, 6, 9], strfunc_args
2035 class ActionCompareTestCase(unittest.TestCase):
2037 def test_1_solo_name(self):
2038 """Test Lazy Cmd Generator Action get_name alone.
2040 Basically ensures we can locate the builder, comparing it to
2041 itself along the way."""
2042 bar = SCons.Builder.Builder(action = {})
2043 env = Environment( BUILDERS = {'BAR' : bar} )
2044 name = bar.get_name(env)
2045 assert name == 'BAR', name
2047 def test_2_multi_name(self):
2048 """Test LazyCmdGenerator Action get_name multi builders.
2050 Ensure that we can compare builders (and thereby actions) to
2051 each other safely."""
2052 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
2053 bar = SCons.Builder.Builder(action = {})
2055 assert foo.action != bar.action
2056 env = Environment( BUILDERS = {'FOO' : foo,
2058 name = foo.get_name(env)
2059 assert name == 'FOO', name
2060 name = bar.get_name(env)
2061 assert name == 'BAR', name
2063 def test_3_dict_names(self):
2064 """Test Action/Suffix dicts with get_name.
2066 Verifies that Action/Suffix dictionaries work correctly,
2067 especially two builders that can generate the same suffix,
2068 where one of the builders has a suffix dictionary with a None
2071 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
2072 bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'})
2073 bar.add_action('.cow', "$MOO")
2074 dog = SCons.Builder.Builder(suffix = '.bar')
2076 env = Environment( BUILDERS = {'FOO' : foo,
2080 assert foo.get_name(env) == 'FOO', foo.get_name(env)
2081 assert bar.get_name(env) == 'BAR', bar.get_name(env)
2082 assert dog.get_name(env) == 'DOG', dog.get_name(env)
2085 if __name__ == "__main__":
2086 suite = unittest.TestSuite()
2087 tclasses = [ _ActionActionTestCase,
2089 CommandActionTestCase,
2090 CommandGeneratorActionTestCase,
2091 FunctionActionTestCase,
2094 ActionCallerTestCase,
2095 ActionFactoryTestCase,
2096 ActionCompareTestCase ]
2097 for tclass in tclasses:
2098 names = unittest.getTestCaseNames(tclass, 'test_')
2099 suite.addTests(map(tclass, names))
2100 if not unittest.TextTestRunner().run(suite).wasSuccessful():
2105 # indent-tabs-mode:nil
2107 # vim: set expandtab tabstop=4 shiftwidth=4: