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):
179 def get_subst_proxy(self):
182 if os.name == 'java':
183 python = os.path.join(sys.prefix, 'jython')
185 python = sys.executable
187 _python_ = '"' + python + '"'
189 class ActionTestCase(unittest.TestCase):
190 """Test the Action() factory function"""
192 def test_FunctionAction(self):
193 """Test the Action() factory's creation of FunctionAction objects
199 a1 = SCons.Action.Action(foo)
200 assert isinstance(a1, SCons.Action.FunctionAction), a1
201 assert a1.execfunction == foo, a1.execfunction
203 a11 = SCons.Action.Action(foo, strfunction=bar)
204 assert isinstance(a11, SCons.Action.FunctionAction), a11
205 assert a11.execfunction == foo, a11.execfunction
206 assert a11.strfunction == bar, a11.strfunction
208 def test_CommandAction(self):
209 """Test the Action() factory's creation of CommandAction objects
211 a1 = SCons.Action.Action("string")
212 assert isinstance(a1, SCons.Action.CommandAction), a1
213 assert a1.cmd_list == "string", a1.cmd_list
215 if hasattr(types, 'UnicodeType'):
216 exec "a2 = SCons.Action.Action(u'string')"
217 exec "assert isinstance(a2, SCons.Action.CommandAction), a2"
219 a3 = SCons.Action.Action(["a3"])
220 assert isinstance(a3, SCons.Action.CommandAction), a3
221 assert a3.cmd_list == "a3", a3.cmd_list
223 a4 = SCons.Action.Action([[ "explicit", "command", "line" ]])
224 assert isinstance(a4, SCons.Action.CommandAction), a4
225 assert a4.cmd_list == [ "explicit", "command", "line" ], a4.cmd_list
230 a5 = SCons.Action.Action("string", strfunction=foo)
231 assert isinstance(a5, SCons.Action.CommandAction), a5
232 assert a5.cmd_list == "string", a5.cmd_list
233 assert a5.strfunction == foo, a5.strfunction
235 def test_ListAction(self):
236 """Test the Action() factory's creation of ListAction objects
238 a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]])
239 assert isinstance(a1, SCons.Action.ListAction), a1
240 assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0]
241 assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list
242 assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1]
243 assert a1.list[1].cmd_list == "y", a1.list[1].cmd_list
244 assert isinstance(a1.list[2], SCons.Action.CommandAction), a1.list[2]
245 assert a1.list[2].cmd_list == "z", a1.list[2].cmd_list
246 assert isinstance(a1.list[3], SCons.Action.CommandAction), a1.list[3]
247 assert a1.list[3].cmd_list == [ "a", "b", "c" ], a1.list[3].cmd_list
249 a2 = SCons.Action.Action("x\ny\nz")
250 assert isinstance(a2, SCons.Action.ListAction), a2
251 assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0]
252 assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list
253 assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1]
254 assert a2.list[1].cmd_list == "y", a2.list[1].cmd_list
255 assert isinstance(a2.list[2], SCons.Action.CommandAction), a2.list[2]
256 assert a2.list[2].cmd_list == "z", a2.list[2].cmd_list
261 a3 = SCons.Action.Action(["x", foo, "z"])
262 assert isinstance(a3, SCons.Action.ListAction), a3
263 assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0]
264 assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list
265 assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1]
266 assert a3.list[1].execfunction == foo, a3.list[1].execfunction
267 assert isinstance(a3.list[2], SCons.Action.CommandAction), a3.list[2]
268 assert a3.list[2].cmd_list == "z", a3.list[2].cmd_list
270 a4 = SCons.Action.Action(["x", "y"], strfunction=foo)
271 assert isinstance(a4, SCons.Action.ListAction), a4
272 assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0]
273 assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list
274 assert a4.list[0].strfunction == foo, a4.list[0].strfunction
275 assert isinstance(a4.list[1], SCons.Action.CommandAction), a4.list[1]
276 assert a4.list[1].cmd_list == "y", a4.list[1].cmd_list
277 assert a4.list[1].strfunction == foo, a4.list[1].strfunction
279 a5 = SCons.Action.Action("x\ny", strfunction=foo)
280 assert isinstance(a5, SCons.Action.ListAction), a5
281 assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0]
282 assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list
283 assert a5.list[0].strfunction == foo, a5.list[0].strfunction
284 assert isinstance(a5.list[1], SCons.Action.CommandAction), a5.list[1]
285 assert a5.list[1].cmd_list == "y", a5.list[1].cmd_list
286 assert a5.list[1].strfunction == foo, a5.list[1].strfunction
288 def test_CommandGeneratorAction(self):
289 """Test the Action() factory's creation of CommandGeneratorAction objects
295 a1 = SCons.Action.Action(foo, generator=1)
296 assert isinstance(a1, SCons.Action.CommandGeneratorAction), a1
297 assert a1.generator is foo, a1.generator
299 a2 = SCons.Action.Action(foo, strfunction=bar, generator=1)
300 assert isinstance(a2, SCons.Action.CommandGeneratorAction), a2
301 assert a2.generator is foo, a2.generator
303 def test_LazyCmdGeneratorAction(self):
304 """Test the Action() factory's creation of lazy CommandGeneratorAction objects
309 a1 = SCons.Action.Action("$FOO")
310 assert isinstance(a1, SCons.Action.LazyAction), a1
312 a2 = SCons.Action.Action("$FOO", strfunction=foo)
313 assert isinstance(a2, SCons.Action.LazyAction), a2
315 def test_no_action(self):
316 """Test when the Action() factory can't create an action object
318 a5 = SCons.Action.Action(1)
319 assert a5 is None, a5
321 def test_reentrance(self):
322 """Test the Action() factory when the action is already an Action object
324 a1 = SCons.Action.Action("foo")
325 a2 = SCons.Action.Action(a1)
328 class ActionBaseTestCase(unittest.TestCase):
329 def test_get_executor(self):
330 """Test the ActionBase.get_executor() method"""
331 a = SCons.Action.Action('foo')
332 x = a.get_executor({}, {}, [], [], {})
333 assert not x is None, x
335 class _ActionActionTestCase(unittest.TestCase):
337 def test__init__(self):
338 """Test creation of _ActionAction objects
347 a = SCons.Action._ActionAction()
348 assert not hasattr(a, 'strfunction')
350 assert SCons.Action._ActionAction(kwarg = 1)
351 assert not hasattr(a, 'strfunction')
352 assert not hasattr(a, 'kwarg')
354 a = SCons.Action._ActionAction(strfunction=func1)
355 assert a.strfunction is func1, a.strfunction
357 a = SCons.Action._ActionAction(presub=func1)
358 assert a.presub is func1, a.presub
360 a = SCons.Action._ActionAction(chdir=1)
361 assert a.chdir is 1, a.chdir
363 a = SCons.Action._ActionAction(func1, func2, 'x')
364 assert a.strfunction is func1, a.strfunction
365 assert a.presub is func2, a.presub
366 assert a.chdir is 'x', a.chdir
368 def test___cmp__(self):
369 """Test Action comparison
371 a1 = SCons.Action.Action("x")
372 a2 = SCons.Action.Action("x")
374 a3 = SCons.Action.Action("y")
378 def test_print_cmd_lines(self):
379 """Test the print_cmd_lines() method
381 save_stdout = sys.stdout
384 def execfunc(target, source, env):
386 a = SCons.Action.Action(execfunc)
388 sio = StringIO.StringIO()
390 a.print_cmd_line("foo bar", None, None, None)
392 assert s == "foo bar\n", s
395 sys.stdout = save_stdout
397 def test___call__(self):
398 """Test calling an Action
400 save_stdout = sys.stdout
402 save_print_actions = SCons.Action.print_actions
403 save_print_actions_presub = SCons.Action.print_actions_presub
404 save_execute_actions = SCons.Action.execute_actions
405 #SCons.Action.print_actions = 0
407 test = TestCmd.TestCmd(workdir = '')
408 test.subdir('sub', 'xyz')
409 os.chdir(test.workpath())
414 def execfunc(target, source, env):
415 assert type(target) is type([]), type(target)
416 assert type(source) is type([]), type(source)
418 a = SCons.Action.Action(execfunc)
420 def firstfunc(target, source, env):
421 assert type(target) is type([]), type(target)
422 assert type(source) is type([]), type(source)
424 def lastfunc(target, source, env):
425 assert type(target) is type([]), type(target)
426 assert type(source) is type([]), type(source)
428 b = SCons.Action.Action([firstfunc, execfunc, lastfunc])
430 sio = StringIO.StringIO()
432 result = a("out", "in", env)
433 assert result.status == 7, result
435 assert s == 'execfunc(["out"], ["in"])\n', s
438 expect = 'os.chdir(%s)\nexecfunc(["out"], ["in"])\nos.chdir(%s)\n'
440 sio = StringIO.StringIO()
442 result = a("out", "in", env)
443 assert result.status == 7, result.status
445 assert s == expect % (repr('xyz'), repr(test.workpath())), s
447 sio = StringIO.StringIO()
449 result = a("out", "in", env, chdir='sub')
450 assert result.status == 7, result.status
452 assert s == expect % (repr('sub'), repr(test.workpath())), s
456 sio = StringIO.StringIO()
458 result = b("out", "in", env)
459 assert result.status == 7, result.status
461 assert s == 'firstfunc(["out"], ["in"])\nexecfunc(["out"], ["in"])\n', s
463 SCons.Action.execute_actions = 0
465 sio = StringIO.StringIO()
467 result = a("out", "in", env)
468 assert result == 0, result
470 assert s == 'execfunc(["out"], ["in"])\n', s
472 sio = StringIO.StringIO()
474 result = b("out", "in", env)
475 assert result == 0, result
477 assert s == 'firstfunc(["out"], ["in"])\nexecfunc(["out"], ["in"])\nlastfunc(["out"], ["in"])\n', s
479 SCons.Action.print_actions_presub = 1
480 SCons.Action.execute_actions = 1
482 sio = StringIO.StringIO()
484 result = a("out", "in", env)
485 assert result.status == 7, result.status
487 assert s == 'Building out with action:\n execfunc(target, source, env)\nexecfunc(["out"], ["in"])\n', s
489 sio = StringIO.StringIO()
491 result = a("out", "in", env, presub=0)
492 assert result.status == 7, result.status
494 assert s == 'execfunc(["out"], ["in"])\n', s
496 sio = StringIO.StringIO()
498 result = a("out", "in", env, presub=1)
499 assert result.status == 7, result.status
501 assert s == 'Building out with action:\n execfunc(target, source, env)\nexecfunc(["out"], ["in"])\n', s
503 sio = StringIO.StringIO()
505 result = b(["out"], "in", env, presub=1)
506 assert result.status == 7, result.status
508 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
510 sio = StringIO.StringIO()
512 result = b(["out", "list"], "in", env, presub=1)
513 assert result.status == 7, result.status
515 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
517 a2 = SCons.Action.Action(execfunc)
519 sio = StringIO.StringIO()
521 result = a2("out", "in", env)
522 assert result.status == 7, result.status
524 assert s == 'Building out with action:\n execfunc(target, source, env)\nexecfunc(["out"], ["in"])\n', s
526 sio = StringIO.StringIO()
528 result = a2("out", "in", env, presub=0)
529 assert result.status == 7, result.status
531 assert s == 'execfunc(["out"], ["in"])\n', s
533 SCons.Action.execute_actions = 0
535 sio = StringIO.StringIO()
537 result = a2("out", "in", env, presub=0)
538 assert result == 0, result
540 assert s == 'execfunc(["out"], ["in"])\n', s
542 sio = StringIO.StringIO()
544 result = a("out", "in", env, presub=0, execute=1, show=0)
545 assert result.status == 7, result.status
549 sys.stdout = save_stdout
550 exitstatfunc_result = []
552 def exitstatfunc(stat, result=exitstatfunc_result):
556 result = a("out", "in", env, exitstatfunc=exitstatfunc)
557 assert result == 0, result
558 assert exitstatfunc_result == [], exitstatfunc_result
560 result = a("out", "in", env, execute=1, exitstatfunc=exitstatfunc)
561 assert result.status == 7, result.status
562 assert exitstatfunc_result == [7], exitstatfunc_result
564 SCons.Action.execute_actions = 1
567 def my_print_cmd_line(s, target, source, env, result=result):
569 env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line
570 a("output", "input", env)
571 assert result == ['execfunc(["output"], ["input"])'], result
575 sys.stdout = save_stdout
576 SCons.Action.print_actions = save_print_actions
577 SCons.Action.print_actions_presub = save_print_actions_presub
578 SCons.Action.execute_actions = save_execute_actions
580 def test_presub_lines(self):
581 """Test the presub_lines() method
584 a = SCons.Action.Action("x")
585 s = a.presub_lines(env)
588 a = SCons.Action.Action(["y", "z"])
589 s = a.presub_lines(env)
590 assert s == ['y', 'z'], s
594 a = SCons.Action.Action(func)
595 s = a.presub_lines(env)
596 assert s == ["func(target, source, env)"], s
598 def gen(target, source, env, for_signature):
599 return 'generat' + env.get('GEN', 'or')
600 a = SCons.Action.Action(gen, generator=1)
601 s = a.presub_lines(env)
602 assert s == ["generator"], s
603 s = a.presub_lines(Environment(GEN = 'ed'))
604 assert s == ["generated"], s
606 a = SCons.Action.Action("$ACT")
607 s = a.presub_lines(env)
609 s = a.presub_lines(Environment(ACT = 'expanded action'))
610 assert s == ['expanded action'], s
613 """Test adding Actions to stuff."""
614 # Adding actions to other Actions or to stuff that can
615 # be converted into an Action should produce a ListAction
616 # containing all the Actions.
619 baz = SCons.Action.Action(bar, generator=1)
620 act1 = SCons.Action.Action('foo bar')
621 act2 = SCons.Action.Action([ 'foo', bar ])
624 assert isinstance(sum, SCons.Action.ListAction), str(sum)
625 assert len(sum.list) == 3, len(sum.list)
626 assert map(lambda x: isinstance(x, SCons.Action.ActionBase),
627 sum.list) == [ 1, 1, 1 ]
630 assert isinstance(sum, SCons.Action.ListAction), str(sum)
631 assert len(sum.list) == 2, len(sum.list)
634 assert isinstance(sum, SCons.Action.ListAction), str(sum)
635 assert len(sum.list) == 4, len(sum.list)
637 # Should also be able to add command generators to each other
640 assert isinstance(sum, SCons.Action.ListAction), str(sum)
641 assert len(sum.list) == 2, len(sum.list)
644 assert isinstance(sum, SCons.Action.ListAction), str(sum)
645 assert len(sum.list) == 2, len(sum.list)
648 assert isinstance(sum, SCons.Action.ListAction), str(sum)
649 assert len(sum.list) == 3, len(sum.list)
651 # Also should be able to add Actions to anything that can
652 # be converted into an action.
654 assert isinstance(sum, SCons.Action.ListAction), str(sum)
655 assert len(sum.list) == 2, len(sum.list)
656 assert isinstance(sum.list[1], SCons.Action.FunctionAction)
658 sum = 'foo bar' + act2
659 assert isinstance(sum, SCons.Action.ListAction), str(sum)
660 assert len(sum.list) == 3, len(sum.list)
661 assert isinstance(sum.list[0], SCons.Action.CommandAction)
663 sum = [ 'foo', 'bar' ] + act1
664 assert isinstance(sum, SCons.Action.ListAction), str(sum)
665 assert len(sum.list) == 3, sum.list
666 assert isinstance(sum.list[0], SCons.Action.CommandAction)
667 assert isinstance(sum.list[1], SCons.Action.CommandAction)
669 sum = act2 + [ baz, bar ]
670 assert isinstance(sum, SCons.Action.ListAction), str(sum)
671 assert len(sum.list) == 4, len(sum.list)
672 assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction)
673 assert isinstance(sum.list[3], SCons.Action.FunctionAction)
680 assert 0, "Should have thrown a TypeError adding to an int."
687 assert 0, "Should have thrown a TypeError adding to an int."
689 class CommandActionTestCase(unittest.TestCase):
691 def test___init__(self):
692 """Test creation of a command Action
694 a = SCons.Action.CommandAction(["xyzzy"])
695 assert a.cmd_list == [ "xyzzy" ], a.cmd_list
696 assert a.cmdstr is None, a.cmdstr
698 a = SCons.Action.CommandAction(["abra"], "cadabra")
699 assert a.cmd_list == [ "abra" ], a.cmd_list
700 assert a.cmdstr == "cadabra", a.cmdstr
702 def test_bad_cmdstr(self):
703 """Test handling of bad CommandAction(cmdstr) arguments
706 a = SCons.Action.CommandAction('foo', [])
707 except SCons.Errors.UserError, e:
709 m = 'Invalid command display variable'
710 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
712 raise Exception, "did not catch expected UserError"
714 def test___str__(self):
715 """Test fetching the pre-substitution string for command Actions
718 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
720 assert s == 'xyzzy $TARGET $SOURCE', s
722 act = SCons.Action.CommandAction(['xyzzy',
723 '$TARGET', '$SOURCE',
724 '$TARGETS', '$SOURCES'])
726 assert s == "xyzzy $TARGET $SOURCE $TARGETS $SOURCES", s
728 def test_genstring(self):
729 """Test the genstring() method for command Actions
737 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
738 expect = 'xyzzy $TARGET $SOURCE'
739 s = act.genstring([], [], env)
740 assert s == expect, s
741 s = act.genstring([t1], [s1], env)
742 assert s == expect, s
743 s = act.genstring([t1, t2], [s1, s2], env)
744 assert s == expect, s
746 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
747 expect = 'xyzzy $TARGETS $SOURCES'
748 s = act.genstring([], [], env)
749 assert s == expect, s
750 s = act.genstring([t1], [s1], env)
751 assert s == expect, s
752 s = act.genstring([t1, t2], [s1, s2], env)
753 assert s == expect, s
755 act = SCons.Action.CommandAction(['xyzzy',
756 '$TARGET', '$SOURCE',
757 '$TARGETS', '$SOURCES'])
758 expect = "xyzzy $TARGET $SOURCE $TARGETS $SOURCES"
759 s = act.genstring([], [], env)
760 assert s == expect, s
761 s = act.genstring([t1], [s1], env)
762 assert s == expect, s
763 s = act.genstring([t1, t2], [s1, s2], env)
764 assert s == expect, s
766 def test_strfunction(self):
767 """Test fetching the string representation of command Actions
775 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
776 s = act.strfunction([], [], env)
777 assert s == 'xyzzy', s
778 s = act.strfunction([t1], [s1], env)
779 assert s == 'xyzzy t1 s1', s
780 s = act.strfunction([t1, t2], [s1, s2], env)
781 assert s == 'xyzzy t1 s1', s
783 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE',
784 'cmdstr - $SOURCE - $TARGET -')
785 s = act.strfunction([], [], env)
786 assert s == 'cmdstr - - -', s
787 s = act.strfunction([t1], [s1], env)
788 assert s == 'cmdstr - s1 - t1 -', s
789 s = act.strfunction([t1, t2], [s1, s2], env)
790 assert s == 'cmdstr - s1 - t1 -', s
792 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
793 s = act.strfunction([], [], env)
794 assert s == 'xyzzy', s
795 s = act.strfunction([t1], [s1], env)
796 assert s == 'xyzzy t1 s1', s
797 s = act.strfunction([t1, t2], [s1, s2], env)
798 assert s == 'xyzzy t1 t2 s1 s2', s
800 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
801 'cmdstr = $SOURCES = $TARGETS =')
802 s = act.strfunction([], [], env)
803 assert s == 'cmdstr = = =', s
804 s = act.strfunction([t1], [s1], env)
805 assert s == 'cmdstr = s1 = t1 =', s
806 s = act.strfunction([t1, t2], [s1, s2], env)
807 assert s == 'cmdstr = s1 s2 = t1 t2 =', s
809 act = SCons.Action.CommandAction(['xyzzy',
810 '$TARGET', '$SOURCE',
811 '$TARGETS', '$SOURCES'])
812 s = act.strfunction([], [], env)
813 assert s == 'xyzzy', s
814 s = act.strfunction([t1], [s1], env)
815 assert s == 'xyzzy t1 s1 t1 s1', s
816 s = act.strfunction([t1, t2], [s1, s2], env)
817 assert s == 'xyzzy t1 s1 t1 t2 s1 s2', s
819 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
820 'cmdstr\t$TARGETS\n$SOURCES ')
822 s = act.strfunction([], [], env)
823 assert s == 'cmdstr\t\n ', s
824 s = act.strfunction([t1], [s1], env)
825 assert s == 'cmdstr\tt1\ns1 ', s
826 s = act.strfunction([t1, t2], [s1, s2], env)
827 assert s == 'cmdstr\tt1 t2\ns1 s2 ', s
829 def sf(target, source, env):
830 return "sf was called"
831 act = SCons.Action.CommandAction('foo', strfunction=sf)
832 s = act.strfunction([], [], env)
833 assert s == "sf was called", s
836 def __init__(self, targets, sources, env):
841 def __init__(self, targets, sources, env):
846 def __init__(self, targets, sources, env):
850 def strfunction(self, targets, sources, env):
851 return 'actclass3 on %s to get %s'%(str(sources[0]),
854 def __init__(self, targets, sources, env):
860 act1 = SCons.Action.Action(actclass1([t1], [s1], env))
861 s = act1.strfunction([t1], [s1], env)
862 assert s == 'actclass1(["t1"], ["s1"])', s
864 act2 = SCons.Action.Action(actclass2([t1], [s1], env))
865 s = act2.strfunction([t1], [s1], env)
866 assert s == 'actclass2(["t1"], ["s1"])', s
868 act3 = SCons.Action.Action(actclass3([t1], [s1], env))
869 s = act3.strfunction([t1], [s1], env)
870 assert s == 'actclass3 on s1 to get t1', s
872 act4 = SCons.Action.Action(actclass4([t1], [s1], env))
873 s = act4.strfunction([t1], [s1], env)
876 act = SCons.Action.CommandAction("@foo bar")
877 s = act.strfunction([], [], env)
880 act = SCons.Action.CommandAction("@-foo bar")
881 s = act.strfunction([], [], env)
884 act = SCons.Action.CommandAction("-@foo bar")
885 s = act.strfunction([], [], env)
888 act = SCons.Action.CommandAction("-foo bar")
889 s = act.strfunction([], [], env)
890 assert s == "foo bar", s
892 act = SCons.Action.CommandAction("@ foo bar")
893 s = act.strfunction([], [], env)
896 act = SCons.Action.CommandAction("@- foo bar")
897 s = act.strfunction([], [], env)
900 act = SCons.Action.CommandAction("-@ foo bar")
901 s = act.strfunction([], [], env)
904 act = SCons.Action.CommandAction("- foo bar")
905 s = act.strfunction([], [], env)
906 assert s == "foo bar", s
908 def test_execute(self):
909 """Test execution of command Actions
914 except AttributeError:
917 cmd1 = r'%s %s %s xyzzy' % (_python_, act_py, outfile)
919 act = SCons.Action.CommandAction(cmd1)
920 r = act([], [], env.Clone())
922 c = test.read(outfile, 'r')
923 assert c == "act.py: 'xyzzy'\n", c
925 cmd2 = r'%s %s %s $TARGET' % (_python_, act_py, outfile)
927 act = SCons.Action.CommandAction(cmd2)
928 r = act(DummyNode('foo'), [], env.Clone())
930 c = test.read(outfile, 'r')
931 assert c == "act.py: 'foo'\n", c
933 cmd3 = r'%s %s %s ${TARGETS}' % (_python_, act_py, outfile)
935 act = SCons.Action.CommandAction(cmd3)
936 r = act(map(DummyNode, ['aaa', 'bbb']), [], env.Clone())
938 c = test.read(outfile, 'r')
939 assert c == "act.py: 'aaa' 'bbb'\n", c
941 cmd4 = r'%s %s %s $SOURCES' % (_python_, act_py, outfile)
943 act = SCons.Action.CommandAction(cmd4)
944 r = act([], [DummyNode('one'), DummyNode('two')], env.Clone())
946 c = test.read(outfile, 'r')
947 assert c == "act.py: 'one' 'two'\n", c
949 cmd4 = r'%s %s %s ${SOURCES[:2]}' % (_python_, act_py, outfile)
951 act = SCons.Action.CommandAction(cmd4)
952 sources = [DummyNode('three'), DummyNode('four'), DummyNode('five')]
954 r = act([], source = sources, env = env2)
956 c = test.read(outfile, 'r')
957 assert c == "act.py: 'three' 'four'\n", c
959 cmd5 = r'%s %s %s $TARGET XYZZY' % (_python_, act_py, outfile)
961 act = SCons.Action.CommandAction(cmd5)
963 if scons_env.has_key('ENV'):
964 env5['ENV'] = scons_env['ENV']
965 PATH = scons_env['ENV'].get('PATH', '')
970 env5['ENV']['XYZZY'] = 'xyzzy'
971 r = act(target = DummyNode('out5'), source = [], env = env5)
973 act = SCons.Action.CommandAction(cmd5)
974 r = act(target = DummyNode('out5'),
976 env = env.Clone(ENV = {'XYZZY' : 'xyzzy5',
979 c = test.read(outfile, 'r')
980 assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy5'\n", c
983 def __init__(self, str):
989 def get_subst_proxy(self):
992 cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (_python_, act_py, outfile)
994 act = SCons.Action.CommandAction(cmd6)
995 r = act(target = [Obj('111'), Obj('222')],
996 source = [Obj('333'), Obj('444'), Obj('555')],
999 c = test.read(outfile, 'r')
1000 assert c == "act.py: '222' '111' '333' '444'\n", c
1003 # NT treats execs of directories and non-executable files
1004 # as "file not found" errors
1005 expect_nonexistent = 1
1006 expect_nonexecutable = 1
1007 elif sys.platform == 'cygwin':
1008 expect_nonexistent = 127
1009 # Newer cygwin seems to return 126 for following
1010 expect_nonexecutable_file = 126
1011 expect_nonexecutable_dir = 127
1013 expect_nonexistent = 127
1014 expect_nonexecutable_file = 126
1015 expect_nonexecutable_dir = 126
1017 # Test that a nonexistent command returns 127
1018 act = SCons.Action.CommandAction(python + "_no_such_command_")
1019 r = act([], [], env.Clone(out = outfile))
1020 assert r.status == expect_nonexistent, r.status
1022 # Test that trying to execute a directory returns 126
1023 dir, tail = os.path.split(python)
1024 act = SCons.Action.CommandAction(dir)
1025 r = act([], [], env.Clone(out = outfile))
1026 assert r.status == expect_nonexecutable_file, r.status
1028 # Test that trying to execute a non-executable file returns 126
1029 act = SCons.Action.CommandAction(outfile)
1030 r = act([], [], env.Clone(out = outfile))
1031 assert r.status == expect_nonexecutable_dir, r.status
1033 act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py))
1034 r = act([], [], env)
1035 assert r.status == 1, r.status
1037 act = SCons.Action.CommandAction('@%s %s 1' % (_python_, exit_py))
1038 r = act([], [], env)
1039 assert r.status == 1, r.status
1041 act = SCons.Action.CommandAction('@-%s %s 1' % (_python_, exit_py))
1042 r = act([], [], env)
1045 act = SCons.Action.CommandAction('-%s %s 1' % (_python_, exit_py))
1046 r = act([], [], env)
1049 act = SCons.Action.CommandAction('@ %s %s 1' % (_python_, exit_py))
1050 r = act([], [], env)
1051 assert r.status == 1, r.status
1053 act = SCons.Action.CommandAction('@- %s %s 1' % (_python_, exit_py))
1054 r = act([], [], env)
1057 act = SCons.Action.CommandAction('- %s %s 1' % (_python_, exit_py))
1058 r = act([], [], env)
1061 def _DO_NOT_EXECUTE_test_pipe_execute(self):
1062 """Test capturing piped output from an action
1064 We used to have PIPE_BUILD support built right into
1065 Action.execute() for the benefit of the SConf subsystem, but we've
1066 moved that logic back into SConf itself. We'll leave this code
1067 here, just in case we ever want to resurrect this functionality
1068 in the future, but change the name of the test so it doesn't
1069 get executed as part of the normal test suite.
1071 pipe = open( pipe_file, "w" )
1072 self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1,
1073 PSTDOUT = pipe, PSTDERR = pipe)
1074 # everything should also work when piping output
1076 self.env['PSTDOUT'].close()
1077 pipe_out = test.read( pipe_file )
1079 act_out = "act.py: stdout: executed act.py"
1080 act_err = "act.py: stderr: executed act.py"
1082 # Since we are now using select(), stdout and stderr can be
1083 # intermixed, so count the lines separately.
1084 outlines = re.findall(act_out, pipe_out)
1085 errlines = re.findall(act_err, pipe_out)
1086 assert len(outlines) == 6, pipe_out + repr(outlines)
1087 assert len(errlines) == 6, pipe_out + repr(errlines)
1089 # test redirection operators
1090 def test_redirect(self, redir, stdout_msg, stderr_msg):
1091 cmd = r'%s %s %s xyzzy %s' % (_python_, act_py, outfile, redir)
1092 # Write the output and error messages to files because
1093 # Windows can't handle strings that are too big in its
1094 # external environment (os.spawnve() returns EINVAL,
1095 # "Invalid argument").
1096 stdout_file = test.workpath('stdout_msg')
1097 stderr_file = test.workpath('stderr_msg')
1098 open(stdout_file, 'w').write(stdout_msg)
1099 open(stderr_file, 'w').write(stderr_msg)
1100 pipe = open( pipe_file, "w" )
1101 act = SCons.Action.CommandAction(cmd)
1102 env = Environment( ENV = {'ACTPY_PIPE' : '1',
1103 'PIPE_STDOUT_FILE' : stdout_file,
1104 'PIPE_STDERR_FILE' : stderr_file},
1106 PSTDOUT = pipe, PSTDERR = pipe )
1107 r = act([], [], env)
1110 return (test.read(outfile2, 'r'), test.read(pipe_file, 'r'))
1112 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1114 assert redirected == act_out
1115 assert pipe_out == act_err
1117 (redirected, pipe_out) = test_redirect(self,'2> %s' % outfile2,
1119 assert redirected == act_err
1120 assert pipe_out == act_out
1122 (redirected, pipe_out) = test_redirect(self,'> %s 2>&1' % outfile2,
1124 assert (redirected == act_out + act_err or
1125 redirected == act_err + act_out)
1126 assert pipe_out == ""
1128 act_err = "Long Command Output\n"*3000
1129 # the size of the string should exceed the system's default block size
1131 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1133 assert (redirected == act_out)
1134 assert (pipe_out == act_err)
1136 def test_set_handler(self):
1137 """Test setting the command handler...
1143 def func(sh, escape, cmd, args, env, test=t):
1144 test.executed = args
1147 def escape_func(cmd):
1148 return '**' + cmd + '**'
1151 def __init__(self, x):
1155 def escape(self, escape_func):
1156 return escape_func(self.data)
1157 def is_literal(self):
1160 a = SCons.Action.CommandAction(["xyzzy"])
1161 e = Environment(SPAWN = func)
1163 assert t.executed == [ 'xyzzy' ], t.executed
1165 a = SCons.Action.CommandAction(["xyzzy"])
1166 e = Environment(SPAWN = '$FUNC', FUNC = func)
1168 assert t.executed == [ 'xyzzy' ], t.executed
1170 a = SCons.Action.CommandAction(["xyzzy"])
1171 e = Environment(SPAWN = func, SHELL = 'fake shell')
1173 assert t.executed == [ 'xyzzy' ], t.executed
1174 assert t.shell == 'fake shell', t.shell
1176 a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ])
1177 e = Environment(SPAWN = func, ESCAPE = escape_func)
1179 assert t.executed == [ '**xyzzy**' ], t.executed
1181 def test_get_contents(self):
1182 """Test fetching the contents of a command Action
1184 def CmdGen(target, source, env, for_signature):
1185 assert for_signature
1187 (env["foo"], env["bar"])
1189 # The number 1 is there to make sure all args get converted to strings.
1190 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
1191 "$)", "|", "$baz", 1])
1192 c = a.get_contents(target=[], source=[],
1193 env=Environment(foo = 'FFF', bar = 'BBB',
1195 assert c == "| | FFF BBB 1", c
1197 # Make sure that CommandActions use an Environment's
1198 # subst_target_source() method for substitution.
1199 class SpecialEnvironment(Environment):
1200 def subst_target_source(self, strSubst, raw=0, target=[], source=[]):
1201 return 'subst_target_source: ' + strSubst
1203 c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'),
1204 env=SpecialEnvironment(foo = 'GGG', bar = 'CCC',
1206 assert c == 'subst_target_source: | $( $foo | $bar $) | $baz 1', c
1208 # We've discussed using the real target and source names in a
1209 # CommandAction's signature contents. This would have have the
1210 # advantage of recompiling when a file's name changes (keeping
1211 # debug info current), but it would currently break repository
1212 # logic that will change the file name based on whether the
1213 # files come from a repository or locally. If we ever move to
1214 # that scheme, then all of the '__t1__' and '__s6__' file names
1215 # in the asserts below would change to 't1' and 's6' and the
1217 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
1218 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
1221 a = SCons.Action.CommandAction(["$TARGET"])
1222 c = a.get_contents(target=t, source=s, env=env)
1225 a = SCons.Action.CommandAction(["$TARGETS"])
1226 c = a.get_contents(target=t, source=s, env=env)
1227 assert c == "t1 t2 t3 t4 t5 t6", c
1229 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
1230 c = a.get_contents(target=t, source=s, env=env)
1233 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
1234 c = a.get_contents(target=t, source=s, env=env)
1235 assert c == "t4 t5", c
1237 a = SCons.Action.CommandAction(["$SOURCE"])
1238 c = a.get_contents(target=t, source=s, env=env)
1241 a = SCons.Action.CommandAction(["$SOURCES"])
1242 c = a.get_contents(target=t, source=s, env=env)
1243 assert c == "s1 s2 s3 s4 s5 s6", c
1245 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
1246 c = a.get_contents(target=t, source=s, env=env)
1249 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
1250 c = a.get_contents(target=t, source=s, env=env)
1251 assert c == "s4 s5", c
1253 class CommandGeneratorActionTestCase(unittest.TestCase):
1255 def test___init__(self):
1256 """Test creation of a command generator Action
1258 def f(target, source, env):
1260 a = SCons.Action.CommandGeneratorAction(f)
1261 assert a.generator == f
1263 def test___str__(self):
1264 """Test the pre-substitution strings for command generator Actions
1266 def f(target, source, env, for_signature, self=self):
1268 # See if "env" is really a construction environment (or
1269 # looks like one) by accessing the FindIxes attribute.
1270 # (The Tool/mingw.py module has a generator that uses this,
1271 # and the __str__() method used to cause problems by passing
1272 # us a regular dictionary as a fallback.)
1276 a = SCons.Action.CommandGeneratorAction(f)
1278 assert s == 'FOO', s
1280 def test_genstring(self):
1281 """Test the command generator Action genstring() method
1283 def f(target, source, env, for_signature, self=self):
1284 dummy = env['dummy']
1286 return "$FOO $TARGET $SOURCE $TARGETS $SOURCES"
1287 a = SCons.Action.CommandGeneratorAction(f)
1289 s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1))
1290 assert self.dummy == 1, self.dummy
1291 assert s == "$FOO $TARGET $SOURCE $TARGETS $SOURCES", s
1293 def test_execute(self):
1294 """Test executing a command generator Action
1297 def f(target, source, env, for_signature, self=self):
1298 dummy = env['dummy']
1300 s = env.subst("$FOO")
1301 assert s == 'foo baz\nbar ack', s
1303 def func_action(target, source, env, self=self):
1305 s = env.subst('$foo')
1306 assert s == 'bar', s
1308 def f2(target, source, env, for_signature, f=func_action):
1310 def ch(sh, escape, cmd, args, env, self=self):
1311 self.cmd.append(cmd)
1312 self.args.append(args)
1314 a = SCons.Action.CommandGeneratorAction(f)
1318 a([], [], env=Environment(FOO = 'foo baz\nbar ack',
1321 assert self.dummy == 1, self.dummy
1322 assert self.cmd == ['foo', 'bar'], self.cmd
1323 assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args
1325 b = SCons.Action.CommandGeneratorAction(f2)
1327 b(target=[], source=[], env=Environment(foo = 'bar',
1329 assert self.dummy==2, self.dummy
1333 def __init__(self, t):
1336 self.t.rfile_called = 1
1338 def get_subst_proxy(self):
1340 def f3(target, source, env, for_signature):
1342 c = SCons.Action.CommandGeneratorAction(f3)
1343 c(target=[], source=DummyFile(self), env=Environment())
1344 assert self.rfile_called
1346 def test_get_contents(self):
1347 """Test fetching the contents of a command generator Action
1349 def f(target, source, env, for_signature):
1352 assert for_signature, for_signature
1353 return [["guux", foo, "$(", "$ignore", "$)", bar,
1354 '${test("$( foo $bar $)")}' ]]
1357 assert mystr == "$( foo $bar $)", mystr
1360 env = Environment(foo = 'FFF', bar = 'BBB',
1361 ignore = 'foo', test=test)
1362 a = SCons.Action.CommandGeneratorAction(f)
1363 c = a.get_contents(target=[], source=[], env=env)
1364 assert c == "guux FFF BBB test", c
1367 class FunctionActionTestCase(unittest.TestCase):
1369 def test___init__(self):
1370 """Test creation of a function Action
1381 a = SCons.Action.FunctionAction(func1)
1382 assert a.execfunction == func1, a.execfunction
1383 assert isinstance(a.strfunction, types.MethodType), type(a.strfunction)
1385 a = SCons.Action.FunctionAction(func2, strfunction=func3)
1386 assert a.execfunction == func2, a.execfunction
1387 assert a.strfunction == func3, a.strfunction
1389 def test_cmdstr_bad(self):
1390 """Test handling of bad FunctionAction(cmdstr) arguments
1395 a = SCons.Action.FunctionAction(func, [])
1396 except SCons.Errors.UserError, e:
1398 m = 'Invalid function display variable'
1399 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
1401 raise "did not catch expected UserError"
1403 def test___str__(self):
1404 """Test the __str__() method for function Actions
1408 a = SCons.Action.FunctionAction(func1)
1410 assert s == "func1(target, source, env)", s
1415 a = SCons.Action.FunctionAction(class1())
1417 assert s == "class1(target, source, env)", s
1419 def test_execute(self):
1420 """Test executing a function Action
1423 def f(target, source, env):
1428 assert env.subst("$BAR") == 'foo bar', env.subst("$BAR")
1430 a = SCons.Action.FunctionAction(f)
1431 a(target=1, source=2, env=Environment(BAR = 'foo bar',
1433 assert self.inc == 1, self.inc
1434 assert self.source == [2], self.source
1435 assert self.target == [1], self.target
1439 def function1(target, source, env):
1443 open(t, 'w').write("function1\n")
1446 act = SCons.Action.FunctionAction(function1)
1447 r = act(target = [outfile, outfile2], source=[], env=Environment())
1448 assert r.status == 1, r.status
1450 assert count == 1, count
1451 c = test.read(outfile, 'r')
1452 assert c == "function1\n", c
1453 c = test.read(outfile2, 'r')
1454 assert c == "function1\n", c
1457 def __init__(self, target, source, env):
1458 open(env['out'], 'w').write("class1a\n")
1460 act = SCons.Action.FunctionAction(class1a)
1461 r = act([], [], Environment(out = outfile))
1462 assert isinstance(r.status, class1a), r.status
1463 c = test.read(outfile, 'r')
1464 assert c == "class1a\n", c
1467 def __call__(self, target, source, env):
1468 open(env['out'], 'w').write("class1b\n")
1471 act = SCons.Action.FunctionAction(class1b())
1472 r = act([], [], Environment(out = outfile))
1473 assert r.status == 2, r.status
1474 c = test.read(outfile, 'r')
1475 assert c == "class1b\n", c
1477 def build_it(target, source, env, self=self):
1480 def string_it(target, source, env, self=self):
1483 act = SCons.Action.FunctionAction(build_it, strfunction=string_it)
1484 r = act([], [], Environment())
1486 assert self.build_it
1487 assert self.string_it
1489 def test_get_contents(self):
1490 """Test fetching the contents of a function Action
1497 "0,0,0,0,(),(),(d\000\000S),(),()",
1498 "0,0,0,0,(),(),(d\x00\x00S),(),()",
1502 "1,1,0,0,(),(),(d\000\000S),(),()",
1503 "1,1,0,0,(),(),(d\x00\x00S),(),()",
1506 a = SCons.Action.FunctionAction(GlobalFunc)
1507 c = a.get_contents(target=[], source=[], env=Environment())
1508 assert c in func_matches, repr(c)
1510 a = SCons.Action.FunctionAction(LocalFunc)
1511 c = a.get_contents(target=[], source=[], env=Environment())
1512 assert c in func_matches, repr(c)
1514 a = SCons.Action.FunctionAction(GlobalFunc, varlist=['XYZ'])
1516 matches_foo = map(lambda x: x + "foo", func_matches)
1518 c = a.get_contents(target=[], source=[], env=Environment())
1519 assert c in func_matches, repr(c)
1520 c = a.get_contents(target=[], source=[], env=Environment(XYZ = 'foo'))
1521 assert c in matches_foo, repr(c)
1524 def get_contents(self, target, source, env):
1526 a = SCons.Action.FunctionAction(Foo())
1527 c = a.get_contents(target=[], source=[], env=Environment())
1528 assert c == 'xyzzy', repr(c)
1531 def LocalMethod(self):
1534 a = SCons.Action.FunctionAction(lc.LocalMethod)
1535 c = a.get_contents(target=[], source=[], env=Environment())
1536 assert c in meth_matches, repr(c)
1538 def test_strfunction(self):
1539 """Test the FunctionAction.strfunction() method
1544 a = SCons.Action.FunctionAction(func)
1545 s = a.strfunction(target=[], source=[], env=Environment())
1546 assert s == 'func([], [])', s
1548 a = SCons.Action.FunctionAction(func, None)
1549 s = a.strfunction(target=[], source=[], env=Environment())
1552 a = SCons.Action.FunctionAction(func, 'function')
1553 s = a.strfunction(target=[], source=[], env=Environment())
1554 assert s == 'function', s
1556 class ListActionTestCase(unittest.TestCase):
1558 def test___init__(self):
1559 """Test creation of a list of subsidiary Actions
1563 a = SCons.Action.ListAction(["x", func, ["y", "z"]])
1564 assert isinstance(a.list[0], SCons.Action.CommandAction)
1565 assert isinstance(a.list[1], SCons.Action.FunctionAction)
1566 assert isinstance(a.list[2], SCons.Action.ListAction)
1567 assert a.list[2].list[0].cmd_list == 'y'
1569 def test___str__(self):
1570 """Test the __str__() method for a list of subsidiary Actions
1572 def f(target,source,env):
1574 def g(target,source,env):
1576 a = SCons.Action.ListAction([f, g, "XXX", f])
1578 assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s
1580 def test_genstring(self):
1581 """Test the genstring() method for a list of subsidiary Actions
1583 def f(target,source,env):
1585 def g(target,source,env,for_signature):
1586 return 'generated %s %s' % (target[0], source[0])
1587 g = SCons.Action.Action(g, generator=1)
1588 a = SCons.Action.ListAction([f, g, "XXX", f])
1589 s = a.genstring(['foo.x'], ['bar.y'], Environment())
1590 assert s == "f(target, source, env)\ngenerated foo.x bar.y\nXXX\nf(target, source, env)", s
1592 def test_execute(self):
1593 """Test executing a list of subsidiary Actions
1596 def f(target,source,env):
1599 a = SCons.Action.ListAction([f, f, f])
1600 a([], [], Environment(s = self))
1601 assert self.inc == 3, self.inc
1603 cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile)
1605 def function2(target, source, env):
1606 open(env['out'], 'a').write("function2\n")
1610 def __call__(self, target, source, env):
1611 open(env['out'], 'a').write("class2a\n")
1615 def __init__(self, target, source, env):
1616 open(env['out'], 'a').write("class2b\n")
1617 act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
1618 r = act([], [], Environment(out = outfile))
1619 assert isinstance(r.status, class2b), r.status
1620 c = test.read(outfile, 'r')
1621 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
1623 def test_get_contents(self):
1624 """Test fetching the contents of a list of subsidiary Actions
1627 def gen(target, source, env, for_signature):
1631 a = SCons.Action.ListAction(["x",
1632 SCons.Action.Action(gen, generator=1),
1634 c = a.get_contents(target=[], source=[], env=Environment(s = self))
1635 assert self.foo==1, self.foo
1636 assert c == "xyz", c
1638 class LazyActionTestCase(unittest.TestCase):
1639 def test___init__(self):
1640 """Test creation of a lazy-evaluation Action
1642 # Environment variable references should create a special type
1643 # of LazyAction that lazily evaluates the variable for whether
1644 # it's a string or something else before doing anything.
1645 a9 = SCons.Action.Action('$FOO')
1646 assert isinstance(a9, SCons.Action.LazyAction), a9
1647 assert a9.var == 'FOO', a9.var
1649 a10 = SCons.Action.Action('${FOO}')
1650 assert isinstance(a10, SCons.Action.LazyAction), a10
1651 assert a10.var == 'FOO', a10.var
1653 def test_genstring(self):
1654 """Test the lazy-evaluation Action genstring() method
1656 def f(target, source, env):
1658 a = SCons.Action.Action('$BAR')
1659 env1 = Environment(BAR=f, s=self)
1660 env2 = Environment(BAR='xxx', s=self)
1661 s = a.genstring([], [], env=env1)
1662 assert s == "f(target, source, env)", s
1663 s = a.genstring([], [], env=env2)
1664 assert s == 'xxx', s
1666 def test_execute(self):
1667 """Test executing a lazy-evaluation Action
1669 def f(target, source, env):
1673 a = SCons.Action.Action('$BAR')
1674 a([], [], env=Environment(BAR = f, s = self))
1675 assert self.test == 1, self.test
1676 cmd = r'%s %s %s lazy' % (_python_, act_py, outfile)
1677 a([], [], env=Environment(BAR = cmd, s = self))
1678 c = test.read(outfile, 'r')
1679 assert c == "act.py: 'lazy'\n", c
1681 def test_get_contents(self):
1682 """Test fetching the contents of a lazy-evaluation Action
1684 a = SCons.Action.Action("${FOO}")
1685 env = Environment(FOO = [["This", "is", "a", "test"]])
1686 c = a.get_contents(target=[], source=[], env=env)
1687 assert c == "This is a test", c
1689 class ActionCallerTestCase(unittest.TestCase):
1690 def test___init__(self):
1691 """Test creation of an ActionCaller"""
1692 ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO' : 4, 'BAR' : 5})
1693 assert ac.parent == 1, ac.parent
1694 assert ac.args == [2, 3], ac.args
1695 assert ac.kw == {'FOO' : 4, 'BAR' : 5}, ac.kw
1697 def test_get_contents(self):
1698 """Test fetching the contents of an ActionCaller"""
1710 af = SCons.Action.ActionFactory(GlobalFunc, strfunc)
1711 ac = SCons.Action.ActionCaller(af, [], {})
1712 c = ac.get_contents([], [], Environment())
1713 assert c in matches, repr(c)
1715 af = SCons.Action.ActionFactory(LocalFunc, strfunc)
1716 ac = SCons.Action.ActionCaller(af, [], {})
1717 c = ac.get_contents([], [], Environment())
1718 assert c in matches, repr(c)
1729 af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc)
1730 ac = SCons.Action.ActionCaller(af, [], {})
1731 c = ac.get_contents([], [], Environment())
1732 assert c in matches, repr(c)
1734 af = SCons.Action.ActionFactory(LocalActFunc(), strfunc)
1735 ac = SCons.Action.ActionCaller(af, [], {})
1736 c = ac.get_contents([], [], Environment())
1737 assert c in matches, repr(c)
1740 "<built-in function str>",
1744 af = SCons.Action.ActionFactory(str, strfunc)
1745 ac = SCons.Action.ActionCaller(af, [], {})
1746 c = ac.get_contents([], [], Environment())
1747 assert c == "<built-in function str>" or \
1748 c == "<type 'str'>", repr(c)
1750 def test___call__(self):
1751 """Test calling an ActionCaller"""
1753 def actfunc(a1, a2, a3, args=actfunc_args):
1754 args.extend([a1, a2, a3])
1755 def strfunc(a1, a2, a3):
1758 e = Environment(FOO = 2, BAR = 5)
1760 af = SCons.Action.ActionFactory(actfunc, strfunc)
1761 ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {})
1763 assert actfunc_args[0] is e, actfunc_args
1764 assert actfunc_args[1] == '2', actfunc_args
1765 assert actfunc_args[2] == 3, actfunc_args
1768 ac = SCons.Action.ActionCaller(af, [], {'a3' : '$__env__', 'a2' : '$BAR', 'a1' : 4})
1770 assert actfunc_args[0] == 4, actfunc_args
1771 assert actfunc_args[1] == '5', actfunc_args
1772 assert actfunc_args[2] is e, actfunc_args
1775 def test_strfunction(self):
1776 """Test calling the ActionCaller strfunction() method"""
1778 def actfunc(a1, a2, a3, a4):
1780 def strfunc(a1, a2, a3, a4, args=strfunc_args):
1781 args.extend([a1, a2, a3, a4])
1783 af = SCons.Action.ActionFactory(actfunc, strfunc)
1784 ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3, '$WS'], {})
1785 ac.strfunction([], [], Environment(FOO = 2, WS='white space'))
1786 assert strfunc_args == [1, '2', 3, 'white space'], strfunc_args
1789 d = {'a3' : 6, 'a2' : '$BAR', 'a1' : 4, 'a4' : '$WS'}
1790 ac = SCons.Action.ActionCaller(af, [], d)
1791 ac.strfunction([], [], Environment(BAR = 5, WS='w s'))
1792 assert strfunc_args == [4, '5', 6, 'w s'], strfunc_args
1794 class ActionFactoryTestCase(unittest.TestCase):
1795 def test___init__(self):
1796 """Test creation of an ActionFactory"""
1801 ac = SCons.Action.ActionFactory(actfunc, strfunc)
1802 assert ac.actfunc is actfunc, ac.actfunc
1803 assert ac.strfunc is strfunc, ac.strfunc
1805 def test___call__(self):
1806 """Test calling whatever's returned from an ActionFactory"""
1809 def actfunc(a1, a2, a3, args=actfunc_args):
1810 args.extend([a1, a2, a3])
1811 def strfunc(a1, a2, a3, args=strfunc_args):
1812 args.extend([a1, a2, a3])
1813 af = SCons.Action.ActionFactory(actfunc, strfunc)
1814 af(3, 6, 9)([], [], Environment())
1815 assert actfunc_args == [3, 6, 9], actfunc_args
1816 assert strfunc_args == [3, 6, 9], strfunc_args
1819 class ActionCompareTestCase(unittest.TestCase):
1821 def test_1_solo_name(self):
1822 """Test Lazy Cmd Generator Action get_name alone.
1824 Basically ensures we can locate the builder, comparing it to
1825 itself along the way."""
1826 bar = SCons.Builder.Builder(action = {})
1827 env = Environment( BUILDERS = {'BAR' : bar} )
1828 name = bar.get_name(env)
1829 assert name == 'BAR', name
1831 def test_2_multi_name(self):
1832 """Test LazyCmdGenerator Action get_name multi builders.
1834 Ensure that we can compare builders (and thereby actions) to
1835 each other safely."""
1836 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1837 bar = SCons.Builder.Builder(action = {})
1839 assert foo.action != bar.action
1840 env = Environment( BUILDERS = {'FOO' : foo,
1842 name = foo.get_name(env)
1843 assert name == 'FOO', name
1844 name = bar.get_name(env)
1845 assert name == 'BAR', name
1847 def test_3_dict_names(self):
1848 """Test Action/Suffix dicts with get_name.
1850 Verifies that Action/Suffix dictionaries work correctly,
1851 especially two builders that can generate the same suffix,
1852 where one of the builders has a suffix dictionary with a None
1855 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1856 bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'})
1857 bar.add_action('.cow', "$MOO")
1858 dog = SCons.Builder.Builder(suffix = '.bar')
1860 env = Environment( BUILDERS = {'FOO' : foo,
1864 assert foo.get_name(env) == 'FOO', foo.get_name(env)
1865 assert bar.get_name(env) == 'BAR', bar.get_name(env)
1866 assert dog.get_name(env) == 'DOG', dog.get_name(env)
1869 if __name__ == "__main__":
1870 suite = unittest.TestSuite()
1871 tclasses = [ ActionTestCase,
1873 _ActionActionTestCase,
1874 CommandActionTestCase,
1875 CommandGeneratorActionTestCase,
1876 FunctionActionTestCase,
1879 ActionCallerTestCase,
1880 ActionFactoryTestCase,
1881 ActionCompareTestCase ]
1882 for tclass in tclasses:
1883 names = unittest.getTestCaseNames(tclass, 'test_')
1884 suite.addTests(map(tclass, names))
1885 if not unittest.TextTestRunner().run(suite).wasSuccessful():