summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Actions/function.py192
-rw-r--r--test/CPPDEFINES/basic.py64
-rw-r--r--test/CPPDEFINES/live.py (renamed from test/CPPDEFINES.py)45
-rw-r--r--test/CPPDEFINES/scan.py181
-rw-r--r--test/CPPDEFINES/undefined.py45
-rw-r--r--test/CPPPATH/absolute-path.py75
-rw-r--r--test/CPPPATH/function-expansion.py137
-rw-r--r--test/CPPPATH/list-expansion.py132
-rw-r--r--test/Configure/Builder-call.py4
-rw-r--r--test/D/DMD.py (renamed from test/DMD.py)0
-rw-r--r--test/D/Scanner.py144
-rw-r--r--test/Errors/SyntaxError.py4
-rw-r--r--test/Errors/execute-a-directory.py109
-rw-r--r--test/Errors/non-executable-file.py103
-rw-r--r--test/Errors/nonexistent-executable.py107
-rw-r--r--test/Errors/permission-denied.py64
-rw-r--r--test/Install/option--install-sandbox.py9
-rw-r--r--test/Interactive/Alias.py85
-rw-r--r--test/Interactive/Default-None.py96
-rw-r--r--test/Interactive/Default.py86
-rw-r--r--test/Interactive/added-include.py118
-rw-r--r--test/Interactive/basic.py84
-rw-r--r--test/Interactive/cache-debug.py117
-rw-r--r--test/Interactive/cache-disable.py115
-rw-r--r--test/Interactive/cache-force.py113
-rw-r--r--test/Interactive/cache-show.py115
-rw-r--r--test/Interactive/clean.py105
-rw-r--r--test/Interactive/exit.py64
-rw-r--r--test/Interactive/help.py85
-rw-r--r--test/Interactive/implicit-BuildDir.py142
-rw-r--r--test/Interactive/option--Q.py83
-rw-r--r--test/Interactive/option-i.py106
-rw-r--r--test/Interactive/option-j.py164
-rw-r--r--test/Interactive/option-k.py108
-rw-r--r--test/Interactive/option-n.py79
-rw-r--r--test/Interactive/option-s.py79
-rw-r--r--test/Interactive/repeat-line.py87
-rw-r--r--test/Interactive/shell.py116
-rw-r--r--test/Interactive/taskmastertrace.py90
-rw-r--r--test/Interactive/tree.py91
-rw-r--r--test/Interactive/unknown-command.py66
-rw-r--r--test/Interactive/version.py84
-rw-r--r--test/Java/JAR.py20
-rw-r--r--test/Java/JARCHDIR.py17
-rw-r--r--test/Java/JARFLAGS.py23
-rw-r--r--test/Java/JAVABOOTCLASSPATH.py17
-rw-r--r--test/Java/JAVACFLAGS.py9
-rw-r--r--test/Java/JAVACLASSPATH.py17
-rw-r--r--test/Java/JAVAH.py25
-rw-r--r--test/Java/JAVASOURCEPATH.py9
-rw-r--r--test/Java/Java-1.4.py33
-rw-r--r--test/Java/Java-1.5.py16
-rw-r--r--test/Java/Java-1.6.py16
-rw-r--r--test/Java/RMIC.py40
-rw-r--r--test/Java/RMICCOM.py6
-rw-r--r--test/Java/RMICCOMSTR.py6
-rw-r--r--test/Java/multi-step.py18
-rw-r--r--test/Java/no-JARCHDIR.py122
-rw-r--r--test/Java/source-files.py9
-rw-r--r--test/Java/swig-dependencies.py29
-rw-r--r--test/Libs/LIBPATH.py (renamed from test/LIBPATH.py)0
-rw-r--r--test/Libs/LIBPREFIX.py (renamed from test/LIBPREFIX.py)0
-rw-r--r--test/Libs/LIBPREFIXES.py (renamed from test/LIBPREFIXES.py)0
-rw-r--r--test/Libs/LIBS.py (renamed from test/LIBS.py)0
-rw-r--r--test/Libs/LIBSUFFIX.py (renamed from test/LIBSUFFIX.py)0
-rw-r--r--test/Libs/LIBSUFFIXES.py (renamed from test/LIBSUFFIXES.py)0
-rw-r--r--test/Libs/Library.py (renamed from test/Library.py)0
-rw-r--r--test/Libs/SHLIBPREFIX.py (renamed from test/SHLIBPREFIX.py)0
-rw-r--r--test/Libs/SHLIBSUFFIX.py (renamed from test/SHLIBSUFFIX.py)0
-rw-r--r--test/Libs/SharedLibrary.py (renamed from test/SharedLibrary.py)0
-rw-r--r--test/Libs/SharedLibraryIxes.py261
-rw-r--r--test/LoadableModule.py3
-rw-r--r--test/MSVC/pdb-manifest.py81
-rw-r--r--test/QT/moc-from-header.py4
-rw-r--r--test/QT/warnings.py7
-rw-r--r--test/Repository/Java.py16
-rw-r--r--test/Repository/JavaH.py22
-rw-r--r--test/Repository/LIBPATH.py7
-rw-r--r--test/Repository/RMIC.py88
-rw-r--r--test/SWIG/module-parens.py102
-rw-r--r--test/Scanner/generated.py8
-rw-r--r--test/TEX/build_dir_dup0.py257
-rw-r--r--test/TEX/multi-run.py88
-rw-r--r--test/YACC/live.py10
-rw-r--r--test/build-errors.py223
-rw-r--r--test/builderrors.py16
-rw-r--r--test/import.py1
-rw-r--r--test/option-k.py168
-rw-r--r--test/option/debug-includes.py9
-rw-r--r--test/option/debug-memoizer.py32
-rw-r--r--test/option/stack-size.py357
-rw-r--r--test/scons-time/func/file.py27
-rw-r--r--test/scons-time/mem/file.py9
-rw-r--r--test/scons-time/obj/file.py9
-rw-r--r--test/scons-time/run/aegis.py17
-rw-r--r--test/scons-time/run/config/archive_list.py6
-rw-r--r--test/scons-time/run/option/quiet.py21
-rw-r--r--test/scons-time/run/option/verbose.py21
-rw-r--r--test/scons-time/run/subversion.py17
-rw-r--r--test/scons-time/time/empty.py91
-rw-r--r--test/scons-time/time/file.py9
-rw-r--r--test/scons-time/time/no-result.py75
-rw-r--r--test/subclassing.py37
-rw-r--r--test/timestamp-fallback.py9
104 files changed, 5734 insertions, 699 deletions
diff --git a/test/Actions/function.py b/test/Actions/function.py
new file mode 100644
index 0000000..00aa688
--- /dev/null
+++ b/test/Actions/function.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+#
+# Test that the signature of function action includes all the
+# necessary pieces.
+#
+
+test.write('SConstruct', r"""
+import re
+
+import SCons.Action
+import SCons.Builder
+
+options = Options()
+options.AddOptions(
+ ('header', 'Header string (default cell argument)', 'Head:'),
+ ('trailer', 'Trailer string (default cell argument)', 'Tail'),
+ ('NbDeps', 'Number of dependencies', '2'),
+ ('separator', 'Separator for the dependencies (function constant)', ':'),
+ ('closure_cell_value', 'Value of a closure cell', '25'),
+ ('b', 'Value of b (value default argument', '7'),
+ ('regexp', 'Regexp (object as a default argument', 'a(a*)'),
+ ('docstring', 'Docstring', 'docstring'),
+ ('extracode', 'Extra code for the builder function', ''),
+ ('extraarg', 'Extra arg builder function', ''),
+ ('nestedfuncexp', 'Expression for the nested function', 'xxx - b'),
+)
+
+optEnv = Environment(options=options, tools=[])
+
+r = re.compile(optEnv['regexp'])
+
+toto = \
+r'''
+def toto(header='%(header)s', trailer='%(trailer)s'):
+ xxx = %(closure_cell_value)s
+ def writeDeps(target, source, env, b=%(b)s, r=r %(extraarg)s ,
+ header=header, trailer=trailer, xxx=xxx):
+ """+'"""%(docstring)s"""'+"""
+ def foo(b=b, xxx=xxx):
+ return %(nestedfuncexp)s
+ f = open(str(target[0]),'wb')
+ f.write(header)
+ for d in env['ENVDEPS']:
+ f.write(d+'%(separator)s')
+ f.write(trailer+'\\n')
+ f.write(str(foo())+'\\n')
+ f.write(r.match('aaaa').group(1)+'\\n')
+ %(extracode)s
+ try:
+ f.write(str(xarg)+'\\n')
+ except NameError:
+ pass
+ f.close()
+
+ return writeDeps
+'''
+
+exec( toto % optEnv )
+
+genHeaderBld = SCons.Builder.Builder(
+ action = SCons.Action.Action(
+ toto(),
+ 'Generating $TARGET',
+ varlist=['ENVDEPS']
+ ),
+ suffix = '.gen.h'
+ )
+
+env = Environment()
+env.Append(BUILDERS = {'GenHeader' : genHeaderBld})
+
+envdeps = map(str, range(int(optEnv['NbDeps'])))
+
+env.GenHeader('Out', None, ENVDEPS=envdeps)
+""")
+
+
+rebuildstr = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+Generating Out.gen.h
+scons: done building targets.
+"""
+
+nobuildstr = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+scons: `.' is up to date.
+scons: done building targets.
+"""
+
+def runtest( arguments, expectedOutFile, expectedRebuild=True):
+ test.run(arguments=arguments,
+ stdout=expectedRebuild and rebuildstr or nobuildstr)
+ test.must_match('Out.gen.h', expectedOutFile)
+
+ # Should not be rebuild when ran a second time with the same
+ # arguments.
+
+ test.run(arguments = arguments, stdout=nobuildstr)
+ test.must_match('Out.gen.h', expectedOutFile)
+
+
+# Original build.
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing a docstring should not cause a rebuild
+runtest('docstring=ThisBuilderDoesXAndY', """Head:0:1:Tail\n18\naaa\n""", False)
+runtest('docstring=SuperBuilder', """Head:0:1:Tail\n18\naaa\n""", False)
+runtest('docstring=', """Head:0:1:Tail\n18\naaa\n""", False)
+
+# Changing a variable listed in the varlist should cause a rebuild
+runtest('NbDeps=3', """Head:0:1:2:Tail\n18\naaa\n""")
+runtest('NbDeps=4', """Head:0:1:2:3:Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the function code should cause a rebuild
+runtest('extracode=f.write("XX\\n")', """Head:0:1:Tail\n18\naaa\nXX\n""")
+runtest('extracode=a=2', """Head:0:1:Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing a constant used in the function code should cause a rebuild
+runtest('separator=,', """Head:0,1,Tail\n18\naaa\n""")
+runtest('separator=;', """Head:0;1;Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the code of a nested function should cause a rebuild
+runtest('nestedfuncexp=b-xxx', """Head:0:1:Tail\n-18\naaa\n""")
+runtest('nestedfuncexp=b+xxx', """Head:0:1:Tail\n32\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Adding an extra argument should cause a rebuild.
+runtest('extraarg=,xarg=2', """Head:0:1:Tail\n18\naaa\n2\n""")
+runtest('extraarg=,xarg=5', """Head:0:1:Tail\n18\naaa\n5\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the value of a default argument should cause a rebuild
+# case 1: a value
+runtest('b=0', """Head:0:1:Tail\n25\naaa\n""")
+runtest('b=9', """Head:0:1:Tail\n16\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# case 2: an object
+runtest('regexp=(aaaa)', """Head:0:1:Tail\n18\naaaa\n""")
+runtest('regexp=aa(a+)', """Head:0:1:Tail\n18\naa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the value of a closure cell value should cause a rebuild
+# case 1: a value
+runtest('closure_cell_value=32', """Head:0:1:Tail\n25\naaa\n""")
+runtest('closure_cell_value=7', """Head:0:1:Tail\n0\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# case 2: a default argument
+runtest('header=MyHeader:', """MyHeader:0:1:Tail\n18\naaa\n""")
+runtest('trailer=MyTrailer', """Head:0:1:MyTrailer\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+test.pass_test()
diff --git a/test/CPPDEFINES/basic.py b/test/CPPDEFINES/basic.py
new file mode 100644
index 0000000..5c302c3
--- /dev/null
+++ b/test/CPPDEFINES/basic.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify basic use of CPPPDEFINES with various data types.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+test_list = [
+ 'xyz',
+ ['x', 'y', 'z'],
+ ['x', ['y', 123], 'z', ('int', '$INTEGER')],
+ { 'c' : 3, 'b': None, 'a' : 1 },
+]
+env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0)
+for i in test_list:
+ print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
+env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1)
+for i in test_list:
+ print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
+""")
+
+expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
+ read_str = """\
+-Dxyz
+-Dx -Dy -Dz
+-Dx -Dy=123 -Dz -Dint=0
+-Da=1 -Db -Dc=3
+|xyz|
+|x| |y| |z|
+|x| |y=123| |z| |int=1|
+|a=1| |b| |c=3|
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPDEFINES.py b/test/CPPDEFINES/live.py
index c38f857..7a169e8 100644
--- a/test/CPPDEFINES.py
+++ b/test/CPPDEFINES/live.py
@@ -25,56 +25,13 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-XXX Put a description of the test here.
+Verify basic use of CPPDEFINES with live compilation.
"""
-import string
-
import TestSCons
test = TestSCons.TestSCons()
-# Make sure $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined.
-test.write('SConstruct', """\
-env = Environment()
-print env.subst('$_CPPDEFFLAGS')
-""")
-
-expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
- read_str = "\n")
-
-test.run(arguments = '.', stdout=expect)
-
-# Test CPPDEFINES as a string and a list.
-test.write('SConstruct', """\
-test_list = [
- 'xyz',
- ['x', 'y', 'z'],
- ['x', ['y', 123], 'z', ('int', '$INTEGER')],
- { 'c' : 3, 'b': None, 'a' : 1 },
-]
-env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0)
-for i in test_list:
- print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
-env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1)
-for i in test_list:
- print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
-""")
-
-expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
- read_str = """\
--Dxyz
--Dx -Dy -Dz
--Dx -Dy=123 -Dz -Dint=0
--Da=1 -Db -Dc=3
-|xyz|
-|x| |y| |z|
-|x| |y=123| |z| |int=1|
-|a=1| |b| |c=3|
-""")
-
-test.run(arguments = '.', stdout=expect)
-
test.write('SConstruct', """\
foo = Environment(CPPDEFINES = ['FOO', ('VAL', '$VALUE')], VALUE=7)
bar = Environment(CPPDEFINES = {'BAR':None, 'VAL':8})
diff --git a/test/CPPDEFINES/scan.py b/test/CPPDEFINES/scan.py
new file mode 100644
index 0000000..c9b60c3
--- /dev/null
+++ b/test/CPPDEFINES/scan.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that use of the Scanner that evaluates CPP lines works as expected.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+m = 'Scanner evaluation of CPP lines not yet supported; skipping test.\n'
+test.skip_test(m)
+
+f1_exe = 'f1' + TestSCons._exe
+f2_exe = 'f2' + TestSCons._exe
+f3_exe = 'f3' + TestSCons._exe
+f4_exe = 'f4' + TestSCons._exe
+
+test.write('SConstruct', """\
+env = Environment(CPPPATH = ['.'])
+
+f1 = env.Object('f1', 'fff.c', CPPDEFINES = ['F1'])
+f2 = env.Object('f2', 'fff.c', CPPDEFINES = [('F2', 1)])
+f3 = env.Object('f3', 'fff.c', CPPDEFINES = {'F3':None})
+f4 = env.Object('f4', 'fff.c', CPPDEFINES = {'F4':1})
+
+env.Program('f1', ['prog.c', f1])
+env.Program('f2', ['prog.c', f2])
+env.Program('f3', ['prog.c', f3])
+env.Program('f4', ['prog.c', f4])
+""")
+
+test.write('f1.h', """
+#define STRING "F1"
+""")
+
+test.write('f2.h', """
+#define STRING "F2"
+""")
+
+test.write('f3.h', """
+#define STRING "F3"
+""")
+
+test.write('f4.h', """
+#define STRING "F4"
+""")
+
+test.write('fff.c', """
+#ifdef F1
+#include <f1.h>
+#endif
+#if F2
+#include <f2.h>
+#endif
+#ifdef F3
+#include <f3.h>
+#endif
+#ifdef F4
+#include <f4.h>
+#endif
+
+char *
+foo(void)
+{
+ return (STRING);
+}
+""")
+
+
+test.write('prog.c', r"""
+#include <stdio.h>
+#include <stdlib.h>
+
+extern char *foo(void);
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("prog.c: %s\n", foo());
+ exit (0);
+}
+""")
+
+
+
+test.run(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f1.h', """
+#define STRING "F1 again"
+""")
+
+test.up_to_date(arguments = '%(f2_exe)s %(f3_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f2.h', """
+#define STRING "F2 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f3_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f3.h', """
+#define STRING "F3 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f4.h', """
+#define STRING "F4 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f3_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4 again\n")
+
+
+
+test.pass_test()
diff --git a/test/CPPDEFINES/undefined.py b/test/CPPDEFINES/undefined.py
new file mode 100644
index 0000000..b6b8b44
--- /dev/null
+++ b/test/CPPDEFINES/undefined.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+print env.subst('$_CPPDEFFLAGS')
+""")
+
+expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
+ read_str = "\n")
+
+test.run(arguments = '.', stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPPATH/absolute-path.py b/test/CPPPATH/absolute-path.py
new file mode 100644
index 0000000..9adb206
--- /dev/null
+++ b/test/CPPPATH/absolute-path.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the ability to #include a file with an absolute path name. (Which
+is not strictly a test of using $CPPPATH, but it's in the ball park...)
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('include', 'work')
+
+inc_h = test.workpath('include', 'inc.h')
+does_not_exist_h = test.workpath('include', 'does_not_exist.h')
+
+test.write(['work', 'SConstruct'], """\
+Program('prog.c')
+""")
+
+test.write(['work', 'prog.c'], """\
+#include <stdio.h>
+#include "%(inc_h)s"
+#if 0
+#include "%(does_not_exist_h)s"
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("%%s\\n", STRING);
+ return 0;
+}
+""" % locals())
+
+test.write(['include', 'inc.h'], """\
+#define STRING "include/inc.h 1\\n"
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+test.write(['include', 'inc.h'], """\
+#define STRING "include/inc.h 2\\n"
+""")
+
+test.not_up_to_date(chdir = 'work', arguments = '.')
+
+test.pass_test()
diff --git a/test/CPPPATH/function-expansion.py b/test/CPPPATH/function-expansion.py
new file mode 100644
index 0000000..7c80f22
--- /dev/null
+++ b/test/CPPPATH/function-expansion.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that expansion of construction variables whose values are functions
+(that return lists that contain Nodes, even) works as expected within
+a $CPPPATH list definition.
+
+This used to cause TypeErrors when the _concat expansion tried to
+join the Nodes with the strings.
+
+Test courtesy Konstantin Bozhikov.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('list_inc1',
+ 'list_inc2',
+ 'inc1',
+ 'inc2',
+ 'inc3',
+ ['inc3', 'subdir'])
+
+test.write('SConstruct', """\
+env = Environment()
+def my_cpppaths( target, source, env, for_signature ):
+ return [ Dir('list_inc1'), Dir('list_inc2') ]
+
+env = Environment( CPPPATH = [Dir('inc1'), '$INC2', '$INC3/subdir', '$MY_CPPPATHS' ],
+ INC2 = Dir('inc2'),
+ INC3 = Dir('inc3'),
+ MY_CPPPATHS = my_cpppaths )
+
+env.Program('prog.c')
+""")
+
+test.write('prog.c', """\
+#include <stdio.h>
+#include <stdlib.h>
+#include "string_list_1.h"
+#include "string_list_2.h"
+#include "string_1.h"
+#include "string_2.h"
+#include "string_3.h"
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("prog.c\\n");
+ printf("%s\\n", STRING_LIST_1);
+ printf("%s\\n", STRING_LIST_2);
+ printf("%s\\n", STRING_1);
+ printf("%s\\n", STRING_2);
+ printf("%s\\n", STRING_3);
+ exit (0);
+}
+""")
+
+test.write(['list_inc1', 'string_list_1.h'], """\
+#define STRING_LIST_1 "list_inc1/string_list_1.h"
+""")
+
+test.write(['list_inc2', 'string_list_2.h'], """\
+#define STRING_LIST_2 "list_inc2/string_list_2.h"
+""")
+
+test.write(['inc1', 'string_1.h'], """\
+#define STRING_1 "inc1/string_1.h"
+""")
+
+test.write(['inc2', 'string_2.h'], """\
+#define STRING_2 "inc2/string_2.h"
+""")
+
+test.write(['inc3', 'subdir', 'string_3.h'], """\
+#define STRING_3 "inc3/subdir/string_3.h"
+""")
+
+test.run()
+
+test.up_to_date(arguments = '.')
+
+expect = """\
+prog.c
+list_inc1/string_list_1.h
+list_inc2/string_list_2.h
+inc1/string_1.h
+inc2/string_2.h
+inc3/subdir/string_3.h
+"""
+
+test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect)
+
+test.write(['inc3', 'subdir', 'string_3.h'], """\
+#define STRING_3 "inc3/subdir/string_3.h 2"
+""")
+
+test.not_up_to_date(arguments = '.')
+
+expect = """\
+prog.c
+list_inc1/string_list_1.h
+list_inc2/string_list_2.h
+inc1/string_1.h
+inc2/string_2.h
+inc3/subdir/string_3.h 2
+"""
+
+test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPPATH/list-expansion.py b/test/CPPPATH/list-expansion.py
new file mode 100644
index 0000000..7e5326f
--- /dev/null
+++ b/test/CPPPATH/list-expansion.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that expansion of construction variables whose values are
+lists works as expected within a $CPPPATH list definition.
+
+Previously, the stringification of the expansion of the individual
+variables would turn a list like ['sub1', 'sub2'] below into "-Isub1 sub2"
+on the command line.
+
+Test case courtesy Daniel Svensson.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('sub1', 'sub2', 'sub3', 'sub4')
+
+test.write('SConstruct', """\
+class _inc_test:
+ def __init__(self, name):
+ self.name = name
+
+ def __call__(self, target, source, env, for_signature):
+ return env.something[self.name]
+
+env = Environment()
+
+env.something = {}
+env.something['test'] = ['sub1', 'sub2']
+
+env['INC_PATHS1'] = _inc_test
+
+env['INC_PATHS2'] = ['sub3', 'sub4']
+
+env.Append(CPPPATH = ['${INC_PATHS1("test")}', '$INC_PATHS2'])
+env.Program('test', 'test.c')
+""")
+
+test.write('test.c', """\
+#include <stdio.h>
+#include <stdlib.h>
+#include "string1.h"
+#include "string2.h"
+#include "string3.h"
+#include "string4.h"
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("test.c\\n");
+ printf("%s\\n", STRING1);
+ printf("%s\\n", STRING2);
+ printf("%s\\n", STRING3);
+ printf("%s\\n", STRING4);
+ exit (0);
+}
+""")
+
+test.write(['sub1', 'string1.h'], """\
+#define STRING1 "sub1/string1.h"
+""")
+
+test.write(['sub2', 'string2.h'], """\
+#define STRING2 "sub2/string2.h"
+""")
+
+test.write(['sub3', 'string3.h'], """\
+#define STRING3 "sub3/string3.h"
+""")
+
+test.write(['sub4', 'string4.h'], """\
+#define STRING4 "sub4/string4.h"
+""")
+
+test.run()
+
+test.up_to_date(arguments = '.')
+
+expect = """\
+test.c
+sub1/string1.h
+sub2/string2.h
+sub3/string3.h
+sub4/string4.h
+"""
+
+test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect)
+
+test.write(['sub2', 'string2.h'], """\
+#define STRING2 "sub2/string2.h 2"
+""")
+
+test.not_up_to_date(arguments = '.')
+
+expect = """\
+test.c
+sub1/string1.h
+sub2/string2.h 2
+sub3/string3.h
+sub4/string4.h
+"""
+
+test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect)
+
+test.pass_test()
diff --git a/test/Configure/Builder-call.py b/test/Configure/Builder-call.py
index a6f2fa5..1ce114c 100644
--- a/test/Configure/Builder-call.py
+++ b/test/Configure/Builder-call.py
@@ -35,7 +35,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-test.write('cmd.py', r"""
+test.write('mycommand.py', r"""
import sys
sys.stderr.write( 'Hello World on stderr\n' )
sys.stdout.write( 'Hello World on stdout\n' )
@@ -48,7 +48,7 @@ def CustomTest(*args):
return 0
conf = env.Configure(custom_tests = {'MyTest' : CustomTest})
if not conf.MyTest():
- env.Command("hello", [], '%(_python_)s cmd.py $TARGET')
+ env.Command("hello", [], '%(_python_)s mycommand.py $TARGET')
env = conf.Finish()
""" % locals())
diff --git a/test/DMD.py b/test/D/DMD.py
index 8b443f8..8b443f8 100644
--- a/test/DMD.py
+++ b/test/D/DMD.py
diff --git a/test/D/Scanner.py b/test/D/Scanner.py
new file mode 100644
index 0000000..5c69820
--- /dev/null
+++ b/test/D/Scanner.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the D scanner can return multiple modules imported by
+a single statement.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_obj = TestSCons._obj
+
+dmd = test.where_is('dmd')
+if not dmd:
+ test.skip_test("Could not find 'dmd'; skipping test.\n")
+
+test.subdir(['p'])
+
+test.write('SConstruct', """
+env = Environment()
+env.Program('test1.d')
+env.Program('test2.d')
+""")
+
+test.write(['test1.d'], """\
+import module1;
+import module2;
+import module3;
+import p.submodule1;
+import p.submodule2;
+
+int main() {
+ return 0;
+}
+""")
+
+test.write(['test2.d'], """\
+import
+ module1,
+ module2,
+ module3;
+import
+ p.submodule1,
+ p.submodule2;
+
+int main() {
+ return 0;
+}
+""")
+
+test.write(['ignored.d'], """\
+module ignored;
+
+int something;
+""")
+
+test.write(['module1.d'], """\
+module module1;
+
+int something;
+""")
+
+test.write(['module2.d'], """\
+module module2;
+
+int something;
+""")
+
+test.write(['module3.di'], """\
+module module3;
+
+int something;
+""")
+
+test.write(['p', 'ignored.d'], """\
+module p.ignored;
+
+int something;
+""")
+
+test.write(['p', 'submodule1.d'], """\
+module p.submodule1;
+
+int something;
+""")
+
+test.write(['p', 'submodule2.d'], """\
+module p.submodule2;
+
+int something;
+""")
+
+arguments = 'test1%(_obj)s test2%(_obj)s' % locals()
+
+test.run(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.write(['module2.d'], """\
+module module2;
+
+int something_else;
+""")
+
+test.not_up_to_date(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.write(['p', 'submodule2.d'], """\
+module p.submodule2;
+
+int something_else;
+""")
+
+test.not_up_to_date(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.pass_test()
diff --git a/test/Errors/SyntaxError.py b/test/Errors/SyntaxError.py
index b9ff1ff..956caa7 100644
--- a/test/Errors/SyntaxError.py
+++ b/test/Errors/SyntaxError.py
@@ -37,8 +37,10 @@ test.write('SConstruct', """
a ! x
""")
+# It looks like vanilla Python 2.2 is the only version that
+# puts "<string>" here in place of the file name.
test.run(stdout = "scons: Reading SConscript files ...\n",
- stderr = """ File ".+SConstruct", line 2
+ stderr = """ File "(.+SConstruct|<string>)", line 2
a ! x
diff --git a/test/Errors/execute-a-directory.py b/test/Errors/execute-a-directory.py
new file mode 100644
index 0000000..bcdcb7c
--- /dev/null
+++ b/test/Errors/execute-a-directory.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+not_executable = test.workpath("not_executable")
+
+test.write(not_executable, "\n")
+
+test.write("f3.in", "\n")
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld' : bld })
+env.bld(target = 'f3', source = 'f3.in')
+""" % string.replace(test.workdir, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1),
+ stderr = None,
+ status = 2)
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+cannot_execute = """\
+%s: cannot execute
+scons *** [%s] Error 126
+"""
+
+Permission_denied = """\
+%s: Permission denied
+scons: *** [%s] Error 126
+"""
+
+permission_denied = """\
+%s: permission denied
+scons: *** [%s] Error 126
+"""
+
+is_a_directory = """\
+%s: is a directory
+scons: *** [%s] Error 126
+"""
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (test.workdir, 'f3'),
+ unspecified % 'f3'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ cannot_execute % (not_executable, 'f3'),
+ is_a_directory % (test.workdir, 'f3'),
+ Permission_denied % (test.workdir, 'f3'),
+ Permission_denied % (test.workdir, 'f3'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/non-executable-file.py b/test/Errors/non-executable-file.py
new file mode 100644
index 0000000..d6e018b
--- /dev/null
+++ b/test/Errors/non-executable-file.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+not_executable = test.workpath("not_executable")
+
+test.write(not_executable, "\n")
+
+test.write("f1.in", "\n")
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+cannot_execute = """\
+%s: cannot execute
+scons *** [%s] Error 126
+"""
+
+Permission_denied = """\
+%s: Permission denied
+scons: *** [%s] Error 126
+"""
+
+permission_denied = """\
+%s: permission denied
+scons: *** [%s] Error 126
+"""
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld': bld })
+env.bld(target = 'f1', source = 'f1.in')
+""" % string.replace(not_executable, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f1.in f1\n" % not_executable, error=1),
+ stderr = None,
+ status = 2)
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (not_executable, 'f1'),
+ unspecified % 'f1'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ cannot_execute % (not_executable, 'f1'),
+ Permission_denied % (not_executable, 'f1'),
+ permission_denied % (not_executable, 'f1'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/nonexistent-executable.py b/test/Errors/nonexistent-executable.py
new file mode 100644
index 0000000..b2a9557
--- /dev/null
+++ b/test/Errors/nonexistent-executable.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+no_such_file = test.workpath("no_such_file")
+
+test.write("f1.in", "\n")
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld' : bld })
+env.bld(target = 'f1', source = 'f1.in')
+""" % string.replace(no_such_file, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1),
+ stderr = None,
+ status = 2)
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+not_found_1 = """
+sh: %s: not found
+scons: *** [%s] Error 1
+"""
+
+not_found_2 = """
+sh: %s: not found
+scons: *** [%s] Error 1
+"""
+
+not_found_127 = """\
+sh: %s: not found
+scons: *** [%s] Error 127
+"""
+
+No_such = """\
+%s: No such file or directory
+scons: *** [%s] Error 127
+"""
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (no_such_file, 'f1'),
+ unspecified % 'f1'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ not_found_1 % (no_such_file, 'f1'),
+ not_found_2 % (no_such_file, 'f1'),
+ not_found_127 % (no_such_file, 'f1'),
+ No_such % (no_such_file, 'f1'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/permission-denied.py b/test/Errors/permission-denied.py
new file mode 100644
index 0000000..05d1e9d
--- /dev/null
+++ b/test/Errors/permission-denied.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', r"""
+env = Environment()
+env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE'))
+env.InstallAs('test2.out', 'test.out')
+# Mark test2.out as precious so we'll handle the exception in
+# FunctionAction() rather than when the target is cleaned before building.
+env.Precious('test2.out')
+env.Default('test2.out')
+""")
+
+test.write('test.in', "test.in 1\n")
+
+test.run(arguments = '.')
+
+test.write('test.in', "test.in 2\n")
+
+test.writable('test2.out', 0)
+f = open(test.workpath('test2.out'))
+
+test.run(arguments = '.',
+ stderr = None,
+ status = 2)
+
+f.close()
+test.writable('test2.out', 1)
+
+test.description_set("Incorrect STDERR:\n%s" % test.stderr())
+errs = [
+ "scons: *** [test2.out] test2.out: Permission denied\n",
+ "scons: *** [test2.out] test2.out: permission denied\n",
+]
+test.fail_test(test.stderr() not in errs)
+
+test.pass_test()
diff --git a/test/Install/option--install-sandbox.py b/test/Install/option--install-sandbox.py
index 4cf9310..38a7915 100644
--- a/test/Install/option--install-sandbox.py
+++ b/test/Install/option--install-sandbox.py
@@ -48,9 +48,10 @@ file1_out = target+os.path.join( target, destdir, 'file1.out' )
#
test.write('SConstruct', r"""
env = Environment(SUBDIR='subdir')
-env.Install(r'%(destdir)s', 'file1.out')
-env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'],
- ['file2.in', r'%(_SUBDIR_file3_in)s'])
+f1 = env.Install(r'%(destdir)s', 'file1.out')
+f2 = env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'],
+ ['file2.in', r'%(_SUBDIR_file3_in)s'])
+env.Depends(f2, f1)
""" % locals())
test.write('file1.out', "file1.out\n")
@@ -58,9 +59,9 @@ test.write('file2.in', "file2.in\n")
test.write(['subdir', 'file3.in'], "subdir/file3.in\n")
expect = test.wrap_stdout("""\
+Install file: "file1.out" as "%(file1_out)s"
Install file: "file2.in" as "%(target_file2_out)s"
Install file: "%(subdir_file3_in)s" as "%(target_subdir_file3_out)s"
-Install file: "file1.out" as "%(file1_out)s"
""" % locals())
test.run(arguments = '--install-sandbox=%s' % destdir, stdout=expect)
diff --git a/test/Interactive/Alias.py b/test/Interactive/Alias.py
new file mode 100644
index 0000000..fc05b9a
--- /dev/null
+++ b/test/Interactive/Alias.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the ability to build an Alias in --interactive mode.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+foo = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Alias('foo-alias', foo)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo-alias\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmyn for the "build" command.
+scons.send("scons foo-alias\n")
+
+scons.send("scons 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo-alias\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo-alias' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/Default-None.py b/test/Interactive/Default-None.py
new file mode 100644
index 0000000..36ebf2f
--- /dev/null
+++ b/test/Interactive/Default-None.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we get the expected error message when we use a "build"
+command without arguments and there are no default targets (because they
+explicitly called Default(None) in the SConstruct file).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Default(None)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build\n")
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmyn for the "build" command.
+scons.send("scons\n")
+
+scons.send("scons foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build\n")
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/Default.py b/test/Interactive/Default.py
new file mode 100644
index 0000000..d6205e2
--- /dev/null
+++ b/test/Interactive/Default.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we can use a "build" command without arguments to (re-)build
+the Default() targets, without exiting the command loop.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+foo_out = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Default(foo_out)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmy for the "build" command.
+scons.send("scons\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/added-include.py b/test/Interactive/added-include.py
new file mode 100644
index 0000000..8c30314
--- /dev/null
+++ b/test/Interactive/added-include.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+This verifies the --interactive command line option's ability to
+rebuild a target when an implicit dependency (include line) is
+added to the source file.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('foo.h.in', """
+#define FOO_STRING "foo.h.in"
+""")
+
+test.write('foo.c', """
+#include <stdio.h>
+
+int main()
+{
+ printf("foo.c\\n");
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+env = Environment(CPPPATH=['.'])
+env.Command('foo.h', ['foo.h.in'], Copy('$TARGET', '$SOURCE'))
+env.Program('foo', ['foo.c'])
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+foo_exe = test.workpath('foo' + TestSCons._exe)
+_foo_exe_ = '"%s"' % string.replace(foo_exe, '\\', '\\\\')
+
+
+
+# Start scons, to build "foo"
+scons = test.start(arguments = '--interactive')
+
+scons.send("build %(_foo_exe_)s 1\n" % locals())
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.run(program = foo_exe, stdout = 'foo.c\n')
+
+
+
+
+# Update foo.c
+# We add a new #include line, to make sure that scons notices
+# the new implicit dependency and builds foo.h first.
+test.write('foo.c', """
+#include <foo.h>
+
+#include <stdio.h>
+
+int main()
+{
+ printf("%s\\n", FOO_STRING);
+ return 0;
+}
+""")
+
+scons.send("build %(_foo_exe_)s 2\n" % locals())
+
+test.wait_for(test.workpath('2'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = foo_exe, stdout = 'foo.h.in\n')
+
+
+
+test.write('foo.h.in', """
+#define FOO_STRING "foo.h.in 3"
+""")
+
+
+
+scons.send("build %(_foo_exe_)s 3\n" % locals())
+
+test.wait_for(test.workpath('3'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = foo_exe, stdout = 'foo.h.in 3\n')
+
+
+
+test.pass_test()
diff --git a/test/Interactive/basic.py b/test/Interactive/basic.py
new file mode 100644
index 0000000..4c78f69
--- /dev/null
+++ b/test/Interactive/basic.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify basic operation of the --interactive command line option to build
+a target, rebuild it when the input changes, and not rebuild it when
+the input doesn't change.
+
+Also tests that "scons" can be used as a synonym for "build".
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmy for the "build" command.
+scons.send("scons foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-debug.py b/test/Interactive/cache-debug.py
new file mode 100644
index 0000000..dab5159
--- /dev/null
+++ b/test/Interactive/cache-debug.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the --interactive command line option to build a target when the
+--cache-debug option is used.
+"""
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-debug=- foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = \
+r"""scons>>> Copy\("foo.out", "foo.in"\)
+scons>>> Touch\("1"\)
+scons>>> Removed foo.out
+scons>>> Touch\("2"\)
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch\("3"\)
+scons>>> Removed foo.out
+scons>>> Touch\("4"\)
+scons>>> Retrieved `foo.out' from cache
+CacheRetrieve\(foo.out\): retrieving from [0-9A-za-z]+
+scons>>> Touch\("5"\)
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout, match=TestCmd.match_re)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-disable.py b/test/Interactive/cache-disable.py
new file mode 100644
index 0000000..0fb8435
--- /dev/null
+++ b/test/Interactive/cache-disable.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the --interactive command line option to build
+a target when the --cache-disable option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-disable foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> Removed foo.out
+scons>>> Touch("4")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("5")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-force.py b/test/Interactive/cache-force.py
new file mode 100644
index 0000000..8fd3f92
--- /dev/null
+++ b/test/Interactive/cache-force.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the --interactive command line option to build a target when the
+--cache-force option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+import shutil
+shutil.rmtree(test.workpath('cache'))
+
+
+
+scons.send("build --cache-force foo.out\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> scons: `foo.out' is up to date.
+scons>>> Removed foo.out
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("4")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-show.py b/test/Interactive/cache-show.py
new file mode 100644
index 0000000..c1fe487
--- /dev/null
+++ b/test/Interactive/cache-show.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the --interactive command line option to build a target when the
+--cache-show option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-show foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> Removed foo.out
+scons>>> Touch("4")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("5")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/clean.py b/test/Interactive/clean.py
new file mode 100644
index 0000000..4f4f80d
--- /dev/null
+++ b/test/Interactive/clean.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verifies operation of the --interactive command line option
+"clean" subcommand.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build f1.out f2.out f3.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('f1.out'), "f1.in\n")
+test.must_match(test.workpath('f2.out'), "f2.in\n")
+test.must_match(test.workpath('f3.out'), "f3.in\n")
+
+
+
+scons.send("clean f1.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist('f1.out')
+test.must_exist('f2.out')
+test.must_exist('f3.out')
+
+
+
+scons.send("build -c\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_not_exist('f1.out')
+test.must_not_exist('f2.out')
+test.must_not_exist('f3.out')
+
+expect_stdout = """\
+scons>>> Copy("f1.out", "f1.in")
+Copy("f2.out", "f2.in")
+Copy("f3.out", "f3.in")
+scons>>> Touch("1")
+scons>>> Removed f1.out
+scons>>> Touch("2")
+scons>>> Removed 1
+Removed 2
+Removed f2.out
+Removed f3.out
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/exit.py b/test/Interactive/exit.py
new file mode 100644
index 0000000..df06d5d
--- /dev/null
+++ b/test/Interactive/exit.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify use of the "exit" subcommand.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('exit\n')
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> """
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/help.py b/test/Interactive/help.py
new file mode 100644
index 0000000..ef4c578
--- /dev/null
+++ b/test/Interactive/help.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the behavior of the "help" subcommand (and its "h" and "?" aliases).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('help\n')
+
+scons.send('h\n')
+
+scons.send('?\n')
+
+help_text = """\
+build [TARGETS] Build the specified TARGETS and their dependencies.
+ 'b' is a synonym.
+clean [TARGETS] Clean (remove) the specified TARGETS and their
+ dependencies. 'c' is a synonym.
+exit Exit SCons interactive mode.
+help [COMMAND] Prints help for the specified COMMAND. 'h' and
+ '?' are synonyms.
+shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!'
+ are synonyms.
+version Prints SCons version information.
+"""
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> %(help_text)s
+scons>>> %(help_text)s
+scons>>> %(help_text)s
+scons>>>
+""" % locals()
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/implicit-BuildDir.py b/test/Interactive/implicit-BuildDir.py
new file mode 100644
index 0000000..7b7aa4b
--- /dev/null
+++ b/test/Interactive/implicit-BuildDir.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+This is a regression test for a bug in earlier versions of the
+--interactive command line option (specifically the original prototype
+submitted by Adam Simpkins, who created this test case).
+
+It tests to make sure that cached state is cleared between files for
+nodes in both the build tree and the source tree when BuildDirs are used.
+This is needed especially with BuildDirs created with duplicate=0, since
+the scanners scan the files in the source tree. Any cached implicit
+deps must be cleared on the source files.
+"""
+
+import os.path
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('src',
+ ['src', 'inc'])
+
+# Create the top-level SConstruct file
+test.write('SConstruct', """
+BUILD_ENV = Environment()
+Export('BUILD_ENV')
+
+hdr_dir = '#build/include'
+BUILD_ENV['HDR_DIR'] = hdr_dir
+BUILD_ENV.Append(CPPPATH = hdr_dir)
+
+BUILD_ENV.BuildDir('build', 'src', duplicate = 0)
+SConscript('build/SConscript')
+
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+# Create the src/SConscript file
+test.write(['src', 'SConscript'], """
+Import('BUILD_ENV')
+BUILD_ENV.Install(BUILD_ENV['HDR_DIR'], ['inc/foo.h'])
+BUILD_ENV.Program('foo', ['foo.c'])
+""")
+
+# Create src/foo.c
+test.write(['src', 'foo.c'], """
+#include <stdio.h>
+
+#define FOO_PRINT_STRING "Hello from foo.c"
+
+int main()
+{
+ printf(FOO_PRINT_STRING "\\n");
+ return 0;
+}
+""")
+
+# Create src/inc/foo.h
+test.write(['src', 'inc', 'foo.h'], """
+#ifndef INCLUDED_foo_h
+#define INCLUDED_foo_h
+
+#define FOO_PRINT_STRING "Hello from foo.h"
+
+#endif /* INCLUDED_foo_h */
+""")
+
+# Start scons, to build only "build/foo"
+build_foo_exe = os.path.join('build', 'foo' + TestSCons._exe)
+_build_foo_exe_ = '"%s"' % string.replace(build_foo_exe, '\\', '\\\\')
+abs_foo_exe = test.workpath(build_foo_exe)
+
+scons = test.start(arguments = '--interactive', combine=1)
+
+
+
+# Build build/foo
+scons.send('build %(_build_foo_exe_)s 1\n' % locals())
+
+test.wait_for(test.workpath('1'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = abs_foo_exe, stdout = 'Hello from foo.c\n')
+
+
+
+# Update foo.c to include foo.h
+test.write(['src', 'foo.c'], """
+#include "foo.h"
+#include <stdio.h>
+
+int main()
+{
+ printf(FOO_PRINT_STRING "\\n");
+ return 0;
+}
+""")
+
+# Build build/foo
+scons.send('build %(_build_foo_exe_)s 2\n' % locals())
+
+test.wait_for(test.workpath('2'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = abs_foo_exe, stdout = 'Hello from foo.h\n')
+
+
+
+scons.send('exit\n')
+
+test.finish(scons)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option--Q.py b/test/Interactive/option--Q.py
new file mode 100644
index 0000000..4c02fa7
--- /dev/null
+++ b/test/Interactive/option--Q.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that use of the -Q option on an individual "build" command
+will suppress the progress messages.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '--interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build -Q foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+expect_stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons>>> scons: Building targets ...
+Copy("foo.out", "foo.in")
+Touch("1")
+scons: done building targets.
+scons: Clearing cached node information ...
+scons: done clearing node information.
+scons>>> Copy("foo.out", "foo.in")
+Touch("2")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-i.py b/test/Interactive/option-i.py
new file mode 100644
index 0000000..a2935a7
--- /dev/null
+++ b/test/Interactive/option-i.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the -i option, specified on the build command, causes
+build errors to be ignored, just for that command.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def error(target, source, env):
+ return 1
+e1 = Command('e1.out', 'e1.in', Action(error))
+e2 = Command('e2.out', 'e2.in', Action(error))
+f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+f2 = Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Depends(f1, e1)
+Depends(f2, e2)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('e1.in', "e1.in\n")
+test.write('e2.in', "e2.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive', combine=1)
+
+scons.send("build f1.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+
+
+
+scons.send("build -i e1.out f1.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('f1.out'), "f1.in\n")
+
+
+
+scons.send("build f2.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_not_exist(test.workpath('f2.out'))
+
+
+
+expect_stdout = """\
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("1")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+Copy("f1.out", "f1.in")
+scons>>> Touch("2")
+scons>>> error(["e2.out"], ["e2.in"])
+scons: *** [e2.out] Error 1
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-j.py b/test/Interactive/option-j.py
new file mode 100644
index 0000000..29bba88
--- /dev/null
+++ b/test/Interactive/option-j.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that "build" command of --interactive mode can take a -j
+option to build things in parallel.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+test.write('SConstruct', """\
+import os
+import time
+from SCons.Script import *
+def cat(target, source, env):
+ t = str(target[0])
+ os.mkdir(t + '.started')
+ fp = open(t, 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+ os.mkdir(t + '.finished')
+
+def must_be_finished(target, source, env, dir):
+ if not os.path.exists(dir):
+ msg = 'build failed, %s does not exist\\n' % dir
+ sys.stderr.write(msg)
+ return 1
+ return cat(target, source, env)
+
+def f1_a_out_must_be_finished(target, source, env):
+ return must_be_finished(target, source, env, 'f1-a.out.finished')
+def f3_a_out_must_be_finished(target, source, env):
+ return must_be_finished(target, source, env, 'f3-a.out.finished')
+
+def must_wait_for_f2_b_out(target, source, env):
+ t = str(target[0])
+ os.mkdir(t + '.started')
+ f2_b_started = 'f2-b.out.started'
+ while not os.path.exists(f2_b_started):
+ time.sleep(1)
+ fp = open(t, 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+ os.mkdir(t + '.finished')
+
+def _f2_a_out_must_not_be_finished(target, source, env):
+ f2_a_started = 'f2-a.out.started'
+ f2_a_finished = 'f2-a.out.finished'
+ while not os.path.exists(f2_a_started):
+ time.sleep(1)
+ msg = 'f2_a_out_must_not_be_finished(["%s"], ["%s"])\\n' % (target[0], source[0])
+ sys.stdout.write(msg)
+ if os.path.exists(f2_a_finished):
+ msg = 'build failed, %s exists\\n' % f2_a_finished
+ sys.stderr.write(msg)
+ return 1
+ return cat(target, source, env)
+
+f2_a_out_must_not_be_finished = Action(_f2_a_out_must_not_be_finished,
+ strfunction = None)
+
+Cat = Action(cat)
+f1_a = Command('f1-a.out', 'f1-a.in', cat)
+f1_b = Command('f1-b.out', 'f1-b.in', f1_a_out_must_be_finished)
+f2_a = Command('f2-a.out', 'f2-a.in', must_wait_for_f2_b_out)
+f2_b = Command('f2-b.out', 'f2-b.in', f2_a_out_must_not_be_finished)
+f3_a = Command('f3-a.out', 'f3-a.in', cat)
+f3_b = Command('f3-b.out', 'f3-b.in', f3_a_out_must_be_finished)
+Command('f1.out', f1_a + f1_b, cat)
+Command('f2.out', f2_a + f2_b, cat)
+Command('f3.out', f3_a + f3_b, cat)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('f1-a.in', "f1-a.in\n")
+test.write('f1-b.in', "f1-b.in\n")
+test.write('f2-a.in', "f2-a.in\n")
+test.write('f2-b.in', "f2-b.in\n")
+test.write('f3-a.in', "f3-a.in\n")
+test.write('f3-b.in', "f3-b.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build f1.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('f1.out'), "f1-a.in\nf1-b.in\n")
+
+
+
+scons.send("build -j2 f2.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('f2.out'), "f2-a.in\nf2-b.in\n")
+
+
+
+scons.send("build f3.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('f3.out'), "f3-a.in\nf3-b.in\n")
+
+
+
+expect_stdout = """\
+scons>>> cat(["f1-a.out"], ["f1-a.in"])
+f1_a_out_must_be_finished(["f1-b.out"], ["f1-b.in"])
+cat(["f1.out"], ["f1-a.out", "f1-b.out"])
+scons>>> Touch("1")
+scons>>> must_wait_for_f2_b_out(["f2-a.out"], ["f2-a.in"])
+f2_a_out_must_not_be_finished(["f2-b.out"], ["f2-b.in"])
+cat(["f2.out"], ["f2-a.out", "f2-b.out"])
+scons>>> Touch("2")
+scons>>> cat(["f3-a.out"], ["f3-a.in"])
+f3_a_out_must_be_finished(["f3-b.out"], ["f3-b.in"])
+cat(["f3.out"], ["f3-a.out", "f3-b.out"])
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-k.py b/test/Interactive/option-k.py
new file mode 100644
index 0000000..f15605e
--- /dev/null
+++ b/test/Interactive/option-k.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the -k option, specified on the build command, causes
+us to keep going and build additional targets.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def error(target, source, env):
+ return 1
+e1 = Command('e1.out', 'e1.in', Action(error))
+f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE'))
+Depends(f1, e1)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('e1.in', "e1.in\n")
+test.write('e2.in', "e2.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive', combine=1)
+
+scons.send("build f1.out f2.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_not_exist(test.workpath('f2.out'))
+
+
+
+scons.send("build -k f1.out f2.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_match(test.workpath('f2.out'), "f2.in\n")
+
+
+
+scons.send("build f1.out f3.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_not_exist(test.workpath('f3.out'))
+
+
+
+expect_stdout = """\
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("1")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+Copy("f2.out", "f2.in")
+scons>>> Touch("2")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-n.py b/test/Interactive/option-n.py
new file mode 100644
index 0000000..f5ee1e3
--- /dev/null
+++ b/test/Interactive/option-n.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the -n option, specified on the build command, reports
+what would be built but doesn't actually build anything.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build -n foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-s.py b/test/Interactive/option-s.py
new file mode 100644
index 0000000..167d581
--- /dev/null
+++ b/test/Interactive/option-s.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify basic operation of the --interactive command line option
+to build a target, rebuild it when the input changes, and not rebuild
+it when the input doesn't change.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build -s foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/repeat-line.py b/test/Interactive/repeat-line.py
new file mode 100644
index 0000000..e85b9ea
--- /dev/null
+++ b/test/Interactive/repeat-line.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that a blank line repeats the last (build) command.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> build foo.out 1
+Copy("foo.out", "foo.in")
+scons: `1' is up to date.
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>> build foo.out
+scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/shell.py b/test/Interactive/shell.py
new file mode 100644
index 0000000..9d5e8a2
--- /dev/null
+++ b/test/Interactive/shell.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the ability of the "shell" command (and its "sh" and "!" aliases)
+to shell out of interactive mode.
+"""
+
+import string
+import sys
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+_python_ = TestSCons._python_
+
+shell_command_py = test.workpath('shell_command.py')
+_shell_command_py_ = '"%s"' % string.replace(shell_command_py, '\\', '\\\\')
+
+test.write(shell_command_py, """\
+print 'hello from shell_command.py'
+""")
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('!%(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('shell %(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('sh %(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('!no_such_command arg1 arg2\n')
+
+scons.send("\n")
+
+scons.send("build foo.out\n")
+
+scons.send("\n")
+
+if sys.platform == 'win32':
+ no_such_error = 'The system cannot find the file specified'
+else:
+ no_such_error = 'No such file or directory'
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> hello from shell_command.py
+scons>>> !%(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> hello from shell_command.py
+scons>>> shell %(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> hello from shell_command.py
+scons>>> sh %(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> scons: no_such_command: %(no_such_error)s
+scons>>> !no_such_command arg1 arg2
+scons: no_such_command: %(no_such_error)s
+scons>>> scons: `foo.out' is up to date.
+scons>>> build foo.out
+scons: `foo.out' is up to date.
+scons>>>
+""" % locals()
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/taskmastertrace.py b/test/Interactive/taskmastertrace.py
new file mode 100644
index 0000000..23b9ad9
--- /dev/null
+++ b/test/Interactive/taskmastertrace.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify use of the --taskmastertrace= option to the "build" command
+of --interactive mode.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build --taskmastertrace=- foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> Taskmaster: 'foo.out': children:
+ ['foo.in']
+ waiting on unfinished children:
+ ['foo.in']
+Taskmaster: 'foo.in': evaluating foo.in
+Taskmaster: 'foo.out': children:
+ ['foo.in']
+ evaluating foo.out
+Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/tree.py b/test/Interactive/tree.py
new file mode 100644
index 0000000..96e7d4a
--- /dev/null
+++ b/test/Interactive/tree.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify basic operation of the --interactive command line option to build
+a target, rebuild it when the input changes, and not rebuild it when
+the input doesn't change.
+
+Also tests that "scons" can be used as a synonym for "build".
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build --tree=all foo.out\n")
+
+scons.send("scons 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build --debug=tree foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
++-foo.out
+ +-foo.in
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
++-foo.out
+ +-foo.in
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/unknown-command.py b/test/Interactive/unknown-command.py
new file mode 100644
index 0000000..2b77378
--- /dev/null
+++ b/test/Interactive/unknown-command.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the error message when an unknown command is typed in.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('this-is-an-unknown-command hello\n')
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> *** Unknown command: this-is-an-unknown-command
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/version.py b/test/Interactive/version.py
new file mode 100644
index 0000000..84f70e8
--- /dev/null
+++ b/test/Interactive/version.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the behavior of the "version" subcommand.
+"""
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestCmd.match_re)
+
+test.write('SConstruct', "")
+
+
+
+# Construct the standard copyright marker so it doesn't get replaced
+# by the packaging build.
+copyright_marker = '__' + 'COPYRIGHT' + '__'
+
+copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007'
+
+fmt = '(%s|Copyright \\(c\\) %s The SCons Foundation)\n'
+
+copyright_line = fmt % (copyright_marker, copyright_years)
+
+
+
+expect1 = """\
+scons>>>
+scons>>>
+"""
+
+expect2 = """\
+scons>>>
+scons>>>
+"""
+
+test.run(arguments = '-Q --interactive',
+ stdin = "version\nexit\n")
+
+# Windows may or may not print a line for the script version
+# depending on whether it's invoked through scons.py or scons.bat.
+expect1 = r"""scons>>> SCons by Steven Knight et al\.:
+\tengine: v\S+, [^,]*, by \S+ on \S+
+%(copyright_line)sscons>>>
+""" % locals()
+
+expect2 = r"""scons>>> SCons by Steven Knight et al\.:
+\tscript: v\S+, [^,]*, by \S+ on \S+
+\tengine: v\S+, [^,]*, by \S+ on \S+
+%(copyright_line)sscons>>>
+""" % locals()
+
+stdout = test.stdout() + '\n'
+if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2):
+ print repr(stdout)
+ test.fail_test()
+
+
+
+test.pass_test()
diff --git a/test/Java/JAR.py b/test/Java/JAR.py
index f0951c6..ee552f4 100644
--- a/test/Java/JAR.py
+++ b/test/Java/JAR.py
@@ -120,21 +120,11 @@ test.run(arguments='classes.jar')
test.must_match('classes.jar',
'cvfm classes.jar foo.mf -C testdir bar.class\n')
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+
+
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
test.write("wrapper.py", """\
diff --git a/test/Java/JARCHDIR.py b/test/Java/JARCHDIR.py
index f7d9fca..a3f2ec4 100644
--- a/test/Java/JARCHDIR.py
+++ b/test/Java/JARCHDIR.py
@@ -40,21 +40,8 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
diff --git a/test/Java/JARFLAGS.py b/test/Java/JARFLAGS.py
index 3939d98..03a222b 100644
--- a/test/Java/JARFLAGS.py
+++ b/test/Java/JARFLAGS.py
@@ -33,21 +33,10 @@ test = TestSCons.TestSCons()
test.subdir('src')
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
+
test.write('SConstruct', """
env = Environment(tools = ['javac', 'jar'],
@@ -75,9 +64,9 @@ public class Example1
expect = test.wrap_stdout("""\
%(where_javac)s -d classes -sourcepath src src/Example1\.java
-%(where_jar)s cvf test.jar classes/src/Example1\.class
+%(where_jar)s cvf test.jar -C classes src/Example1\.class
.*
-adding: classes/src/Example1\.class.*
+adding: src/Example1\.class.*
""" % locals())
expect = string.replace(expect, '/', os.sep)
diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py
index 7723224..5962b94 100644
--- a/test/Java/JAVABOOTCLASSPATH.py
+++ b/test/Java/JAVABOOTCLASSPATH.py
@@ -38,21 +38,8 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/JAVACFLAGS.py b/test/Java/JAVACFLAGS.py
index 045fb7b..e287054 100644
--- a/test/Java/JAVACFLAGS.py
+++ b/test/Java/JAVACFLAGS.py
@@ -31,14 +31,7 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.subdir('src')
diff --git a/test/Java/JAVACLASSPATH.py b/test/Java/JAVACLASSPATH.py
index 0ae7dea..11f7c2c 100644
--- a/test/Java/JAVACLASSPATH.py
+++ b/test/Java/JAVACLASSPATH.py
@@ -36,21 +36,8 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py
index ecd3737..95abd33 100644
--- a/test/Java/JAVAH.py
+++ b/test/Java/JAVAH.py
@@ -24,9 +24,9 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
+import os.path
import string
-import sys
+
import TestSCons
_python_ = TestSCons._python_
@@ -95,21 +95,11 @@ line 3
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+if java_version:
+ java_version = repr(java_version)
@@ -125,6 +115,9 @@ test.write('SConstruct', """
foo = Environment(tools = ['javac', 'javah', 'install'],
JAVAC = r'%(where_javac)s',
JAVAH = r'%(where_javah)s')
+jv = %(java_version)s
+if jv:
+ foo['JAVAVERSION'] = jv
javah = foo.Dictionary('JAVAH')
bar = foo.Clone(JAVAH = r'%(_python_)s wrapper.py ' + javah)
foo.Java(target = 'class1', source = 'com/sub/foo')
diff --git a/test/Java/JAVASOURCEPATH.py b/test/Java/JAVASOURCEPATH.py
index 069e228..87e90ad 100644
--- a/test/Java/JAVASOURCEPATH.py
+++ b/test/Java/JAVASOURCEPATH.py
@@ -36,14 +36,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/Java-1.4.py b/test/Java/Java-1.4.py
index 3d3d47a..3c0e1ed 100644
--- a/test/Java/Java-1.4.py
+++ b/test/Java/Java-1.4.py
@@ -38,14 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.4')
@@ -234,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -256,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
@@ -268,7 +261,7 @@ public class NestedExample
test.write(['src5', 'TestSCons.java'], """\
class TestSCons {
public static void main(String[] args) {
- Foo[] fooArray = new Foo[] { new Foo() };
+ new Foo();
}
}
@@ -355,12 +348,16 @@ def classes_must_match(dir, expect):
global failed
got = get_class_files(test.workpath(dir))
if expect != got:
- sys.stderr.write("Expected the following class files in '%s':\n" % dir)
- for c in expect:
- sys.stderr.write(' %s\n' % c)
- sys.stderr.write("Got the following class files in '%s':\n" % dir)
- for c in got:
- sys.stderr.write(' %s\n' % c)
+ missing = set(expect) - set(got)
+ if missing:
+ sys.stderr.write("Missing the following class files from '%s':\n" % dir)
+ for c in missing:
+ sys.stderr.write(' %s\n' % c)
+ unexpected = set(got) - set(expect)
+ if unexpected:
+ sys.stderr.write("Found the following unexpected class files in '%s':\n" % dir)
+ for c in unexpected:
+ sys.stderr.write(' %s\n' % c)
failed = 1
def classes_must_not_exist(dir, expect):
diff --git a/test/Java/Java-1.5.py b/test/Java/Java-1.5.py
index 4ac3d96..f6d93c7 100644
--- a/test/Java/Java-1.5.py
+++ b/test/Java/Java-1.5.py
@@ -38,15 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-ENV['PATH'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11/bin' + os.pathsep + os.environ['PATH']
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.5')
@@ -235,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -257,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
diff --git a/test/Java/Java-1.6.py b/test/Java/Java-1.6.py
index f2b629a..5bd8e2f 100644
--- a/test/Java/Java-1.6.py
+++ b/test/Java/Java-1.6.py
@@ -38,15 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-ENV['PATH'] = '/usr/lib/jvm/java-6-sun-1.6.0.00/bin' + os.pathsep + os.environ['PATH']
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.6')
@@ -235,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -257,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
diff --git a/test/Java/RMIC.py b/test/Java/RMIC.py
index 2ab1804..f9721c2 100644
--- a/test/Java/RMIC.py
+++ b/test/Java/RMIC.py
@@ -92,21 +92,8 @@ line 3
test.fail_test(test.read(['outdir', 'test2.class']) != "test2.JAVA\nline 3\n")
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping non-simulated test(s).\n")
-
-if test.detect_tool('rmic', ENV=ENV):
- where_rmic = test.detect('RMIC', 'rmic', ENV=ENV)
-else:
- where_rmic = test.where_is('rmic')
-if not where_rmic:
- test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_rmic = test.java_where_rmic()
test.write("wrapper.py", """\
import os
@@ -319,15 +306,20 @@ test.run(arguments = '.')
test.fail_test(test.read('wrapper.out') != "wrapper.py %s -d outdir2 -classpath class2 com.sub.bar.Example3 com.sub.bar.Example4\n" % where_rmic)
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class')))
-
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class')))
+test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class'))
+test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class'))
+test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class'))
+test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class'))
+
+# We used to check for _Skel.class files as well, but they're not
+# generated by default starting with Java 1.5, and they apparently
+# haven't been needed for a while. Don't bother looking, even if we're
+# running Java 1.4. If we think they're needed but they don't exist
+# the test.up_to_date() call below will detect it.
+#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class'))
+#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class'))
+#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class'))
+#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class'))
test.up_to_date(arguments = '.')
diff --git a/test/Java/RMICCOM.py b/test/Java/RMICCOM.py
index ed5e0d6..e8a5655 100644
--- a/test/Java/RMICCOM.py
+++ b/test/Java/RMICCOM.py
@@ -40,9 +40,9 @@ test.subdir('src')
-out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
-out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
-out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+out_file1 = os.path.join('out', 'file1', 'class_Stub.class')
+out_file2 = os.path.join('out', 'file2', 'class_Stub.class')
+out_file3 = os.path.join('out', 'file3', 'class_Stub.class')
diff --git a/test/Java/RMICCOMSTR.py b/test/Java/RMICCOMSTR.py
index 5a451eb..a92bac5 100644
--- a/test/Java/RMICCOMSTR.py
+++ b/test/Java/RMICCOMSTR.py
@@ -41,9 +41,9 @@ test.subdir('src')
-out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
-out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
-out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+out_file1 = os.path.join('out', 'file1', 'class_Stub.class')
+out_file2 = os.path.join('out', 'file2', 'class_Stub.class')
+out_file3 = os.path.join('out', 'file3', 'class_Stub.class')
diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py
index d185b4d..9cac759 100644
--- a/test/Java/multi-step.py
+++ b/test/Java/multi-step.py
@@ -33,22 +33,8 @@ import TestSCons
test = TestSCons.TestSCons()
-# This test requires javac and swig
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
swig = test.where_is('swig')
if not swig:
diff --git a/test/Java/no-JARCHDIR.py b/test/Java/no-JARCHDIR.py
new file mode 100644
index 0000000..795689c
--- /dev/null
+++ b/test/Java/no-JARCHDIR.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the Jar() behavior when we have no JARCHDIR set (it should
+automatically use the classdir that was deduced from the Java() call)
+and when we explicity set it to None (it should not use the Java()
+classdir attribute at all).
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
+test.subdir('src')
+
+
+
+test.write(['src', 'a.java'], """\
+package foo.bar;
+public class a {}
+""")
+
+test.write(['src', 'b.java'], """\
+package foo.bar;
+public class b {}
+""")
+
+
+
+test.write('SConstruct', """\
+env = Environment(tools = ['javac', 'jar'],
+ JAVAC = r'%(where_javac)s',
+ JAR = r'%(where_jar)s')
+
+jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src'))
+""" % locals())
+
+test.run(arguments = '.')
+
+
+
+test.run(program = where_jar, arguments = 'tf x.jar')
+
+expect = """\
+foo/bar/a.class
+foo/bar/b.class
+"""
+
+if string.find(test.stdout(), expect) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print expect
+ print "Output ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+
+
+test.run(arguments = '-c')
+
+
+
+test.write('SConstruct', """\
+env = Environment(tools = ['javac', 'jar'],
+ JAVAC = r'%(where_javac)s',
+ JAR = r'%(where_jar)s',
+ JARCHDIR = None)
+
+jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src'))
+""" % locals())
+
+test.run(arguments = '.')
+
+
+
+test.run(program = where_jar, arguments = 'tf x.jar')
+
+expect = """\
+classes/foo/bar/a.class
+classes/foo/bar/b.class
+"""
+
+if string.find(test.stdout(), expect) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print expect
+ print "Output ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+
+
+test.pass_test()
diff --git a/test/Java/source-files.py b/test/Java/source-files.py
index 8d2506f..63d1d92 100644
--- a/test/Java/source-files.py
+++ b/test/Java/source-files.py
@@ -35,14 +35,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.write('SConstruct', """
diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py
index 8df5e09..5477a2d 100644
--- a/test/Java/swig-dependencies.py
+++ b/test/Java/swig-dependencies.py
@@ -34,29 +34,14 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+swig = test.where_is('swig')
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
+where_jar = test.java_where_jar()
test.subdir(['foo'],
['java'],
diff --git a/test/LIBPATH.py b/test/Libs/LIBPATH.py
index 7fd4f9b..7fd4f9b 100644
--- a/test/LIBPATH.py
+++ b/test/Libs/LIBPATH.py
diff --git a/test/LIBPREFIX.py b/test/Libs/LIBPREFIX.py
index a71e967..a71e967 100644
--- a/test/LIBPREFIX.py
+++ b/test/Libs/LIBPREFIX.py
diff --git a/test/LIBPREFIXES.py b/test/Libs/LIBPREFIXES.py
index 1e5d6c2..1e5d6c2 100644
--- a/test/LIBPREFIXES.py
+++ b/test/Libs/LIBPREFIXES.py
diff --git a/test/LIBS.py b/test/Libs/LIBS.py
index e9f6545..e9f6545 100644
--- a/test/LIBS.py
+++ b/test/Libs/LIBS.py
diff --git a/test/LIBSUFFIX.py b/test/Libs/LIBSUFFIX.py
index a71e967..a71e967 100644
--- a/test/LIBSUFFIX.py
+++ b/test/Libs/LIBSUFFIX.py
diff --git a/test/LIBSUFFIXES.py b/test/Libs/LIBSUFFIXES.py
index 29cbb18..29cbb18 100644
--- a/test/LIBSUFFIXES.py
+++ b/test/Libs/LIBSUFFIXES.py
diff --git a/test/Library.py b/test/Libs/Library.py
index 4bcb2c7..4bcb2c7 100644
--- a/test/Library.py
+++ b/test/Libs/Library.py
diff --git a/test/SHLIBPREFIX.py b/test/Libs/SHLIBPREFIX.py
index 87b92fa..87b92fa 100644
--- a/test/SHLIBPREFIX.py
+++ b/test/Libs/SHLIBPREFIX.py
diff --git a/test/SHLIBSUFFIX.py b/test/Libs/SHLIBSUFFIX.py
index dc88e3b..dc88e3b 100644
--- a/test/SHLIBSUFFIX.py
+++ b/test/Libs/SHLIBSUFFIX.py
diff --git a/test/SharedLibrary.py b/test/Libs/SharedLibrary.py
index f8447ca..f8447ca 100644
--- a/test/SharedLibrary.py
+++ b/test/Libs/SharedLibrary.py
diff --git a/test/Libs/SharedLibraryIxes.py b/test/Libs/SharedLibraryIxes.py
new file mode 100644
index 0000000..f9d1471
--- /dev/null
+++ b/test/Libs/SharedLibraryIxes.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that we can build shared libraries and link against shared
+libraries that have non-standard library prefixes and suffixes.
+"""
+
+import re
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import sys
+isWindows = sys.platform == 'win32'
+
+env = Environment()
+
+# Make sure that the shared library can be located at runtime.
+env.Append(RPATH=['.'])
+env.Append(LIBPATH=['.'])
+
+# We first bake the LIBSUFFIXES, so that it will not change as a
+# side-effect of changing SHLIBSUFFIX.
+env['LIBSUFFIXES'] = map( env.subst, env.get('LIBSUFFIXES', []))
+
+weird_prefixes = ['libXX', 'libYY']
+
+if isWindows:
+ weird_suffixes = ['.xxx', '.yyy', '.xxx.dll', '.yyy.dll']
+ env.Append(CCFLAGS = '/MD')
+elif env['PLATFORM'] == 'darwin':
+ weird_suffixes = ['.xxx.dylib', '.yyy.dylib']
+else:
+ weird_suffixes = ['.xxx.so', '.yyy.so']
+
+shlibprefix = env.subst('$SHLIBPREFIX')
+shlibsuffix = env.subst('$SHLIBSUFFIX')
+
+progprefix = env.subst('$PROGPREFIX')
+progsuffix = env.subst('$PROGSUFFIX')
+
+goo_obj = env.SharedObject(source='goo.c')
+foo_obj = env.SharedObject(source='foo.c')
+prog_obj = env.SharedObject(source='prog.c')
+
+#
+# The following functions define all the different way that one can
+# use link againt a shared library.
+#
+def nodeInSrc(source, lib, libname):
+ return (source+lib, '')
+
+def pathInSrc(source, lib, libname):
+ return (source+map(str,lib), '')
+
+def nodeInLib(source, lib, libname):
+ return (source, lib)
+
+def pathInLib(source, lib, libname):
+ return (source, map(str,lib))
+
+def nameInLib(source, lib, libname):
+ # NOTE: libname must contain both the proper prefix and suffix.
+ #
+ # When using non-standard prefixes and suffixes, one has to
+ # provide the full name of the library since scons can not know
+ # which of the non-standard extension to use.
+ #
+ # Note that this is not necessarally SHLIBPREFIX and
+ # SHLIBSUFFIX. These are the ixes of the target library, not the
+ # ixes of the library that we are linking againt.
+ return (source, libname)
+
+libmethods = [
+ nodeInSrc, pathInSrc, nodeInLib, pathInLib,
+ nameInLib ]
+
+def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw):
+ '''Build a target using a given builder while linking againt a given
+ library using a specified method for linking against the library.'''
+
+ # On Windows, we have to link against the .lib file.
+ if isWindows:
+ for l in lib:
+ if str(l)[-4:] == '.lib':
+ lib = [l]
+ break
+ (source, LIBS) = method(source, lib, libname)
+ #build = builder(target=target, source=source, LIBS=LIBS, **kw)
+ kw = kw.copy()
+ kw['target'] = target
+ kw['source'] = source
+ kw['LIBS'] = LIBS
+ build = apply(builder, (), kw)
+
+ # Check that the build target depends on at least one of the
+ # library target.
+ found_dep = False
+ children = build[0].children()
+ for l in lib:
+ if l in children:
+ found_dep = True
+ break;
+ assert found_dep, \
+ "One of %s not found in %s, method=%s, libname=%s, shlibsuffix=%s" % \
+ (map(str,lib), map(str, build[0].children()), method.__name__, libname, shlibsuffix)
+ return build
+
+def prog(i,
+ goomethod, goolibprefix, goolibsuffix,
+ foomethod, foolibprefix, foolibsuffix):
+ '''Build a program
+
+ The program links against a shared library foo which itself links
+ against a shared library goo. The libraries foo and goo can use
+ arbitrary library prefixes and suffixes.'''
+
+ goo_name = goolibprefix+'goo'+str(i)+goolibsuffix
+ foo_name = foolibprefix+'foo'+str(i)+foolibsuffix
+ prog_name = progprefix+'prog'+str(i)+progsuffix
+
+ print 'Prog: %d, %s, %s, %s' % (i, goo_name, foo_name, prog_name)
+
+ # On Windows, we have to link against the .lib file.
+ if isWindows:
+ goo_libname = goolibprefix+'goo'+str(i)+'.lib'
+ foo_libname = foolibprefix+'foo'+str(i)+'.lib'
+ else:
+ goo_libname = goo_name
+ foo_libname = foo_name
+
+ goo_lib = env.SharedLibrary(
+ goo_name, goo_obj, SHLIBSUFFIX=goolibsuffix)
+ foo_lib = buildAndlinkAgainst(
+ env.SharedLibrary, foo_name, foo_obj,
+ goomethod, goo_lib, goo_libname, SHLIBSUFFIX=foolibsuffix)
+ prog = buildAndlinkAgainst(env.Program, prog_name, prog_obj,
+ foomethod, foo_lib, foo_libname)
+
+
+#
+# Create the list of all possible permutations to test.
+#
+i = 0
+tests = []
+prefixes = [shlibprefix] + weird_prefixes
+suffixes = [shlibsuffix] + weird_suffixes
+for foolibprefix in prefixes:
+ for foolibsuffix in suffixes:
+ for foomethod in libmethods:
+ for goolibprefix in prefixes:
+ for goolibsuffix in suffixes:
+ for goomethod in libmethods:
+ tests.append(
+ (i,
+ goomethod, goolibprefix, goolibsuffix,
+ foomethod, foolibprefix, foolibsuffix))
+ i = i + 1
+
+#
+# Pseudo-randomly choose 200 tests to run out of the possible
+# tests. (Testing every possible permutation would take too long.)
+#
+import random
+random.seed(123456)
+try:
+ random.shuffle(tests)
+except AttributeError:
+ pass
+
+for i in range(200):
+ apply(prog, tests[i])
+
+""")
+
+test.write('goo.c', r"""
+#include <stdio.h>
+
+#ifdef _WIN32
+#define EXPORT __declspec( dllexport )
+#else
+#define EXPORT
+#endif
+
+EXPORT void
+goo(void)
+{
+ printf("goo.c\n");
+}
+""")
+
+test.write('foo.c', r"""
+#include <stdio.h>
+
+#ifdef _WIN32
+#define EXPORT __declspec( dllexport )
+#else
+#define EXPORT
+#endif
+
+EXPORT void
+foo(void)
+{
+ goo();
+ printf("foo.c\n");
+}
+""")
+
+test.write('prog.c', r"""
+#include <stdio.h>
+
+void foo(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ foo();
+ printf("prog.c\n");
+ return 0;
+}
+""")
+
+test.run(arguments = '.',
+ stderr=TestSCons.noisy_ar,
+ match=TestSCons.match_re_dotall)
+
+tests = re.findall(r'Prog: (\d+), (\S+), (\S+), (\S+)', test.stdout())
+expected = "goo.c\nfoo.c\nprog.c\n"
+
+for t in tests:
+ test.must_exist(t[1])
+ test.must_exist(t[2])
+ test.must_exist(t[3])
+ test.run(program = test.workpath(t[3]), stdout=expected)
+
+test.pass_test()
diff --git a/test/LoadableModule.py b/test/LoadableModule.py
index 5243fbf..4a8e1ed 100644
--- a/test/LoadableModule.py
+++ b/test/LoadableModule.py
@@ -105,7 +105,8 @@ test.run(arguments = '.',
if string.find(sys.platform, 'darwin') != -1:
test.run(program='/usr/bin/file',
arguments = "foo1",
- stdout="foo1: Mach-O bundle ppc\n")
+ match = TestCmd.match_re,
+ stdout="foo1: Mach-O bundle (ppc|i386)\n")
if sys.platform in platforms_with_dlopen:
os.environ['LD_LIBRARY_PATH'] = test.workpath()
diff --git a/test/MSVC/pdb-manifest.py b/test/MSVC/pdb-manifest.py
new file mode 100644
index 0000000..00f3ee2
--- /dev/null
+++ b/test/MSVC/pdb-manifest.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that .pdb files work correctly in conjunction with manifest files.
+"""
+
+import sys
+
+import TestSCons
+
+_exe = TestSCons._exe
+_dll = TestSCons._dll
+_lib = TestSCons._lib
+
+test = TestSCons.TestSCons()
+
+if sys.platform != 'win32':
+ msg = "Skipping Visual C/C++ test on non-Windows platform '%s'\n" % sys.platform
+ test.skip_test(msg)
+
+test.write('SConstruct', """\
+env = Environment()
+
+env['WINDOWS_INSERT_DEF'] = True
+env['WINDOWS_INSERT_MANIFEST'] = True
+env['PDB'] = '${TARGET.base}.pdb'
+env.Program('test', 'test.cpp')
+env.SharedLibrary('sharedlib', 'test.cpp')
+env.StaticLibrary('staticlib', 'test.cpp')
+""")
+
+test.write('test.cpp', """\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv)
+{
+ printf("test.cpp\\n");
+ exit (0);
+}
+""")
+
+test.write('sharedlib.def', """\
+""")
+
+test.run(arguments = '.')
+
+test.must_exist('test%s' % _exe)
+test.must_exist('test.pdb')
+
+test.must_exist('sharedlib%s' % _dll)
+test.must_exist('sharedlib.pdb')
+
+test.must_exist('staticlib%s' % _lib)
+test.must_not_exist('staticlib.pdb')
+
+test.pass_test()
diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py
index 2878136..9936490 100644
--- a/test/QT/moc-from-header.py
+++ b/test/QT/moc-from-header.py
@@ -55,6 +55,8 @@ test.Qt_create_SConstruct('SConstruct')
test.write('SConscript', """\
Import("env")
env.Program(target = 'aaa', source = 'aaa.cpp')
+if env['PLATFORM'] == 'darwin':
+ env.Install('.', 'qt/lib/libmyqt.dylib')
""")
test.write('aaa.cpp', r"""
@@ -67,7 +69,7 @@ test.write('aaa.h', r"""
void aaa(void) Q_OBJECT;
""")
-test.run(arguments = aaa_exe)
+test.run()
test.up_to_date(options = '-n', arguments=aaa_exe)
diff --git a/test/QT/warnings.py b/test/QT/warnings.py
index baa1e6f..ef94dd6 100644
--- a/test/QT/warnings.py
+++ b/test/QT/warnings.py
@@ -59,9 +59,10 @@ match12 = r"""
scons: warning: Generated moc file 'aaa.moc' is not included by 'aaa.cpp'
""" + TestSCons.file_expr
-# In case 'ar' gives a warning about creating a library.
-test.fail_test(not test.match_re(test.stderr(), match12) and \
- not test.match_re(test.stderr(), match12 + ".+\n"))
+if not re.search(match12, test.stderr()):
+ print "Did not find expected regular expression in stderr:"
+ print test.stderr()
+ test.fail_test()
os.environ['QTDIR'] = test.QT
diff --git a/test/Repository/Java.py b/test/Repository/Java.py
index 6e8bbd6..67ef605 100644
--- a/test/Repository/Java.py
+++ b/test/Repository/Java.py
@@ -37,18 +37,8 @@ python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
java = where_java
@@ -115,6 +105,8 @@ test.writable('repository', 0)
#
test.run(chdir = 'work1', options = opts, arguments = ".")
+os.environ['JAVA_HOME'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11'
+
test.run(program = java,
arguments = "-cp %s Foo1" % work1_classes,
stdout = "rep1/src/Foo1.java\n")
diff --git a/test/Repository/JavaH.py b/test/Repository/JavaH.py
index fc87904..258d9bd 100644
--- a/test/Repository/JavaH.py
+++ b/test/Repository/JavaH.py
@@ -37,25 +37,9 @@ python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
+where_javah = test.java_where_javah()
java = where_java
javac = where_javac
diff --git a/test/Repository/LIBPATH.py b/test/Repository/LIBPATH.py
index 9216a8b..0f80ace 100644
--- a/test/Repository/LIBPATH.py
+++ b/test/Repository/LIBPATH.py
@@ -59,6 +59,13 @@ def write_LIBDIRFLAGS(env, target, source):
return 0
env_zzz.Command('zzz.out', aaa_exe, write_LIBDIRFLAGS)
env_yyy.Command('yyy.out', bbb_exe, write_LIBDIRFLAGS)
+
+if env_yyy['PLATFORM'] == 'darwin':
+ # The Mac OS X linker complains about nonexistent directories
+ # specified as -L arguments. Suppress its warnings so we don't
+ # treat the warnings on stderr as a failure.
+ env_yyy.Append(LINKFLAGS=['-w'])
+ env_zzz.Append(LINKFLAGS=['-w'])
""")
test.write(['work', 'aaa.c'], r"""
diff --git a/test/Repository/RMIC.py b/test/Repository/RMIC.py
index ebe6a83..bf8edff 100644
--- a/test/Repository/RMIC.py
+++ b/test/Repository/RMIC.py
@@ -28,34 +28,17 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test building Java applications when using Repositories.
"""
-import os
import string
-import sys
+
import TestSCons
python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('rmic', ENV=ENV):
- where_rmic = test.detect('RMIC', 'rmic', ENV=ENV)
-else:
- where_rmic = test.where_is('rmic')
-if not where_rmic:
- test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
+where_rmic = test.java_where_rmic()
java = where_java
javac = where_javac
@@ -185,15 +168,20 @@ test.run(chdir = 'work1', options = opts, arguments = ".")
# see that they were built from the proper rep1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+# We used to check for _Skel.class files as well, but they're not
+# generated by default starting with Java 1.5, and they apparently
+# haven't been needed for a while. Don't bother looking, even if we're
+# running Java 1.4. If we think they're needed but they don't exist
+# the variou test.up_to_date() calls below will detect it.
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
@@ -294,15 +282,15 @@ test.fail_test(string.find(test.stdout(), ' com.sub.foo.Foo1 com.sub.foo.Foo2')
# see that they were built from the proper work1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
@@ -315,10 +303,11 @@ test.run(chdir = 'rep1', options = opts, arguments = ".")
# see that they were built from the proper work1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'rep1', options = opts, arguments = ".")
@@ -343,13 +332,16 @@ Local(rmi_classes)
test.run(chdir = 'work3', options = opts, arguments = ".")
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class')))
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class')))
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class')))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class'))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class'))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class'))
+
+test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.up_to_date(chdir = 'work3', options = opts, arguments = ".")
test.pass_test()
diff --git a/test/SWIG/module-parens.py b/test/SWIG/module-parens.py
new file mode 100644
index 0000000..0d89ebe
--- /dev/null
+++ b/test/SWIG/module-parens.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we handle %module(directors="1") statements, both with and
+without white space before the opening parenthesis.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+swig = test.where_is('swig')
+
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
+python_include_dir = test.get_python_inc()
+
+test.write(['SConstruct'], """\
+env = Environment(SWIGFLAGS = '-python',
+ CPPPATH=r"%(python_include_dir)s")
+
+import sys
+if sys.version[0] == '1':
+ # SWIG requires the -classic flag on pre-2.0 Python versions.
+ env.Append(SWIGFLAGS = ' -classic')
+
+env.SharedLibrary('test1.so', 'test1.i')
+env.SharedLibrary('test2.so', 'test2.i')
+""" % locals())
+
+test.write(['test1.cc'], """\
+int test1func()
+{
+ return 0;
+}
+""")
+
+test.write(['test1.h'], """\
+int test1func();
+""")
+
+test.write(['test1.i'], """\
+%module(directors="1") test1
+
+%{
+#include "test1.h"
+%}
+
+%include "test1.h"
+""")
+
+test.write(['test2.cc'], """\
+int test2func()
+{
+ return 0;
+}
+""")
+
+test.write(['test2.h'], """\
+int test2func();
+""")
+
+test.write(['test2.i'], """\
+%module (directors="1") test2
+
+%{
+#include "test2.h"
+%}
+
+%include "test2.h"
+""")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py
index dd2c938..ef91189 100644
--- a/test/Scanner/generated.py
+++ b/test/Scanner/generated.py
@@ -318,10 +318,10 @@ def write_out(file, dict):
f.write(file + ": " + str(dict[k]) + "\\n")
f.close()
-orig_function = CScan.scan
+orig_function = CScan.__call__
-def MyCScan(node, paths, orig_function=orig_function):
- deps = orig_function(node, paths)
+def MyCScan(node, paths, cwd, orig_function=orig_function):
+ deps = orig_function(node, paths, cwd)
global Scanned
n = str(node)
@@ -333,7 +333,7 @@ def MyCScan(node, paths, orig_function=orig_function):
return deps
-CScan.scan = MyCScan
+CScan.__call__ = MyCScan
env = Environment(CPPPATH = ".")
l = env.StaticLibrary("g", Split("libg_1.c libg_2.c libg_3.c"))
diff --git a/test/TEX/build_dir_dup0.py b/test/TEX/build_dir_dup0.py
new file mode 100644
index 0000000..8035957
--- /dev/null
+++ b/test/TEX/build_dir_dup0.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test creation of a fully-featured TeX document (with bibliography
+and index) in a build_dir.
+
+Test courtesy Rob Managan.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+latex = test.where_is('latex')
+dvipdf = test.where_is('dvipdf')
+makeindex = test.where_is('makeindex')
+bibtex = test.where_is('bibtex')
+if not latex or not makeindex or not bibtex or not dvipdf:
+ test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or dvipdf; skipping test.\n")
+
+test.subdir(['docs'])
+
+
+test.write(['SConstruct'], """\
+import os
+
+env = Environment(ENV = { 'PATH' : os.environ['PATH'] },
+ TOOLS = ['tex', 'latex', 'dvipdf'])
+Export(['env'])
+
+SConscript(os.path.join('docs', 'SConscript'),
+ build_dir=os.path.join('mybuild','docs'),
+ duplicate=0)
+""")
+
+
+test.write(['docs', 'SConscript'], """\
+Import('env')
+
+test_dvi = env.DVI(source='test.tex')
+testpdf = env.PDF(source=test_dvi)
+""")
+
+
+test.write(['docs', 'Fig1.ps'], """\
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: Fig1.fig
+%%Creator: fig2dev Version 3.2 Patchlevel 4
+%%CreationDate: Tue Apr 25 09:56:11 2006
+%%BoundingBox: 0 0 98 98
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+
+end
+save
+newpath 0 98 moveto 0 0 lineto 98 0 lineto 98 98 lineto closepath clip newpath
+-24.9 108.2 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/sc {scale} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/tr {translate} bind def
+ /DrawEllipse {
+ /endangle exch def
+ /startangle exch def
+ /yrad exch def
+ /xrad exch def
+ /y exch def
+ /x exch def
+ /savematrix mtrx currentmatrix def
+ x y tr xrad yrad sc 0 0 1 startangle endangle arc
+ closepath
+ savematrix setmatrix
+ } def
+
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06299 0.06299 sc
+%
+% Fig objects follow
+%
+7.500 slw
+% Ellipse
+n 1170 945 766 766 0 360 DrawEllipse gs col0 s gr
+
+$F2psEnd
+rs
+""")
+
+
+test.write(['docs', 'Fig1.tex'],
+r"""\begin{picture}(0,0)%
+\includegraphics{Fig1.ps}%
+\end{picture}%
+\setlength{\unitlength}{4144sp}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined%
+\gdef\SetFigFont#1#2#3#4#5{%
+ \reset@font\fontsize{#1}{#2pt}%
+ \fontfamily{#3}\fontseries{#4}\fontshape{#5}%
+ \selectfont}%
+\fi\endgroup%
+\begin{picture}(1548,1546)(397,-879)
+\put(856,-196){\makebox(0,0)[lb]{\smash{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}center $r_0$}%
+}}}
+\end{picture}
+""")
+
+
+test.write(['docs', 'test.bib'], """\
+%% This BibTeX bibliography file was created using BibDesk.
+%% http://bibdesk.sourceforge.net/
+
+%% Saved with string encoding Western (ASCII)
+
+@techreport{AnAuthor:2006fk,
+ Author = {A. N. Author},
+ Date-Added = {2006-11-15 12:51:30 -0800},
+ Date-Modified = {2006-11-15 12:52:35 -0800},
+ Institution = {none},
+ Month = {November},
+ Title = {A Test Paper},
+ Year = {2006}}
+""")
+
+
+test.write(['docs', 'test.tex'],
+r"""\documentclass{report}
+
+\usepackage{graphicx}
+\usepackage{epsfig,color} % for .tex version of figures if we go that way
+
+\usepackage{makeidx}
+\makeindex
+
+\begin{document}
+
+\title{Report Title}
+
+\author{A. N. Author}
+
+\maketitle
+
+\begin{abstract}
+there is no abstract
+\end{abstract}
+
+\tableofcontents
+\listoffigures
+
+\chapter{Introduction}
+
+The introduction is short.
+
+\index{Acknowledgements}
+
+\section{Acknowledgements}
+
+The Acknowledgements are show as well \cite{AnAuthor:2006fk}.
+
+\index{Getting the Report}
+
+To get a hard copy of this report call me.
+
+\begin{figure}[htbp]
+\begin{center}
+\input{Fig1.tex} % testing figure variant that uses TeX labeling
+\caption{Zone and Node indexing}
+\label{fig1}
+\end{center}
+\end{figure}
+
+All done now.
+
+\bibliographystyle{unsrt}
+\bibliography{test}
+\newpage
+
+\printindex
+
+\end{document}
+""")
+
+
+# makeindex will write status messages to stderr (grrr...), so ignore it.
+test.run(arguments = '.', stderr=None)
+
+
+# All (?) the files we expect will get created in the build_dir
+# (mybuild/docs) and not in the srcdir (docs).
+files = [
+ 'test.aux',
+ 'test.bbl',
+ 'test.blg',
+ 'test.dvi',
+ 'test.idx',
+ 'test.ilg',
+ 'test.ind',
+ 'test.lof',
+ 'test.log',
+ 'test.pdf',
+ 'test.toc',
+]
+
+for f in files:
+ test.must_exist(['mybuild', 'docs', f])
+ test.must_not_exist(['docs', f])
+
+
+test.pass_test()
diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py
index d4e2d79..686263d 100644
--- a/test/TEX/multi-run.py
+++ b/test/TEX/multi-run.py
@@ -28,6 +28,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Validate that both .tex and .ltx files can handle a LaTeX-style
bibliography (by calling $BIBTEX to generate a .bbl file) and
correctly re-run to resolve undefined references.
+
+Also verifies that package warnings are caught and re-run as needed.
"""
import string
@@ -42,7 +44,7 @@ latex = test.where_is('latex')
if not tex and not latex:
test.skip_test("Could not find tex or latex; skipping test(s).\n")
-test.subdir('work1', 'work2', 'work4')
+test.subdir('work1', 'work2', 'work3', 'work4')
input_file = r"""
@@ -64,6 +66,62 @@ Hello world.
\end{document}
"""
+input_file3 = r"""
+\documentclass{article}
+\usepackage{longtable}
+
+\begin{document}
+As stated in the last paper, this is a bug-a-boo.
+here is some more junk and another table
+here is some more junk and another table
+
+\begin{longtable}[l]{rlll}
+ Isotope &\multicolumn{1}{c}{Abar} &Name\\
+\\
+ 1001 &1.0078 &Proton &$p$\\
+ 1002 &2.0141 &Deuterium &$d$\\
+ 1003 &3.0170 &Tritium &$t$\\
+ 2003 &3.0160 &Helium 3 &He$^3$\\
+ 2004 &4.0026 &Helium 4 &He$^{4}$\\
+\end{longtable}
+
+and a closing comment
+
+ These parameters and arrays are filled in when the parameter \textbf{iftnrates}
+ is set to 1:
+
+\begin{longtable}[l]{ll}
+\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\\
+\textbf{reactot}(r) &Total number of reactions for reaction r\\
+\textbf{reacreg}(r,ir) &Total number of reactions for reaction r in region ir\\
+\end{longtable}
+
+
+\end{document}
+"""
+
bibfile = r"""
@Article{X,
author = "Mr. X",
@@ -95,6 +153,20 @@ PDF( "foo.tex" )
print foo_log
test.fail_test(1)
+ test.write(['work3', 'SConstruct'], """\
+DVI( "foo3.tex" )
+""")
+
+ test.write(['work3', 'foo3.tex'], input_file3)
+
+ test.run(chdir = 'work3', arguments = '.')
+
+ foo_log = test.read(['work3', 'foo3.log'])
+ if string.find(foo_log, 'Rerun LaTeX') != -1:
+ print 'foo.log contains "Rerun LaTeX":'
+ print foo_log
+ test.fail_test(1)
+
if latex:
@@ -117,6 +189,20 @@ PDF( "foo.ltx" )
print foo_log
test.fail_test(1)
+ test.write(['work3', 'SConstruct'], """\
+DVI( "foo3.tex" )
+PDF( "foo3.tex" )
+""")
+
+ test.write(['work3', 'foo3.tex'], input_file3)
+
+ test.run(chdir = 'work3', arguments = '.')
+
+ foo_log = test.read(['work3', 'foo3.log'])
+ if string.find(foo_log, 'Rerun LaTeX') != -1:
+ print 'foo.log contains "Rerun LaTeX":'
+ print foo_log
+ test.fail_test(1)
test.write(['work4', 'SConstruct'], """\
diff --git a/test/YACC/live.py b/test/YACC/live.py
index 4934570..0e5f156 100644
--- a/test/YACC/live.py
+++ b/test/YACC/live.py
@@ -103,13 +103,19 @@ graph: GRAPH_T
%%
""")
+import sys
+if sys.platform == 'darwin':
+ file_hpp = 'file.cpp.h'
+else:
+ file_hpp = 'file.hpp'
+
test.write("hello.cpp", """\
-#include "file.hpp"
+#include "%(file_hpp)s"
int main()
{
}
-""")
+""" % locals())
test.write('foo.y', yacc % 'foo.y')
diff --git a/test/build-errors.py b/test/build-errors.py
deleted file mode 100644
index e25fbd5..0000000
--- a/test/build-errors.py
+++ /dev/null
@@ -1,223 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
-import string
-import sys
-import TestCmd
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-no_such_file = test.workpath("no_such_file")
-not_executable = test.workpath("not_executable")
-
-test.write(not_executable, "\n")
-
-test.write("f1.in", "\n")
-test.write("f2.in", "\n")
-test.write("f3.in", "\n")
-
-test.write('SConstruct1', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld' : bld })
-env.bld(target = 'f1', source = 'f1.in')
-""" % string.replace(no_such_file, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct1 .',
- stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1),
- stderr = None,
- status = 2)
-
-bad_command = """\
-Bad command or file name
-"""
-
-unrecognized = """\
-'%s' is not recognized as an internal or external command,
-operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-unspecified = """\
-The name specified is not recognized as an
-internal or external command, operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-not_found_1 = """
-sh: %s: not found
-scons: *** [%s] Error 1
-"""
-
-not_found_2 = """
-sh: %s: not found
-scons: *** [%s] Error 1
-"""
-
-No_such = """\
-%s: No such file or directory
-scons: *** [%s] Error 127
-"""
-
-cannot_execute = """\
-%s: cannot execute
-scons *** [%s] Error 126
-"""
-
-Permission_denied = """\
-%s: Permission denied
-scons: *** [%s] Error 126
-"""
-
-permission_denied = """\
-%s: permission denied
-scons: *** [%s] Error 126
-"""
-
-is_a_directory = """\
-%s: is a directory
-scons: *** [%s] Error 126
-"""
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (no_such_file, 'f1'),
- unspecified % 'f1'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- not_found_1 % (no_such_file, 'f1'),
- not_found_2 % (no_such_file, 'f1'),
- No_such % (no_such_file, 'f1'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct2', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld': bld })
-env.bld(target = 'f2', source = 'f2.in')
-""" % string.replace(not_executable, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct2 .',
- stdout = test.wrap_stdout("%s f2.in f2\n" % not_executable, error=1),
- stderr = None,
- status = 2)
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (not_executable, 'f2'),
- unspecified % 'f2'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- cannot_execute % (not_executable, 'f2'),
- Permission_denied % (not_executable, 'f2'),
- permission_denied % (not_executable, 'f2'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct3', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld' : bld })
-env.bld(target = 'f3', source = 'f3.in')
-""" % string.replace(test.workdir, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct3 .',
- stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1),
- stderr = None,
- status = 2)
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (test.workdir, 'f3'),
- unspecified % 'f3'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- cannot_execute % (not_executable, 'f3'),
- is_a_directory % (test.workdir, 'f3'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct4', r"""
-env = Environment()
-env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE'))
-env.InstallAs('test2.out', 'test.out')
-# Mark test2.out as precious so we'll handle the exception in
-# FunctionAction() rather than when the target is cleaned before building.
-env.Precious('test2.out')
-env.Default('test2.out')
-""")
-
-test.write('test.in', "test.in 1\n")
-
-test.run(arguments = '-f SConstruct4 .')
-
-test.write('test.in', "test.in 2\n")
-
-test.writable('test2.out', 0)
-f = open(test.workpath('test2.out'))
-
-test.run(arguments = '-f SConstruct4 .',
- stderr = None,
- status = 2)
-
-f.close()
-test.writable('test2.out', 1)
-
-test.description_set("Incorrect STDERR:\n%s" % test.stderr())
-errs = [
- "scons: *** [test2.out] test2.out: Permission denied\n",
- "scons: *** [test2.out] test2.out: permission denied\n",
-]
-test.fail_test(test.stderr() not in errs)
-
-test.pass_test()
diff --git a/test/builderrors.py b/test/builderrors.py
index 8c7c4ab..28c9a0a 100644
--- a/test/builderrors.py
+++ b/test/builderrors.py
@@ -145,10 +145,10 @@ test.fail_test(string.find(err, 'Exception') != -1 or \
# Test bad shell ('./one' is a dir, so it can't be used as a shell).
# This will also give an exit status not in exitvalmap,
-# with error "Permission denied".
+# with error "Permission denied" or "No such file or directory".
test.write('SConstruct', """
env=Environment()
-if env['PLATFORM'] == 'posix':
+if env['PLATFORM'] in ('posix', 'darwin'):
from SCons.Platform.posix import fork_spawn
env['SPAWN'] = fork_spawn
env['SHELL'] = 'one'
@@ -157,10 +157,14 @@ env.Command(target='badshell.out', source=[], action='foo')
test.run(status=2, stderr=None)
err = test.stderr()
-test.fail_test(string.find(err, 'Exception') != -1 or \
- string.find(err, 'Traceback') != -1)
-test.fail_test(string.find(err, "ermission") == -1 and \
- string.find(err, "such file") == -1)
+if string.find(err, 'Exception') != -1 or string.find(err, 'Traceback') != -1:
+ print "Exception or Traceback found in the following error output:"
+ print err
+ test.fail_test()
+if string.find(err, 'ermission') == -1 and string.find(err, 'such file') == -1:
+ print "Missing '[Pp]ermission' or 'such file' string in the following error output:"
+ print err
+ test.fail_test()
# Test command with exit status -1.
diff --git a/test/import.py b/test/import.py
index 9c5d3af..85948f9 100644
--- a/test/import.py
+++ b/test/import.py
@@ -96,6 +96,7 @@ tools = [
'g77',
'gas',
'gcc',
+ 'gfortran',
'gnulink',
'gs',
'hpc++',
diff --git a/test/option-k.py b/test/option-k.py
index 0a46606..4a460a2 100644
--- a/test/option-k.py
+++ b/test/option-k.py
@@ -32,7 +32,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-test.subdir('work1', 'work2')
+test.subdir('work1', 'work2', 'work3')
@@ -49,6 +49,11 @@ import sys
sys.exit(1)
""")
+
+#
+# Test: work1
+#
+
test.write(['work1', 'SConstruct'], """\
Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS')
@@ -90,7 +95,27 @@ test.must_not_exist(test.workpath('work1', 'aaa.1'))
test.must_not_exist(test.workpath('work1', 'aaa.out'))
test.must_match(['work1', 'bbb.out'], "succeed.py: bbb.out\n")
+expect = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Cleaning targets ...
+Removed bbb.out
+scons: done cleaning targets.
+"""
+
+test.run(chdir = 'work1',
+ arguments = '--clean --keep-going aaa.out bbb.out',
+ stdout = expect)
+
+test.must_not_exist(test.workpath('work1', 'aaa.1'))
+test.must_not_exist(test.workpath('work1', 'aaa.out'))
+test.must_not_exist(test.workpath('work1', 'bbb.out'))
+
+
+#
+# Test: work2
+#
test.write(['work2', 'SConstruct'], """\
Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
@@ -126,4 +151,145 @@ test.must_match(['work2', 'ddd.out'], "succeed.py: ddd.out\n")
+#
+# Test: work3
+#
+# Check that the -k (keep-going) switch works correctly when the Nodes
+# forms a DAG. The test case is the following
+#
+# all
+# |
+# +-----+-----+-------------+
+# | | |
+# a1 a2 a3
+# | | |
+# + +---+---+ +---+---+
+# \ | / | |
+# \ bbb.out / a4 ccc.out
+# \ / /
+# \ / /
+# \ / /
+# aaa.out (fails)
+#
+
+test.write(['work3', 'SConstruct'], """\
+Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
+Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS')
+env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail })
+a = env.Fail('aaa.out', 'aaa.in')
+b = env.Succeed('bbb.out', 'bbb.in')
+c = env.Succeed('ccc.out', 'ccc.in')
+
+a1 = Alias( 'a1', a )
+a2 = Alias( 'a2', a+b)
+a4 = Alias( 'a4', c)
+a3 = Alias( 'a3', a4+c)
+
+Alias('all', a1+a2+a3)
+""" % locals())
+
+test.write(['work3', 'aaa.in'], "aaa.in\n")
+test.write(['work3', 'bbb.in'], "bbb.in\n")
+test.write(['work3', 'ccc.in'], "ccc.in\n")
+
+
+# Test tegular build (i.e. without -k)
+test.run(chdir = 'work3',
+ arguments = '.',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+scons: building terminated because of errors.
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Current directory
+test.run(chdir = 'work3',
+ arguments = '-k .',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Single target
+test.run(chdir = 'work3',
+ arguments = '--keep-going all',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Separate top-level targets
+test.run(chdir = 'work3',
+ arguments = '-k a1 a2 a3',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
test.pass_test()
diff --git a/test/option/debug-includes.py b/test/option/debug-includes.py
index 172cbb0..70857e6 100644
--- a/test/option/debug-includes.py
+++ b/test/option/debug-includes.py
@@ -79,7 +79,14 @@ includes = """
+-bar.h
"""
test.run(arguments = "--debug=includes foo.ooo")
-test.fail_test(string.find(test.stdout(), includes) == -1)
+
+if string.find(test.stdout(), includes) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print includes
+ print "Actual ============================================================"
+ print test.stdout()
+ test.fail_test()
# In an ideal world, --debug=includes would also work when there's a build
# failure, but this would require even more complicated logic to scan
diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py
index 8c8b2cf..ad35b5d 100644
--- a/test/option/debug-memoizer.py
+++ b/test/option/debug-memoizer.py
@@ -29,6 +29,7 @@ Test calling the --debug=memoizer option.
"""
import os
+import new
import string
import TestSCons
@@ -39,15 +40,22 @@ test = TestSCons.TestSCons(match = TestSCons.match_re)
class M:
def __init__(cls, name, bases, cls_dict):
- cls.has_metaclass = 1
-
-class A:
- __metaclass__ = M
+ cls.use_metaclass = 1
+ def fake_method(self):
+ pass
+ new.instancemethod(fake_method, None, cls)
try:
- has_metaclass = A.has_metaclass
+ class A:
+ __metaclass__ = M
+
+ use_metaclass = A.use_metaclass
except AttributeError:
- has_metaclass = None
+ use_metaclass = None
+ reason = 'no metaclasses'
+except TypeError:
+ use_metaclass = None
+ reason = 'new.instancemethod\\(\\) bug'
@@ -72,12 +80,8 @@ expect = [
"Node._children_get()",
]
-expect_no_metaclasses = """
-scons: warning: memoization is not supported in this version of Python \\(no metaclasses\\)
-""" + TestSCons.file_expr
-
-if has_metaclass:
+if use_metaclass:
def run_and_check(test, args, desc):
test.run(arguments = args)
@@ -92,6 +96,12 @@ if has_metaclass:
else:
+ expect_no_metaclasses = """
+scons: warning: memoization is not supported in this version of Python \\(%s\\)
+""" % reason
+
+ expect_no_metaclasses = expect_no_metaclasses + TestSCons.file_expr
+
def run_and_check(test, args, desc):
test.run(arguments = args, stderr = expect_no_metaclasses)
stdout = test.stdout()
diff --git a/test/option/stack-size.py b/test/option/stack-size.py
new file mode 100644
index 0000000..495f86d
--- /dev/null
+++ b/test/option/stack-size.py
@@ -0,0 +1,357 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import string
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+isStackSizeAvailable = False
+try:
+ import threading
+ isStackSizeAvailable = hasattr(threading,'stack_size')
+except ImportError:
+ pass
+
+test.subdir('work1', 'work2')
+
+test.write('build.py', r"""
+import sys
+contents = open(sys.argv[2], 'rb').read()
+file = open(sys.argv[1], 'wb')
+file.write(contents)
+file.close()
+""")
+
+
+test.write(['work1', 'SConstruct'], """
+B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+f1 = env.B(target = 'f1.out', source = 'f1.in')
+f2 = env.B(target = 'f2.out', source = 'f2.in')
+Requires(f2, f1)
+""" % locals())
+
+test.write(['work1', 'f1.in'], "f1.in\n")
+test.write(['work1', 'f2.in'], "f2.in\n")
+
+
+test.write(['work2', 'SConstruct'], """
+SetOption('stack_size', 128)
+B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+f1 = env.B(target = 'f1.out', source = 'f1.in')
+f2 = env.B(target = 'f2.out', source = 'f2.in')
+Requires(f2, f1)
+""" % locals())
+
+test.write(['work2', 'f1.in'], "f1.in\n")
+test.write(['work2', 'f2.in'], "f2.in\n")
+
+
+
+expected_stdout = test.wrap_stdout("""\
+%(_python_)s ../build.py f1.out f1.in
+%(_python_)s ../build.py f2.out f2.in
+""" % locals())
+
+re_expected_stdout = string.replace(expected_stdout, '\\', '\\\\')
+
+expect_unsupported = """
+scons: warning: Setting stack size is unsupported by this version of Python:
+ (('module' object|'threading' module) has no attribute 'stack_size'|stack_size)
+File .*
+"""
+
+
+#
+# Test without any options
+#
+test.run(chdir='work1',
+ arguments = '.',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '-c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+#
+# Test with -j2
+#
+test.run(chdir='work1',
+ arguments = '-j2 .',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '-j2 -c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+
+#
+# Test with --stack-size
+#
+test.run(chdir='work1',
+ arguments = '--stack-size=128 .',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '--stack-size=128 -c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+#
+# Test with SetOption('stack_size', 128)
+#
+test.run(chdir='work2',
+ arguments = '.',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work2', 'f1.out'])
+test.must_exist(['work2', 'f2.out'])
+
+test.run(chdir='work2',
+ arguments = '--stack-size=128 -c .')
+test.must_not_exist(['work2', 'f1.out'])
+test.must_not_exist(['work2', 'f2.out'])
+
+if isStackSizeAvailable:
+ #
+ # Test with -j2 --stack-size=128
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr="""
+scons: warning: Setting stack size failed:
+ size not valid: 16384 bytes
+File .*
+""")
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 -c .',
+ match=TestSCons.match_re,
+ stderr="""
+scons: warning: Setting stack size failed:
+ size not valid: 16384 bytes
+File .*
+""")
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=128 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+else:
+
+ #
+ # Test with -j2 --stack-size=128
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=128 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+test.pass_test()
diff --git a/test/scons-time/func/file.py b/test/scons-time/func/file.py
index c9486c4..079c125 100644
--- a/test/scons-time/func/file.py
+++ b/test/scons-time/func/file.py
@@ -31,7 +31,7 @@ affect how the func subcommand processes things.
import TestSCons_time
-test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+test = TestSCons_time.TestSCons_time()
try:
import pstats
@@ -56,22 +56,43 @@ prefix = 'foo-001'
expect1 = r'\d.\d\d\d prof1\.py:1\(_main\)' + '\n'
-test.run(arguments = 'func -f st1.conf', stdout = expect1)
+test.run(arguments = 'func -f st1.conf',
+ match = TestSCons_time.match_re,
+ stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.4, 7, None ),
+ ( 1.5, 7, "label 1.5" ),
+ ( 1.6, 7, "label 1.6" ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+set label 3 "label 1.5" at 0.5,1.5 right
+set label 4 "label 1.6" at 0.6,1.5 right
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7, \
+ '-' title "label 1.5" with lines lt 7, \
+ '-' title "label 1.6" with lines lt 7
# Startup
1 0.000
2 0.000
e
+1.4 0
+1.4 1
+e
+1.5 0
+1.5 1
+e
+1.6 0
+1.6 1
+e
"""
test.run(arguments = 'func --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/mem/file.py b/test/scons-time/mem/file.py
index a236df7..a1e7181 100644
--- a/test/scons-time/mem/file.py
+++ b/test/scons-time/mem/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'mem -f st1.conf', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 4000.000
2 4000.000
e
+1.5 0
+1.5 4800
+e
"""
test.run(arguments = 'mem --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/obj/file.py b/test/scons-time/obj/file.py
index c881397..3cf8e74 100644
--- a/test/scons-time/obj/file.py
+++ b/test/scons-time/obj/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'obj -f st1.conf Node.FS.Base', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 16040.000
2 16040.000
e
+1.5 0
+1.5 18000
+e
"""
test.run(arguments = 'obj --file st2.conf --fmt gnuplot Node.FS.Base', stdout = expect2)
diff --git a/test/scons-time/run/aegis.py b/test/scons-time/run/aegis.py
index 8f378cb..641f129 100644
--- a/test/scons-time/run/aegis.py
+++ b/test/scons-time/run/aegis.py
@@ -59,22 +59,9 @@ test.must_exist('foo-329-0.log',
'foo-329-2.log',
'foo-329-2.prof')
-def tempdir_re(*args):
- import os
- import os.path
- import string
- import tempfile
-
- sep = re.escape(os.sep)
- args = (tempfile.gettempdir(), 'scons-time-aegis-',) + args
- x = apply(os.path.join, args)
- x = re.escape(x)
- x = string.replace(x, 'aegis\\-', 'aegis\\-[^%s]*' % sep)
- return x
-
expect = [
- tempdir_re('src', 'script', 'scons.py'),
- 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'),
+ test.tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'),
]
content = test.read(test.workpath('foo-321-2.log'))
diff --git a/test/scons-time/run/config/archive_list.py b/test/scons-time/run/config/archive_list.py
index 8d48d26..8ddde3d 100644
--- a/test/scons-time/run/config/archive_list.py
+++ b/test/scons-time/run/config/archive_list.py
@@ -38,9 +38,11 @@ test.write_fake_scons_py()
test.write_sample_project('foo.tar.gz')
test.write('config', """\
-archive_list = ['foo.tar.gz']
+archive_list = ['foo.tar.gz', 'foo-file']
""")
+test.write('foo-file', "foo-file\n")
+
test.run(arguments = 'run -f config')
test.must_exist('foo-000-0.log',
@@ -50,6 +52,8 @@ test.must_exist('foo-000-0.log',
'foo-000-2.log',
'foo-000-2.prof')
+test.must_exist('foo-file')
+
test.write_sample_project('bar.tar.gz')
diff --git a/test/scons-time/run/option/quiet.py b/test/scons-time/run/option/quiet.py
index f5a3d8c..453829c 100644
--- a/test/scons-time/run/option/quiet.py
+++ b/test/scons-time/run/option/quiet.py
@@ -37,28 +37,11 @@ python = TestSCons_time.python
test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
test.diff_function = TestSCons_time.diff_re
-
-def tempdir_re(*args):
- import os,sys
- import os.path
- import string
- import tempfile
-
- sep = re.escape(os.sep)
- args = (tempfile.gettempdir(), 'scons-time-',) + args
- x = apply(os.path.join, args)
- x = re.escape(x)
- x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep)
- if sys.platform=='darwin':
- # OSX has /tmp in /private/tmp.
- x = '(/private)?' + x
- return x
-
scons_py = re.escape(test.workpath('src', 'script', 'scons.py'))
src_engine = re.escape(test.workpath('src', 'engine'))
-tmp_scons_time = tempdir_re()
-tmp_scons_time_foo = tempdir_re('foo')
+tmp_scons_time = test.tempdir_re()
+tmp_scons_time_foo = test.tempdir_re('foo')
test.write_fake_scons_py()
diff --git a/test/scons-time/run/option/verbose.py b/test/scons-time/run/option/verbose.py
index fb95dab..935e2a9 100644
--- a/test/scons-time/run/option/verbose.py
+++ b/test/scons-time/run/option/verbose.py
@@ -38,28 +38,11 @@ _python_ = re.escape(TestSCons_time._python_)
test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
test.diff_function = TestSCons_time.diff_re
-
-def tempdir_re(*args):
- import os,sys
- import os.path
- import string
- import tempfile
-
- sep = re.escape(os.sep)
- args = (tempfile.gettempdir(), 'scons-time-',) + args
- x = apply(os.path.join, args)
- x = re.escape(x)
- x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep)
- if sys.platform=='darwin':
- # OSX has /tmp in /private/tmp.
- x = '(/private)?' + x
- return x
-
scons_py = re.escape(test.workpath('src', 'script', 'scons.py'))
src_engine = re.escape(test.workpath('src', 'engine'))
-tmp_scons_time = tempdir_re()
-tmp_scons_time_foo = tempdir_re('foo')
+tmp_scons_time = test.tempdir_re()
+tmp_scons_time_foo = test.tempdir_re('foo')
test.write_fake_scons_py()
diff --git a/test/scons-time/run/subversion.py b/test/scons-time/run/subversion.py
index 3839999..757f6df 100644
--- a/test/scons-time/run/subversion.py
+++ b/test/scons-time/run/subversion.py
@@ -60,22 +60,9 @@ test.must_exist('foo-716-0.log',
'foo-716-2.log',
'foo-716-2.prof')
-def tempdir_re(*args):
- import os
- import os.path
- import string
- import tempfile
-
- sep = re.escape(os.sep)
- args = (tempfile.gettempdir(), 'scons-time-svn-',) + args
- x = apply(os.path.join, args)
- x = re.escape(x)
- x = string.replace(x, 'svn\\-', 'svn\\-[^%s]*' % sep)
- return x
-
expect = [
- tempdir_re('src', 'script', 'scons.py'),
- 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'),
+ test.tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'),
]
content = test.read(test.workpath('foo-617-2.log'), mode='r')
diff --git a/test/scons-time/time/empty.py b/test/scons-time/time/empty.py
new file mode 100644
index 0000000..7542bfc
--- /dev/null
+++ b/test/scons-time/time/empty.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the time subcommand doesn't fail and prints an appropriate
+error message if a log file is empty.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = ' Total SConscripts SCons commands\n'
+
+lines = []
+
+line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n'
+empty_fmt = ' %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s-0.log' % i
+ if i == 5:
+ test.write(test.workpath(logfile_name), "")
+ lines.append(empty_fmt % logfile_name)
+ else:
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = [header] + lines
+
+test.run(arguments = 'time foo-*.log',
+ stdout = ''.join(expect),
+ stderr = "file 'foo-5-0.log' has no contents!\n")
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+0 11.123456
+1 11.123456
+2 11.123456
+3 11.123456
+4 11.123456
+6 11.123456
+7 11.123456
+8 11.123456
+e
+"""
+
+stderr = "file 'foo-5-0.log' has no contents!\n"
+
+test.run(arguments = 'time --fmt gnuplot --which total foo-*.log',
+ stdout = expect,
+ stderr = stderr)
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+e
+"""
+
+test.run(arguments = 'time --fmt gnuplot foo-5-0.log',
+ stdout = expect,
+ stderr = stderr)
+
+test.pass_test()
diff --git a/test/scons-time/time/file.py b/test/scons-time/time/file.py
index f4046c9..96bd035 100644
--- a/test/scons-time/time/file.py
+++ b/test/scons-time/time/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'time -f st1.conf', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 11.123456
2 11.123456
e
+1.5 0
+1.5 12
+e
"""
test.run(arguments = 'time --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/time/no-result.py b/test/scons-time/time/no-result.py
new file mode 100644
index 0000000..ca345b2
--- /dev/null
+++ b/test/scons-time/time/no-result.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the time subcommand's --which option doesn't fail, and prints
+an appropriate error message, if a log file doesn't have its specific
+requested results.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+"""
+
+footer = """\
+e
+"""
+
+line_fmt = "%s 11.123456\n"
+
+lines = []
+
+for i in xrange(9):
+ logfile_name = 'foo-%s-0.log' % i
+ if i == 5:
+ test.write(test.workpath(logfile_name), "NO RESULTS HERE!\n")
+ else:
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % i)
+
+expect = [header] + lines + [footer]
+
+stderr = "file 'foo-5-0.log' has no results!\n"
+
+
+test.run(arguments = 'time --fmt gnuplot --which total foo*.log',
+ stdout = ''.join(expect),
+ stderr = stderr)
+
+expect = [header] + [footer]
+
+test.run(arguments = 'time --fmt gnuplot foo-5-0.log',
+ stdout = ''.join(expect),
+ stderr = stderr)
+
+test.pass_test()
diff --git a/test/subclassing.py b/test/subclassing.py
index 18be1bc..31632a9 100644
--- a/test/subclassing.py
+++ b/test/subclassing.py
@@ -25,7 +25,9 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Verify that we can trivially subclass our "public" classes.
+Verify that we can trivially subclass our "public" classes. Also
+verify that we can use a trivial subclass of new-style str classes
+as well as UserString as Builder input.
"""
import TestSCons
@@ -33,6 +35,8 @@ import TestSCons
test = TestSCons.TestSCons()
test.write('SConstruct', """
+copy_action = Copy('$TARGET', '$SOURCE')
+
# Some day, we'd probably like people to be able to subclass Action and
# Builder, but that's going to take some serious class-hackery to turn
# our factory function into the class itself.
@@ -45,18 +49,31 @@ class my_Scanner(Scanner):
class my_Environment(Environment):
pass
env = my_Environment()
-env.Program('hello', 'hello.c')
-""")
+env.Command('f0.out', 'f0.in', copy_action)
+
+from UserString import UserString
+try:
+ class mystr(str):
+ pass
+except TypeError:
+ class mystr(UserString):
+ pass
-test.write('hello.c', """\
-#include <stdio.h>
-#include <stdlib.h>
-int
-main(int argc, char *argv[]) {
- printf("hello.c\\n");
-}
+Command(mystr('f1.out'), mystr('f1.in'), copy_action)
+Command(UserString('f2.out'), UserString('f2.in'), copy_action)
+
+Install(mystr('install'), mystr('f1.out'))
+Install(mystr('install'), UserString('f2.out'))
""")
+test.write('f0.in', "f0.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
test.run(arguments = '.')
+test.must_match('f0.out', "f0.in\n")
+test.must_match(['install', 'f1.out'], "f1.in\n")
+test.must_match(['install', 'f2.out'], "f2.in\n")
+
test.pass_test()
diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py
index 9d89d70..0774995 100644
--- a/test/timestamp-fallback.py
+++ b/test/timestamp-fallback.py
@@ -79,7 +79,8 @@ test.write('f2.in', "f2.in\n")
test.write('f3.in', "f3.in\n")
test.write('f4.in', "f4.in\n")
-test.run(arguments = 'f1.out f3.out')
+test.run(arguments = 'f1.out f3.out',
+ stderr = None)
test.run(arguments = 'f1.out f2.out f3.out f4.out',
stdout = test.wrap_stdout("""\
@@ -87,7 +88,8 @@ scons: `f1.out' is up to date.
build(["f2.out"], ["f2.in"])
scons: `f3.out' is up to date.
build(["f4.out"], ["f4.in"])
-"""))
+"""),
+ stderr = None)
os.utime(test.workpath('f1.in'),
(os.path.getatime(test.workpath('f1.in')),
@@ -102,7 +104,8 @@ build(["f1.out"], ["f1.in"])
scons: `f2.out' is up to date.
build(["f3.out"], ["f3.in"])
scons: `f4.out' is up to date.
-"""))
+"""),
+ stderr = None)
test.pass_test()