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 == 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 == 7, result
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 == 7, result
452 assert s == expect % (repr('sub'), repr(test.workpath())), s
456 sio = StringIO.StringIO()
458 result = b("out", "in", env)
459 assert result == 7, result
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 == 7, result
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 == 7, result
494 assert s == 'execfunc(["out"], ["in"])\n', s
496 sio = StringIO.StringIO()
498 result = a("out", "in", env, presub=1)
499 assert result == 7, result
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 == 7, result
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 == 7, result
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 == 7, result
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 == 7, result
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 == 7, result
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 == 7, result
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 "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 expect_nonexecutable = 127
1011 expect_nonexistent = 127
1012 expect_nonexecutable = 126
1014 # Test that a nonexistent command returns 127
1015 act = SCons.Action.CommandAction(python + "_no_such_command_")
1016 r = act([], [], env.Clone(out = outfile))
1017 assert r == expect_nonexistent, "r == %d" % r
1019 # Test that trying to execute a directory returns 126
1020 dir, tail = os.path.split(python)
1021 act = SCons.Action.CommandAction(dir)
1022 r = act([], [], env.Clone(out = outfile))
1023 assert r == expect_nonexecutable, "r == %d" % r
1025 # Test that trying to execute a non-executable file returns 126
1026 act = SCons.Action.CommandAction(outfile)
1027 r = act([], [], env.Clone(out = outfile))
1028 assert r == expect_nonexecutable, "r == %d" % r
1030 act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py))
1031 r = act([], [], env)
1034 act = SCons.Action.CommandAction('@%s %s 1' % (_python_, exit_py))
1035 r = act([], [], env)
1038 act = SCons.Action.CommandAction('@-%s %s 1' % (_python_, exit_py))
1039 r = act([], [], env)
1042 act = SCons.Action.CommandAction('-%s %s 1' % (_python_, exit_py))
1043 r = act([], [], env)
1046 act = SCons.Action.CommandAction('@ %s %s 1' % (_python_, exit_py))
1047 r = act([], [], env)
1050 act = SCons.Action.CommandAction('@- %s %s 1' % (_python_, exit_py))
1051 r = act([], [], env)
1054 act = SCons.Action.CommandAction('- %s %s 1' % (_python_, exit_py))
1055 r = act([], [], env)
1058 def _DO_NOT_EXECUTE_test_pipe_execute(self):
1059 """Test capturing piped output from an action
1061 We used to have PIPE_BUILD support built right into
1062 Action.execute() for the benefit of the SConf subsystem, but we've
1063 moved that logic back into SConf itself. We'll leave this code
1064 here, just in case we ever want to resurrect this functionality
1065 in the future, but change the name of the test so it doesn't
1066 get executed as part of the normal test suite.
1068 pipe = open( pipe_file, "w" )
1069 self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1,
1070 PSTDOUT = pipe, PSTDERR = pipe)
1071 # everything should also work when piping output
1073 self.env['PSTDOUT'].close()
1074 pipe_out = test.read( pipe_file )
1076 act_out = "act.py: stdout: executed act.py"
1077 act_err = "act.py: stderr: executed act.py"
1079 # Since we are now using select(), stdout and stderr can be
1080 # intermixed, so count the lines separately.
1081 outlines = re.findall(act_out, pipe_out)
1082 errlines = re.findall(act_err, pipe_out)
1083 assert len(outlines) == 6, pipe_out + repr(outlines)
1084 assert len(errlines) == 6, pipe_out + repr(errlines)
1086 # test redirection operators
1087 def test_redirect(self, redir, stdout_msg, stderr_msg):
1088 cmd = r'%s %s %s xyzzy %s' % (_python_, act_py, outfile, redir)
1089 # Write the output and error messages to files because
1090 # Windows can't handle strings that are too big in its
1091 # external environment (os.spawnve() returns EINVAL,
1092 # "Invalid argument").
1093 stdout_file = test.workpath('stdout_msg')
1094 stderr_file = test.workpath('stderr_msg')
1095 open(stdout_file, 'w').write(stdout_msg)
1096 open(stderr_file, 'w').write(stderr_msg)
1097 pipe = open( pipe_file, "w" )
1098 act = SCons.Action.CommandAction(cmd)
1099 env = Environment( ENV = {'ACTPY_PIPE' : '1',
1100 'PIPE_STDOUT_FILE' : stdout_file,
1101 'PIPE_STDERR_FILE' : stderr_file},
1103 PSTDOUT = pipe, PSTDERR = pipe )
1104 r = act([], [], env)
1107 return (test.read(outfile2, 'r'), test.read(pipe_file, 'r'))
1109 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1111 assert redirected == act_out
1112 assert pipe_out == act_err
1114 (redirected, pipe_out) = test_redirect(self,'2> %s' % outfile2,
1116 assert redirected == act_err
1117 assert pipe_out == act_out
1119 (redirected, pipe_out) = test_redirect(self,'> %s 2>&1' % outfile2,
1121 assert (redirected == act_out + act_err or
1122 redirected == act_err + act_out)
1123 assert pipe_out == ""
1125 act_err = "Long Command Output\n"*3000
1126 # the size of the string should exceed the system's default block size
1128 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1130 assert (redirected == act_out)
1131 assert (pipe_out == act_err)
1133 def test_set_handler(self):
1134 """Test setting the command handler...
1140 def func(sh, escape, cmd, args, env, test=t):
1141 test.executed = args
1144 def escape_func(cmd):
1145 return '**' + cmd + '**'
1148 def __init__(self, x):
1152 def escape(self, escape_func):
1153 return escape_func(self.data)
1154 def is_literal(self):
1157 a = SCons.Action.CommandAction(["xyzzy"])
1158 e = Environment(SPAWN = func)
1160 assert t.executed == [ 'xyzzy' ], t.executed
1162 a = SCons.Action.CommandAction(["xyzzy"])
1163 e = Environment(SPAWN = '$FUNC', FUNC = func)
1165 assert t.executed == [ 'xyzzy' ], t.executed
1167 a = SCons.Action.CommandAction(["xyzzy"])
1168 e = Environment(SPAWN = func, SHELL = 'fake shell')
1170 assert t.executed == [ 'xyzzy' ], t.executed
1171 assert t.shell == 'fake shell', t.shell
1173 a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ])
1174 e = Environment(SPAWN = func, ESCAPE = escape_func)
1176 assert t.executed == [ '**xyzzy**' ], t.executed
1178 def test_get_contents(self):
1179 """Test fetching the contents of a command Action
1181 def CmdGen(target, source, env, for_signature):
1182 assert for_signature
1184 (env["foo"], env["bar"])
1186 # The number 1 is there to make sure all args get converted to strings.
1187 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
1188 "$)", "|", "$baz", 1])
1189 c = a.get_contents(target=[], source=[],
1190 env=Environment(foo = 'FFF', bar = 'BBB',
1192 assert c == "| | FFF BBB 1", c
1194 # Make sure that CommandActions use an Environment's
1195 # subst_target_source() method for substitution.
1196 class SpecialEnvironment(Environment):
1197 def subst_target_source(self, strSubst, raw=0, target=[], source=[]):
1198 return 'subst_target_source: ' + strSubst
1200 c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'),
1201 env=SpecialEnvironment(foo = 'GGG', bar = 'CCC',
1203 assert c == 'subst_target_source: | $( $foo | $bar $) | $baz 1', c
1205 # We've discussed using the real target and source names in a
1206 # CommandAction's signature contents. This would have have the
1207 # advantage of recompiling when a file's name changes (keeping
1208 # debug info current), but it would currently break repository
1209 # logic that will change the file name based on whether the
1210 # files come from a repository or locally. If we ever move to
1211 # that scheme, then all of the '__t1__' and '__s6__' file names
1212 # in the asserts below would change to 't1' and 's6' and the
1214 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
1215 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
1218 a = SCons.Action.CommandAction(["$TARGET"])
1219 c = a.get_contents(target=t, source=s, env=env)
1222 a = SCons.Action.CommandAction(["$TARGETS"])
1223 c = a.get_contents(target=t, source=s, env=env)
1224 assert c == "t1 t2 t3 t4 t5 t6", c
1226 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
1227 c = a.get_contents(target=t, source=s, env=env)
1230 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
1231 c = a.get_contents(target=t, source=s, env=env)
1232 assert c == "t4 t5", c
1234 a = SCons.Action.CommandAction(["$SOURCE"])
1235 c = a.get_contents(target=t, source=s, env=env)
1238 a = SCons.Action.CommandAction(["$SOURCES"])
1239 c = a.get_contents(target=t, source=s, env=env)
1240 assert c == "s1 s2 s3 s4 s5 s6", c
1242 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
1243 c = a.get_contents(target=t, source=s, env=env)
1246 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
1247 c = a.get_contents(target=t, source=s, env=env)
1248 assert c == "s4 s5", c
1250 class CommandGeneratorActionTestCase(unittest.TestCase):
1252 def test___init__(self):
1253 """Test creation of a command generator Action
1255 def f(target, source, env):
1257 a = SCons.Action.CommandGeneratorAction(f)
1258 assert a.generator == f
1260 def test___str__(self):
1261 """Test the pre-substitution strings for command generator Actions
1263 def f(target, source, env, for_signature, self=self):
1265 # See if "env" is really a construction environment (or
1266 # looks like one) by accessing the FindIxes attribute.
1267 # (The Tool/mingw.py module has a generator that uses this,
1268 # and the __str__() method used to cause problems by passing
1269 # us a regular dictionary as a fallback.)
1273 a = SCons.Action.CommandGeneratorAction(f)
1275 assert s == 'FOO', s
1277 def test_genstring(self):
1278 """Test the command generator Action genstring() method
1280 def f(target, source, env, for_signature, self=self):
1281 dummy = env['dummy']
1283 return "$FOO $TARGET $SOURCE $TARGETS $SOURCES"
1284 a = SCons.Action.CommandGeneratorAction(f)
1286 s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1))
1287 assert self.dummy == 1, self.dummy
1288 assert s == "$FOO $TARGET $SOURCE $TARGETS $SOURCES", s
1290 def test_execute(self):
1291 """Test executing a command generator Action
1294 def f(target, source, env, for_signature, self=self):
1295 dummy = env['dummy']
1297 s = env.subst("$FOO")
1298 assert s == 'foo baz\nbar ack', s
1300 def func_action(target, source, env, self=self):
1302 s = env.subst('$foo')
1303 assert s == 'bar', s
1305 def f2(target, source, env, for_signature, f=func_action):
1307 def ch(sh, escape, cmd, args, env, self=self):
1308 self.cmd.append(cmd)
1309 self.args.append(args)
1311 a = SCons.Action.CommandGeneratorAction(f)
1315 a([], [], env=Environment(FOO = 'foo baz\nbar ack',
1318 assert self.dummy == 1, self.dummy
1319 assert self.cmd == ['foo', 'bar'], self.cmd
1320 assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args
1322 b = SCons.Action.CommandGeneratorAction(f2)
1324 b(target=[], source=[], env=Environment(foo = 'bar',
1326 assert self.dummy==2, self.dummy
1330 def __init__(self, t):
1333 self.t.rfile_called = 1
1335 def get_subst_proxy(self):
1337 def f3(target, source, env, for_signature):
1339 c = SCons.Action.CommandGeneratorAction(f3)
1340 c(target=[], source=DummyFile(self), env=Environment())
1341 assert self.rfile_called
1343 def test_get_contents(self):
1344 """Test fetching the contents of a command generator Action
1346 def f(target, source, env, for_signature):
1349 assert for_signature, for_signature
1350 return [["guux", foo, "$(", "$ignore", "$)", bar,
1351 '${test("$( foo $bar $)")}' ]]
1354 assert mystr == "$( foo $bar $)", mystr
1357 env = Environment(foo = 'FFF', bar = 'BBB',
1358 ignore = 'foo', test=test)
1359 a = SCons.Action.CommandGeneratorAction(f)
1360 c = a.get_contents(target=[], source=[], env=env)
1361 assert c == "guux FFF BBB test", c
1364 class FunctionActionTestCase(unittest.TestCase):
1366 def test___init__(self):
1367 """Test creation of a function Action
1378 a = SCons.Action.FunctionAction(func1)
1379 assert a.execfunction == func1, a.execfunction
1380 assert isinstance(a.strfunction, types.MethodType), type(a.strfunction)
1382 a = SCons.Action.FunctionAction(func2, strfunction=func3)
1383 assert a.execfunction == func2, a.execfunction
1384 assert a.strfunction == func3, a.strfunction
1386 def test_cmdstr_bad(self):
1387 """Test handling of bad FunctionAction(cmdstr) arguments
1392 a = SCons.Action.FunctionAction(func, [])
1393 except SCons.Errors.UserError, e:
1395 m = 'Invalid function display variable'
1396 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
1398 raise "did not catch expected UserError"
1400 def test___str__(self):
1401 """Test the __str__() method for function Actions
1405 a = SCons.Action.FunctionAction(func1)
1407 assert s == "func1(target, source, env)", s
1412 a = SCons.Action.FunctionAction(class1())
1414 assert s == "class1(target, source, env)", s
1416 def test_execute(self):
1417 """Test executing a function Action
1420 def f(target, source, env):
1425 assert env.subst("$BAR") == 'foo bar', env.subst("$BAR")
1427 a = SCons.Action.FunctionAction(f)
1428 a(target=1, source=2, env=Environment(BAR = 'foo bar',
1430 assert self.inc == 1, self.inc
1431 assert self.source == [2], self.source
1432 assert self.target == [1], self.target
1436 def function1(target, source, env):
1440 open(t, 'w').write("function1\n")
1443 act = SCons.Action.FunctionAction(function1)
1446 r = act(target = [outfile, outfile2], source=[], env=Environment())
1447 except SCons.Errors.BuildError:
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 r.__class__ == class1a
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))
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
1501 a = SCons.Action.FunctionAction(GlobalFunc)
1502 c = a.get_contents(target=[], source=[], env=Environment())
1503 assert c in matches, repr(c)
1505 a = SCons.Action.FunctionAction(LocalFunc)
1506 c = a.get_contents(target=[], source=[], env=Environment())
1507 assert c in matches, repr(c)
1509 a = SCons.Action.FunctionAction(GlobalFunc, varlist=['XYZ'])
1511 matches_foo = map(lambda x: x + "foo", matches)
1513 c = a.get_contents(target=[], source=[], env=Environment())
1514 assert c in matches, repr(c)
1515 c = a.get_contents(target=[], source=[], env=Environment(XYZ = 'foo'))
1516 assert c in matches_foo, repr(c)
1519 def get_contents(self, target, source, env):
1521 a = SCons.Action.FunctionAction(Foo())
1522 c = a.get_contents(target=[], source=[], env=Environment())
1523 assert c == 'xyzzy', repr(c)
1526 def LocalMethod(self):
1529 a = SCons.Action.FunctionAction(lc.LocalMethod)
1530 c = a.get_contents(target=[], source=[], env=Environment())
1531 assert c in matches, repr(c)
1533 def test_strfunction(self):
1534 """Test the FunctionAction.strfunction() method
1539 a = SCons.Action.FunctionAction(func)
1540 s = a.strfunction(target=[], source=[], env=Environment())
1541 assert s == 'func([], [])', s
1543 a = SCons.Action.FunctionAction(func, None)
1544 s = a.strfunction(target=[], source=[], env=Environment())
1547 a = SCons.Action.FunctionAction(func, 'function')
1548 s = a.strfunction(target=[], source=[], env=Environment())
1549 assert s == 'function', s
1551 class ListActionTestCase(unittest.TestCase):
1553 def test___init__(self):
1554 """Test creation of a list of subsidiary Actions
1558 a = SCons.Action.ListAction(["x", func, ["y", "z"]])
1559 assert isinstance(a.list[0], SCons.Action.CommandAction)
1560 assert isinstance(a.list[1], SCons.Action.FunctionAction)
1561 assert isinstance(a.list[2], SCons.Action.ListAction)
1562 assert a.list[2].list[0].cmd_list == 'y'
1564 def test___str__(self):
1565 """Test the __str__() method for a list of subsidiary Actions
1567 def f(target,source,env):
1569 def g(target,source,env):
1571 a = SCons.Action.ListAction([f, g, "XXX", f])
1573 assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s
1575 def test_genstring(self):
1576 """Test the genstring() method for a list of subsidiary Actions
1578 def f(target,source,env):
1580 def g(target,source,env,for_signature):
1581 return 'generated %s %s' % (target[0], source[0])
1582 g = SCons.Action.Action(g, generator=1)
1583 a = SCons.Action.ListAction([f, g, "XXX", f])
1584 s = a.genstring(['foo.x'], ['bar.y'], Environment())
1585 assert s == "f(target, source, env)\ngenerated foo.x bar.y\nXXX\nf(target, source, env)", s
1587 def test_execute(self):
1588 """Test executing a list of subsidiary Actions
1591 def f(target,source,env):
1594 a = SCons.Action.ListAction([f, f, f])
1595 a([], [], Environment(s = self))
1596 assert self.inc == 3, self.inc
1598 cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile)
1600 def function2(target, source, env):
1601 open(env['out'], 'a').write("function2\n")
1605 def __call__(self, target, source, env):
1606 open(env['out'], 'a').write("class2a\n")
1610 def __init__(self, target, source, env):
1611 open(env['out'], 'a').write("class2b\n")
1612 act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
1613 r = act([], [], Environment(out = outfile))
1614 assert r.__class__ == class2b
1615 c = test.read(outfile, 'r')
1616 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
1618 def test_get_contents(self):
1619 """Test fetching the contents of a list of subsidiary Actions
1622 def gen(target, source, env, for_signature):
1626 a = SCons.Action.ListAction(["x",
1627 SCons.Action.Action(gen, generator=1),
1629 c = a.get_contents(target=[], source=[], env=Environment(s = self))
1630 assert self.foo==1, self.foo
1631 assert c == "xyz", c
1633 class LazyActionTestCase(unittest.TestCase):
1634 def test___init__(self):
1635 """Test creation of a lazy-evaluation Action
1637 # Environment variable references should create a special type
1638 # of LazyAction that lazily evaluates the variable for whether
1639 # it's a string or something else before doing anything.
1640 a9 = SCons.Action.Action('$FOO')
1641 assert isinstance(a9, SCons.Action.LazyAction), a9
1642 assert a9.var == 'FOO', a9.var
1644 a10 = SCons.Action.Action('${FOO}')
1645 assert isinstance(a10, SCons.Action.LazyAction), a10
1646 assert a10.var == 'FOO', a10.var
1648 def test_genstring(self):
1649 """Test the lazy-evaluation Action genstring() method
1651 def f(target, source, env):
1653 a = SCons.Action.Action('$BAR')
1654 env1 = Environment(BAR=f, s=self)
1655 env2 = Environment(BAR='xxx', s=self)
1656 s = a.genstring([], [], env=env1)
1657 assert s == "f(target, source, env)", s
1658 s = a.genstring([], [], env=env2)
1659 assert s == 'xxx', s
1661 def test_execute(self):
1662 """Test executing a lazy-evaluation Action
1664 def f(target, source, env):
1668 a = SCons.Action.Action('$BAR')
1669 a([], [], env=Environment(BAR = f, s = self))
1670 assert self.test == 1, self.test
1671 cmd = r'%s %s %s lazy' % (_python_, act_py, outfile)
1672 a([], [], env=Environment(BAR = cmd, s = self))
1673 c = test.read(outfile, 'r')
1674 assert c == "act.py: 'lazy'\n", c
1676 def test_get_contents(self):
1677 """Test fetching the contents of a lazy-evaluation Action
1679 a = SCons.Action.Action("${FOO}")
1680 env = Environment(FOO = [["This", "is", "a", "test"]])
1681 c = a.get_contents(target=[], source=[], env=env)
1682 assert c == "This is a test", c
1684 class ActionCallerTestCase(unittest.TestCase):
1685 def test___init__(self):
1686 """Test creation of an ActionCaller"""
1687 ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO' : 4, 'BAR' : 5})
1688 assert ac.parent == 1, ac.parent
1689 assert ac.args == [2, 3], ac.args
1690 assert ac.kw == {'FOO' : 4, 'BAR' : 5}, ac.kw
1692 def test_get_contents(self):
1693 """Test fetching the contents of an ActionCaller"""
1705 af = SCons.Action.ActionFactory(GlobalFunc, strfunc)
1706 ac = SCons.Action.ActionCaller(af, [], {})
1707 c = ac.get_contents([], [], Environment())
1708 assert c in matches, repr(c)
1710 af = SCons.Action.ActionFactory(LocalFunc, strfunc)
1711 ac = SCons.Action.ActionCaller(af, [], {})
1712 c = ac.get_contents([], [], Environment())
1713 assert c in matches, repr(c)
1724 af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc)
1725 ac = SCons.Action.ActionCaller(af, [], {})
1726 c = ac.get_contents([], [], Environment())
1727 assert c in matches, repr(c)
1729 af = SCons.Action.ActionFactory(LocalActFunc(), strfunc)
1730 ac = SCons.Action.ActionCaller(af, [], {})
1731 c = ac.get_contents([], [], Environment())
1732 assert c in matches, repr(c)
1735 "<built-in function str>",
1739 af = SCons.Action.ActionFactory(str, strfunc)
1740 ac = SCons.Action.ActionCaller(af, [], {})
1741 c = ac.get_contents([], [], Environment())
1742 assert c == "<built-in function str>" or \
1743 c == "<type 'str'>", repr(c)
1745 def test___call__(self):
1746 """Test calling an ActionCaller"""
1748 def actfunc(a1, a2, a3, args=actfunc_args):
1749 args.extend([a1, a2, a3])
1750 def strfunc(a1, a2, a3):
1753 e = Environment(FOO = 2, BAR = 5)
1755 af = SCons.Action.ActionFactory(actfunc, strfunc)
1756 ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {})
1758 assert actfunc_args[0] is e, actfunc_args
1759 assert actfunc_args[1] == '2', actfunc_args
1760 assert actfunc_args[2] == 3, actfunc_args
1763 ac = SCons.Action.ActionCaller(af, [], {'a3' : '$__env__', 'a2' : '$BAR', 'a1' : 4})
1765 assert actfunc_args[0] == 4, actfunc_args
1766 assert actfunc_args[1] == '5', actfunc_args
1767 assert actfunc_args[2] is e, actfunc_args
1770 def test_strfunction(self):
1771 """Test calling the ActionCaller strfunction() method"""
1773 def actfunc(a1, a2, a3):
1775 def strfunc(a1, a2, a3, args=strfunc_args):
1776 args.extend([a1, a2, a3])
1778 af = SCons.Action.ActionFactory(actfunc, strfunc)
1779 ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3], {})
1780 ac.strfunction([], [], Environment(FOO = 2))
1781 assert strfunc_args == [1, '2', 3], strfunc_args
1784 ac = SCons.Action.ActionCaller(af, [], {'a3' : 6, 'a2' : '$BAR', 'a1' : 4})
1785 ac.strfunction([], [], Environment(BAR = 5))
1786 assert strfunc_args == [4, '5', 6], strfunc_args
1788 class ActionFactoryTestCase(unittest.TestCase):
1789 def test___init__(self):
1790 """Test creation of an ActionFactory"""
1795 ac = SCons.Action.ActionFactory(actfunc, strfunc)
1796 assert ac.actfunc is actfunc, ac.actfunc
1797 assert ac.strfunc is strfunc, ac.strfunc
1799 def test___call__(self):
1800 """Test calling whatever's returned from an ActionFactory"""
1803 def actfunc(a1, a2, a3, args=actfunc_args):
1804 args.extend([a1, a2, a3])
1805 def strfunc(a1, a2, a3, args=strfunc_args):
1806 args.extend([a1, a2, a3])
1807 af = SCons.Action.ActionFactory(actfunc, strfunc)
1808 af(3, 6, 9)([], [], Environment())
1809 assert actfunc_args == [3, 6, 9], actfunc_args
1810 assert strfunc_args == [3, 6, 9], strfunc_args
1813 class ActionCompareTestCase(unittest.TestCase):
1815 def test_1_solo_name(self):
1816 """Test Lazy Cmd Generator Action get_name alone.
1818 Basically ensures we can locate the builder, comparing it to
1819 itself along the way."""
1820 bar = SCons.Builder.Builder(action = {})
1821 env = Environment( BUILDERS = {'BAR' : bar} )
1822 name = bar.get_name(env)
1823 assert name == 'BAR', name
1825 def test_2_multi_name(self):
1826 """Test LazyCmdGenerator Action get_name multi builders.
1828 Ensure that we can compare builders (and thereby actions) to
1829 each other safely."""
1830 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1831 bar = SCons.Builder.Builder(action = {})
1833 assert foo.action != bar.action
1834 env = Environment( BUILDERS = {'FOO' : foo,
1836 name = foo.get_name(env)
1837 assert name == 'FOO', name
1838 name = bar.get_name(env)
1839 assert name == 'BAR', name
1841 def test_3_dict_names(self):
1842 """Test Action/Suffix dicts with get_name.
1844 Verifies that Action/Suffix dictionaries work correctly,
1845 especially two builders that can generate the same suffix,
1846 where one of the builders has a suffix dictionary with a None
1849 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1850 bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'})
1851 bar.add_action('.cow', "$MOO")
1852 dog = SCons.Builder.Builder(suffix = '.bar')
1854 env = Environment( BUILDERS = {'FOO' : foo,
1858 assert foo.get_name(env) == 'FOO', foo.get_name(env)
1859 assert bar.get_name(env) == 'BAR', bar.get_name(env)
1860 assert dog.get_name(env) == 'DOG', dog.get_name(env)
1863 if __name__ == "__main__":
1864 suite = unittest.TestSuite()
1865 tclasses = [ ActionTestCase,
1867 _ActionActionTestCase,
1868 CommandActionTestCase,
1869 CommandGeneratorActionTestCase,
1870 FunctionActionTestCase,
1873 ActionCallerTestCase,
1874 ActionFactoryTestCase,
1875 ActionCompareTestCase ]
1876 for tclass in tclasses:
1877 names = unittest.getTestCaseNames(tclass, 'test_')
1878 suite.addTests(map(tclass, names))
1879 if not unittest.TextTestRunner().run(suite).wasSuccessful():