4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26 # Define a null function and a null class for use as builder actions.
27 # Where these are defined in the file seems to affect their byte-code
28 # contents, so try to minimize changes by defining them here, before we
29 # even import anything.
47 import SCons.Environment
52 # Initial setup of the common environment for all tests,
53 # a temporary working directory containing a
54 # script for writing arguments to an output file.
56 # We don't do this as a setUp() method because it's
57 # unnecessary to create a separate directory and script
58 # for each test, they can just use the one.
59 test = TestCmd.TestCmd(workdir = '')
61 test.write('act.py', """\
62 import os, string, sys
63 f = open(sys.argv[1], 'w')
64 f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n")
67 f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n")
71 if os.environ.has_key( 'ACTPY_PIPE' ):
72 if os.environ.has_key( 'PIPE_STDOUT_FILE' ):
73 stdout_msg = open(os.environ['PIPE_STDOUT_FILE'], 'r').read()
75 stdout_msg = "act.py: stdout: executed act.py %s\\n" % string.join(sys.argv[1:])
76 sys.stdout.write( stdout_msg )
77 if os.environ.has_key( 'PIPE_STDERR_FILE' ):
78 stderr_msg = open(os.environ['PIPE_STDERR_FILE'], 'r').read()
80 stderr_msg = "act.py: stderr: executed act.py %s\\n" % string.join(sys.argv[1:])
81 sys.stderr.write( stderr_msg )
85 test.write('exit.py', """\
87 sys.exit(int(sys.argv[1]))
90 act_py = test.workpath('act.py')
91 exit_py = test.workpath('exit.py')
93 outfile = test.workpath('outfile')
94 outfile2 = test.workpath('outfile2')
95 pipe_file = test.workpath('pipe.out')
97 scons_env = SCons.Environment.Environment()
99 # Capture all the stuff the Actions will print,
100 # so it doesn't clutter the output.
101 sys.stdout = StringIO.StringIO()
103 class CmdStringHolder:
104 def __init__(self, cmd, literal=None):
106 self.literal = literal
108 def is_literal(self):
111 def escape(self, escape_func):
112 """Escape the string with the supplied function. The
113 function is expected to take an arbitrary string, then
114 return it with all special characters escaped and ready
115 for passing to the command interpreter.
117 After calling this function, the next call to str() will
118 return the escaped string.
121 if self.is_literal():
122 return escape_func(self.data)
123 elif ' ' in self.data or '\t' in self.data:
124 return '"%s"' % self.data
129 def __init__(self, **kw):
131 self.d['SHELL'] = scons_env['SHELL']
132 self.d['SPAWN'] = scons_env['SPAWN']
133 self.d['PSPAWN'] = scons_env['PSPAWN']
134 self.d['ESCAPE'] = scons_env['ESCAPE']
135 for k, v in kw.items():
137 # Just use the underlying scons_subst*() utility methods.
138 def subst(self, strSubst, raw=0, target=[], source=[], conv=None):
139 return SCons.Subst.scons_subst(strSubst, self, raw,
140 target, source, self.d, conv=conv)
141 subst_target_source = subst
142 def subst_list(self, strSubst, raw=0, target=[], source=[], conv=None):
143 return SCons.Subst.scons_subst_list(strSubst, self, raw,
144 target, source, self.d, conv=conv)
145 def __getitem__(self, item):
147 def __setitem__(self, item, value):
149 def has_key(self, item):
150 return self.d.has_key(item)
151 def get(self, key, value=None):
152 return self.d.get(key, value)
154 return self.d.items()
155 def Dictionary(self):
157 def Clone(self, **kw):
159 res.d = SCons.Util.semi_deepcopy(self.d)
160 for k, v in kw.items():
165 for k,v in self.items(): d[k] = v
166 d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__']
167 d['TARGET'] = d['TARGETS'][0]
168 d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__']
169 d['SOURCE'] = d['SOURCES'][0]
173 def __init__(self, name):
175 def str_for_display(self):
176 return '"' + self.name + '"'
181 def get_subst_proxy(self):
184 if os.name == 'java':
185 python = os.path.join(sys.prefix, 'jython')
187 python = sys.executable
189 _python_ = '"' + python + '"'
191 class ActionTestCase(unittest.TestCase):
192 """Test the Action() factory function"""
194 def test_FunctionAction(self):
195 """Test the Action() factory's creation of FunctionAction objects
201 a1 = SCons.Action.Action(foo)
202 assert isinstance(a1, SCons.Action.FunctionAction), a1
203 assert a1.execfunction == foo, a1.execfunction
205 a11 = SCons.Action.Action(foo, strfunction=bar)
206 assert isinstance(a11, SCons.Action.FunctionAction), a11
207 assert a11.execfunction == foo, a11.execfunction
208 assert a11.strfunction == bar, a11.strfunction
210 def test_CommandAction(self):
211 """Test the Action() factory's creation of CommandAction objects
213 a1 = SCons.Action.Action("string")
214 assert isinstance(a1, SCons.Action.CommandAction), a1
215 assert a1.cmd_list == "string", a1.cmd_list
217 if hasattr(types, 'UnicodeType'):
218 exec "a2 = SCons.Action.Action(u'string')"
219 exec "assert isinstance(a2, SCons.Action.CommandAction), a2"
221 a3 = SCons.Action.Action(["a3"])
222 assert isinstance(a3, SCons.Action.CommandAction), a3
223 assert a3.cmd_list == "a3", a3.cmd_list
225 a4 = SCons.Action.Action([[ "explicit", "command", "line" ]])
226 assert isinstance(a4, SCons.Action.CommandAction), a4
227 assert a4.cmd_list == [ "explicit", "command", "line" ], a4.cmd_list
232 a5 = SCons.Action.Action("string", strfunction=foo)
233 assert isinstance(a5, SCons.Action.CommandAction), a5
234 assert a5.cmd_list == "string", a5.cmd_list
235 assert a5.strfunction == foo, a5.strfunction
237 def test_ListAction(self):
238 """Test the Action() factory's creation of ListAction objects
240 a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]])
241 assert isinstance(a1, SCons.Action.ListAction), a1
242 assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0]
243 assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list
244 assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1]
245 assert a1.list[1].cmd_list == "y", a1.list[1].cmd_list
246 assert isinstance(a1.list[2], SCons.Action.CommandAction), a1.list[2]
247 assert a1.list[2].cmd_list == "z", a1.list[2].cmd_list
248 assert isinstance(a1.list[3], SCons.Action.CommandAction), a1.list[3]
249 assert a1.list[3].cmd_list == [ "a", "b", "c" ], a1.list[3].cmd_list
251 a2 = SCons.Action.Action("x\ny\nz")
252 assert isinstance(a2, SCons.Action.ListAction), a2
253 assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0]
254 assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list
255 assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1]
256 assert a2.list[1].cmd_list == "y", a2.list[1].cmd_list
257 assert isinstance(a2.list[2], SCons.Action.CommandAction), a2.list[2]
258 assert a2.list[2].cmd_list == "z", a2.list[2].cmd_list
263 a3 = SCons.Action.Action(["x", foo, "z"])
264 assert isinstance(a3, SCons.Action.ListAction), a3
265 assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0]
266 assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list
267 assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1]
268 assert a3.list[1].execfunction == foo, a3.list[1].execfunction
269 assert isinstance(a3.list[2], SCons.Action.CommandAction), a3.list[2]
270 assert a3.list[2].cmd_list == "z", a3.list[2].cmd_list
272 a4 = SCons.Action.Action(["x", "y"], strfunction=foo)
273 assert isinstance(a4, SCons.Action.ListAction), a4
274 assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0]
275 assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list
276 assert a4.list[0].strfunction == foo, a4.list[0].strfunction
277 assert isinstance(a4.list[1], SCons.Action.CommandAction), a4.list[1]
278 assert a4.list[1].cmd_list == "y", a4.list[1].cmd_list
279 assert a4.list[1].strfunction == foo, a4.list[1].strfunction
281 a5 = SCons.Action.Action("x\ny", strfunction=foo)
282 assert isinstance(a5, SCons.Action.ListAction), a5
283 assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0]
284 assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list
285 assert a5.list[0].strfunction == foo, a5.list[0].strfunction
286 assert isinstance(a5.list[1], SCons.Action.CommandAction), a5.list[1]
287 assert a5.list[1].cmd_list == "y", a5.list[1].cmd_list
288 assert a5.list[1].strfunction == foo, a5.list[1].strfunction
290 def test_CommandGeneratorAction(self):
291 """Test the Action() factory's creation of CommandGeneratorAction objects
297 a1 = SCons.Action.Action(foo, generator=1)
298 assert isinstance(a1, SCons.Action.CommandGeneratorAction), a1
299 assert a1.generator is foo, a1.generator
301 a2 = SCons.Action.Action(foo, strfunction=bar, generator=1)
302 assert isinstance(a2, SCons.Action.CommandGeneratorAction), a2
303 assert a2.generator is foo, a2.generator
305 def test_LazyCmdGeneratorAction(self):
306 """Test the Action() factory's creation of lazy CommandGeneratorAction objects
311 a1 = SCons.Action.Action("$FOO")
312 assert isinstance(a1, SCons.Action.LazyAction), a1
314 a2 = SCons.Action.Action("$FOO", strfunction=foo)
315 assert isinstance(a2, SCons.Action.LazyAction), a2
317 def test_no_action(self):
318 """Test when the Action() factory can't create an action object
320 a5 = SCons.Action.Action(1)
321 assert a5 is None, a5
323 def test_reentrance(self):
324 """Test the Action() factory when the action is already an Action object
326 a1 = SCons.Action.Action("foo")
327 a2 = SCons.Action.Action(a1)
330 class ActionBaseTestCase(unittest.TestCase):
331 def test_get_executor(self):
332 """Test the ActionBase.get_executor() method"""
333 a = SCons.Action.Action('foo')
334 x = a.get_executor({}, {}, [], [], {})
335 assert not x is None, x
337 class _ActionActionTestCase(unittest.TestCase):
339 def test__init__(self):
340 """Test creation of _ActionAction objects
349 a = SCons.Action._ActionAction()
350 assert not hasattr(a, 'strfunction')
352 assert SCons.Action._ActionAction(kwarg = 1)
353 assert not hasattr(a, 'strfunction')
354 assert not hasattr(a, 'kwarg')
356 a = SCons.Action._ActionAction(strfunction=func1)
357 assert a.strfunction is func1, a.strfunction
359 a = SCons.Action._ActionAction(presub=func1)
360 assert a.presub is func1, a.presub
362 a = SCons.Action._ActionAction(chdir=1)
363 assert a.chdir is 1, a.chdir
365 a = SCons.Action._ActionAction(func1, func2, 'x')
366 assert a.strfunction is func1, a.strfunction
367 assert a.presub is func2, a.presub
368 assert a.chdir is 'x', a.chdir
370 def test___cmp__(self):
371 """Test Action comparison
373 a1 = SCons.Action.Action("x")
374 a2 = SCons.Action.Action("x")
376 a3 = SCons.Action.Action("y")
380 def test_print_cmd_lines(self):
381 """Test the print_cmd_lines() method
383 save_stdout = sys.stdout
386 def execfunc(target, source, env):
388 a = SCons.Action.Action(execfunc)
390 sio = StringIO.StringIO()
392 a.print_cmd_line("foo bar", None, None, None)
394 assert s == "foo bar\n", s
397 sys.stdout = save_stdout
399 def test___call__(self):
400 """Test calling an Action
402 save_stdout = sys.stdout
404 save_print_actions = SCons.Action.print_actions
405 save_print_actions_presub = SCons.Action.print_actions_presub
406 save_execute_actions = SCons.Action.execute_actions
407 #SCons.Action.print_actions = 0
409 test = TestCmd.TestCmd(workdir = '')
410 test.subdir('sub', 'xyz')
411 os.chdir(test.workpath())
416 def execfunc(target, source, env):
417 assert type(target) is type([]), type(target)
418 assert type(source) is type([]), type(source)
420 a = SCons.Action.Action(execfunc)
422 def firstfunc(target, source, env):
423 assert type(target) is type([]), type(target)
424 assert type(source) is type([]), type(source)
426 def lastfunc(target, source, env):
427 assert type(target) is type([]), type(target)
428 assert type(source) is type([]), type(source)
430 b = SCons.Action.Action([firstfunc, execfunc, lastfunc])
432 sio = StringIO.StringIO()
434 result = a("out", "in", env)
435 assert result.status == 7, result
437 assert s == "execfunc(['out'], ['in'])\n", s
440 expect = "os.chdir(%s)\nexecfunc(['out'], ['in'])\nos.chdir(%s)\n"
442 sio = StringIO.StringIO()
444 result = a("out", "in", env)
445 assert result.status == 7, result.status
447 assert s == expect % (repr('xyz'), repr(test.workpath())), s
449 sio = StringIO.StringIO()
451 result = a("out", "in", env, chdir='sub')
452 assert result.status == 7, result.status
454 assert s == expect % (repr('sub'), repr(test.workpath())), s
458 sio = StringIO.StringIO()
460 result = b("out", "in", env)
461 assert result.status == 7, result.status
463 assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\n", s
465 SCons.Action.execute_actions = 0
467 sio = StringIO.StringIO()
469 result = a("out", "in", env)
470 assert result == 0, result
472 assert s == "execfunc(['out'], ['in'])\n", s
474 sio = StringIO.StringIO()
476 result = b("out", "in", env)
477 assert result == 0, result
479 assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\nlastfunc(['out'], ['in'])\n", s
481 SCons.Action.print_actions_presub = 1
482 SCons.Action.execute_actions = 1
484 sio = StringIO.StringIO()
486 result = a("out", "in", env)
487 assert result.status == 7, result.status
489 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
491 sio = StringIO.StringIO()
493 result = a("out", "in", env, presub=0)
494 assert result.status == 7, result.status
496 assert s == "execfunc(['out'], ['in'])\n", s
498 sio = StringIO.StringIO()
500 result = a("out", "in", env, presub=1)
501 assert result.status == 7, result.status
503 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
505 sio = StringIO.StringIO()
507 result = b(["out"], "in", env, presub=1)
508 assert result.status == 7, result.status
510 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
512 sio = StringIO.StringIO()
514 result = b(["out", "list"], "in", env, presub=1)
515 assert result.status == 7, result.status
517 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
519 a2 = SCons.Action.Action(execfunc)
521 sio = StringIO.StringIO()
523 result = a2("out", "in", env)
524 assert result.status == 7, result.status
526 assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s
528 sio = StringIO.StringIO()
530 result = a2("out", "in", env, presub=0)
531 assert result.status == 7, result.status
533 assert s == "execfunc(['out'], ['in'])\n", s
535 SCons.Action.execute_actions = 0
537 sio = StringIO.StringIO()
539 result = a2("out", "in", env, presub=0)
540 assert result == 0, result
542 assert s == "execfunc(['out'], ['in'])\n", s
544 sio = StringIO.StringIO()
546 result = a("out", "in", env, presub=0, execute=1, show=0)
547 assert result.status == 7, result.status
551 sys.stdout = save_stdout
552 exitstatfunc_result = []
554 def exitstatfunc(stat, result=exitstatfunc_result):
558 result = a("out", "in", env, exitstatfunc=exitstatfunc)
559 assert result == 0, result
560 assert exitstatfunc_result == [], exitstatfunc_result
562 result = a("out", "in", env, execute=1, exitstatfunc=exitstatfunc)
563 assert result.status == 7, result.status
564 assert exitstatfunc_result == [7], exitstatfunc_result
566 SCons.Action.execute_actions = 1
569 def my_print_cmd_line(s, target, source, env, result=result):
571 env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line
572 a("output", "input", env)
573 assert result == ["execfunc(['output'], ['input'])"], result
577 sys.stdout = save_stdout
578 SCons.Action.print_actions = save_print_actions
579 SCons.Action.print_actions_presub = save_print_actions_presub
580 SCons.Action.execute_actions = save_execute_actions
582 def test_presub_lines(self):
583 """Test the presub_lines() method
586 a = SCons.Action.Action("x")
587 s = a.presub_lines(env)
590 a = SCons.Action.Action(["y", "z"])
591 s = a.presub_lines(env)
592 assert s == ['y', 'z'], s
596 a = SCons.Action.Action(func)
597 s = a.presub_lines(env)
598 assert s == ["func(target, source, env)"], s
600 def gen(target, source, env, for_signature):
601 return 'generat' + env.get('GEN', 'or')
602 a = SCons.Action.Action(gen, generator=1)
603 s = a.presub_lines(env)
604 assert s == ["generator"], s
605 s = a.presub_lines(Environment(GEN = 'ed'))
606 assert s == ["generated"], s
608 a = SCons.Action.Action("$ACT")
609 s = a.presub_lines(env)
611 s = a.presub_lines(Environment(ACT = 'expanded action'))
612 assert s == ['expanded action'], s
615 """Test adding Actions to stuff."""
616 # Adding actions to other Actions or to stuff that can
617 # be converted into an Action should produce a ListAction
618 # containing all the Actions.
621 baz = SCons.Action.Action(bar, generator=1)
622 act1 = SCons.Action.Action('foo bar')
623 act2 = SCons.Action.Action([ 'foo', bar ])
626 assert isinstance(sum, SCons.Action.ListAction), str(sum)
627 assert len(sum.list) == 3, len(sum.list)
628 assert map(lambda x: isinstance(x, SCons.Action.ActionBase),
629 sum.list) == [ 1, 1, 1 ]
632 assert isinstance(sum, SCons.Action.ListAction), str(sum)
633 assert len(sum.list) == 2, len(sum.list)
636 assert isinstance(sum, SCons.Action.ListAction), str(sum)
637 assert len(sum.list) == 4, len(sum.list)
639 # Should also be able to add command generators to each other
642 assert isinstance(sum, SCons.Action.ListAction), str(sum)
643 assert len(sum.list) == 2, len(sum.list)
646 assert isinstance(sum, SCons.Action.ListAction), str(sum)
647 assert len(sum.list) == 2, len(sum.list)
650 assert isinstance(sum, SCons.Action.ListAction), str(sum)
651 assert len(sum.list) == 3, len(sum.list)
653 # Also should be able to add Actions to anything that can
654 # be converted into an action.
656 assert isinstance(sum, SCons.Action.ListAction), str(sum)
657 assert len(sum.list) == 2, len(sum.list)
658 assert isinstance(sum.list[1], SCons.Action.FunctionAction)
660 sum = 'foo bar' + act2
661 assert isinstance(sum, SCons.Action.ListAction), str(sum)
662 assert len(sum.list) == 3, len(sum.list)
663 assert isinstance(sum.list[0], SCons.Action.CommandAction)
665 sum = [ 'foo', 'bar' ] + act1
666 assert isinstance(sum, SCons.Action.ListAction), str(sum)
667 assert len(sum.list) == 3, sum.list
668 assert isinstance(sum.list[0], SCons.Action.CommandAction)
669 assert isinstance(sum.list[1], SCons.Action.CommandAction)
671 sum = act2 + [ baz, bar ]
672 assert isinstance(sum, SCons.Action.ListAction), str(sum)
673 assert len(sum.list) == 4, len(sum.list)
674 assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction)
675 assert isinstance(sum.list[3], SCons.Action.FunctionAction)
682 assert 0, "Should have thrown a TypeError adding to an int."
689 assert 0, "Should have thrown a TypeError adding to an int."
691 class CommandActionTestCase(unittest.TestCase):
693 def test___init__(self):
694 """Test creation of a command Action
696 a = SCons.Action.CommandAction(["xyzzy"])
697 assert a.cmd_list == [ "xyzzy" ], a.cmd_list
698 assert a.cmdstr is None, a.cmdstr
700 a = SCons.Action.CommandAction(["abra"], "cadabra")
701 assert a.cmd_list == [ "abra" ], a.cmd_list
702 assert a.cmdstr == "cadabra", a.cmdstr
704 def test_bad_cmdstr(self):
705 """Test handling of bad CommandAction(cmdstr) arguments
708 a = SCons.Action.CommandAction('foo', [])
709 except SCons.Errors.UserError, e:
711 m = 'Invalid command display variable'
712 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
714 raise Exception, "did not catch expected UserError"
716 def test___str__(self):
717 """Test fetching the pre-substitution string for command Actions
720 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
722 assert s == 'xyzzy $TARGET $SOURCE', s
724 act = SCons.Action.CommandAction(['xyzzy',
725 '$TARGET', '$SOURCE',
726 '$TARGETS', '$SOURCES'])
728 assert s == "xyzzy $TARGET $SOURCE $TARGETS $SOURCES", s
730 def test_genstring(self):
731 """Test the genstring() method for command Actions
739 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
740 expect = 'xyzzy $TARGET $SOURCE'
741 s = act.genstring([], [], env)
742 assert s == expect, s
743 s = act.genstring([t1], [s1], env)
744 assert s == expect, s
745 s = act.genstring([t1, t2], [s1, s2], env)
746 assert s == expect, s
748 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
749 expect = 'xyzzy $TARGETS $SOURCES'
750 s = act.genstring([], [], env)
751 assert s == expect, s
752 s = act.genstring([t1], [s1], env)
753 assert s == expect, s
754 s = act.genstring([t1, t2], [s1, s2], env)
755 assert s == expect, s
757 act = SCons.Action.CommandAction(['xyzzy',
758 '$TARGET', '$SOURCE',
759 '$TARGETS', '$SOURCES'])
760 expect = "xyzzy $TARGET $SOURCE $TARGETS $SOURCES"
761 s = act.genstring([], [], env)
762 assert s == expect, s
763 s = act.genstring([t1], [s1], env)
764 assert s == expect, s
765 s = act.genstring([t1, t2], [s1, s2], env)
766 assert s == expect, s
768 def test_strfunction(self):
769 """Test fetching the string representation of command Actions
777 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE')
778 s = act.strfunction([], [], env)
779 assert s == 'xyzzy', s
780 s = act.strfunction([t1], [s1], env)
781 assert s == 'xyzzy t1 s1', s
782 s = act.strfunction([t1, t2], [s1, s2], env)
783 assert s == 'xyzzy t1 s1', s
785 act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE',
786 'cmdstr - $SOURCE - $TARGET -')
787 s = act.strfunction([], [], env)
788 assert s == 'cmdstr - - -', s
789 s = act.strfunction([t1], [s1], env)
790 assert s == 'cmdstr - s1 - t1 -', s
791 s = act.strfunction([t1, t2], [s1, s2], env)
792 assert s == 'cmdstr - s1 - t1 -', s
794 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
795 s = act.strfunction([], [], env)
796 assert s == 'xyzzy', s
797 s = act.strfunction([t1], [s1], env)
798 assert s == 'xyzzy t1 s1', s
799 s = act.strfunction([t1, t2], [s1, s2], env)
800 assert s == 'xyzzy t1 t2 s1 s2', s
802 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
803 'cmdstr = $SOURCES = $TARGETS =')
804 s = act.strfunction([], [], env)
805 assert s == 'cmdstr = = =', s
806 s = act.strfunction([t1], [s1], env)
807 assert s == 'cmdstr = s1 = t1 =', s
808 s = act.strfunction([t1, t2], [s1, s2], env)
809 assert s == 'cmdstr = s1 s2 = t1 t2 =', s
811 act = SCons.Action.CommandAction(['xyzzy',
812 '$TARGET', '$SOURCE',
813 '$TARGETS', '$SOURCES'])
814 s = act.strfunction([], [], env)
815 assert s == 'xyzzy', s
816 s = act.strfunction([t1], [s1], env)
817 assert s == 'xyzzy t1 s1 t1 s1', s
818 s = act.strfunction([t1, t2], [s1, s2], env)
819 assert s == 'xyzzy t1 s1 t1 t2 s1 s2', s
821 act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
822 'cmdstr\t$TARGETS\n$SOURCES ')
824 s = act.strfunction([], [], env)
825 assert s == 'cmdstr\t\n ', s
826 s = act.strfunction([t1], [s1], env)
827 assert s == 'cmdstr\tt1\ns1 ', s
828 s = act.strfunction([t1, t2], [s1, s2], env)
829 assert s == 'cmdstr\tt1 t2\ns1 s2 ', s
831 def sf(target, source, env):
832 return "sf was called"
833 act = SCons.Action.CommandAction('foo', strfunction=sf)
834 s = act.strfunction([], [], env)
835 assert s == "sf was called", s
838 def __init__(self, targets, sources, env):
843 def __init__(self, targets, sources, env):
848 def __init__(self, targets, sources, env):
852 def strfunction(self, targets, sources, env):
853 return 'actclass3 on %s to get %s'%(str(sources[0]),
856 def __init__(self, targets, sources, env):
862 act1 = SCons.Action.Action(actclass1([t1], [s1], env))
863 s = act1.strfunction([t1], [s1], env)
864 assert s == 'actclass1(["t1"], ["s1"])', s
866 act2 = SCons.Action.Action(actclass2([t1], [s1], env))
867 s = act2.strfunction([t1], [s1], env)
868 assert s == 'actclass2(["t1"], ["s1"])', s
870 act3 = SCons.Action.Action(actclass3([t1], [s1], env))
871 s = act3.strfunction([t1], [s1], env)
872 assert s == 'actclass3 on s1 to get t1', s
874 act4 = SCons.Action.Action(actclass4([t1], [s1], env))
875 s = act4.strfunction([t1], [s1], env)
878 act = SCons.Action.CommandAction("@foo bar")
879 s = act.strfunction([], [], env)
882 act = SCons.Action.CommandAction("@-foo bar")
883 s = act.strfunction([], [], env)
886 act = SCons.Action.CommandAction("-@foo bar")
887 s = act.strfunction([], [], env)
890 act = SCons.Action.CommandAction("-foo bar")
891 s = act.strfunction([], [], env)
892 assert s == "foo bar", s
894 act = SCons.Action.CommandAction("@ foo bar")
895 s = act.strfunction([], [], env)
898 act = SCons.Action.CommandAction("@- foo bar")
899 s = act.strfunction([], [], env)
902 act = SCons.Action.CommandAction("-@ foo bar")
903 s = act.strfunction([], [], env)
906 act = SCons.Action.CommandAction("- foo bar")
907 s = act.strfunction([], [], env)
908 assert s == "foo bar", s
910 def test_execute(self):
911 """Test execution of command Actions
916 except AttributeError:
919 cmd1 = r'%s %s %s xyzzy' % (_python_, act_py, outfile)
921 act = SCons.Action.CommandAction(cmd1)
922 r = act([], [], env.Clone())
924 c = test.read(outfile, 'r')
925 assert c == "act.py: 'xyzzy'\n", c
927 cmd2 = r'%s %s %s $TARGET' % (_python_, act_py, outfile)
929 act = SCons.Action.CommandAction(cmd2)
930 r = act(DummyNode('foo'), [], env.Clone())
932 c = test.read(outfile, 'r')
933 assert c == "act.py: 'foo'\n", c
935 cmd3 = r'%s %s %s ${TARGETS}' % (_python_, act_py, outfile)
937 act = SCons.Action.CommandAction(cmd3)
938 r = act(map(DummyNode, ['aaa', 'bbb']), [], env.Clone())
940 c = test.read(outfile, 'r')
941 assert c == "act.py: 'aaa' 'bbb'\n", c
943 cmd4 = r'%s %s %s $SOURCES' % (_python_, act_py, outfile)
945 act = SCons.Action.CommandAction(cmd4)
946 r = act([], [DummyNode('one'), DummyNode('two')], env.Clone())
948 c = test.read(outfile, 'r')
949 assert c == "act.py: 'one' 'two'\n", c
951 cmd4 = r'%s %s %s ${SOURCES[:2]}' % (_python_, act_py, outfile)
953 act = SCons.Action.CommandAction(cmd4)
954 sources = [DummyNode('three'), DummyNode('four'), DummyNode('five')]
956 r = act([], source = sources, env = env2)
958 c = test.read(outfile, 'r')
959 assert c == "act.py: 'three' 'four'\n", c
961 cmd5 = r'%s %s %s $TARGET XYZZY' % (_python_, act_py, outfile)
963 act = SCons.Action.CommandAction(cmd5)
965 if scons_env.has_key('ENV'):
966 env5['ENV'] = scons_env['ENV']
967 PATH = scons_env['ENV'].get('PATH', '')
972 env5['ENV']['XYZZY'] = 'xyzzy'
973 r = act(target = DummyNode('out5'), source = [], env = env5)
975 act = SCons.Action.CommandAction(cmd5)
976 r = act(target = DummyNode('out5'),
978 env = env.Clone(ENV = {'XYZZY' : 'xyzzy5',
981 c = test.read(outfile, 'r')
982 assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy5'\n", c
985 def __init__(self, str):
991 def get_subst_proxy(self):
994 cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (_python_, act_py, outfile)
996 act = SCons.Action.CommandAction(cmd6)
997 r = act(target = [Obj('111'), Obj('222')],
998 source = [Obj('333'), Obj('444'), Obj('555')],
1001 c = test.read(outfile, 'r')
1002 assert c == "act.py: '222' '111' '333' '444'\n", c
1005 # NT treats execs of directories and non-executable files
1006 # as "file not found" errors
1007 expect_nonexistent = 1
1008 expect_nonexecutable_file = 1
1009 expect_nonexecutable_dir = 1
1010 elif sys.platform == 'cygwin':
1011 expect_nonexistent = 127
1012 # Newer cygwin seems to return 126 for following
1013 expect_nonexecutable_file = 126
1014 expect_nonexecutable_dir = 127
1016 expect_nonexistent = 127
1017 expect_nonexecutable_file = 126
1018 expect_nonexecutable_dir = 126
1020 # Test that a nonexistent command returns 127
1021 act = SCons.Action.CommandAction(python + "_no_such_command_")
1022 r = act([], [], env.Clone(out = outfile))
1023 assert r.status == expect_nonexistent, r.status
1025 # Test that trying to execute a directory returns 126
1026 dir, tail = os.path.split(python)
1027 act = SCons.Action.CommandAction(dir)
1028 r = act([], [], env.Clone(out = outfile))
1029 assert r.status == expect_nonexecutable_file, r.status
1031 # Test that trying to execute a non-executable file returns 126
1032 act = SCons.Action.CommandAction(outfile)
1033 r = act([], [], env.Clone(out = outfile))
1034 assert r.status == expect_nonexecutable_dir, r.status
1036 act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py))
1037 r = act([], [], env)
1038 assert r.status == 1, r.status
1040 act = SCons.Action.CommandAction('@%s %s 1' % (_python_, exit_py))
1041 r = act([], [], env)
1042 assert r.status == 1, r.status
1044 act = SCons.Action.CommandAction('@-%s %s 1' % (_python_, exit_py))
1045 r = act([], [], env)
1048 act = SCons.Action.CommandAction('-%s %s 1' % (_python_, exit_py))
1049 r = act([], [], env)
1052 act = SCons.Action.CommandAction('@ %s %s 1' % (_python_, exit_py))
1053 r = act([], [], env)
1054 assert r.status == 1, r.status
1056 act = SCons.Action.CommandAction('@- %s %s 1' % (_python_, exit_py))
1057 r = act([], [], env)
1060 act = SCons.Action.CommandAction('- %s %s 1' % (_python_, exit_py))
1061 r = act([], [], env)
1064 def _DO_NOT_EXECUTE_test_pipe_execute(self):
1065 """Test capturing piped output from an action
1067 We used to have PIPE_BUILD support built right into
1068 Action.execute() for the benefit of the SConf subsystem, but we've
1069 moved that logic back into SConf itself. We'll leave this code
1070 here, just in case we ever want to resurrect this functionality
1071 in the future, but change the name of the test so it doesn't
1072 get executed as part of the normal test suite.
1074 pipe = open( pipe_file, "w" )
1075 self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1,
1076 PSTDOUT = pipe, PSTDERR = pipe)
1077 # everything should also work when piping output
1079 self.env['PSTDOUT'].close()
1080 pipe_out = test.read( pipe_file )
1082 act_out = "act.py: stdout: executed act.py"
1083 act_err = "act.py: stderr: executed act.py"
1085 # Since we are now using select(), stdout and stderr can be
1086 # intermixed, so count the lines separately.
1087 outlines = re.findall(act_out, pipe_out)
1088 errlines = re.findall(act_err, pipe_out)
1089 assert len(outlines) == 6, pipe_out + repr(outlines)
1090 assert len(errlines) == 6, pipe_out + repr(errlines)
1092 # test redirection operators
1093 def test_redirect(self, redir, stdout_msg, stderr_msg):
1094 cmd = r'%s %s %s xyzzy %s' % (_python_, act_py, outfile, redir)
1095 # Write the output and error messages to files because
1096 # Windows can't handle strings that are too big in its
1097 # external environment (os.spawnve() returns EINVAL,
1098 # "Invalid argument").
1099 stdout_file = test.workpath('stdout_msg')
1100 stderr_file = test.workpath('stderr_msg')
1101 open(stdout_file, 'w').write(stdout_msg)
1102 open(stderr_file, 'w').write(stderr_msg)
1103 pipe = open( pipe_file, "w" )
1104 act = SCons.Action.CommandAction(cmd)
1105 env = Environment( ENV = {'ACTPY_PIPE' : '1',
1106 'PIPE_STDOUT_FILE' : stdout_file,
1107 'PIPE_STDERR_FILE' : stderr_file},
1109 PSTDOUT = pipe, PSTDERR = pipe )
1110 r = act([], [], env)
1113 return (test.read(outfile2, 'r'), test.read(pipe_file, 'r'))
1115 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1117 assert redirected == act_out
1118 assert pipe_out == act_err
1120 (redirected, pipe_out) = test_redirect(self,'2> %s' % outfile2,
1122 assert redirected == act_err
1123 assert pipe_out == act_out
1125 (redirected, pipe_out) = test_redirect(self,'> %s 2>&1' % outfile2,
1127 assert (redirected == act_out + act_err or
1128 redirected == act_err + act_out)
1129 assert pipe_out == ""
1131 act_err = "Long Command Output\n"*3000
1132 # the size of the string should exceed the system's default block size
1134 (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2,
1136 assert (redirected == act_out)
1137 assert (pipe_out == act_err)
1139 def test_set_handler(self):
1140 """Test setting the command handler...
1146 def func(sh, escape, cmd, args, env, test=t):
1147 test.executed = args
1150 def escape_func(cmd):
1151 return '**' + cmd + '**'
1154 def __init__(self, x):
1158 def escape(self, escape_func):
1159 return escape_func(self.data)
1160 def is_literal(self):
1163 a = SCons.Action.CommandAction(["xyzzy"])
1164 e = Environment(SPAWN = func)
1166 assert t.executed == [ 'xyzzy' ], t.executed
1168 a = SCons.Action.CommandAction(["xyzzy"])
1169 e = Environment(SPAWN = '$FUNC', FUNC = func)
1171 assert t.executed == [ 'xyzzy' ], t.executed
1173 a = SCons.Action.CommandAction(["xyzzy"])
1174 e = Environment(SPAWN = func, SHELL = 'fake shell')
1176 assert t.executed == [ 'xyzzy' ], t.executed
1177 assert t.shell == 'fake shell', t.shell
1179 a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ])
1180 e = Environment(SPAWN = func, ESCAPE = escape_func)
1182 assert t.executed == [ '**xyzzy**' ], t.executed
1184 def test_get_contents(self):
1185 """Test fetching the contents of a command Action
1187 def CmdGen(target, source, env, for_signature):
1188 assert for_signature
1190 (env["foo"], env["bar"])
1192 # The number 1 is there to make sure all args get converted to strings.
1193 a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$bar",
1194 "$)", "|", "$baz", 1])
1195 c = a.get_contents(target=[], source=[],
1196 env=Environment(foo = 'FFF', bar = 'BBB',
1198 assert c == "| | FFF BBB 1", c
1200 # Make sure that CommandActions use an Environment's
1201 # subst_target_source() method for substitution.
1202 class SpecialEnvironment(Environment):
1203 def subst_target_source(self, strSubst, raw=0, target=[], source=[]):
1204 return 'subst_target_source: ' + strSubst
1206 c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'),
1207 env=SpecialEnvironment(foo = 'GGG', bar = 'CCC',
1209 assert c == 'subst_target_source: | $( $foo | $bar $) | $baz 1', c
1211 # We've discussed using the real target and source names in a
1212 # CommandAction's signature contents. This would have have the
1213 # advantage of recompiling when a file's name changes (keeping
1214 # debug info current), but it would currently break repository
1215 # logic that will change the file name based on whether the
1216 # files come from a repository or locally. If we ever move to
1217 # that scheme, then all of the '__t1__' and '__s6__' file names
1218 # in the asserts below would change to 't1' and 's6' and the
1220 t = map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])
1221 s = map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])
1224 a = SCons.Action.CommandAction(["$TARGET"])
1225 c = a.get_contents(target=t, source=s, env=env)
1228 a = SCons.Action.CommandAction(["$TARGETS"])
1229 c = a.get_contents(target=t, source=s, env=env)
1230 assert c == "t1 t2 t3 t4 t5 t6", c
1232 a = SCons.Action.CommandAction(["${TARGETS[2]}"])
1233 c = a.get_contents(target=t, source=s, env=env)
1236 a = SCons.Action.CommandAction(["${TARGETS[3:5]}"])
1237 c = a.get_contents(target=t, source=s, env=env)
1238 assert c == "t4 t5", c
1240 a = SCons.Action.CommandAction(["$SOURCE"])
1241 c = a.get_contents(target=t, source=s, env=env)
1244 a = SCons.Action.CommandAction(["$SOURCES"])
1245 c = a.get_contents(target=t, source=s, env=env)
1246 assert c == "s1 s2 s3 s4 s5 s6", c
1248 a = SCons.Action.CommandAction(["${SOURCES[2]}"])
1249 c = a.get_contents(target=t, source=s, env=env)
1252 a = SCons.Action.CommandAction(["${SOURCES[3:5]}"])
1253 c = a.get_contents(target=t, source=s, env=env)
1254 assert c == "s4 s5", c
1256 class CommandGeneratorActionTestCase(unittest.TestCase):
1258 def test___init__(self):
1259 """Test creation of a command generator Action
1261 def f(target, source, env):
1263 a = SCons.Action.CommandGeneratorAction(f)
1264 assert a.generator == f
1266 def test___str__(self):
1267 """Test the pre-substitution strings for command generator Actions
1269 def f(target, source, env, for_signature, self=self):
1271 # See if "env" is really a construction environment (or
1272 # looks like one) by accessing the FindIxes attribute.
1273 # (The Tool/mingw.py module has a generator that uses this,
1274 # and the __str__() method used to cause problems by passing
1275 # us a regular dictionary as a fallback.)
1279 a = SCons.Action.CommandGeneratorAction(f)
1281 assert s == 'FOO', s
1283 def test_genstring(self):
1284 """Test the command generator Action genstring() method
1286 def f(target, source, env, for_signature, self=self):
1287 dummy = env['dummy']
1289 return "$FOO $TARGET $SOURCE $TARGETS $SOURCES"
1290 a = SCons.Action.CommandGeneratorAction(f)
1292 s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1))
1293 assert self.dummy == 1, self.dummy
1294 assert s == "$FOO $TARGET $SOURCE $TARGETS $SOURCES", s
1296 def test_execute(self):
1297 """Test executing a command generator Action
1300 def f(target, source, env, for_signature, self=self):
1301 dummy = env['dummy']
1303 s = env.subst("$FOO")
1304 assert s == 'foo baz\nbar ack', s
1306 def func_action(target, source, env, self=self):
1308 s = env.subst('$foo')
1309 assert s == 'bar', s
1311 def f2(target, source, env, for_signature, f=func_action):
1313 def ch(sh, escape, cmd, args, env, self=self):
1314 self.cmd.append(cmd)
1315 self.args.append(args)
1317 a = SCons.Action.CommandGeneratorAction(f)
1321 a([], [], env=Environment(FOO = 'foo baz\nbar ack',
1324 assert self.dummy == 1, self.dummy
1325 assert self.cmd == ['foo', 'bar'], self.cmd
1326 assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args
1328 b = SCons.Action.CommandGeneratorAction(f2)
1330 b(target=[], source=[], env=Environment(foo = 'bar',
1332 assert self.dummy==2, self.dummy
1336 def __init__(self, t):
1339 self.t.rfile_called = 1
1341 def get_subst_proxy(self):
1343 def f3(target, source, env, for_signature):
1345 c = SCons.Action.CommandGeneratorAction(f3)
1346 c(target=[], source=DummyFile(self), env=Environment())
1347 assert self.rfile_called
1349 def test_get_contents(self):
1350 """Test fetching the contents of a command generator Action
1352 def f(target, source, env, for_signature):
1355 assert for_signature, for_signature
1356 return [["guux", foo, "$(", "$ignore", "$)", bar,
1357 '${test("$( foo $bar $)")}' ]]
1360 assert mystr == "$( foo $bar $)", mystr
1363 env = Environment(foo = 'FFF', bar = 'BBB',
1364 ignore = 'foo', test=test)
1365 a = SCons.Action.CommandGeneratorAction(f)
1366 c = a.get_contents(target=[], source=[], env=env)
1367 assert c == "guux FFF BBB test", c
1370 class FunctionActionTestCase(unittest.TestCase):
1372 def test___init__(self):
1373 """Test creation of a function Action
1384 a = SCons.Action.FunctionAction(func1)
1385 assert a.execfunction == func1, a.execfunction
1386 assert isinstance(a.strfunction, types.MethodType), type(a.strfunction)
1388 a = SCons.Action.FunctionAction(func2, strfunction=func3)
1389 assert a.execfunction == func2, a.execfunction
1390 assert a.strfunction == func3, a.strfunction
1392 def test_cmdstr_bad(self):
1393 """Test handling of bad FunctionAction(cmdstr) arguments
1398 a = SCons.Action.FunctionAction(func, [])
1399 except SCons.Errors.UserError, e:
1401 m = 'Invalid function display variable'
1402 assert string.find(s, m) != -1, 'Unexpected string: %s' % s
1404 raise "did not catch expected UserError"
1406 def test___str__(self):
1407 """Test the __str__() method for function Actions
1411 a = SCons.Action.FunctionAction(func1)
1413 assert s == "func1(target, source, env)", s
1418 a = SCons.Action.FunctionAction(class1())
1420 assert s == "class1(target, source, env)", s
1422 def test_execute(self):
1423 """Test executing a function Action
1426 def f(target, source, env):
1431 assert env.subst("$BAR") == 'foo bar', env.subst("$BAR")
1433 a = SCons.Action.FunctionAction(f)
1434 a(target=1, source=2, env=Environment(BAR = 'foo bar',
1436 assert self.inc == 1, self.inc
1437 assert self.source == [2], self.source
1438 assert self.target == [1], self.target
1442 def function1(target, source, env):
1446 open(t, 'w').write("function1\n")
1449 act = SCons.Action.FunctionAction(function1)
1450 r = act(target = [outfile, outfile2], source=[], env=Environment())
1451 assert r.status == 1, r.status
1453 assert count == 1, count
1454 c = test.read(outfile, 'r')
1455 assert c == "function1\n", c
1456 c = test.read(outfile2, 'r')
1457 assert c == "function1\n", c
1460 def __init__(self, target, source, env):
1461 open(env['out'], 'w').write("class1a\n")
1463 act = SCons.Action.FunctionAction(class1a)
1464 r = act([], [], Environment(out = outfile))
1465 assert isinstance(r.status, class1a), r.status
1466 c = test.read(outfile, 'r')
1467 assert c == "class1a\n", c
1470 def __call__(self, target, source, env):
1471 open(env['out'], 'w').write("class1b\n")
1474 act = SCons.Action.FunctionAction(class1b())
1475 r = act([], [], Environment(out = outfile))
1476 assert r.status == 2, r.status
1477 c = test.read(outfile, 'r')
1478 assert c == "class1b\n", c
1480 def build_it(target, source, env, self=self):
1483 def string_it(target, source, env, self=self):
1486 act = SCons.Action.FunctionAction(build_it, strfunction=string_it)
1487 r = act([], [], Environment())
1489 assert self.build_it
1490 assert self.string_it
1492 def test_get_contents(self):
1493 """Test fetching the contents of a function Action
1500 "0,0,0,0,(),(),(d\000\000S),(),()",
1501 "0,0,0,0,(),(),(d\x00\x00S),(),()",
1505 "1,1,0,0,(),(),(d\000\000S),(),()",
1506 "1,1,0,0,(),(),(d\x00\x00S),(),()",
1509 a = SCons.Action.FunctionAction(GlobalFunc)
1510 c = a.get_contents(target=[], source=[], env=Environment())
1511 assert c in func_matches, repr(c)
1513 a = SCons.Action.FunctionAction(LocalFunc)
1514 c = a.get_contents(target=[], source=[], env=Environment())
1515 assert c in func_matches, repr(c)
1517 a = SCons.Action.FunctionAction(GlobalFunc, varlist=['XYZ'])
1519 matches_foo = map(lambda x: x + "foo", func_matches)
1521 c = a.get_contents(target=[], source=[], env=Environment())
1522 assert c in func_matches, repr(c)
1523 c = a.get_contents(target=[], source=[], env=Environment(XYZ = 'foo'))
1524 assert c in matches_foo, repr(c)
1526 # Make sure a bare string varlist works
1527 a = SCons.Action.FunctionAction(GlobalFunc, varlist='XYZ')
1529 matches_foo = map(lambda x: x + "foo", func_matches)
1531 c = a.get_contents(target=[], source=[], env=Environment())
1532 assert c in func_matches, repr(c)
1533 c = a.get_contents(target=[], source=[], env=Environment(XYZ = 'foo'))
1534 assert c in matches_foo, repr(c)
1537 def get_contents(self, target, source, env):
1539 a = SCons.Action.FunctionAction(Foo())
1540 c = a.get_contents(target=[], source=[], env=Environment())
1541 assert c == 'xyzzy', repr(c)
1544 def LocalMethod(self):
1547 a = SCons.Action.FunctionAction(lc.LocalMethod)
1548 c = a.get_contents(target=[], source=[], env=Environment())
1549 assert c in meth_matches, repr(c)
1551 def test_strfunction(self):
1552 """Test the FunctionAction.strfunction() method
1557 a = SCons.Action.FunctionAction(func)
1558 s = a.strfunction(target=[], source=[], env=Environment())
1559 assert s == 'func([], [])', s
1561 a = SCons.Action.FunctionAction(func, None)
1562 s = a.strfunction(target=[], source=[], env=Environment())
1565 a = SCons.Action.FunctionAction(func, 'function')
1566 s = a.strfunction(target=[], source=[], env=Environment())
1567 assert s == 'function', s
1569 class ListActionTestCase(unittest.TestCase):
1571 def test___init__(self):
1572 """Test creation of a list of subsidiary Actions
1576 a = SCons.Action.ListAction(["x", func, ["y", "z"]])
1577 assert isinstance(a.list[0], SCons.Action.CommandAction)
1578 assert isinstance(a.list[1], SCons.Action.FunctionAction)
1579 assert isinstance(a.list[2], SCons.Action.ListAction)
1580 assert a.list[2].list[0].cmd_list == 'y'
1582 def test___str__(self):
1583 """Test the __str__() method for a list of subsidiary Actions
1585 def f(target,source,env):
1587 def g(target,source,env):
1589 a = SCons.Action.ListAction([f, g, "XXX", f])
1591 assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s
1593 def test_genstring(self):
1594 """Test the genstring() method for a list of subsidiary Actions
1596 def f(target,source,env):
1598 def g(target,source,env,for_signature):
1599 return 'generated %s %s' % (target[0], source[0])
1600 g = SCons.Action.Action(g, generator=1)
1601 a = SCons.Action.ListAction([f, g, "XXX", f])
1602 s = a.genstring(['foo.x'], ['bar.y'], Environment())
1603 assert s == "f(target, source, env)\ngenerated foo.x bar.y\nXXX\nf(target, source, env)", s
1605 def test_execute(self):
1606 """Test executing a list of subsidiary Actions
1609 def f(target,source,env):
1612 a = SCons.Action.ListAction([f, f, f])
1613 a([], [], Environment(s = self))
1614 assert self.inc == 3, self.inc
1616 cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile)
1618 def function2(target, source, env):
1619 open(env['out'], 'a').write("function2\n")
1623 def __call__(self, target, source, env):
1624 open(env['out'], 'a').write("class2a\n")
1628 def __init__(self, target, source, env):
1629 open(env['out'], 'a').write("class2b\n")
1630 act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b])
1631 r = act([], [], Environment(out = outfile))
1632 assert isinstance(r.status, class2b), r.status
1633 c = test.read(outfile, 'r')
1634 assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
1636 def test_get_contents(self):
1637 """Test fetching the contents of a list of subsidiary Actions
1640 def gen(target, source, env, for_signature):
1644 a = SCons.Action.ListAction(["x",
1645 SCons.Action.Action(gen, generator=1),
1647 c = a.get_contents(target=[], source=[], env=Environment(s = self))
1648 assert self.foo==1, self.foo
1649 assert c == "xyz", c
1651 class LazyActionTestCase(unittest.TestCase):
1652 def test___init__(self):
1653 """Test creation of a lazy-evaluation Action
1655 # Environment variable references should create a special type
1656 # of LazyAction that lazily evaluates the variable for whether
1657 # it's a string or something else before doing anything.
1658 a9 = SCons.Action.Action('$FOO')
1659 assert isinstance(a9, SCons.Action.LazyAction), a9
1660 assert a9.var == 'FOO', a9.var
1662 a10 = SCons.Action.Action('${FOO}')
1663 assert isinstance(a10, SCons.Action.LazyAction), a10
1664 assert a10.var == 'FOO', a10.var
1666 def test_genstring(self):
1667 """Test the lazy-evaluation Action genstring() method
1669 def f(target, source, env):
1671 a = SCons.Action.Action('$BAR')
1672 env1 = Environment(BAR=f, s=self)
1673 env2 = Environment(BAR='xxx', s=self)
1674 s = a.genstring([], [], env=env1)
1675 assert s == "f(target, source, env)", s
1676 s = a.genstring([], [], env=env2)
1677 assert s == 'xxx', s
1679 def test_execute(self):
1680 """Test executing a lazy-evaluation Action
1682 def f(target, source, env):
1686 a = SCons.Action.Action('$BAR')
1687 a([], [], env=Environment(BAR = f, s = self))
1688 assert self.test == 1, self.test
1689 cmd = r'%s %s %s lazy' % (_python_, act_py, outfile)
1690 a([], [], env=Environment(BAR = cmd, s = self))
1691 c = test.read(outfile, 'r')
1692 assert c == "act.py: 'lazy'\n", c
1694 def test_get_contents(self):
1695 """Test fetching the contents of a lazy-evaluation Action
1697 a = SCons.Action.Action("${FOO}")
1698 env = Environment(FOO = [["This", "is", "a", "test"]])
1699 c = a.get_contents(target=[], source=[], env=env)
1700 assert c == "This is a test", c
1702 class ActionCallerTestCase(unittest.TestCase):
1703 def test___init__(self):
1704 """Test creation of an ActionCaller"""
1705 ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO' : 4, 'BAR' : 5})
1706 assert ac.parent == 1, ac.parent
1707 assert ac.args == [2, 3], ac.args
1708 assert ac.kw == {'FOO' : 4, 'BAR' : 5}, ac.kw
1710 def test_get_contents(self):
1711 """Test fetching the contents of an ActionCaller"""
1723 af = SCons.Action.ActionFactory(GlobalFunc, strfunc)
1724 ac = SCons.Action.ActionCaller(af, [], {})
1725 c = ac.get_contents([], [], Environment())
1726 assert c in matches, repr(c)
1728 af = SCons.Action.ActionFactory(LocalFunc, strfunc)
1729 ac = SCons.Action.ActionCaller(af, [], {})
1730 c = ac.get_contents([], [], Environment())
1731 assert c in matches, repr(c)
1742 af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc)
1743 ac = SCons.Action.ActionCaller(af, [], {})
1744 c = ac.get_contents([], [], Environment())
1745 assert c in matches, repr(c)
1747 af = SCons.Action.ActionFactory(LocalActFunc(), strfunc)
1748 ac = SCons.Action.ActionCaller(af, [], {})
1749 c = ac.get_contents([], [], Environment())
1750 assert c in matches, repr(c)
1753 "<built-in function str>",
1757 af = SCons.Action.ActionFactory(str, strfunc)
1758 ac = SCons.Action.ActionCaller(af, [], {})
1759 c = ac.get_contents([], [], Environment())
1760 assert c == "<built-in function str>" or \
1761 c == "<type 'str'>", repr(c)
1763 def test___call__(self):
1764 """Test calling an ActionCaller"""
1766 def actfunc(a1, a2, a3, args=actfunc_args):
1767 args.extend([a1, a2, a3])
1768 def strfunc(a1, a2, a3):
1771 e = Environment(FOO = 2, BAR = 5)
1773 af = SCons.Action.ActionFactory(actfunc, strfunc)
1774 ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {})
1776 assert actfunc_args[0] is e, actfunc_args
1777 assert actfunc_args[1] == '2', actfunc_args
1778 assert actfunc_args[2] == 3, actfunc_args
1781 ac = SCons.Action.ActionCaller(af, [], {'a3' : '$__env__', 'a2' : '$BAR', 'a1' : 4})
1783 assert actfunc_args[0] == 4, actfunc_args
1784 assert actfunc_args[1] == '5', actfunc_args
1785 assert actfunc_args[2] is e, actfunc_args
1788 def test_strfunction(self):
1789 """Test calling the ActionCaller strfunction() method"""
1791 def actfunc(a1, a2, a3, a4):
1793 def strfunc(a1, a2, a3, a4, args=strfunc_args):
1794 args.extend([a1, a2, a3, a4])
1796 af = SCons.Action.ActionFactory(actfunc, strfunc)
1797 ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3, '$WS'], {})
1798 ac.strfunction([], [], Environment(FOO = 2, WS='white space'))
1799 assert strfunc_args == [1, '2', 3, 'white space'], strfunc_args
1802 d = {'a3' : 6, 'a2' : '$BAR', 'a1' : 4, 'a4' : '$WS'}
1803 ac = SCons.Action.ActionCaller(af, [], d)
1804 ac.strfunction([], [], Environment(BAR = 5, WS='w s'))
1805 assert strfunc_args == [4, '5', 6, 'w s'], strfunc_args
1807 class ActionFactoryTestCase(unittest.TestCase):
1808 def test___init__(self):
1809 """Test creation of an ActionFactory"""
1814 ac = SCons.Action.ActionFactory(actfunc, strfunc)
1815 assert ac.actfunc is actfunc, ac.actfunc
1816 assert ac.strfunc is strfunc, ac.strfunc
1818 def test___call__(self):
1819 """Test calling whatever's returned from an ActionFactory"""
1822 def actfunc(a1, a2, a3, args=actfunc_args):
1823 args.extend([a1, a2, a3])
1824 def strfunc(a1, a2, a3, args=strfunc_args):
1825 args.extend([a1, a2, a3])
1826 af = SCons.Action.ActionFactory(actfunc, strfunc)
1827 af(3, 6, 9)([], [], Environment())
1828 assert actfunc_args == [3, 6, 9], actfunc_args
1829 assert strfunc_args == [3, 6, 9], strfunc_args
1832 class ActionCompareTestCase(unittest.TestCase):
1834 def test_1_solo_name(self):
1835 """Test Lazy Cmd Generator Action get_name alone.
1837 Basically ensures we can locate the builder, comparing it to
1838 itself along the way."""
1839 bar = SCons.Builder.Builder(action = {})
1840 env = Environment( BUILDERS = {'BAR' : bar} )
1841 name = bar.get_name(env)
1842 assert name == 'BAR', name
1844 def test_2_multi_name(self):
1845 """Test LazyCmdGenerator Action get_name multi builders.
1847 Ensure that we can compare builders (and thereby actions) to
1848 each other safely."""
1849 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1850 bar = SCons.Builder.Builder(action = {})
1852 assert foo.action != bar.action
1853 env = Environment( BUILDERS = {'FOO' : foo,
1855 name = foo.get_name(env)
1856 assert name == 'FOO', name
1857 name = bar.get_name(env)
1858 assert name == 'BAR', name
1860 def test_3_dict_names(self):
1861 """Test Action/Suffix dicts with get_name.
1863 Verifies that Action/Suffix dictionaries work correctly,
1864 especially two builders that can generate the same suffix,
1865 where one of the builders has a suffix dictionary with a None
1868 foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo')
1869 bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'})
1870 bar.add_action('.cow', "$MOO")
1871 dog = SCons.Builder.Builder(suffix = '.bar')
1873 env = Environment( BUILDERS = {'FOO' : foo,
1877 assert foo.get_name(env) == 'FOO', foo.get_name(env)
1878 assert bar.get_name(env) == 'BAR', bar.get_name(env)
1879 assert dog.get_name(env) == 'DOG', dog.get_name(env)
1882 if __name__ == "__main__":
1883 suite = unittest.TestSuite()
1884 tclasses = [ ActionTestCase,
1886 _ActionActionTestCase,
1887 CommandActionTestCase,
1888 CommandGeneratorActionTestCase,
1889 FunctionActionTestCase,
1892 ActionCallerTestCase,
1893 ActionFactoryTestCase,
1894 ActionCompareTestCase ]
1895 for tclass in tclasses:
1896 names = unittest.getTestCaseNames(tclass, 'test_')
1897 suite.addTests(map(tclass, names))
1898 if not unittest.TextTestRunner().run(suite).wasSuccessful():