summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Actions/addpost-link.py22
-rw-r--r--test/Actions/exitstatfunc.py67
-rw-r--r--test/Actions/timestamp.py56
-rw-r--r--test/AddMethod.py12
-rw-r--r--test/Alias/Depends.py162
-rw-r--r--test/BuildDir/errors.py1
-rw-r--r--test/Builder/ensure_suffix.py55
-rw-r--r--test/CacheDir/multiple-targets.py66
-rw-r--r--test/CacheDir/scanner-target.py80
-rw-r--r--test/CacheDir/timestamp.py48
-rw-r--r--test/Configure/clean.py96
-rw-r--r--test/Configure/help.py109
-rw-r--r--test/Copy.py13
-rw-r--r--test/Decider/Environment.py61
-rw-r--r--test/Decider/MD5-timestamp.py81
-rw-r--r--test/Decider/Node.py61
-rw-r--r--test/Decider/default.py59
-rw-r--r--test/Decider/mixed.py115
-rw-r--r--test/Decider/timestamp.py113
-rw-r--r--test/Decider/unknown.py46
-rw-r--r--test/Delete.py20
-rw-r--r--test/Depends.py3
-rw-r--r--test/Dir/source.py4
-rw-r--r--test/Errors/preparation.py11
-rw-r--r--test/Install/Install.py22
-rw-r--r--test/Install/tool.py51
-rw-r--r--test/Java/JAVABOOTCLASSPATH.py108
-rw-r--r--test/Java/multi-step.py22
-rw-r--r--test/Java/swig-dependencies.py19
-rw-r--r--test/LIBS.py2
-rw-r--r--test/MinGW/RCCOM.py4
-rw-r--r--test/MinGW/RCCOMSTR.py4
-rw-r--r--test/NodeOps.py10
-rw-r--r--test/Parallel/duplicate-target.py74
-rw-r--r--test/Progress/TARGET.py66
-rw-r--r--test/Progress/dots.py60
-rw-r--r--test/Progress/file.py81
-rw-r--r--test/Progress/function.py75
-rw-r--r--test/Progress/interval.py68
-rw-r--r--test/Progress/object.py78
-rw-r--r--test/Progress/spinner.py66
-rw-r--r--test/QT/installed.py9
-rw-r--r--test/QT/moc-from-header.py3
-rw-r--r--test/SConscript/Return.py93
-rw-r--r--test/SWIG/build-dir.py8
-rw-r--r--test/Scanner/generated.py9
-rw-r--r--test/Sig.py62
-rw-r--r--test/SourceCode.py2
-rw-r--r--test/SourceSignatures.py268
-rw-r--r--test/SourceSignatures/basic.py124
-rw-r--r--test/SourceSignatures/env.py96
-rw-r--r--test/SourceSignatures/implicit-cache.py87
-rw-r--r--test/SourceSignatures/no-csigs.py70
-rw-r--r--test/SourceSignatures/overrides.py56
-rw-r--r--test/SourceSignatures/switch-rebuild.py81
-rw-r--r--test/TEX/auxiliaries.py13
-rw-r--r--test/TEX/clean.py94
-rw-r--r--test/TargetSignatures/build-content.py (renamed from test/TargetSignatures.py)100
-rw-r--r--test/TargetSignatures/content.py81
-rw-r--r--test/TargetSignatures/overrides.py52
-rw-r--r--test/Value.py22
-rw-r--r--test/bad-drive.py2
-rw-r--r--test/chained-build.py29
-rw-r--r--test/exceptions.py63
-rw-r--r--test/explain/get_csig.py75
-rw-r--r--test/implicit-cache/basic.py6
-rw-r--r--test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py125
-rw-r--r--test/implicit/asynchronous-modification.py89
-rw-r--r--test/implicit/changed-node.py (renamed from test/changed-node.py)0
-rw-r--r--test/option-u.py1
-rw-r--r--test/option/debug-memoizer.py1
-rw-r--r--test/option/debug-stree.py38
-rw-r--r--test/option/debug-time.py6
-rw-r--r--test/option/debug-tree.py46
-rw-r--r--test/option/taskmastertrace.py65
-rw-r--r--test/option/tree-all.py89
-rw-r--r--test/option/tree-lib.py88
-rw-r--r--test/packaging/convenience-functions.py76
-rw-r--r--test/packaging/msi/explicit-target.py92
-rw-r--r--test/packaging/multiple-packages-at-once.py82
-rw-r--r--test/packaging/multiple-subdirs.py80
-rw-r--r--test/packaging/option--package-type.py11
-rw-r--r--test/packaging/place-files-in-subdirectory.py2
-rw-r--r--test/packaging/rpm/cleanup.py8
-rw-r--r--test/packaging/rpm/explicit-target.py95
-rw-r--r--test/packaging/rpm/internationalization.py2
-rw-r--r--test/packaging/rpm/multipackage.py115
-rw-r--r--test/packaging/strip-install-dir.py5
-rw-r--r--test/question/Configure.py (renamed from test/option-q.py)101
-rw-r--r--test/question/basic.py75
-rw-r--r--test/question/no-builder.py45
-rw-r--r--test/runtest/fallback.py14
-rw-r--r--test/runtest/noqmtest.py14
-rw-r--r--test/runtest/python.py10
-rw-r--r--test/sconsign/script/Configure.py87
-rw-r--r--test/sconsign/script/SConsignFile.py362
-rw-r--r--test/sconsign/script/Signatures.py44
-rw-r--r--test/sconsign/script/dblite.py50
-rw-r--r--test/sconsign/script/no-SConsignFile.py210
-rw-r--r--test/timestamp-fallback.py14
-rw-r--r--test/up-to-date.py33
101 files changed, 5007 insertions, 844 deletions
diff --git a/test/Actions/addpost-link.py b/test/Actions/addpost-link.py
index f97d4a3..0a08cda 100644
--- a/test/Actions/addpost-link.py
+++ b/test/Actions/addpost-link.py
@@ -32,11 +32,20 @@ This is a test for fix of Issue 1004, reported by Matt Doar and
packaged by Gary Oberbrunner.
"""
+import string
+
import TestSCons
+_python_ = TestSCons._python_
test = TestSCons.TestSCons()
+test.write('strip.py', """\
+import string
+import sys
+print "strip.py: %s" % string.join(sys.argv[1:])
+""")
+
test.write('SConstruct', """\
env = Environment()
@@ -44,10 +53,12 @@ mylib = env.StaticLibrary('mytest', 'test_lib.c')
myprog = env.Program('test1.c',
LIBPATH = ['.'],
- LIBS = ['mytest'])
+ LIBS = ['mytest'],
+ OBJSUFFIX = '.obj',
+ PROGSUFFIX = '.exe')
if ARGUMENTS['case']=='2':
- AddPostAction(myprog, Action('strip ' + myprog[0].abspath))
-""")
+ AddPostAction(myprog, Action(r'%(_python_)s strip.py ' + myprog[0].abspath))
+""" % locals())
test.write('test1.c', """\
extern void test_lib_fn();
@@ -69,8 +80,11 @@ test.run(arguments="-Q case=1", stderr=None)
test.run(arguments="-Q -c case=1")
-test.must_not_exist('test1.o')
+test.must_not_exist('test1.obj')
test.run(arguments="-Q case=2", stderr=None)
+expect = 'strip.py: %s' % test.workpath('test1.exe')
+test.fail_test(string.find(test.stdout(), expect) == -1)
+
test.pass_test()
diff --git a/test/Actions/exitstatfunc.py b/test/Actions/exitstatfunc.py
new file mode 100644
index 0000000..c52e1f5
--- /dev/null
+++ b/test/Actions/exitstatfunc.py
@@ -0,0 +1,67 @@
+#!/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 setting exitstatfunc on an Action works as advertised.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def always_succeed(s):
+ # Always return 0, which indicates success.
+ return 0
+
+def copy_fail(target, source, env):
+ content = open(str(source[0]), 'rb').read()
+ open(str(target[0]), 'wb').write(content)
+ return 2
+
+a = Action(copy_fail, exitstatfunc=always_succeed)
+Alias('test1', Command('test1.out', 'test1.in', a))
+
+def fail(target, source, env):
+ return 2
+
+t2 = Command('test2.out', 'test2.in', Copy('$TARGET', '$SOURCE'))
+AddPostAction(t2, Action(fail, exitstatfunc=always_succeed))
+Alias('test2', t2)
+""")
+
+test.write('test1.in', "test1.in\n")
+test.write('test2.in', "test2.in\n")
+
+test.run(arguments = 'test1')
+
+test.must_match('test1.out', "test1.in\n")
+
+test.run(arguments = 'test2')
+
+test.must_match('test2.out', "test2.in\n")
+
+test.pass_test()
diff --git a/test/Actions/timestamp.py b/test/Actions/timestamp.py
new file mode 100644
index 0000000..ee93596
--- /dev/null
+++ b/test/Actions/timestamp.py
@@ -0,0 +1,56 @@
+#!/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 changing an Action causes rebuilds when using timestamp
+signatures.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env.Decider('timestamp-match')
+env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('file.in', "file.in\n")
+
+test.not_up_to_date(arguments = 'file.out')
+
+test.write('SConstruct', """\
+def my_copy(target, source, env):
+ open(str(target[0]), 'w').write(open(str(source[0]), 'r').read())
+env = Environment()
+env.Decider('timestamp-match')
+env.Command('file.out', 'file.in', my_copy)
+""")
+
+test.not_up_to_date(arguments = 'file.out')
+
+test.pass_test()
diff --git a/test/AddMethod.py b/test/AddMethod.py
index ef4a8d0..584ab4c 100644
--- a/test/AddMethod.py
+++ b/test/AddMethod.py
@@ -36,7 +36,7 @@ test = TestSCons.TestSCons()
test.write('SConstruct', """
def foo(self):
- return 'foo-' + env['FOO']
+ return 'foo-' + self['FOO']
AddMethod(Environment, foo)
env = Environment(FOO = '111')
@@ -46,14 +46,20 @@ env = Environment(FOO = '222')
print env.foo()
env.AddMethod(foo, 'bar')
-print env.bar()
+env['FOO'] = '333'
+
+e = env.Clone()
+e['FOO'] = '444'
+print env.bar()
+print e.bar()
""")
expect = """\
foo-111
foo-222
-foo-222
+foo-333
+foo-444
"""
test.run(arguments = '-Q -q', stdout = expect)
diff --git a/test/Alias/Depends.py b/test/Alias/Depends.py
new file mode 100644
index 0000000..b4ea95c
--- /dev/null
+++ b/test/Alias/Depends.py
@@ -0,0 +1,162 @@
+#!/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 sys
+import TestSCons
+import TestCmd
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons(match=TestCmd.match_re)
+
+test.subdir('sub1', 'sub2')
+
+test.write('build.py', r"""
+import sys
+open(sys.argv[1], 'wb').write(open(sys.argv[2], 'rb').read())
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+B = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES')
+env = Environment()
+env['BUILDERS']['B'] = B
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env.B(target = 'f3.out', source = 'f3.in')
+SConscript('sub1/SConscript', "env")
+SConscript('sub2/SConscript', "env")
+
+foo = Alias('foo')
+foo2 = env.Alias('foo', ['f2.out', 'sub1'])
+assert foo == foo2
+bar = Alias('bar', ['sub2', 'f3.out'])
+env.Alias('blat', ['sub2', 'f3.out'])
+env.Alias('blat', ['f2.out', 'sub1'])
+env.Depends('f1.out', 'bar')
+
+Alias('a1', 'a1-file.in')
+Depends(Alias('a2'), 'a1')
+env.B('a2-file.out', 'a2-file.in')
+Depends('a2-file.out', 'a2')
+""" % locals())
+
+test.write(['sub1', 'SConscript'], """
+Import("env")
+env.B(target = 'f4.out', source = 'f4.in')
+env.B(target = 'f5.out', source = 'f5.in')
+env.B(target = 'f6.out', source = 'f6.in')
+""")
+
+test.write(['sub2', 'SConscript'], """
+Import("env")
+env.B(target = 'f7.out', source = 'f7.in')
+env.B(target = 'f8.out', source = 'f8.in')
+env.B(target = 'f9.out', source = 'f9.in')
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+
+test.write(['sub1', 'f4.in'], "sub1/f4.in\n")
+test.write(['sub1', 'f5.in'], "sub1/f5.in\n")
+test.write(['sub1', 'f6.in'], "sub1/f6.in\n")
+
+test.write(['sub2', 'f7.in'], "sub2/f7.in\n")
+test.write(['sub2', 'f8.in'], "sub2/f8.in\n")
+test.write(['sub2', 'f9.in'], "sub2/f9.in\n")
+
+
+
+test.run(arguments = 'foo')
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_exist(test.workpath('f2.out'))
+test.must_not_exist(test.workpath('f3.out'))
+
+test.must_exist(test.workpath('sub1', 'f4.out'))
+test.must_exist(test.workpath('sub1', 'f5.out'))
+test.must_exist(test.workpath('sub1', 'f6.out'))
+
+test.must_not_exist(test.workpath('sub2', 'f7.out'))
+test.must_not_exist(test.workpath('sub2', 'f8.out'))
+test.must_not_exist(test.workpath('sub2', 'f9.out'))
+
+test.up_to_date(arguments = 'foo')
+
+test.write(['sub1', 'f5.in'], "sub1/f5.in 2\n")
+
+test.not_up_to_date(arguments = 'foo')
+
+
+
+test.run(arguments = 'f1.out')
+
+test.must_exist(test.workpath('f1.out'))
+test.must_exist(test.workpath('f3.out'))
+
+test.up_to_date(arguments = 'f1.out')
+
+
+
+os.unlink(test.workpath('f2.out'))
+os.unlink(test.workpath('f3.out'))
+
+test.run(arguments = 'blat')
+
+test.must_exist(test.workpath('f2.out'))
+test.must_exist(test.workpath('f3.out'))
+
+test.write('f3.in', "f3.in 2 \n")
+
+expect = """.* build.py f3.out f3.in
+.* build.py f1.out f1.in
+"""
+
+test.run(arguments = '-Q f1.out', stdout = expect)
+
+test.up_to_date(arguments = 'f1.out')
+
+
+
+test.write('a1-file.in', "a1-file.in\n")
+test.write('a2-file.in', "a2-file.in\n")
+
+test.run(arguments = 'a2-file.out')
+
+test.must_match(test.workpath('a2-file.out'), "a2-file.in\n")
+
+test.up_to_date(arguments = 'a2-file.out')
+
+test.write('a1-file.in', "a1-file.in 2\n")
+
+test.not_up_to_date(arguments = 'a2-file.out')
+
+
+
+test.pass_test()
diff --git a/test/BuildDir/errors.py b/test/BuildDir/errors.py
index 44096a1..3954f2b 100644
--- a/test/BuildDir/errors.py
+++ b/test/BuildDir/errors.py
@@ -70,7 +70,6 @@ env = Environment(BUILDERS={'Build':Builder(action=cat)},
# Do some Node test operations to ensure no side-effects cause failures
File('file.in').exists()
File('file.in').is_derived()
-File('file.in').is_pseudo_derived()
env.Build('file.out', 'file.in')
""")
diff --git a/test/Builder/ensure_suffix.py b/test/Builder/ensure_suffix.py
new file mode 100644
index 0000000..ee23635
--- /dev/null
+++ b/test/Builder/ensure_suffix.py
@@ -0,0 +1,55 @@
+#!/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 ensure_suffix argument to causes us to add the suffix
+configured for the Builder even if it looks like the target already has
+a different suffix.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+
+tbuilder = Builder(action=Copy('$TARGET', '$SOURCE'),
+ suffix='.dll',
+ ensure_suffix=True)
+
+env['BUILDERS']['TBuilder'] = tbuilder
+
+env.TBuilder("aa.bb.cc.dd","aa.aa.txt")
+""")
+
+test.write('aa.aa.txt', "clean test\n")
+
+test.run(arguments = '.')
+
+test.must_match('aa.bb.cc.dd.dll', "clean test\n")
+
+test.pass_test()
diff --git a/test/CacheDir/multiple-targets.py b/test/CacheDir/multiple-targets.py
new file mode 100644
index 0000000..77b8f6f
--- /dev/null
+++ b/test/CacheDir/multiple-targets.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__"
+
+"""
+Test that multiple target files get retrieved from a CacheDir correctly.
+"""
+
+import os.path
+import shutil
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('cache')
+
+test.write('SConstruct', """\
+def touch(env, source, target):
+ open('foo', 'w').write("")
+ open('bar', 'w').write("")
+CacheDir(r'%s')
+env = Environment()
+env.Command(['foo', 'bar'], ['input'], touch)
+""" % (test.workpath('cache')))
+
+test.write('input', "multiple/input\n")
+
+test.run()
+
+test.must_exist(test.workpath('foo'))
+test.must_exist(test.workpath('bar'))
+
+test.run(arguments = '-c')
+
+test.must_not_exist(test.workpath('foo'))
+test.must_not_exist(test.workpath('bar'))
+
+test.run()
+
+test.must_exist(test.workpath('foo'))
+test.must_exist(test.workpath('bar'))
+
+test.pass_test()
diff --git a/test/CacheDir/scanner-target.py b/test/CacheDir/scanner-target.py
new file mode 100644
index 0000000..33930d8
--- /dev/null
+++ b/test/CacheDir/scanner-target.py
@@ -0,0 +1,80 @@
+#!/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 the case (reported by Jeff Petkau, bug #694744) where a target
+is source for another target with a scanner, which used to cause us
+to push the file to the CacheDir after the build signature had already
+been cleared (as a sign that the built file should now be rescanned).
+"""
+
+import os.path
+import shutil
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('cache')
+
+test.write('SConstruct', """\
+import SCons
+
+CacheDir(r'%s')
+
+def docopy(target,source,env):
+ data = source[0].get_contents()
+ f = open(target[0].rfile().get_abspath(), "wb")
+ f.write(data)
+ f.close()
+
+def sillyScanner(node, env, dirs):
+ print 'This is never called (unless we build file.out)'
+ return []
+
+SillyScanner = SCons.Scanner.Base(function = sillyScanner, skeys = ['.res'])
+
+env = Environment(tools=[],
+ SCANNERS = [SillyScanner],
+ BUILDERS = {})
+
+r = env.Command('file.res', 'file.ma', docopy)
+
+env.Command('file.out', r, docopy)
+
+# make r the default. Note that we don't even try to build file.out,
+# and so SillyScanner never runs. The bug is the same if we build
+# file.out, though.
+Default(r)
+""" % test.workpath('cache'))
+
+test.write('file.ma', "file.ma\n")
+
+test.run()
+
+test.must_not_exist(test.workpath('cache', 'N', 'None'))
+
+test.pass_test()
diff --git a/test/CacheDir/timestamp.py b/test/CacheDir/timestamp.py
new file mode 100644
index 0000000..b0d45b6
--- /dev/null
+++ b/test/CacheDir/timestamp.py
@@ -0,0 +1,48 @@
+#!/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 CacheDir() works even when using timestamp signatures.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+SourceSignatures('timestamp')
+TargetSignatures('content')
+CacheDir('cache')
+Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run()
+
+test.must_match('file.out', "file.in\n")
+
+test.pass_test()
diff --git a/test/Configure/clean.py b/test/Configure/clean.py
new file mode 100644
index 0000000..5b8e43d
--- /dev/null
+++ b/test/Configure/clean.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 don't perform Configure context actions when the
+-c or --clean options have been specified.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error
+env = conf.Finish()
+Export( 'env' )
+SConscript( 'SConscript' )
+""")
+
+test.write('SConscript', """\
+Import( 'env' )
+env.Program( 'TestProgram', 'TestProgram.c' )
+""")
+
+test.write('TestProgram.c', """\
+#include <stdio.h>
+
+int main() {
+ printf( "Hello\\n" );
+}
+""")
+
+lines = [
+ "Checking for C header file math.h... ",
+ "Checking for C header file no_std_c_header.h... "
+]
+
+unexpected = []
+
+test.run(arguments = '-c')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '--clean')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.pass_test()
diff --git a/test/Configure/help.py b/test/Configure/help.py
new file mode 100644
index 0000000..f79831c
--- /dev/null
+++ b/test/Configure/help.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__"
+
+"""
+Verify that we don't perform Configure context actions when the
+-H, -h or --help options have been specified.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error
+env = conf.Finish()
+Export( 'env' )
+SConscript( 'SConscript' )
+""")
+
+test.write('SConscript', """\
+Import( 'env' )
+env.Program( 'TestProgram', 'TestProgram.c' )
+""")
+
+test.write('TestProgram.c', """\
+#include <stdio.h>
+
+int main() {
+ printf( "Hello\\n" );
+}
+""")
+
+lines = [
+ "Checking for C header file math.h... ",
+ "Checking for C header file no_std_c_header.h... "
+]
+
+unexpected = []
+
+test.run(arguments = '-H')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '-h')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '--help')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.pass_test()
diff --git a/test/Copy.py b/test/Copy.py
index 4da725e..6659d93 100644
--- a/test/Copy.py
+++ b/test/Copy.py
@@ -79,6 +79,11 @@ test.write('f11.in', "f11.in\n")
test.subdir('d5')
test.write(['d5', 'f12.in'], "f12.in\n")
+d4_f10_in = os.path.join('d4', 'f10.in')
+d4_f11_out = os.path.join('d4', 'f11.out')
+d4_f12_out = os.path.join('d4', 'f12.out')
+d5_f12_in = os.path.join('d5', 'f12.in')
+
expect = test.wrap_stdout(read_str = """\
Copy("f1.out", "f1.in")
Copy("d2.out", "d2.in")
@@ -89,14 +94,14 @@ cat(["bar.out"], ["bar.in"])
Copy("f4.out", "f4.in")
Copy("d5.out", "d5.in")
Copy("d6.out", "f6.in")
-Copy file(s): "f10.in" to "d4/f10.in"
-Copy file(s): "f11.in" to "d4/f11.out"
-Copy file(s): "d5/f12.in" to "d4/f12.out"
+Copy file(s): "f10.in" to "%(d4_f10_in)s"
+Copy file(s): "f11.in" to "%(d4_f11_out)s"
+Copy file(s): "%(d5_f12_in)s" to "%(d4_f12_out)s"
Copy("f7.out", "f7.in")
cat(["f8.out"], ["f8.in"])
cat(["f9.out"], ["f9.in"])
Copy("f9.out-Copy", "f9.in")
-""")
+""" % locals())
test.run(options = '-n', arguments = '.', stdout = expect)
test.must_not_exist('f1.out')
diff --git a/test/Decider/Environment.py b/test/Decider/Environment.py
new file mode 100644
index 0000000..989e187
--- /dev/null
+++ b/test/Decider/Environment.py
@@ -0,0 +1,61 @@
+#!/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 an up-to-date Decider method through a construction
+environment.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+env = Environment()
+env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+env.Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/MD5-timestamp.py b/test/Decider/MD5-timestamp.py
new file mode 100644
index 0000000..d31a2db
--- /dev/null
+++ b/test/Decider/MD5-timestamp.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 behavior of the MD5-timestamp Decider() setting.
+"""
+
+import os
+import stat
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+m = Environment()
+m.Decider('MD5-timestamp')
+m.Command('content1.out', 'content1.in', Copy('$TARGET', '$SOURCE'))
+m.Command('content2.out', 'content2.in', Copy('$TARGET', '$SOURCE'))
+m.Command('content3.out', 'content3.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('content1.in', "content1.in 1\n")
+test.write('content2.in', "content2.in 1\n")
+test.write('content3.in', "content3.in 1\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+
+
+test.sleep()
+
+test.write('content1.in', "content1.in 2\n")
+
+test.touch('content2.in')
+
+time_content = os.stat('content3.in')[stat.ST_MTIME]
+test.write('content3.in', "content3.in 2\n")
+test.touch('content3.in', time_content)
+
+# We should only see content1.out rebuilt. The timestamp of content2.in
+# has changed, but its content hasn't, so the follow-on content check says
+# to not rebuild it. The content of content3.in has changed, but that's
+# masked by the fact that its timestamp is the same as the last run.
+
+expect = test.wrap_stdout("""\
+Copy("content1.out", "content1.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+test.up_to_date(arguments = '.')
+
+
+
+test.pass_test()
diff --git a/test/Decider/Node.py b/test/Decider/Node.py
new file mode 100644
index 0000000..b11e223
--- /dev/null
+++ b/test/Decider/Node.py
@@ -0,0 +1,61 @@
+#!/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 an up-to-date Decider method on a Node.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+file_in = File('file.in')
+file_out = File('file.out')
+Command(file_out, file_in, Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+file_in.Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/default.py b/test/Decider/default.py
new file mode 100644
index 0000000..c2886fb
--- /dev/null
+++ b/test/Decider/default.py
@@ -0,0 +1,59 @@
+#!/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 a default up-to-date Decider method.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/mixed.py b/test/Decider/mixed.py
new file mode 100644
index 0000000..7a83c74
--- /dev/null
+++ b/test/Decider/mixed.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 use of an up-to-date Decider method through a construction
+environment.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+denv = Environment()
+env = Environment()
+n1_in = File('n1.in')
+n2_in = File('n2.in')
+n3_in = File('n3.in')
+Command( 'ccc.out', 'ccc.in', Copy('$TARGET', '$SOURCE'))
+Command( 'n1.out', n1_in, Copy('$TARGET', '$SOURCE'))
+denv.Command('ddd.out', 'ddd.in', Copy('$TARGET', '$SOURCE'))
+denv.Command('n2.out', n2_in, Copy('$TARGET', '$SOURCE'))
+env.Command( 'eee.out', 'eee.in', Copy('$TARGET', '$SOURCE'))
+env.Command( 'n3.out', n3_in, Copy('$TARGET', '$SOURCE'))
+def default_decider(dependency, target, prev_ni):
+ return os.path.exists('default-has-changed')
+def env_decider(dependency, target, prev_ni):
+ return os.path.exists('env-has-changed')
+def node_decider(dependency, target, prev_ni):
+ return os.path.exists('node-has-changed')
+Decider(default_decider)
+env.Decider(env_decider)
+n1_in.Decider(node_decider)
+n2_in.Decider(node_decider)
+n3_in.Decider(node_decider)
+""")
+
+test.write('ccc.in', "ccc.in\n")
+test.write('ddd.in', "ddd.in\n")
+test.write('eee.in', "eee.in\n")
+test.write('n1.in', "n1.in\n")
+test.write('n2.in', "n2.in\n")
+test.write('n3.in', "n3.in\n")
+
+
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+
+
+test.write('env-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'eee.out')
+test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out')
+
+test.not_up_to_date(arguments = 'eee.out')
+test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out')
+
+test.unlink('env-has-changed')
+
+
+
+test.write('default-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'ccc.out ddd.out')
+test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out')
+
+test.not_up_to_date(arguments = 'ccc.out ddd.out')
+test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out')
+
+test.unlink('default-has-changed')
+
+
+
+test.up_to_date(arguments = '.')
+
+test.write('node-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'n1.out n2.out n3.out')
+test.up_to_date(arguments = 'ccc.out ddd.out eee.out')
+
+test.not_up_to_date(arguments = 'n1.out n2.out n3.out')
+test.up_to_date(arguments = 'ccc.out ddd.out eee.out')
+
+test.unlink('node-has-changed')
+
+
+
+test.pass_test()
diff --git a/test/Decider/timestamp.py b/test/Decider/timestamp.py
new file mode 100644
index 0000000..6975607
--- /dev/null
+++ b/test/Decider/timestamp.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 various interactions of the timestamp-match and timestamp-newer
+Decider() settings:.
+"""
+
+import os
+import stat
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+m = Environment()
+m.Decider('timestamp-match')
+m.Command('match1.out', 'match1.in', Copy('$TARGET', '$SOURCE'))
+m.Command('match2.out', 'match2.in', Copy('$TARGET', '$SOURCE'))
+n = Environment()
+n.Decider('timestamp-newer')
+n.Command('newer1.out', 'newer1.in', Copy('$TARGET', '$SOURCE'))
+n.Command('newer2.out', 'newer2.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('match1.in', "match1.in\n")
+test.write('match2.in', "match2.in\n")
+test.write('newer1.in', "newer1.in\n")
+test.write('newer2.in', "newer2.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+time_match = os.stat('match2.out')[stat.ST_MTIME]
+time_newer = os.stat('newer2.out')[stat.ST_MTIME]
+
+
+
+# Now make all the source files newer than (different timestamps from)
+# the last time the targets were built, and touch the target files
+# of match1.out and newer1.out to see the different effects.
+
+test.sleep()
+
+test.touch('match1.in')
+test.touch('newer1.in')
+test.touch('match2.in')
+test.touch('newer2.in')
+
+test.sleep()
+
+test.touch('match1.out')
+test.touch('newer1.out')
+
+# We should see both match1.out and match2.out rebuilt, because the
+# source file timestamps do not match the last time they were built,
+# but only newer2.out rebuilt. newer1.out is *not* rebuilt because
+# the actual target file timestamp is, in fact, newer than the
+# source file (newer1.in) timestamp.
+
+expect = test.wrap_stdout("""\
+Copy("match1.out", "match1.in")
+Copy("match2.out", "match2.in")
+Copy("newer2.out", "newer2.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+# Now, for the somewhat pathological case, reset the match2.out and
+# newer2.out timestamps to the older timestamp when the targets were
+# first built. This will cause newer2.out to be rebuilt, because
+# the newer1.in timestamp is now newer than the older, reset target
+# file timestamp, but match2.out is *not* rebuilt because its source
+# file (match2.in) timestamp still exactly matches the timestamp
+# recorded when the target file was last built.
+
+test.touch('match2.out', time_match)
+test.touch('newer2.out', time_newer)
+
+expect = test.wrap_stdout("""\
+Copy("newer2.out", "newer2.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+
+
+test.pass_test()
diff --git a/test/Decider/unknown.py b/test/Decider/unknown.py
new file mode 100644
index 0000000..b6d071d
--- /dev/null
+++ b/test/Decider/unknown.py
@@ -0,0 +1,46 @@
+#!/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 when the Decider() function is handed an unknown
+function string.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+Decider('fiddle-dee-dee')
+""")
+
+expect = r"""
+scons: \*\*\* Unknown Decider value 'fiddle-dee-dee'
+""" + TestSCons.file_expr
+
+test.run(arguments = '.', status = 2, stderr = expect)
+
+test.pass_test()
diff --git a/test/Delete.py b/test/Delete.py
index 138dc95..31febbe 100644
--- a/test/Delete.py
+++ b/test/Delete.py
@@ -53,14 +53,18 @@ env.Command('f8.out', 'f8.in', [Delete("$FILE"), Delete("$DIR"), Cat])
env.Command('f9.out', 'f9.in', [Cat,
Delete("Delete-$SOURCE"),
Delete("$TARGET-Delete")])
-env.Command('f10-nonexistent.out', 'f10.in', [Delete("$TARGET"),
- Cat])
-env.Command('d11-nonexistent.out', 'd11.in', [Delete("$TARGET"),
- Mkdir("$TARGET")])
-env.Command('f12-nonexistent.out', 'f12.in', [Delete("$TARGET", must_exist=0),
- Cat])
-env.Command('d13-nonexistent.out', 'd13.in', [Delete("$TARGET", must_exist=0),
- Mkdir("$TARGET")])
+
+env.Command('f10-nonexistent.out', 'f10.in',
+ [Delete("$TARGET"), Cat])
+
+env.Command(Dir('d11-nonexistent.out'), 'd11.in',
+ [Delete("$TARGET"), Mkdir("$TARGET")])
+
+env.Command('f12-nonexistent.out', 'f12.in',
+ [Delete("$TARGET", must_exist=0), Cat])
+
+env.Command(Dir('d13-nonexistent.out'), 'd13.in',
+ [Delete("$TARGET", must_exist=0), Mkdir("$TARGET")])
""")
test.write('f1', "f1\n")
diff --git a/test/Depends.py b/test/Depends.py
index d0b2199..4870739 100644
--- a/test/Depends.py
+++ b/test/Depends.py
@@ -143,6 +143,9 @@ file2 = File('file2')
env.Depends(file1, [[file2, 'file3']])
""")
+test.write('file2', "file2\n")
+test.write('file3', "file3\n")
+
test.up_to_date(arguments = '.')
test.pass_test()
diff --git a/test/Dir/source.py b/test/Dir/source.py
index fa07a88..9852660 100644
--- a/test/Dir/source.py
+++ b/test/Dir/source.py
@@ -165,8 +165,6 @@ test.up_to_date(arguments='cmd-csig-noscan.out')
test.write('junk.txt', 'junk.txt 2\n')
test.not_up_to_date(arguments='bsig.out')
-# XXX For some reason, 'csig' is still reported as up to date.
-# XXX Comment out this test until someone can look at it.
-#test.not_up_to_date(arguments='csig.out')
+test.not_up_to_date(arguments='csig.out')
test.pass_test()
diff --git a/test/Errors/preparation.py b/test/Errors/preparation.py
index 3f98894..9857f99 100644
--- a/test/Errors/preparation.py
+++ b/test/Errors/preparation.py
@@ -35,19 +35,18 @@ import TestSCons
test = TestSCons.TestSCons()
-install = test.workpath('install')
-install_file = test.workpath('install', 'file')
-work_file = test.workpath('work', 'file')
+work_file_out = test.workpath('work', 'file.out')
test.subdir('install', 'work')
test.write(['work', 'SConstruct'], """\
-Alias("install", Install(r"%(install)s", File('file')))
+file_out = Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+Alias("install", file_out)
# Make a directory where we expect the File() to be. This causes an
# IOError or OSError when we try to open it to read its signature.
import os
-os.mkdir(r'%(work_file)s')
+os.mkdir('file.in')
""" % locals())
if sys.platform == 'win32':
@@ -56,7 +55,7 @@ else:
error_message = "Is a directory"
expect = """\
-scons: *** [%(install_file)s] %(work_file)s: %(error_message)s
+scons: *** [install] %(work_file_out)s: %(error_message)s
""" % locals()
test.run(chdir = 'work',
diff --git a/test/Install/Install.py b/test/Install/Install.py
index f7f8e26..6d44c45 100644
--- a/test/Install/Install.py
+++ b/test/Install/Install.py
@@ -91,18 +91,18 @@ test.write(['work', 'sub', 'f4.in'], "sub/f4.in\n")
test.write(f5_txt, "f5.txt\n")
test.write(f6_txt, "f6.txt\n")
-test.run(chdir = 'work', arguments = '--debug=stacktrace .')
+test.run(chdir = 'work', arguments = '.')
-test.fail_test(test.read(f1_out) != "f1.in\n")
-test.fail_test(test.read(f2_out) != "f2.in\n")
-test.fail_test(test.read(f3_out) != "f3.in\n")
-test.fail_test(test.read(f4_out) != "sub/f4.in\n")
-test.fail_test(test.read(['work', 'f5.txt']) != "f5.txt\n")
-test.fail_test(test.read(['work', 'export', 'f5.txt']) != "f5.txt\n")
-test.fail_test(test.read(['work', 'f6.txt']) != "f6.txt\n")
-test.fail_test(test.read(['work', 'export', 'f6.txt']) != "f6.txt\n")
+test.must_match(f1_out, "f1.in\n")
+test.must_match(f2_out, "f2.in\n")
+test.must_match(f3_out, "f3.in\n")
+test.must_match(f4_out, "sub/f4.in\n")
+test.must_match(['work', 'f5.txt'], "f5.txt\n")
+test.must_match(['work', 'export', 'f5.txt'], "f5.txt\n")
+test.must_match(['work', 'f6.txt'], "f6.txt\n")
+test.must_match(['work', 'export', 'f6.txt'], "f6.txt\n")
-test.fail_test(test.read(['work', 'my_install.out']) != os.path.join('export', 'f3.out'))
+test.must_match(['work', 'my_install.out'], os.path.join('export', 'f3.out'))
# make sure the programs didn't get rebuilt, because nothing changed:
oldtime1 = os.path.getmtime(f1_out)
@@ -119,7 +119,7 @@ test.fail_test(oldtime2 != os.path.getmtime(f2_out))
# Verify that we didn't link to the Installed file.
open(f2_out, 'wb').write("xyzzy\n")
-test.fail_test(test.read(['work', 'f2.out']) != "f2.in\n")
+test.must_match(['work', 'f2.out'], "f2.in\n")
# Verify that scons prints an error message
# if a target can not be unlinked before building it:
diff --git a/test/Install/tool.py b/test/Install/tool.py
new file mode 100644
index 0000000..4f09b73
--- /dev/null
+++ b/test/Install/tool.py
@@ -0,0 +1,51 @@
+#!/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 still call Install() and InstallAs() even when
+no Tool modules have been loaded.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('iii')
+
+test.write('SConstruct', """
+env = Environment(tools = [])
+env.Install('iii', 'foo.in')
+env.InstallAs('foo.out', 'foo.in')
+""")
+
+test.write('foo.in', "foo.in\n")
+
+test.run(arguments = '.')
+
+test.must_match(['iii', 'foo.in'], "foo.in\n")
+test.must_match('foo.out', "foo.in\n")
+
+test.pass_test()
diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py
new file mode 100644
index 0000000..7723224
--- /dev/null
+++ b/test/Java/JAVABOOTCLASSPATH.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 use of $JAVABOOTCLASSPATH sets the -bootclasspath option
+on javac compilations.
+"""
+
+import os
+import string
+
+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('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")
+
+test.write('SConstruct', """
+env = Environment(tools = ['javac', 'javah'],
+ JAVAC = r'%(where_javac)s',
+ JAVABOOTCLASSPATH = ['dir1', 'dir2'])
+j1 = env.Java(target = 'class', source = 'com/Example1.java')
+j2 = env.Java(target = 'class', source = 'com/Example2.java')
+""" % locals())
+
+test.subdir('com')
+
+test.write(['com', 'Example1.java'], """\
+package com;
+
+public class Example1
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+test.write(['com', 'Example2.java'], """\
+package com;
+
+public class Example2
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+# Setting -bootclasspath messes with the Java runtime environment, so
+# we'll just take the easy way out and examine the -n output to see if
+# the expected option shows up on the command line.
+
+bootclasspath = string.join(['dir1', 'dir2'], os.pathsep)
+
+expect = """\
+%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example1.java
+%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example2.java
+""" % locals()
+
+test.run(arguments = '-Q -n .', stdout = expect)
+
+test.pass_test()
diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py
index 1b69838..d185b4d 100644
--- a/test/Java/multi-step.py
+++ b/test/Java/multi-step.py
@@ -43,6 +43,13 @@ else:
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")
+
swig = test.where_is('swig')
if not swig:
test.skip_test('Can not find installed "swig", skipping test.\n')
@@ -70,7 +77,9 @@ test.subdir(['src'],
test.write(['SConstruct'], """\
import os,sys
-env=Environment(tools = ['default', 'javac', 'javah'])
+env=Environment(tools = ['default', 'javac', 'javah'],
+ JAVAC = r'%(where_javac)s',
+ JAVAH = r'%(where_javah)s')
Export('env')
env.PrependENVPath('PATH',os.environ.get('PATH',[]))
env['INCPREFIX']='-I'
@@ -94,7 +103,7 @@ env.SConscript(['buildout/server/JavaSource/SConscript',
'buildout/HelloApplet/SConscript',
'buildout/jni/SConscript',
'buildout/javah/SConscript'])
-""")
+""" % locals())
test.write(['src', 'HelloApplet', 'Hello.html'], """\
<HTML>
@@ -559,9 +568,16 @@ test.must_exist(['buildout', 'jni', 'Sample.class'])
test.must_exist(['buildout', 'jni', 'Sample.java'])
test.must_exist(['buildout', 'jni', 'SampleJNI.class'])
test.must_exist(['buildout', 'jni', 'SampleJNI.java'])
-test.must_exist(['buildout', 'jni', 'SampleTest.class'])
test.must_exist(['buildout', 'jni', 'SampleTest.java'])
+# Some combinations of Java + SWIG apparently don't actually generate
+# a SampleTest.class file, while others do. Only issue a warning if
+# it doesn't exist.
+p = test.workpath('buildout', 'jni', 'SampleTest.class')
+import os.path
+if not os.path.exists(p):
+ print 'Warning: %s does not exist' % p
+
test.up_to_date(arguments = '.')
test.pass_test()
diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py
index c6961f2..8df5e09 100644
--- a/test/Java/swig-dependencies.py
+++ b/test/Java/swig-dependencies.py
@@ -35,6 +35,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:
@@ -42,6 +43,13 @@ else:
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:
@@ -57,7 +65,9 @@ test.subdir(['foo'],
test.write(['SConstruct'], """\
import os
-env = Environment(ENV = os.environ)
+env = Environment(ENV = os.environ,
+ JAVAC = r'%(where_javac)s',
+ JAVAH = r'%(where_javah)s')
env.Append(CPPFLAGS = ' -g -Wall')
@@ -65,7 +75,7 @@ Export('env')
SConscript('#foo/SConscript')
SConscript('#java/SConscript')
-""")
+""" % locals())
test.write(['foo', 'SConscript'], """\
Import('env')
@@ -123,7 +133,10 @@ env['JARCHDIR'] = 'java/classes'
foopack_jar = env.Jar(target = 'foopack.jar', source = 'classes')
""")
-test.run(arguments = '.')
+# Disable looking at stderr because some combinations of SWIG/gcc
+# generate a warning about the sWIG_JavaThrowException() function
+# being defined but not used.
+test.run(arguments = '.', stderr=None)
#test.must_exist(['java', 'classes', 'foopack', 'foopack.class'])
#test.must_exist(['java', 'classes', 'foopack', 'foopackJNI.class'])
diff --git a/test/LIBS.py b/test/LIBS.py
index 708ce63..e9f6545 100644
--- a/test/LIBS.py
+++ b/test/LIBS.py
@@ -272,7 +272,7 @@ test.write(['src', 'component2', 'message2.c'], """\
#include <stdio.h>
#include "message1.h"
-int DisplayMessage2 (void)
+void DisplayMessage2 (void)
{
DisplayMessage1();
printf ("src/component2/hello.c\\n");
diff --git a/test/MinGW/RCCOM.py b/test/MinGW/RCCOM.py
index 2db0563..a272af7 100644
--- a/test/MinGW/RCCOM.py
+++ b/test/MinGW/RCCOM.py
@@ -29,13 +29,15 @@ Test the ability to configure the $RCCOM construction variable
when using MinGW.
"""
+import sys
import TestSCons
_python_ = TestSCons._python_
test = TestSCons.TestSCons()
-
+if sys.platform in ('irix6',):
+ test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform)
test.write('myrc.py', """
import sys
diff --git a/test/MinGW/RCCOMSTR.py b/test/MinGW/RCCOMSTR.py
index 96565f1..d04c5d6 100644
--- a/test/MinGW/RCCOMSTR.py
+++ b/test/MinGW/RCCOMSTR.py
@@ -29,13 +29,15 @@ Test that the $RCCOMSTR construction variable allows you to customize
the displayed string when rc is called.
"""
+import sys
import TestSCons
_python_ = TestSCons._python_
test = TestSCons.TestSCons()
-
+if sys.platform in ('irix6',):
+ test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform)
test.write('myrc.py', """
import sys
diff --git a/test/NodeOps.py b/test/NodeOps.py
index 3869228..7e656f7 100644
--- a/test/NodeOps.py
+++ b/test/NodeOps.py
@@ -32,9 +32,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
# However, this should *not* occur during a dryrun (-n). When not
# performed during a dryrun, this should not affect buildability.
# 2) Calling is_derived() should not affect buildability.
-# 3) Calling is_pseudo_derived() may cause the sbuilder to be set, and
-# it may caues the builder to be set as well, but it should not
-# adversely affect buildability.
import sys
import TestSCons
@@ -73,13 +70,11 @@ SConscript('bld/SConscript', ['Nodes'])
if %(_E)s:
import os
derived = map(lambda N: N.is_derived(), Nodes)
- p_derived = map(lambda N: N.is_pseudo_derived(), Nodes)
real1 = map(lambda N: os.path.exists(str(N)), Nodes)
exists = map(lambda N: N.exists(), Nodes)
real2 = map(lambda N: os.path.exists(str(N)), Nodes)
- for N,D,P,R,E,F in map(None, Nodes, derived, p_derived,
- real1, exists, real2):
- print '%%s: %%s %%s %%s %%s %%s'%%(N,D,P,R,E,F)
+ for N,D,R,E,F in map(None, Nodes, derived, real1, exists, real2):
+ print '%%s: %%s %%s %%s %%s'%%(N,D,R,E,F)
foo.SharedLibrary(target = 'foo', source = 'foo%(_obj)s')
bar.SharedLibrary(target = 'bar', source = 'bar%(_obj)s')
@@ -147,7 +142,6 @@ def exists_test(node):
via_node = node.exists() # side effect causes copy from src
after = os.path.exists(str(node))
node.is_derived()
- node.is_pseudo_derived()
import SCons.Script
if GetOption('no_exec'):
if (before,via_node,after) != (False,False,False):
diff --git a/test/Parallel/duplicate-target.py b/test/Parallel/duplicate-target.py
new file mode 100644
index 0000000..5d4f5e1
--- /dev/null
+++ b/test/Parallel/duplicate-target.py
@@ -0,0 +1,74 @@
+#!/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, when a file is specified multiple times in a target
+list, we still build all of the necessary targets.
+
+This used to cause a target to "disappear" from the DAG when its reference
+count dropped below 0, because we were subtracting the duplicated target
+mutiple times even though we'd only visit it once. This was particularly
+hard to track down because the DAG itself (when printed with --tree=prune,
+for example) doesn't show the duplication in the *target* list.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.subdir('work')
+
+tar_output = test.workpath('work.tar')
+
+test.write(['work', 'copy.py'], """\
+import sys
+import time
+time.sleep(int(sys.argv[1]))
+open(sys.argv[2], 'wb').write(open(sys.argv[3], 'rb').read())
+""")
+
+test.write(['work', 'SConstruct'], """\
+env = Environment()
+out1 = File('f1.out')
+out2 = File('f2.out')
+env.Command([out1, out1], 'f1.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE')
+env.Command([out2, out2], 'f2.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE')
+
+env.Tar(r'%(tar_output)s', Dir('.'))
+""" % locals())
+
+test.write(['work', 'f1.in'], "work/f1.in\n")
+test.write(['work', 'f2.in'], "work/f2.in\n")
+
+test.run(chdir = 'work', arguments = tar_output + ' -j2')
+
+test.must_match(['work', 'f1.out'], "work/f1.in\n")
+test.must_match(['work', 'f2.out'], "work/f2.in\n")
+test.must_exist(tar_output)
+
+test.pass_test()
diff --git a/test/Progress/TARGET.py b/test/Progress/TARGET.py
new file mode 100644
index 0000000..e45f859
--- /dev/null
+++ b/test/Progress/TARGET.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 substition of the $TARGET string in progress output, including
+overwriting it by setting the overwrite= keyword argument.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(universal_newlines=None)
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('$TARGET\\r', overwrite=True)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+S1.in\r \rS1.out\rCopy("S1.out", "S1.in")
+ \rS2.in\r \rS2.out\rCopy("S2.out", "S2.in")
+ \rS3.in\r \rS3.out\rCopy("S3.out", "S3.in")
+ \rS4.in\r \rS4.out\rCopy("S4.out", "S4.in")
+ \rSConstruct\r \r.\r"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/Progress/dots.py b/test/Progress/dots.py
new file mode 100644
index 0000000..23b3e72
--- /dev/null
+++ b/test/Progress/dots.py
@@ -0,0 +1,60 @@
+#!/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 expected behavior of just telling a Progress() object to print
+a dot for every visited Node.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('.')
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+..Copy("S1.out", "S1.in")
+..Copy("S2.out", "S2.in")
+..Copy("S3.out", "S3.in")
+..Copy("S4.out", "S4.in")
+.."""
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/Progress/file.py b/test/Progress/file.py
new file mode 100644
index 0000000..f0116c0
--- /dev/null
+++ b/test/Progress/file.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 the file= argument to Progress() allows us to redirect the
+progress output.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('stderr: $TARGET\\n', file=open('progress.out', 'w'))
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+test.run(arguments = '-Q .', stdout=expect)
+
+expect = """\
+stderr: S1.in
+stderr: S1.out
+stderr: S2.in
+stderr: S2.out
+stderr: S3.in
+stderr: S3.out
+stderr: S4.in
+stderr: S4.out
+stderr: SConstruct
+stderr: .
+"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.must_match('progress.out', expect)
+
+test.pass_test()
diff --git a/test/Progress/function.py b/test/Progress/function.py
new file mode 100644
index 0000000..2fcb671
--- /dev/null
+++ b/test/Progress/function.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 behavior of passing our own function to Progress().
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+def my_progress_function(node, *args, **kw):
+ sys.stderr.write('mpf: %s\\n' % node)
+Progress(my_progress_function)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+mpf: S1.in
+mpf: S1.out
+mpf: S2.in
+mpf: S2.out
+mpf: S3.in
+mpf: S3.out
+mpf: S4.in
+mpf: S4.out
+mpf: SConstruct
+mpf: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/interval.py b/test/Progress/interval.py
new file mode 100644
index 0000000..767bf20
--- /dev/null
+++ b/test/Progress/interval.py
@@ -0,0 +1,68 @@
+#!/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 "interval=" parameter to Progress skips Nodes.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('stderr: $TARGET\\n', file=sys.stderr, interval=2)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+stderr: S1.out
+stderr: S2.out
+stderr: S3.out
+stderr: S4.out
+stderr: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/object.py b/test/Progress/object.py
new file mode 100644
index 0000000..4dad1a1
--- /dev/null
+++ b/test/Progress/object.py
@@ -0,0 +1,78 @@
+#!/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 passing a callable object to Progress().
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+class my_progress:
+ count = 0
+ def __call__(self, node, *args, **kw):
+ self.count = self.count + 1
+ sys.stderr.write('%s: %s\\n' % (self.count, node))
+Progress(my_progress())
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+1: S1.in
+2: S1.out
+3: S2.in
+4: S2.out
+5: S3.in
+6: S3.out
+7: S4.in
+8: S4.out
+9: SConstruct
+10: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/spinner.py b/test/Progress/spinner.py
new file mode 100644
index 0000000..c600b67
--- /dev/null
+++ b/test/Progress/spinner.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 output when a Progress() call is initialized with the list
+that represents a canonical "spinner" on the output.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(universal_newlines=None)
+
+test.write('SConstruct', r"""
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress(['-\r', '\\\r', '|\r', '/\r'])
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+\\\r|\rCopy("S1.out", "S1.in")
+/\r-\rCopy("S2.out", "S2.in")
+\\\r|\rCopy("S3.out", "S3.in")
+/\r-\rCopy("S4.out", "S4.in")
+\\\r|\r"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/QT/installed.py b/test/QT/installed.py
index 8cb9ab1..d746d9e 100644
--- a/test/QT/installed.py
+++ b/test/QT/installed.py
@@ -191,10 +191,11 @@ if test.stdout() != "Hello World\n" or test.stderr() != '' or test.status:
# If so, then print whatever it showed us (which is in and of itself
# an indication that it built correctly) but don't fail the test.
expect = 'cannot connect to X server'
- test.fail_test(test.stdout() != '' or
- string.find(test.stderr(), expect) == -1 or \
- (test.status>>8) != 1)
-
+ test.fail_test(test.stdout())
+ test.fail_test(string.find(test.stderr(), expect) == -1)
+ if test.status != 1 and (test.status>>8) != 1:
+ sys.stdout.write('test_realqt returned status %s\n' % test.status)
+ test.fail_test()
QTDIR = os.environ['QTDIR']
PATH = os.environ['PATH']
diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py
index 1dbcd0f..2878136 100644
--- a/test/QT/moc-from-header.py
+++ b/test/QT/moc-from-header.py
@@ -92,7 +92,6 @@ test.must_exist(test.workpath('build', moc))
test.run(arguments = "build_dir=1 chdir=1 dup=0 " +
test.workpath('build_dup0', aaa_exe) )
-test.must_exist(['build_dup0', moc],
- ['build_dup0', aaa_exe])
+test.must_exist(['build_dup0', moc])
test.pass_test()
diff --git a/test/SConscript/Return.py b/test/SConscript/Return.py
new file mode 100644
index 0000000..453c0b8
--- /dev/null
+++ b/test/SConscript/Return.py
@@ -0,0 +1,93 @@
+#!/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 Return() function stops processing the SConscript file
+at the point is called, unless the stop= keyword argument is supplied.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+SConscript('SConscript1')
+x = SConscript('SConscript2')
+y, z = SConscript('SConscript3')
+a4, b4 = SConscript('SConscript4')
+print "x =", x
+print "y =", y
+print "z =", z
+print "a4 =", a4
+print "b4 =", b4
+""")
+
+test.write('SConscript1', """\
+print "line 1"
+Return()
+print "line 2"
+""")
+
+test.write('SConscript2', """\
+print "line 3"
+x = 7
+Return('x')
+print "line 4"
+""")
+
+test.write('SConscript3', """\
+print "line 5"
+y = 8
+z = 9
+Return('y z')
+print "line 6"
+""")
+
+test.write('SConscript4', """\
+a4 = 'aaa'
+b4 = 'bbb'
+print "line 7"
+Return('a4', 'b4', stop=False)
+b4 = 'b-after'
+print "line 8"
+""")
+
+expect = """\
+line 1
+line 3
+line 5
+line 7
+line 8
+x = 7
+y = 8
+z = 9
+a4 = aaa
+b4 = bbb
+"""
+
+test.run(arguments = '-q -Q', stdout=expect)
+
+test.pass_test()
diff --git a/test/SWIG/build-dir.py b/test/SWIG/build-dir.py
index 593a26a..58ad0cd 100644
--- a/test/SWIG/build-dir.py
+++ b/test/SWIG/build-dir.py
@@ -37,6 +37,11 @@ import TestSCons
test = TestSCons.TestSCons()
+swig = test.where_is('swig')
+
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
# swig-python expects specific filenames.
# the platform specific suffix won't necessarily work.
if sys.platform == 'win32':
@@ -129,9 +134,6 @@ public:
%extend
{
const char* __str__() { return "linalg.Vector()"; }
- int __len__() { return $self->size(); }
- double __getitem__(int key) { return $self->operator[](key); }
- void __setitem__(int key, double value) { $self->operator[](key) = value; }
%pythoncode %{
def __iter__(self):
diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py
index 2dfd322..dd2c938 100644
--- a/test/Scanner/generated.py
+++ b/test/Scanner/generated.py
@@ -411,18 +411,17 @@ int g_3()
test.run(stderr=TestSCons.noisy_ar,
match=TestSCons.match_re_dotall)
-# XXX Note that the generated .h files still get scanned twice,
-# once before they're generated and once after. That's the
-# next thing to fix here.
+# Note that the generated .h files still get scanned twice,
+# but that's really once each as a child of libg_1.o and libg_2.o.
test.must_match("MyCScan.out", """\
libg_1.c: 1
libg_2.c: 1
libg_3.c: 1
-libg_gx.h: 1
+libg_gx.h: 2
libg_gy.h: 1
libg_gz.h: 1
-libg_w.h: 1
+libg_w.h: 2
""")
test.pass_test()
diff --git a/test/Sig.py b/test/Sig.py
new file mode 100644
index 0000000..8565735
--- /dev/null
+++ b/test/Sig.py
@@ -0,0 +1,62 @@
+#!/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 generate the proper warning, but don't die, when someone
+tries to import the SCons.Sig module (which no longer exists) and
+use the things we used to define therein.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+SConstruct = test.workpath('SConstruct')
+
+test.write(SConstruct, """
+import SCons.Sig
+x = SCons.Sig.default_calc
+x = SCons.Sig.default_module
+x = SCons.Sig.MD5.current()
+x = SCons.Sig.MD5.collect()
+x = SCons.Sig.MD5.signature()
+x = SCons.Sig.MD5.to_string()
+x = SCons.Sig.MD5.from_string()
+x = SCons.Sig.TimeStamp.current()
+x = SCons.Sig.TimeStamp.collect()
+x = SCons.Sig.TimeStamp.signature()
+x = SCons.Sig.TimeStamp.to_string()
+x = SCons.Sig.TimeStamp.from_string()
+""")
+
+expect = """
+scons: warning: The SCons.Sig module no longer exists.
+ Remove the following "import SCons.Sig" line to eliminate this warning:
+""" + test.python_file_line(SConstruct, 2)
+
+test.run(arguments = '.', stderr=expect)
+
+test.pass_test()
diff --git a/test/SourceCode.py b/test/SourceCode.py
index 86cc2a6..b74f8b1 100644
--- a/test/SourceCode.py
+++ b/test/SourceCode.py
@@ -59,7 +59,7 @@ env = Environment(BUILDERS={'Cat':Builder(action=cat)}, SUBDIR='sub')
env.SourceCode('$SUBDIR', Builder(action=sc_cat, env=env))
env.Cat('aaa.out', 'sub/aaa.in')
bbb_in = File('sub/bbb.in')
-bbb_in.is_pseudo_derived()
+bbb_in.is_derived()
env.Cat('bbb.out', bbb_in)
env.Cat('ccc.out', 'sub/ccc.in')
env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
diff --git a/test/SourceSignatures.py b/test/SourceSignatures.py
deleted file mode 100644
index b85f8ec..0000000
--- a/test/SourceSignatures.py
+++ /dev/null
@@ -1,268 +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 imp
-import os
-import os.path
-import time
-
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-
-SourceSignatures('timestamp')
-""")
-
-test.write('f1.in', "f1.in\n")
-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 f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-scons: `f1.out' is up to date.
-build(["f2.out"], ["f2.in"])
-scons: `f3.out' is up to date.
-build(["f4.out"], ["f4.in"])
-"""))
-
-os.utime(test.workpath('f1.in'),
- (os.path.getatime(test.workpath('f1.in')),
- os.path.getmtime(test.workpath('f1.in'))+10))
-os.utime(test.workpath('f3.in'),
- (os.path.getatime(test.workpath('f3.in')),
- os.path.getmtime(test.workpath('f3.in'))+10))
-
-test.run(arguments = 'f1.out f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-build(["f1.out"], ["f1.in"])
-scons: `f2.out' is up to date.
-build(["f3.out"], ["f3.in"])
-scons: `f4.out' is up to date.
-"""))
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-
-SourceSignatures('MD5')
-""")
-
-test.write('f1.in', "f1.in\n")
-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 f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-scons: `f1.out' is up to date.
-build(["f2.out"], ["f2.in"])
-scons: `f3.out' is up to date.
-build(["f4.out"], ["f4.in"])
-"""))
-
-os.utime(test.workpath('f1.in'),
- (os.path.getatime(test.workpath('f1.in')),
- os.path.getmtime(test.workpath('f1.in'))+10))
-os.utime(test.workpath('f3.in'),
- (os.path.getatime(test.workpath('f3.in')),
- os.path.getmtime(test.workpath('f3.in'))+10))
-
-test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-""")
-
-test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env2 = env.Clone()
-env2.SourceSignatures('MD5')
-env.B(target = 'f5.out', source = 'f5.in')
-env.B(target = 'f6.out', source = 'f6.in')
-env2.B(target = 'f7.out', source = 'f7.in')
-env2.B(target = 'f8.out', source = 'f8.in')
-
-SourceSignatures('timestamp')
-""")
-
-test.write('f5.in', "f5.in\n")
-test.write('f6.in', "f6.in\n")
-test.write('f7.in', "f7.in\n")
-test.write('f8.in', "f8.in\n")
-
-test.run(arguments = 'f5.out f7.out')
-
-test.run(arguments = 'f5.out f6.out f7.out f8.out',
- stdout = test.wrap_stdout("""\
-scons: `f5.out' is up to date.
-build(["f6.out"], ["f6.in"])
-scons: `f7.out' is up to date.
-build(["f8.out"], ["f8.in"])
-"""))
-
-os.utime(test.workpath('f5.in'),
- (os.path.getatime(test.workpath('f5.in')),
- os.path.getmtime(test.workpath('f5.in'))+10))
-os.utime(test.workpath('f7.in'),
- (os.path.getatime(test.workpath('f7.in')),
- os.path.getmtime(test.workpath('f7.in'))+10))
-
-test.run(arguments = 'f5.out f6.out f7.out f8.out',
- stdout = test.wrap_stdout("""\
-build(["f5.out"], ["f5.in"])
-scons: `f6.out' is up to date.
-scons: `f7.out' is up to date.
-scons: `f8.out' is up to date.
-"""))
-
-test.up_to_date(arguments = 'f5.out f6.out f7.out f8.out')
-
-# Ensure that switching signature types causes a rebuild:
-test.write('SConstruct', """
-SourceSignatures('MD5')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.write('switch.in', "switch.in\n")
-
-switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('SConstruct', """
-SourceSignatures('timestamp')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('SConstruct', """
-SourceSignatures('MD5')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('switch.in', "switch.in 2\n")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-
-# Test both implicit_cache and timestamp signatures at the same time:
-test.write('SConstruct', """
-SetOption('implicit_cache', 1)
-SourceSignatures('timestamp')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'both.out', source = 'both.in')
-""")
-
-test.write('both.in', "both.in 1\n")
-
-both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n')
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 2\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 3\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 4\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.up_to_date(arguments = 'both.out')
-
-test.pass_test()
diff --git a/test/SourceSignatures/basic.py b/test/SourceSignatures/basic.py
new file mode 100644
index 0000000..7042fac
--- /dev/null
+++ b/test/SourceSignatures/basic.py
@@ -0,0 +1,124 @@
+#!/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 os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+
+base_sconstruct_contents = """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env.B(target = 'f3.out', source = 'f3.in')
+env.B(target = 'f4.out', source = 'f4.in')
+"""
+
+def write_SConstruct(test, sigtype):
+ contents = base_sconstruct_contents
+ if sigtype:
+ contents = contents + ("\nSourceSignatures('%s')\n" % sigtype)
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, 'timestamp')
+
+test.write('f1.in', "f1.in\n")
+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 f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+scons: `f1.out' is up to date.
+build(["f2.out"], ["f2.in"])
+scons: `f3.out' is up to date.
+build(["f4.out"], ["f4.in"])
+"""))
+
+
+
+os.utime(test.workpath('f1.in'),
+ (os.path.getatime(test.workpath('f1.in')),
+ os.path.getmtime(test.workpath('f1.in'))+10))
+os.utime(test.workpath('f3.in'),
+ (os.path.getatime(test.workpath('f3.in')),
+ os.path.getmtime(test.workpath('f3.in'))+10))
+
+test.run(arguments = 'f1.out f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+build(["f1.out"], ["f1.in"])
+scons: `f2.out' is up to date.
+build(["f3.out"], ["f3.in"])
+scons: `f4.out' is up to date.
+"""))
+
+
+
+# Switching to content signatures from timestamps should rebuild,
+# because we didn't record the content signatures last time.
+
+write_SConstruct(test, 'MD5')
+
+test.not_up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.sleep()
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+test.write('f4.in', "f4.in\n")
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.touch('f1.in', os.path.getmtime(test.workpath('f1.in'))+10)
+test.touch('f3.in', os.path.getmtime(test.workpath('f3.in'))+10)
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+write_SConstruct(test, None)
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/env.py b/test/SourceSignatures/env.py
new file mode 100644
index 0000000..3bef2a6
--- /dev/null
+++ b/test/SourceSignatures/env.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__"
+
+"""
+Test that use of env.SourceSignatures() correctly overrides the
+default behavior.
+"""
+
+import os
+import os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+base_sconstruct_contents = """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env2 = env.Copy()
+env2.SourceSignatures('%s')
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env2.B(target = 'f3.out', source = 'f3.in')
+env2.B(target = 'f4.out', source = 'f4.in')
+
+SourceSignatures('%s')
+"""
+
+def write_SConstruct(test, env_sigtype, default_sigtype):
+ contents = base_sconstruct_contents % (env_sigtype, default_sigtype)
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, 'MD5', 'timestamp')
+
+test.write('f1.in', "f1.in\n")
+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 f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+scons: `f1.out' is up to date.
+build(["f2.out"], ["f2.in"])
+scons: `f3.out' is up to date.
+build(["f4.out"], ["f4.in"])
+"""))
+
+
+
+test.sleep()
+
+test.touch('f1.in')
+test.touch('f3.in')
+
+test.run(arguments = 'f1.out f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+build(["f1.out"], ["f1.in"])
+scons: `f2.out' is up to date.
+scons: `f3.out' is up to date.
+scons: `f4.out' is up to date.
+"""))
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/implicit-cache.py b/test/SourceSignatures/implicit-cache.py
new file mode 100644
index 0000000..de66b72
--- /dev/null
+++ b/test/SourceSignatures/implicit-cache.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__"
+
+"""
+Test the simultaneous use of implicit_cache and
+SourceSignatures('timestamp')
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+SetOption('implicit_cache', 1)
+SourceSignatures('timestamp')
+
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'both.out', source = 'both.in')
+""")
+
+both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n')
+
+
+
+test.write('both.in', "both.in 1\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 2\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 3\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 4\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.up_to_date(arguments = 'both.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/no-csigs.py b/test/SourceSignatures/no-csigs.py
new file mode 100644
index 0000000..3702901
--- /dev/null
+++ b/test/SourceSignatures/no-csigs.py
@@ -0,0 +1,70 @@
+
+#!/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 os.path
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+
+test.write('SConstruct', """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+SourceSignatures('timestamp')
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+test.run(arguments = '.')
+
+
+
+expect = r"""=== .:
+SConstruct: None \d+ \d+
+f1.in: None \d+ \d+
+f1.out: \S+ \d+ \d+
+ f1.in: None \d+ \d+
+ \S+ \[build\(target, source, env\)\]
+f2.in: None \d+ \d+
+f2.out: \S+ \d+ \d+
+ f2.in: None \d+ \d+
+ \S+ \[build\(target, source, env\)\]
+"""
+
+test.run_sconsign(arguments = test.workpath('.sconsign'),
+ stdout = expect)
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/overrides.py b/test/SourceSignatures/overrides.py
new file mode 100644
index 0000000..cf83488
--- /dev/null
+++ b/test/SourceSignatures/overrides.py
@@ -0,0 +1,56 @@
+#!/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__"
+
+"""
+Make sure that SourceSignatures() works when overrides are used on a
+Builder call. (Previous implementations used methods that would stay
+bound to the underlying construction environment, which in this case
+meant ignoring the 'timestamp' setting and still using the underlying
+content signature.)
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+DefaultEnvironment().SourceSignatures('MD5')
+env = Environment()
+env.SourceSignatures('timestamp')
+env.Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=1)
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+test.run(arguments = 'foo.out')
+
+test.sleep()
+
+test.write('foo.in', "foo.in 1\n")
+
+test.not_up_to_date(arguments = 'foo.out')
+
+test.pass_test()
diff --git a/test/SourceSignatures/switch-rebuild.py b/test/SourceSignatures/switch-rebuild.py
new file mode 100644
index 0000000..85c2b22
--- /dev/null
+++ b/test/SourceSignatures/switch-rebuild.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__"
+
+"""
+Test that switching SourceSignature() types no longer causes rebuilds.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+base_sconstruct_contents = """\
+SourceSignatures('%s')
+
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'switch.out', source = 'switch.in')
+"""
+
+def write_SConstruct(test, sig_type):
+ contents = base_sconstruct_contents % sig_type
+ test.write('SConstruct', contents)
+
+
+write_SConstruct(test, 'MD5')
+
+test.write('switch.in', "switch.in\n")
+
+switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')
+
+test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
+
+test.up_to_date(arguments = 'switch.out')
+
+
+
+write_SConstruct(test, 'timestamp')
+
+test.up_to_date(arguments = 'switch.out')
+
+
+
+write_SConstruct(test, 'MD5')
+
+test.not_up_to_date(arguments = 'switch.out')
+
+
+
+test.write('switch.in', "switch.in 2\n")
+
+test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
+
+
+
+test.pass_test()
diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py
index e189d57..8df2e79 100644
--- a/test/TEX/auxiliaries.py
+++ b/test/TEX/auxiliaries.py
@@ -141,7 +141,7 @@ if pdf_output_1 != pdf_output_2:
import sys
test.write(['build', 'docs', 'test.normalized.1.pdf'], pdf_output_1)
test.write(['build', 'docs', 'test.normalized.2.pdf'], pdf_output_2)
- sys.stdout.write("***** 1 and 2 are different!\n")
+ sys.stdout.write("***** 1.pdf and 2.pdf are different!\n")
sys.stdout.write(test.diff_substr(pdf_output_1, pdf_output_2, 80, 80) + '\n')
sys.stdout.write("Output from run 1:\n")
sys.stdout.write(test.stdout(-1) + '\n')
@@ -150,7 +150,16 @@ if pdf_output_1 != pdf_output_2:
sys.stdout.flush()
test.fail_test()
-assert ps_output_1 == ps_output_2, test.diff_substr(ps_output_1, ps_output_2, 80, 80)
+if ps_output_1 != ps_output_2:
+ import sys
+ sys.stdout.write("***** 1.ps and 2.ps are different!\n")
+ sys.stdout.write(test.diff_substr(ps_output_1, ps_output_2, 80, 80) + '\n')
+ sys.stdout.write("Output from run 1:\n")
+ sys.stdout.write(test.stdout(-1) + '\n')
+ sys.stdout.write("Output from run 2:\n")
+ sys.stdout.write(test.stdout() + '\n')
+ sys.stdout.flush()
+ test.fail_test()
diff --git a/test/TEX/clean.py b/test/TEX/clean.py
new file mode 100644
index 0000000..6615fc9
--- /dev/null
+++ b/test/TEX/clean.py
@@ -0,0 +1,94 @@
+#!/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__"
+
+"""
+Check that all auxilary files created by LaTeX are properly cleaned by scons -c.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+latex = test.where_is('latex')
+
+if not latex:
+ test.skip_test("Could not find tex or latex; skipping test(s).\n")
+
+# package hyperref generates foo.out
+# package comment generates comment.cut
+# todo: add makeindex etc.
+input_file = r"""
+\documentclass{article}
+\usepackage{hyperref}
+\usepackage{comment}
+\specialcomment{foocom}{}{}
+\begin{document}
+\begin{foocom}
+Hi
+\end{foocom}
+As stated in \cite{X}, this is a bug-a-boo.
+\bibliography{fooref}
+\bibliographystyle{plain}
+\end{document}
+"""
+
+bibfile = r"""
+@Article{X,
+ author = "Mr. X",
+ title = "A determination of bug-a-boo-ness",
+ journal = "Journal of B.a.B.",
+ year = 1920,
+ volume = 62,
+ pages = 291
+}
+"""
+
+test.write('SConstruct', """\
+DVI( "foo.ltx" )
+""")
+
+test.write('foo.ltx', input_file)
+test.write('fooref.bib', bibfile)
+
+test.run()
+
+test.must_exist('foo.log')
+test.must_exist('foo.aux')
+test.must_exist('foo.bbl')
+test.must_exist('foo.blg')
+test.must_exist('comment.cut')
+test.must_exist('foo.out')
+
+test.run(arguments = '-c')
+
+test.must_not_exist('foo.log')
+test.must_not_exist('foo.aux')
+test.must_not_exist('foo.bbl')
+test.must_not_exist('foo.blg')
+test.must_not_exist('comment.cut')
+test.must_not_exist('foo.out')
+
+test.pass_test()
diff --git a/test/TargetSignatures.py b/test/TargetSignatures/build-content.py
index c3b506b..2cd7a89 100644
--- a/test/TargetSignatures.py
+++ b/test/TargetSignatures/build-content.py
@@ -24,17 +24,26 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify basic interaction of the historic TargetSignatures('build')
+and TargetSignatures('content') settings, overriding one with
+the other in specific construction environments.
+"""
+
import TestSCons
test = TestSCons.TestSCons()
-test.write('SConstruct', """
+
+
+sconstruct_contents = """\
env = Environment()
def copy1(env, source, target):
open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
def copy2(env, source, target):
+ %s
return copy1(env, source, target)
env['BUILDERS']['Copy1'] = Builder(action=copy1)
@@ -44,12 +53,20 @@ env.Copy2('foo.mid', 'foo.in')
env.Copy1('foo.out', 'foo.mid')
env2 = env.Clone()
-env2.TargetSignatures('build')
+env2.TargetSignatures('%s')
env2.Copy2('bar.mid', 'bar.in')
env2.Copy1('bar.out', 'bar.mid')
-TargetSignatures('content')
-""")
+TargetSignatures('%s')
+"""
+
+def write_SConstruct(test, *args):
+ contents = sconstruct_contents % args
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, '', 'build', 'content')
test.write('foo.in', 'foo.in')
test.write('bar.in', 'bar.in')
@@ -64,29 +81,12 @@ copy1(["foo.out"], ["foo.mid"])
test.up_to_date(arguments='bar.out foo.out')
-test.write('SConstruct', """
-env = Environment()
-
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
-
-def copy2(env, source, target):
- x = 2 # added this line
- return copy1(env, source, target)
-
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-env2 = env.Clone()
-env2.TargetSignatures('build')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
+# Change the code in the the copy2() function, which should change
+# its content and trigger a rebuild of the targets built with it.
-TargetSignatures('content')
-""")
+write_SConstruct(test, 'x = 2 # added this line', 'build', 'content')
test.run(arguments="bar.out foo.out",
stdout=test.wrap_stdout("""\
@@ -96,58 +96,21 @@ copy2(["foo.mid"], ["foo.in"])
scons: `foo.out' is up to date.
"""))
-test.write('SConstruct', """
-env = Environment()
-
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
-
-def copy2(env, source, target):
- x = 2 # added this line
- return copy1(env, source, target)
-
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-
-env2 = env.Copy()
-env2.TargetSignatures('content')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
-
-TargetSignatures('build')
-""")
-test.run(arguments="bar.out foo.out",
- stdout=test.wrap_stdout("""\
-copy1(["bar.out"], ["bar.mid"])
-copy1(["foo.out"], ["foo.mid"])
-"""))
-test.write('SConstruct', """
-env = Environment()
+# Swapping content and build signatures no longer causes a rebuild
+# because we record the right underlying information regardless.
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+write_SConstruct(test, 'x = 2 # added this line', 'content', 'build')
-def copy2(env, source, target):
- return copy1(env, source, target)
+test.up_to_date(arguments="bar.out foo.out")
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-env2 = env.Copy()
-env2.TargetSignatures('content')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
+# Change the code in the the copy2() function back again, which should
+# trigger another rebuild of the targets built with it.
-TargetSignatures('build')
-""")
+write_SConstruct(test, '', 'content', 'build')
test.run(arguments='bar.out foo.out',
stdout=test.wrap_stdout("""\
@@ -158,4 +121,5 @@ copy1(["foo.out"], ["foo.mid"])
"""))
+
test.pass_test()
diff --git a/test/TargetSignatures/content.py b/test/TargetSignatures/content.py
new file mode 100644
index 0000000..8d9f213
--- /dev/null
+++ b/test/TargetSignatures/content.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 use of the TargetSignatures('content') setting to override
+SourceSignatures('timestamp') settings.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('SConstruct', """\
+env = Environment()
+
+def copy(env, source, target):
+ fp = open(str(target[0]), 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+
+copyAction = Action(copy, "Copying $TARGET")
+
+SourceSignatures('timestamp')
+
+env['BUILDERS']['Copy'] = Builder(action=copyAction)
+
+env.Copy('foo.out', 'foo.in')
+
+env2 = env.Clone()
+env2.TargetSignatures('content')
+env2.Copy('bar.out', 'bar.in')
+AlwaysBuild('bar.out')
+
+env.Copy('final', ['foo.out', 'bar.out', 'extra.in'])
+env.Ignore('final', 'extra.in')
+""")
+
+test.write('foo.in', "foo.in\n")
+test.write('bar.in', "bar.in\n")
+test.write('extra.in', "extra.in 1\n")
+
+test.run()
+
+test.must_match('final', "foo.in\nbar.in\nextra.in 1\n")
+
+test.sleep()
+test.write('extra.in', "extra.in 2\n")
+
+test.run()
+
+test.must_match('final', "foo.in\nbar.in\nextra.in 1\n")
+
+
+
+test.pass_test()
diff --git a/test/TargetSignatures/overrides.py b/test/TargetSignatures/overrides.py
new file mode 100644
index 0000000..5d9dd99
--- /dev/null
+++ b/test/TargetSignatures/overrides.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Make sure that TargetSignatures() works when overrides are used on a
+Builder call. Previous implementations used methods that would stay
+bound to the underlying construction environment and cause weird
+behavior like infinite recursion.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env.TargetSignatures('content')
+env.Command('foo.out', 'foo.mid', Copy('$TARGET', '$SOURCE'), FOO=1)
+env.Command('foo.mid', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=2)
+""")
+
+test.write('foo.in', "foo.in\n")
+
+test.run(arguments = '.')
+
+test.must_match('foo.mid', "foo.in\n")
+test.must_match('foo.out', "foo.in\n")
+
+test.pass_test()
diff --git a/test/Value.py b/test/Value.py
index 85fcbd1..fd7afb7 100644
--- a/test/Value.py
+++ b/test/Value.py
@@ -35,13 +35,9 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons(match=TestCmd.match_re)
-# Run all of the tests with both types of source signature
-# to make sure there's no difference in behavior.
-for source_signature in ['MD5', 'timestamp']:
+python = TestSCons.python
- print "Testing Value node with source signatures:", source_signature
-
- test.write('SConstruct', """
+SConstruct_content = """
SourceSignatures(r'%(source_signature)s')
class Custom:
@@ -57,7 +53,7 @@ def create(target, source, env):
env = Environment()
env['BUILDERS']['B'] = Builder(action = create)
-env['BUILDERS']['S'] = Builder(action = '%(_python_)s put $SOURCES into $TARGET')
+env['BUILDERS']['S'] = Builder(action = r'%(_python_)s put.py $SOURCES into $TARGET')
env.B('f1.out', Value(P))
env.B('f2.out', env.Value(L))
env.B('f3.out', Value(C))
@@ -75,15 +71,23 @@ env['BUILDERS']['B3'] = Builder(action = create_value_file)
V = Value('my value')
env.B2(V, 'f3.out')
env.B3('f5.out', V)
-""" % locals())
+"""
- test.write('put', """
+test.write('put.py', """\
import os
import string
import sys
open(sys.argv[-1],'wb').write(string.join(sys.argv[1:-2]))
""")
+# Run all of the tests with both types of source signature
+# to make sure there's no difference in behavior.
+for source_signature in ['MD5', 'timestamp']:
+
+ print "Testing Value node with source signatures:", source_signature
+
+ test.write('SConstruct', SConstruct_content % locals())
+
test.run(arguments='-c')
test.run()
diff --git a/test/bad-drive.py b/test/bad-drive.py
index a642a7c..f07da2b 100644
--- a/test/bad-drive.py
+++ b/test/bad-drive.py
@@ -93,7 +93,7 @@ test.fail_test(test.read('aaa.out') != "aaa.in\n")
# becomes an issue or some refactoring restores the old behavior.
test.run(arguments = bad_drive + 'not_mentioned',
- stderr = "scons: *** No drive `%s' for target `%snot_mentioned'. Stop.\n" % (bad_drive, bad_drive),
+ stderr = "scons: *** Do not know how to make target `%snot_mentioned'. Stop.\n" % (bad_drive),
status = 2)
test.run(arguments = bad_drive + 'no_target_1',
diff --git a/test/chained-build.py b/test/chained-build.py
index 9d87347..6ec9d1c 100644
--- a/test/chained-build.py
+++ b/test/chained-build.py
@@ -59,6 +59,7 @@ test.write(['w1', 'foo.in'], "foo.in 1")
test.run(chdir='w1',
arguments="--max-drift=0 -f SConstruct1 foo.mid",
stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
+
test.run(chdir='w1',
arguments="--max-drift=0 -f SConstruct2 foo.out",
stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'))
@@ -66,6 +67,7 @@ test.run(chdir='w1',
test.up_to_date(chdir='w1',
options="--max-drift=0 -f SConstruct1",
arguments="foo.mid")
+
test.up_to_date(chdir='w1',
options="--max-drift=0 -f SConstruct2",
arguments="foo.out")
@@ -73,28 +75,23 @@ test.up_to_date(chdir='w1',
test.sleep() # make sure foo.in rewrite has new mod-time
test.write(['w1', 'foo.in'], "foo.in 2")
-test.run(chdir='w1',
- arguments="--max-drift=0 -f SConstruct1 foo.mid",
- stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
# Because we're using --max-drift=0, we use the cached csig value
-# and think that foo.mid hasn't changed even though it has on disk.
+# and think that foo.in hasn't changed even though it has on disk.
test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct2",
- arguments="foo.out")
+ options="--max-drift=0 -f SConstruct1",
+ arguments="foo.mid")
+# Now try with --max-drift disabled. The build of foo.out should still
+# be considered up-to-date, but the build of foo.mid now detects the
+# change and rebuilds, too, which then causes a rebuild of foo.out.
test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct1",
- arguments="foo.mid")
-test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct2",
+ options="--max-drift=-1 -f SConstruct2",
arguments="foo.out")
-# Now try with --max-drift disabled. The build of foo.mid should still
-# be considered up-to-date, but the build of foo.out now detects the
-# change and rebuilds, too.
-test.up_to_date(chdir='w1',
- options="--max-drift=-1 -f SConstruct1",
- arguments="foo.mid")
+test.run(chdir='w1',
+ arguments="--max-drift=-1 -f SConstruct1 foo.mid",
+ stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
+
test.run(chdir='w1',
arguments="--max-drift=-1 -f SConstruct2 foo.out",
stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'))
diff --git a/test/exceptions.py b/test/exceptions.py
index 34c24f4..c4bfb37 100644
--- a/test/exceptions.py
+++ b/test/exceptions.py
@@ -65,7 +65,7 @@ test.run(arguments = "-j2 foo.out", stderr = expected_stderr, status = 2)
# Verify that exceptions caused by exit values of builder actions are
-# correectly signalled, for both Serial and Parallel jobs.
+# correctly signalled, for both Serial and Parallel jobs.
test.write('myfail.py', r"""\
import sys
@@ -75,12 +75,12 @@ sys.exit(1)
test.write(SConstruct_path, """
Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE')
env = Environment(BUILDERS = { 'Fail' : Fail })
-env.Fail(target = 'f1', source = 'f1.in')
+env.Fail(target = 'out.f1', source = 'in.f1')
""" % locals())
-test.write('f1.in', "f1.in\n")
+test.write('in.f1', "in.f1\n")
-expected_stderr = "scons: \*\*\* \[f1\] Error 1\n"
+expected_stderr = "scons: \\*\\*\\* \\[out.f1\\] Error 1\n"
test.run(arguments = '.', status = 2, stderr = expected_stderr)
test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr)
@@ -93,13 +93,14 @@ test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr)
test.write(SConstruct_path, """
Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE')
env = Environment(BUILDERS = { 'Fail' : Fail })
-env.Fail(target = 'f1', source = 'f1.in')
-env.Fail(target = 'f2', source = 'f2.in')
-env.Fail(target = 'f3', source = 'f3.in')
+env.Fail(target = 'out.f1', source = 'in.f1')
+env.Fail(target = 'out.f2', source = 'in.f2')
+env.Fail(target = 'out.f3', source = 'in.f3')
""" % locals())
-# f2.in is not created to cause a Task.prepare exception
-test.write('f3.in', 'f3.in\n')
+# in.f2 is not created to cause a Task.prepare exception
+test.write('in.f1', 'in.f1\n')
+test.write('in.f3', 'in.f3\n')
# In Serial task mode, get the first exception and stop
test.run(arguments = '.', status = 2, stderr = expected_stderr)
@@ -107,24 +108,32 @@ test.run(arguments = '.', status = 2, stderr = expected_stderr)
# In Parallel task mode, we will get all three exceptions.
expected_stderr_list = [
- expected_stderr,
- "scons: \*\*\* Source `f2\.in' not found, needed by target `f2'\. Stop\.\n",
- string.replace(expected_stderr, 'f1', 'f3')
- ]
-
-# Unfortunately, we aren't guaranteed what order we will get the
-# exceptions in...
-orders = [ (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1) ]
-otexts = []
-for A,B,C in orders:
- otexts.append("%s%s%s"%(expected_stderr_list[A-1],
- expected_stderr_list[B-1],
- expected_stderr_list[C-1]))
-
-
-expected_stderrs = "(" + string.join(otexts, "|") + ")"
-
-test.run(arguments = '-j3 .', status = 2, stderr = expected_stderrs)
+ "scons: *** [out.f1] Error 1\n",
+ "scons: *** Source `in.f2' not found, needed by target `out.f2'. Stop.\n",
+ "scons: *** [out.f3] Error 1\n",
+]
+
+# To get all three exceptions simultaneously, we execute -j7 to create
+# one thread each for the SConstruct file and {in,out}.f[123]. Note that
+# it's important that the input (source) files sort earlier alphabetically
+# than the output files, so they're visited first in the dependency graph
+# walk of '.' and are already considered up-to-date when we kick off the
+# "simultaneous" builds of the output (target) files.
+
+test.run(arguments = '-j7 .', status = 2, stderr = None)
+
+missing = []
+for es in expected_stderr_list:
+ if string.find(test.stderr(), es) == -1:
+ missing.append(es)
+
+if missing:
+ sys.stderr.write("Missing the following lines from stderr:\n")
+ for m in missing:
+ sys.stderr.write(m)
+ sys.stderr.write('STDERR ===============================================\n')
+ sys.stderr.write(test.stderr())
+ test.fail_test(1)
test.pass_test()
diff --git a/test/explain/get_csig.py b/test/explain/get_csig.py
new file mode 100644
index 0000000..4bf4981
--- /dev/null
+++ b/test/explain/get_csig.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 we can call get_csig() from a function action without
+causing problems. (This messed up a lot of internal state before
+the Big Signature Refactoring.)
+
+Test case courtesy of Damyan Pepper.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+args = "--debug=explain"
+
+test.write('SConstruct', """\
+env = Environment()
+
+def action( source, target, env ):
+ target[0].get_csig()
+ f = open( str(target[0]), 'w' )
+ for s in source:
+ f.write( s.get_contents() )
+ f.close()
+
+builder = env.Builder( action=action )
+
+builder( env, target = "target.txt", source = "source.txt" )
+""")
+
+test.write("source.txt", "source.txt 1\n")
+
+test.run(arguments=args)
+
+
+
+test.write("source.txt", "source.txt 2")
+
+
+
+expect_rebuild = test.wrap_stdout("""\
+scons: rebuilding `target.txt' because `source.txt' changed
+action(["target.txt"], ["source.txt"])
+""")
+
+test.not_up_to_date(arguments=args)
+
+
+
+test.pass_test()
diff --git a/test/implicit-cache/basic.py b/test/implicit-cache/basic.py
index 0c9196c..265f589 100644
--- a/test/implicit-cache/basic.py
+++ b/test/implicit-cache/basic.py
@@ -41,7 +41,13 @@ test = TestSCons.TestSCons()
test.subdir('include', 'subdir', ['subdir', 'include'], 'inc2')
+# Set TargetSignatures('build') because a lot of the test below expect
+# the old behavior of non-essential changes in .h files will propagate
+# and cause the executable file to be re-linked as well (even if the
+# object file was rebuilt to the exact same contents as last time).
+
test.write('SConstruct', """
+TargetSignatures('build')
env = Environment(CPPPATH = Split('inc2 include'))
obj = env.Object(target='prog', source='subdir/prog.c')
env.Program(target='prog', source=obj)
diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py
new file mode 100644
index 0000000..47acc2f
--- /dev/null
+++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py
@@ -0,0 +1,125 @@
+#!/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 $IMPLICIT_COMMAND_DEPENDENCIES variable controls
+whether or not the implicit dependency on executed commands
+is added to targets.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+generate_build_py_py_contents = """\
+#!%(python)s
+import os
+import sys
+
+open(sys.argv[1], 'w').write('''\
+#!/usr/bin/env %(python)s
+import os.path
+import string
+import sys
+fp = open(sys.argv[1], 'wb')
+args = [os.path.split(sys.argv[0])[1]] + sys.argv[1:]
+fp.write(string.join(args) + '\\\\n' + '%(extra)s')
+for infile in sys.argv[2:]:
+ fp.write(open(infile, 'rb').read())
+fp.close()
+''')
+os.chmod(sys.argv[1], 0755)
+
+"""
+
+extra = ''
+test.write('generate_build_py.py', generate_build_py_py_contents % locals())
+
+test.write('SConstruct', """
+generate = Builder(action = r'%(_python_)s $GENERATE $TARGET')
+build = Builder(action = r'$BUILD_PY $TARGET $SOURCES')
+env = Environment(BUILDERS = {
+ 'GenerateBuild' : generate,
+ 'BuildFile' : build,
+ },
+ GENERATE = 'generate_build_py.py',
+ BUILD_PY = 'build.py',
+ )
+env.PrependENVPath('PATH', '.')
+env.PrependENVPath('PATHEXT', '.PY')
+env0 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0)
+env1 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 1)
+envNone = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = None)
+envFalse = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = False)
+envTrue = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = True)
+
+build_py = env.GenerateBuild('${BUILD_PY}', [])
+AlwaysBuild(build_py)
+
+env.BuildFile('file.out', 'file.in')
+env0.BuildFile('file0.out', 'file.in')
+env1.BuildFile('file1.out', 'file.in')
+envNone.BuildFile('fileNone.out', 'file.in')
+envFalse.BuildFile('fileFalse.out', 'file.in')
+envTrue.BuildFile('fileTrue.out', 'file.in')
+""" % locals())
+
+
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '--tree=all .')
+
+expect_none = 'build.py %s file.in\nfile.in\n'
+
+test.must_match('file.out', expect_none % 'file.out')
+test.must_match('file0.out', expect_none % 'file0.out')
+test.must_match('file1.out', expect_none % 'file1.out')
+test.must_match('fileNone.out', expect_none % 'fileNone.out')
+test.must_match('fileFalse.out', expect_none % 'fileFalse.out')
+test.must_match('fileTrue.out', expect_none % 'fileTrue.out')
+
+
+
+extra = 'xyzzy\\\\n'
+test.write('generate_build_py.py', generate_build_py_py_contents % locals())
+
+test.run(arguments = '--tree=all .')
+
+expect_extra = 'build.py %s file.in\nxyzzy\nfile.in\n'
+
+test.must_match('file.out', expect_extra % 'file.out')
+test.must_match('file0.out', expect_none % 'file0.out')
+test.must_match('file1.out', expect_extra % 'file1.out')
+test.must_match('fileNone.out', expect_none % 'fileNone.out')
+test.must_match('fileFalse.out', expect_none % 'fileFalse.out')
+test.must_match('fileTrue.out', expect_extra % 'fileTrue.out')
+
+
+test.pass_test()
diff --git a/test/implicit/asynchronous-modification.py b/test/implicit/asynchronous-modification.py
new file mode 100644
index 0000000..d10f823
--- /dev/null
+++ b/test/implicit/asynchronous-modification.py
@@ -0,0 +1,89 @@
+#!/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 expected behavior when an implicit dependency is modified
+asynchronously (that is, mid-build and without our knowledge).
+
+Test case courtesy Greg Noel.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.write(['SConstruct'], """\
+import SCons.Defaults
+env = Environment()
+env['BUILDERS']['C'] = Builder(action = Copy('$TARGET', '$SOURCE'),
+ source_scanner = SCons.Defaults.CScan)
+env['BUILDERS']['Mod'] = Builder(action = r'%(_python_)s mod.py')
+Alias('seq', env.C('one.c'))
+Alias('seq', env.Mod('mod', 'mod.py'))
+Alias('seq', env.C('two.c'))
+Default('seq')
+""" % locals())
+
+test.write(['hdr.h'], """\
+/* empty header */
+""")
+
+test.write(['mod.py'], """\
+open('mod', 'w').write(open('mod.py', 'r').read())
+open('hdr.h', 'w').write("/* modified */\\n")
+""")
+
+test.write(['one.c'], """\
+#include "hdr.h"
+""")
+
+test.write(['two.c'], """\
+#include "hdr.h"
+""")
+
+# The first run builds the file 'one', then runs the 'mod' script
+# (which update modifies the 'hdr.h' file) then builds the file 'two'.
+test.run(arguments = 'seq')
+
+# The 'hdr.h' file had its original contents when 'one' was built,
+# and modified contents when 'two' was built. Because we took a
+# look at 'hdr.h' once, up front, we think both files are out of
+# date and will rebuild both (even though 'two' is really up to date).
+#
+# A future enhancement might add some sort of verification mode that
+# would examine 'hdr.h' again when 'two' was built, thereby avoiding
+# the unnecessary rebuild. In that case, the second line below
+# will need to change to "test.up_to_date(...)".
+test.not_up_to_date(arguments = 'one')
+test.not_up_to_date(arguments = 'two')
+
+# Regardless of what happened on the middle run(s), both files should
+# be up to date now.
+test.up_to_date(arguments = 'seq')
+
+test.pass_test()
diff --git a/test/changed-node.py b/test/implicit/changed-node.py
index 99a16ac..99a16ac 100644
--- a/test/changed-node.py
+++ b/test/implicit/changed-node.py
diff --git a/test/option-u.py b/test/option-u.py
index 9b5e88c..439daa2 100644
--- a/test/option-u.py
+++ b/test/option-u.py
@@ -73,7 +73,6 @@ env.Cat(target = 'f4a.out', source = 'f4a.in')
f4b_in = File('dir/f4b.in')
f4b_in.exists()
f4b_in.is_derived()
-f4b_in.is_pseudo_derived()
env.Cat(target = 'dir/f4b.out', source = f4b_in)
""")
diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py
index 33f0f4d..8c8b2cf 100644
--- a/test/option/debug-memoizer.py
+++ b/test/option/debug-memoizer.py
@@ -69,7 +69,6 @@ expect = [
"Base.stat()",
"Dir.srcdir_list()",
"File.exists()",
- "FS._doLookup()",
"Node._children_get()",
]
diff --git a/test/option/debug-stree.py b/test/option/debug-stree.py
index 21ca386..d25b7fa 100644
--- a/test/option/debug-stree.py
+++ b/test/option/debug-stree.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('foo', Split('foo.c bar.c'))
@@ -75,14 +79,17 @@ test.write('bar.h', """
stree = """
[E B C ]+-foo.xxx
[E B C ] +-foo.ooo
-[E ] | +-foo.c
-[E ] | +-foo.h
-[E ] | +-bar.h
+[E C ] | +-foo.c
+[E C ] | +-foo.h
+[E C ] | +-bar.h
+[E C ] | +-%(CC)s
[E B C ] +-bar.ooo
-[E ] +-bar.c
-[E ] +-bar.h
-[E ] +-foo.h
-"""
+[E C ] | +-bar.c
+[E C ] | +-bar.h
+[E C ] | +-foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = "--debug=stree foo.xxx")
test.fail_test(string.find(test.stdout(), stree) == -1)
@@ -101,14 +108,17 @@ stree2 = """
[ B ]+-foo.xxx
[ B ] +-foo.ooo
-[E ] | +-foo.c
-[E ] | +-foo.h
-[E ] | +-bar.h
+[E C ] | +-foo.c
+[E C ] | +-foo.h
+[E C ] | +-bar.h
+[E C ] | +-%(CC)s
[ B ] +-bar.ooo
-[E ] +-bar.c
-[E ] +-bar.h
-[E ] +-foo.h
-"""
+[E C ] | +-bar.c
+[E C ] | +-bar.h
+[E C ] | +-foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = '-c foo.xxx')
diff --git a/test/option/debug-time.py b/test/option/debug-time.py
index e8873cf..8a975a3 100644
--- a/test/option/debug-time.py
+++ b/test/option/debug-time.py
@@ -64,6 +64,12 @@ test.write('f4.in', "f4.in\n")
+# Before anything else, make sure we get valid --debug=time results
+# when just running the help option.
+test.run(arguments = "-h --debug=time")
+
+
+
def num(s, match):
return float(re.search(match, s).group(1))
diff --git a/test/option/debug-tree.py b/test/option/debug-tree.py
index 4f025c2..09cdffb 100644
--- a/test/option/debug-tree.py
+++ b/test/option/debug-tree.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('Foo', Split('Foo.c Bar.c'))
@@ -82,40 +86,57 @@ tree1 = """
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Bar.ooo
- +-Bar.c
- +-Bar.h
- +-Foo.h
-"""
+ | +-Bar.c
+ | +-Bar.h
+ | +-Foo.h
+ | +-%(CC)s
+ +-%(LINK)s
+""" % locals()
test.run(arguments = "--debug=tree Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree2 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-Foo.ooo
| | +-Foo.c
| | +-Foo.h
| | +-Bar.h
+ | | +-%(CC)s
| +-Bar.ooo
- | +-Bar.c
- | +-Bar.h
- | +-Foo.h
+ | | +-Bar.c
+ | | +-Bar.h
+ | | +-Foo.h
+ | | +-%(CC)s
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
+
test.run(arguments = "--debug=tree .")
-test.fail_test(string.find(test.stdout(), tree2) == -1)
+if string.find(test.stdout(), tree2) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
# Make sure we print the debug stuff even if there's a build failure.
test.write('Bar.h', """
@@ -129,6 +150,9 @@ THIS SHOULD CAUSE A BUILD FAILURE
test.run(arguments = "--debug=tree Foo.xxx",
status = 2,
stderr = None)
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.pass_test()
diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py
index 30faced..3139504 100644
--- a/test/option/taskmastertrace.py
+++ b/test/option/taskmastertrace.py
@@ -34,29 +34,35 @@ test = TestSCons.TestSCons()
test.write('SConstruct', """
env = Environment()
-env.Command('file.out', 'file.mid', Copy('$TARGET', '$SOURCE'))
-env.Command('file.mid', 'file.in', Copy('$TARGET', '$SOURCE'))
+
+# We name the files 'Tfile' so that they will sort after the SConstruct
+# file regardless of whether the test is being run on a case-sensitive
+# or case-insensitive system.
+
+env.Command('Tfile.out', 'Tfile.mid', Copy('$TARGET', '$SOURCE'))
+env.Command('Tfile.mid', 'Tfile.in', Copy('$TARGET', '$SOURCE'))
""")
-test.write('file.in', "file.in\n")
+test.write('Tfile.in', "Tfile.in\n")
expect_stdout = test.wrap_stdout("""\
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
- waiting on unstarted children:
- ['file.mid', 'file.out']
-Taskmaster: 'file.mid': children:
- ['file.in']
- evaluating file.mid
-Copy("file.mid", "file.in")
-Taskmaster: 'file.out': children:
- ['file.mid']
- evaluating file.out
-Copy("file.out", "file.mid")
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+ waiting on unfinished children:
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+Taskmaster: 'SConstruct': evaluating SConstruct
+Taskmaster: 'Tfile.in': evaluating Tfile.in
+Taskmaster: 'Tfile.mid': children:
+ ['Tfile.in']
+ evaluating Tfile.mid
+Copy("Tfile.mid", "Tfile.in")
+Taskmaster: 'Tfile.out': children:
+ ['Tfile.mid']
+ evaluating Tfile.out
+Copy("Tfile.out", "Tfile.mid")
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
evaluating .
-Taskmaster: '.': already handled (executed)
""")
test.run(arguments='--taskmastertrace=- .', stdout=expect_stdout)
@@ -68,27 +74,28 @@ test.run(arguments='-c .')
expect_stdout = test.wrap_stdout("""\
-Copy("file.mid", "file.in")
-Copy("file.out", "file.mid")
+Copy("Tfile.mid", "Tfile.in")
+Copy("Tfile.out", "Tfile.mid")
""")
test.run(arguments='--taskmastertrace=trace.out .', stdout=expect_stdout)
expect_trace = """\
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
- waiting on unstarted children:
- ['file.mid', 'file.out']
-Taskmaster: 'file.mid': children:
- ['file.in']
- evaluating file.mid
-Taskmaster: 'file.out': children:
- ['file.mid']
- evaluating file.out
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+ waiting on unfinished children:
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+Taskmaster: 'SConstruct': evaluating SConstruct
+Taskmaster: 'Tfile.in': evaluating Tfile.in
+Taskmaster: 'Tfile.mid': children:
+ ['Tfile.in']
+ evaluating Tfile.mid
+Taskmaster: 'Tfile.out': children:
+ ['Tfile.mid']
+ evaluating Tfile.out
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
evaluating .
-Taskmaster: '.': already handled (executed)
"""
test.must_match('trace.out', expect_trace)
diff --git a/test/option/tree-all.py b/test/option/tree-all.py
index ec7c7d8..7940d47 100644
--- a/test/option/tree-all.py
+++ b/test/option/tree-all.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('Foo', Split('Foo.c Bar.c'))
@@ -82,65 +86,92 @@ tree1 = """
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Bar.ooo
- +-Bar.c
- +-Bar.h
- +-Foo.h
-"""
+ | +-Bar.c
+ | +-Bar.h
+ | +-Foo.h
+ | +-%(CC)s
+ +-%(LINK)s
+""" % locals()
test.run(arguments = "--tree=all Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree2 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-Foo.ooo
| | +-Foo.c
| | +-Foo.h
| | +-Bar.h
+ | | +-%(CC)s
| +-Bar.ooo
- | +-Bar.c
- | +-Bar.h
- | +-Foo.h
+ | | +-Bar.c
+ | | +-Bar.h
+ | | +-Foo.h
+ | | +-%(CC)s
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
test.run(arguments = "--tree=all .")
-test.fail_test(string.find(test.stdout(), tree2) == -1)
+if string.find(test.stdout(), tree2) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree3 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-[Foo.ooo]
| +-[Bar.ooo]
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
test.run(arguments = "--tree=all,prune .")
-test.fail_test(string.find(test.stdout(), tree3) == -1)
+if string.find(test.stdout(), tree3) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.run(arguments = "--tree=prune .")
-test.fail_test(string.find(test.stdout(), tree3) == -1)
+if string.find(test.stdout(), tree3) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree4 = """
E = exists
@@ -156,22 +187,31 @@ tree4 = """
[ B ]+-Foo.xxx
[ B ] +-Foo.ooo
-[E ] | +-Foo.c
-[E ] | +-Foo.h
-[E ] | +-Bar.h
+[E C ] | +-Foo.c
+[E C ] | +-Foo.h
+[E C ] | +-Bar.h
+[E C ] | +-%(CC)s
[ B ] +-Bar.ooo
-[E ] +-Bar.c
-[E ] +-Bar.h
-[E ] +-Foo.h
-"""
+[E C ] | +-Bar.c
+[E C ] | +-Bar.h
+[E C ] | +-Foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = '-c Foo.xxx')
test.run(arguments = "--no-exec --tree=all,status Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree4) == -1)
+if string.find(test.stdout(), tree4) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.run(arguments = "--no-exec --tree=status Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree4) == -1)
+if string.find(test.stdout(), tree4) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
# Make sure we print the debug stuff even if there's a build failure.
test.write('Bar.h', """
@@ -185,6 +225,9 @@ THIS SHOULD CAUSE A BUILD FAILURE
test.run(arguments = "--tree=all Foo.xxx",
status = 2,
stderr = None)
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.pass_test()
diff --git a/test/option/tree-lib.py b/test/option/tree-lib.py
new file mode 100644
index 0000000..fc29d50
--- /dev/null
+++ b/test/option/tree-lib.py
@@ -0,0 +1,88 @@
+#!/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__"
+
+"""
+Make sure that --tree=derived output with a library dependency shows
+the dependency on the library. (On earlier versions of the Microsoft
+toolchain this wouldn't show up unless the library already existed
+on disk.)
+
+Issue 1363: http://scons.tigris.org/issues/show_bug.cgi?id=1363
+"""
+
+import string
+import sys
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+env = Environment(LIBPREFIX='',
+ LIBSUFFIX='.lib',
+ OBJSUFFIX='.obj',
+ EXESUFFIX='.exe')
+env.AppendENVPath('PATH', '.')
+l = env.Library( 'util.lib', 'util.c' )
+p = env.Program( 'test.exe', 'main.c', LIBS=l )
+env.Command( 'foo.h', p, '$SOURCE > $TARGET')
+""")
+
+test.write('main.c', """\
+#include <stdlib.h>
+#include <stdio.h>
+int
+main(int argc, char *argv)
+{
+ printf("#define FOO_H \\"foo.h\\"\\n");
+ return (0);
+}
+""")
+
+test.write('util.c', """\
+void
+util(void)
+{
+ ;
+}
+""")
+
+expect = """
+ +-test.exe
+ +-main.obj
+ +-util.lib
+ +-util.obj
+"""
+
+test.run(arguments = '--tree=derived foo.h')
+if string.find(test.stdout(), expect) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
+
+test.up_to_date(arguments = 'foo.h')
+
+test.pass_test()
diff --git a/test/packaging/convenience-functions.py b/test/packaging/convenience-functions.py
new file mode 100644
index 0000000..6eae270
--- /dev/null
+++ b/test/packaging/convenience-functions.py
@@ -0,0 +1,76 @@
+#!/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 the FindInstalledFiles() and the FindSourceFiles() functions.
+"""
+
+import os.path
+import string
+import TestSCons
+
+python = TestSCons.python
+test = TestSCons.TestSCons()
+
+test.write( "f1", "" )
+test.write( "f2", "" )
+test.write( "f3", "" )
+
+test.write( 'SConstruct', r"""
+env = Environment(tools=['default', 'packaging'])
+prog = env.Install( 'bin/', ["f1", "f2"] )
+env.File( "f3" )
+
+src_files = map(str, env.FindSourceFiles())
+oth_files = map(str, env.FindInstalledFiles())
+src_files.sort()
+oth_files.sort()
+
+print src_files
+print oth_files
+""")
+
+bin_f1 = os.path.join('bin', 'f1')
+bin_f2 = os.path.join('bin', 'f2')
+
+bin__f1 = string.replace(bin_f1, '\\', '\\\\')
+bin__f2 = string.replace(bin_f2, '\\', '\\\\')
+
+expect_read = """\
+['SConstruct', 'f1', 'f2', 'f3']
+['%(bin__f1)s', '%(bin__f2)s']
+""" % locals()
+
+expect_build = """\
+Install file: "f1" as "%(bin_f1)s"
+Install file: "f2" as "%(bin_f2)s"
+""" % locals()
+
+expected = test.wrap_stdout(read_str = expect_read, build_str = expect_build)
+
+test.run(stdout=expected)
+
+test.pass_test()
diff --git a/test/packaging/msi/explicit-target.py b/test/packaging/msi/explicit-target.py
new file mode 100644
index 0000000..745f0c1
--- /dev/null
+++ b/test/packaging/msi/explicit-target.py
@@ -0,0 +1,92 @@
+#!/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 the ability to use a explicit target package name and the use
+of FindInstalledFiles() in conjuction with .msi packages.
+"""
+
+import os
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+try:
+ from xml.dom.minidom import *
+except ImportError:
+ test.skip_test('Canoot import xml.dom.minidom skipping test\n')
+
+wix = test.Environment().WhereIs('candle')
+
+if not wix:
+ test.skip_test("No 'candle' found; skipping test\n")
+
+#
+# build with minimal tag set and test for the given package meta-data
+#
+test.write( 'file1.exe', "file1" )
+test.write( 'file2.exe', "file2" )
+
+test.write('SConstruct', """
+import os
+
+env = Environment(tools=['default', 'packaging'])
+
+f1 = env.Install( '/usr/' , 'file1.exe' )
+f2 = env.Install( '/usr/' , 'file2.exe' )
+
+env.Alias( 'install', [ f1, f2 ] )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2',
+ PACKAGETYPE = 'msi',
+ SUMMARY = 'balalalalal',
+ DESCRIPTION = 'this should be reallly really long',
+ VENDOR = 'Nanosoft_2000',
+ source = env.FindInstalledFiles(),
+ target = "mypackage.msi",
+ )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'foo-1.2.wxs' )
+test.must_exist( 'foo-1.2.msi' )
+
+dom = parse( test.workpath( 'foo-1.2.wxs' ) )
+Product = dom.getElementsByTagName( 'Product' )[0]
+Package = dom.getElementsByTagName( 'Package' )[0]
+
+test.fail_test( not Product.attributes['Manufacturer'].value == 'Nanosoft_2000' )
+test.fail_test( not Product.attributes['Version'].value == '1.2' )
+test.fail_test( not Product.attributes['Name'].value == 'foo' )
+
+test.fail_test( not Package.attributes['Description'].value == 'balalalalal' )
+test.fail_test( not Package.attributes['Comments'].value == 'this should be reallly really long' )
+
+test.pass_test()
diff --git a/test/packaging/multiple-packages-at-once.py b/test/packaging/multiple-packages-at-once.py
new file mode 100644
index 0000000..3151c05
--- /dev/null
+++ b/test/packaging/multiple-packages-at-once.py
@@ -0,0 +1,82 @@
+#!/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__"
+
+"""
+See if the packaging tool is able to build multiple packages at once.
+
+TODO: test if the packages are clean versions (i.e. do not contain files
+ added by different packager runs)
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+zip = test.detect('ZIP', 'zip')
+
+if not zip:
+ test.skip_test('zip not found, skipping test\n')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+Program( 'src/main.c' )
+env=Environment(tools=['default', 'packaging'])
+env.Package( PACKAGETYPE = ['src_zip', 'src_targz'],
+ target = ['src.zip', 'src.tar.gz'],
+ PACKAGEROOT = 'test',
+ source = [ 'src/main.c', 'SConstruct' ] )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'src.zip' )
+test.must_exist( 'src.tar.gz' )
+
+test.write('SConstruct', """
+Program( 'src/main.c' )
+env=Environment(tools=['default', 'packaging'])
+env.Package( PACKAGETYPE = ['src_zip', 'src_targz'],
+ NAME = "src", VERSION = "1.0",
+ PACKAGEROOT = 'test',
+ source = [ 'src/main.c', 'SConstruct' ] )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'src-1.0.zip' )
+test.must_exist( 'src-1.0.tar.gz' )
+
+test.pass_test()
diff --git a/test/packaging/multiple-subdirs.py b/test/packaging/multiple-subdirs.py
new file mode 100644
index 0000000..80758ab
--- /dev/null
+++ b/test/packaging/multiple-subdirs.py
@@ -0,0 +1,80 @@
+#!/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 build packages in different subdirectories.
+
+Test case courtesy Andrew Smith.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+tar = test.detect('TAR', 'tar')
+
+if not tar:
+ test.skip_test('No TAR executable found; skipping test\n')
+
+test.subdir('one', 'two', 'three')
+
+test.write('SConstruct', """\
+env = Environment(tools=['default', 'packaging'])
+Export('env')
+SConscript(dirs = ['one', 'two', 'three'])
+""")
+
+SConscript_template = """\
+Import('*')
+
+files = env.Install('/usr/bin', '%s.sh')
+
+pkg = env.Package(NAME = '%s',
+ VERSION = '1.0.0',
+ PACKAGETYPE = 'targz',
+ source = [files]
+ )
+"""
+
+test.write(['one', 'SConscript'], SConscript_template % ('one', 'one'))
+test.write(['two', 'SConscript'], SConscript_template % ('two', 'two'))
+test.write(['three', 'SConscript'], SConscript_template % ('three', 'three'))
+
+test.write(['one', 'one.sh'], "one/one.sh\n")
+test.write(['two', 'two.sh'], "two/two.sh\n")
+test.write(['three', 'three.sh'], "three/three.sh\n")
+
+test.run(arguments = '.')
+
+test.must_match(['one', 'one-1.0.0', 'usr', 'bin', 'one.sh'], "one/one.sh\n")
+test.must_match(['two', 'two-1.0.0', 'usr', 'bin', 'two.sh'], "two/two.sh\n")
+test.must_match(['three', 'three-1.0.0', 'usr', 'bin', 'three.sh'], "three/three.sh\n")
+
+test.must_exist(['one', 'one-1.0.0.tar.gz'])
+test.must_exist(['two', 'two-1.0.0.tar.gz'])
+test.must_exist(['three', 'three-1.0.0.tar.gz'])
+
+test.pass_test()
diff --git a/test/packaging/option--package-type.py b/test/packaging/option--package-type.py
index 00a569e..ce16e95 100644
--- a/test/packaging/option--package-type.py
+++ b/test/packaging/option--package-type.py
@@ -67,14 +67,21 @@ env.Package( NAME = 'foo',
)
""" % locals())
-test.run(arguments='package PACKAGETYPE=rpm', stderr = None)
-
src_rpm = 'foo-1.2.3-0.src.rpm'
machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+test.run(arguments='package PACKAGETYPE=rpm', stderr = None)
+
test.must_exist( src_rpm )
test.must_exist( machine_rpm )
+test.must_not_exist( 'bin/main.c' )
+test.must_not_exist( '/bin/main.c' )
+
+test.run(arguments='-c package PACKAGETYPE=rpm', stderr = None)
+test.run(arguments='package --package-type=rpm', stderr = None)
+test.must_exist( src_rpm )
+test.must_exist( machine_rpm )
test.must_not_exist( 'bin/main.c' )
test.must_not_exist( '/bin/main.c' )
diff --git a/test/packaging/place-files-in-subdirectory.py b/test/packaging/place-files-in-subdirectory.py
index d9758a1..66bdd53 100644
--- a/test/packaging/place-files-in-subdirectory.py
+++ b/test/packaging/place-files-in-subdirectory.py
@@ -38,7 +38,7 @@ test = TestSCons.TestSCons()
tar = test.detect('TAR', 'tar')
if not tar:
- test.skipt_test('tar not found, skipping test\n')
+ test.skip_test('tar not found, skipping test\n')
#
# TEST: subdir creation and file copying
diff --git a/test/packaging/rpm/cleanup.py b/test/packaging/rpm/cleanup.py
index 5472fbb..11f6645 100644
--- a/test/packaging/rpm/cleanup.py
+++ b/test/packaging/rpm/cleanup.py
@@ -83,9 +83,11 @@ env.Alias( 'install', prog )
""" % locals())
# first run: build the package
-# second run: test if the intermediate files have been cleaned
-test.run( arguments='' )
-test.run( arguments='-c' )
+# second run: make sure everything is up-to-date (sanity check)
+# third run: test if the intermediate files have been cleaned
+test.run( arguments='.' )
+test.up_to_date( arguments='.' )
+test.run( arguments='-c .' )
src_rpm = 'foo-1.2.3-0.src.rpm'
machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
diff --git a/test/packaging/rpm/explicit-target.py b/test/packaging/rpm/explicit-target.py
new file mode 100644
index 0000000..12a6c6c
--- /dev/null
+++ b/test/packaging/rpm/explicit-target.py
@@ -0,0 +1,95 @@
+#!/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 the ability to create a rpm package from a explicit target name.
+"""
+
+import os
+import TestSCons
+
+machine = TestSCons.machine
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+scons = test.program
+
+rpm = test.Environment().WhereIs('rpm')
+
+if not rpm:
+ test.skip_test('rpm not found, skipping test\n')
+
+rpm_build_root = test.workpath('rpm_build_root')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+import os
+
+env=Environment(tools=['default', 'packaging'])
+
+env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ')
+env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s')
+
+prog = env.Install( '/bin/' , Program( 'src/main.c') )
+
+env.Alias( 'install', prog )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ target = "my_rpm_package.rpm",
+ SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz'
+ )
+""" % locals())
+
+test.run(arguments='', stderr = None)
+
+src_rpm = 'foo-1.2.3-0.src.rpm'
+machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+
+test.must_exist( machine_rpm )
+test.must_exist( src_rpm )
+test.must_not_exist( 'bin/main' )
+test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n')
+test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n')
+
+test.pass_test()
diff --git a/test/packaging/rpm/internationalization.py b/test/packaging/rpm/internationalization.py
index af0bc75..24d8ddd 100644
--- a/test/packaging/rpm/internationalization.py
+++ b/test/packaging/rpm/internationalization.py
@@ -104,12 +104,10 @@ test.must_not_exist( 'bin/main' )
cmd = 'rpm -qp --queryformat \'%%{GROUP}-%%{SUMMARY}-%%{DESCRIPTION}\' %s'
-os.environ['LC_ALL'] = 'de_DE.utf8'
os.environ['LANGUAGE'] = 'de'
out = os.popen( cmd % test.workpath(machine_rpm) ).read()
test.fail_test( out != 'Applikation/büro-hallo-das sollte wirklich lang sein' )
-os.environ['LC_ALL'] = 'fr_FR.utf8'
os.environ['LANGUAGE'] = 'fr'
out = os.popen( cmd % test.workpath(machine_rpm) ).read()
test.fail_test( out != 'Application/bureau-bonjour-ceci devrait être vraiment long' )
diff --git a/test/packaging/rpm/multipackage.py b/test/packaging/rpm/multipackage.py
new file mode 100644
index 0000000..5b85db3
--- /dev/null
+++ b/test/packaging/rpm/multipackage.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__"
+
+"""
+Test the ability to create more than rpm file with different package root
+from one SCons environment.
+"""
+
+import os
+import TestSCons
+
+machine = TestSCons.machine
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+scons = test.program
+
+rpm = test.Environment().WhereIs('rpm')
+
+if not rpm:
+ test.skip_test('rpm not found, skipping test\n')
+
+rpm_build_root = test.workpath('rpm_build_root')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+import os
+
+env=Environment(tools=['default', 'packaging'])
+
+env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ')
+env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s')
+
+prog = env.Install( '/bin/' , Program( 'src/main.c') )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz'
+ )
+
+env.Package( NAME = 'foo2',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ )
+
+
+
+env.Alias( 'install', prog )
+""" % locals())
+
+test.run(arguments='', stderr = None)
+
+src_rpm = 'foo-1.2.3-0.src.rpm'
+machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+src_rpm2 = 'foo2-1.2.3-0.src.rpm'
+machine_rpm2 = 'foo2-1.2.3-0.%s.rpm' % machine
+
+test.must_exist( machine_rpm )
+test.must_exist( src_rpm )
+
+test.must_exist( machine_rpm2 )
+test.must_exist( src_rpm2 )
+
+test.must_not_exist( 'bin/main' )
+test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n')
+test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n')
+
+test.pass_test()
diff --git a/test/packaging/strip-install-dir.py b/test/packaging/strip-install-dir.py
index 65b6a61..ec40220 100644
--- a/test/packaging/strip-install-dir.py
+++ b/test/packaging/strip-install-dir.py
@@ -34,6 +34,11 @@ python = TestSCons.python
test = TestSCons.TestSCons()
+tar = test.detect('TAR', 'tar')
+
+if not tar:
+ test.skip_test('tar not found, skipping test\n')
+
test.write( 'main.c', '' )
test.write('SConstruct', """
prog = Install( '/bin', 'main.c' )
diff --git a/test/option-q.py b/test/question/Configure.py
index 9b67d0a..aeaba8a 100644
--- a/test/option-q.py
+++ b/test/question/Configure.py
@@ -24,64 +24,25 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify operation of the -q (--question) option in conjunction
+with Configure tests.
+
+(This was originally mostly copied and pasted from test/option-n.py.)
+"""
+
import os.path
import re
-import string
-import sys
import TestCmd
import TestSCons
-test = TestSCons.TestSCons()
-
-_python_ = TestSCons._python_
-
-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('SConstruct', """
-B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'aaa.out', source = 'aaa.in')
-env.B(target = 'bbb.out', source = 'bbb.in')
-""" % locals())
-
-test.write('aaa.in', "aaa.in\n")
-test.write('bbb.in', "bbb.in\n")
-
-test.run(arguments = '-q aaa.out', status = 1)
-
-test.fail_test(os.path.exists(test.workpath('aaa.out')))
-
-test.run(arguments = 'aaa.out')
-
-test.fail_test(test.read('aaa.out') != "aaa.in\n")
-
-test.run(arguments = '-q aaa.out', status = 0)
+test = TestSCons.TestSCons(match = TestCmd.match_re_dotall)
-test.run(arguments = '--question bbb.out', status = 1)
+test.write('aaa.in', 'Hello world\n')
-test.fail_test(os.path.exists(test.workpath('bbb.out')))
-
-test.run(arguments = 'bbb.out')
-
-test.fail_test(test.read('bbb.out') != "bbb.in\n")
-
-test.run(arguments = '--question bbb.out', status = 0)
-
-
-# test -q in conjunction with Configure Tests
-# mostly copy&paste from test/option-n.py
-test.subdir('configure')
-test.match_func = TestCmd.match_re_dotall
-test.write('configure/aaa.in', 'Hello world')
-test.write('configure/SConstruct',
-"""def userAction(target,source,env):
+test.write('SConstruct', """\
+def userAction(target,source,env):
import shutil
shutil.copyfile( str(source[0]), str(target[0]))
@@ -108,15 +69,16 @@ else:
env.B(target='aaa.out', source='aaa.in')
""")
+
# test that conf_dir isn't created and an error is raised
stderr=r"""
scons: \*\*\* Cannot create configure directory "config\.test" within a dry-run\.
File \S+, line \S+, in \S+
"""
-test.run(arguments="-q aaa.out",stderr=stderr,status=2,
- chdir=test.workpath("configure"))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
+test.run(arguments="-q aaa.out",stderr=stderr,status=2)
+
+test.must_not_exist(test.workpath("config.test"))
+test.must_not_exist(test.workpath("config.log"))
# test that targets are not built, if conf_dir exists.
# verify that .cache and config.log are not created.
@@ -125,27 +87,28 @@ stderr=r"""
scons: \*\*\* Cannot update configure test "%s" within a dry-run\.
File \S+, line \S+, in \S+
""" % re.escape(os.path.join("config.test", "conftest_0.in"))
-test.subdir(['configure','config.test'])
-test.run(arguments="-q aaa.out",stderr=stderr,status=2,
- chdir=test.workpath("configure"))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- ".cache")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- "conftest_0")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- "conftest_0.in")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
+
+test.subdir('config.test')
+
+test.run(arguments="-q aaa.out",stderr=stderr,status=2)
+
+test.must_not_exist(test.workpath("config.test", ".cache"))
+test.must_not_exist(test.workpath("config.test", "conftest_0"))
+test.must_not_exist(test.workpath("config.test", "conftest_0.in"))
+test.must_not_exist(test.workpath("config.log"))
# test that no error is raised, if all targets are up-to-date. In this
# case .cache and config.log shouldn't be created
stdout=test.wrap_stdout(build_str='cp aaa.in aaa.out\n',
read_str="""Executing Custom Test ... yes
""")
-test.run(stdout=stdout,arguments="aaa.out",status=0,chdir=test.workpath("configure"))
-log1_mtime = os.path.getmtime(test.workpath("configure","config.log"))
-test.run(arguments="-q aaa.out",status=0,
- chdir=test.workpath("configure"))
-log2_mtime = os.path.getmtime(test.workpath("configure","config.log"))
+
+test.run(stdout=stdout,arguments="aaa.out",status=0)
+
+log1_mtime = os.path.getmtime(test.workpath("config.log"))
+
+test.run(arguments="-q aaa.out",status=0)
+log2_mtime = os.path.getmtime(test.workpath("config.log"))
test.fail_test( log1_mtime != log2_mtime )
test.pass_test()
diff --git a/test/question/basic.py b/test/question/basic.py
new file mode 100644
index 0000000..dc07e48
--- /dev/null
+++ b/test/question/basic.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 basic operation of the -q (--question) option.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_python_ = TestSCons._python_
+
+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('SConstruct', """
+B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'aaa.out', source = 'aaa.in')
+env.B(target = 'bbb.out', source = 'bbb.in')
+""" % locals())
+
+test.write('aaa.in', "aaa.in\n")
+test.write('bbb.in', "bbb.in\n")
+
+test.run(arguments = '-q aaa.out', status = 1)
+
+test.must_not_exist(test.workpath('aaa.out'))
+
+test.run(arguments = 'aaa.out')
+
+test.must_match('aaa.out', "aaa.in\n")
+
+test.run(arguments = '-q aaa.out', status = 0)
+
+test.run(arguments = '--question bbb.out', status = 1)
+
+test.must_not_exist(test.workpath('bbb.out'))
+
+test.run(arguments = 'bbb.out')
+
+test.must_match('bbb.out', "bbb.in\n")
+
+test.run(arguments = '--question bbb.out', status = 0)
+
+test.pass_test()
diff --git a/test/question/no-builder.py b/test/question/no-builder.py
new file mode 100644
index 0000000..d038724
--- /dev/null
+++ b/test/question/no-builder.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 operation of the -q (--question) option when a specified
+target has no builder.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_python_ = TestSCons._python_
+
+test.write('SConstruct', """
+""")
+
+test.run(arguments = '-q no_such_target', status = 1)
+
+test.run(arguments = '--question no_such_target', status = 1)
+
+test.pass_test()
diff --git a/test/runtest/fallback.py b/test/runtest/fallback.py
index 90cd4f2..8b6ae42 100644
--- a/test/runtest/fallback.py
+++ b/test/runtest/fallback.py
@@ -68,12 +68,20 @@ if re.search('\s', python):
else:
expect_python = python
+def escape(s):
+ return string.replace(s, '\\', '\\\\')
+
+expect_python = escape(expect_python)
+expect_workpath_pass_py = escape(workpath_pass_py)
+expect_workpath_fail_py = escape(workpath_fail_py)
+expect_workpath_no_result_py = escape(workpath_no_result_py)
+
expect_stdout = """\
-%(expect_python)s -tt %(workpath_fail_py)s
+%(expect_python)s -tt %(expect_workpath_fail_py)s
FAILING TEST STDOUT
-%(expect_python)s -tt %(workpath_no_result_py)s
+%(expect_python)s -tt %(expect_workpath_no_result_py)s
NO RESULT TEST STDOUT
-%(expect_python)s -tt %(workpath_pass_py)s
+%(expect_python)s -tt %(expect_workpath_pass_py)s
PASSING TEST STDOUT
Failed the following test:
diff --git a/test/runtest/noqmtest.py b/test/runtest/noqmtest.py
index c442125..f2bf6eb 100644
--- a/test/runtest/noqmtest.py
+++ b/test/runtest/noqmtest.py
@@ -59,12 +59,20 @@ if re.search('\s', python):
else:
expect_python = python
+def escape(s):
+ return string.replace(s, '\\', '\\\\')
+
+expect_python = escape(expect_python)
+expect_workpath_pass_py = escape(workpath_pass_py)
+expect_workpath_fail_py = escape(workpath_fail_py)
+expect_workpath_no_result_py = escape(workpath_no_result_py)
+
expect_stdout = """\
-%(expect_python)s -tt %(workpath_fail_py)s
+%(expect_python)s -tt %(expect_workpath_fail_py)s
FAILING TEST STDOUT
-%(expect_python)s -tt %(workpath_no_result_py)s
+%(expect_python)s -tt %(expect_workpath_no_result_py)s
NO RESULT TEST STDOUT
-%(expect_python)s -tt %(workpath_pass_py)s
+%(expect_python)s -tt %(expect_workpath_pass_py)s
PASSING TEST STDOUT
Failed the following test:
diff --git a/test/runtest/python.py b/test/runtest/python.py
index 1af32dd..95b5f0f 100644
--- a/test/runtest/python.py
+++ b/test/runtest/python.py
@@ -46,17 +46,11 @@ head, dir = os.path.split(head)
mypython = os.path.join(head, dir, os.path.pardir, dir, python)
-if re.search('\s', mypython):
- _mypython_ = '"' + mypython + '"'
-else:
- _mypython_ = mypython
-
test.subdir('test')
test.write_passing_test(['test', 'pass.py'])
-# NOTE: The "test/fail.py : FAIL" and "test/pass.py : PASS" lines both
-# have spaces at the end.
+# NOTE: The "test/pass.py : PASS" line has spaces at the end.
expect = r"""qmtest.py run --output results.qmr --format none --result-stream="scons_tdb.AegisChangeStream" --context python="%(mypython)s" test
--- TEST RESULTS -------------------------------------------------------------
@@ -75,6 +69,6 @@ expect = r"""qmtest.py run --output results.qmr --format none --result-stream="s
1 (100%%) tests PASS
""" % locals()
-test.run(arguments = '-P %s test' % _mypython_, stdout = expect)
+test.run(arguments = ['-P', mypython, 'test'], stdout = expect)
test.pass_test()
diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py
new file mode 100644
index 0000000..8e17e95
--- /dev/null
+++ b/test/sconsign/script/Configure.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 we can print .sconsign files with Configure context
+info in them (which have different BuildInfo entries).
+"""
+
+import os.path
+
+import TestSCons
+import TestSConsign
+
+_obj = TestSCons._obj
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+CC = test.detect('CC', norm=1)
+CC_dir, CC_file = os.path.split(CC)
+
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+_sconf_temp_conftest_0_c = '.sconf_temp/conftest_0.c'
+
+test.write('SConstruct', """
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+env = conf.Finish()
+""")
+
+test.run(arguments = '.')
+
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
+# Note: There's a space at the end of the '.*': line, because the
+# Value node being printed actually begins with a newline. It would
+# probably be good to change that to a repr() of the contents.
+expect = r"""=== .:
+SConstruct: None \d+ \d+
+=== .sconf_temp:
+conftest_0.c:
+ '.*':
+#include "math.h"
+
+
+ %(sig_re)s \[.*\]
+conftest_0%(_obj)s:
+ %(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+=== %(CC_dir)s:
+%(CC_file)s: %(sig_re)s \d+ \d+
+""" % locals()
+
+test.run_sconsign(arguments = ".sconsign",
+ stdout = expect)
+
+test.pass_test()
diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py
index 2f5ddf3..99845e3 100644
--- a/test/sconsign/script/SConsignFile.py
+++ b/test/sconsign/script/SConsignFile.py
@@ -29,12 +29,30 @@ Verify that the sconsign script works with files generated when
using the signatures in an SConsignFile().
"""
+import os.path
+
import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+CC_dir, CC_file = os.path.split(CC)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+sub2_hello_c = 'sub2/hello.c'
+sub2_hello_obj = 'sub2/hello.obj'
+sub2_inc1_h = 'sub2/inc1.h'
+sub2_inc2_h = 'sub2/inc2.h'
+
test.write(['SConstruct'], """\
SConsignFile()
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
@@ -79,182 +97,328 @@ test.write(['sub2', 'inc2.h'], r"""\
test.run(arguments = '--implicit-cache .')
+sig_re = r'[0-9a-fA-F]{32}'
+
test.run_sconsign(arguments = ".sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct: None \d+ \d+
+=== %(CC_dir)s:
+%(CC_file)s: %(sig_re)s \d+ \d+
=== sub1:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+inc1.h: %(sig_re)s \d+ \d+
+inc2.h: %(sig_re)s \d+ \d+
+""" % locals())
test.run_sconsign(arguments = "--raw .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct: {'csig': None, 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+=== %(CC_dir)s:
+%(CC_file)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
=== sub1:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
+hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
=== sub2:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_inc1_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_inc2_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+inc1.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+inc2.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+""" % locals())
-test.run_sconsign(arguments = "-v .sconsign",
- stdout = """\
+expect = r"""=== .:
+SConstruct:
+ csig: None
+ timestamp: \d+
+ size: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
=== sub1:
+hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub1_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
+ %(sub1_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
=== sub2:
+hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub2_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+ %(sub2_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(sub2_inc1_h)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(sub2_inc2_h)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
+inc1.h:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+inc2.h:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+""" % locals()
-test.run_sconsign(arguments = "-b -v .sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-=== sub2:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
+test.run_sconsign(arguments = "-v .sconsign", stdout=expect)
test.run_sconsign(arguments = "-c -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ csig: None
+=== %(CC_dir)s:
+%(CC_file)s:
+ csig: %(sig_re)s
=== sub1:
+hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
+ csig: %(sig_re)s
=== sub2:
+hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
-""")
+ csig: %(sig_re)s
+inc1.h:
+ csig: %(sig_re)s
+inc2.h:
+ csig: %(sig_re)s
+""" % locals())
test.run_sconsign(arguments = "-s -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ size: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ size: \d+
=== sub1:
+hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
=== sub2:
+hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
-""")
+inc1.h:
+ size: \d+
+inc2.h:
+ size: \d+
+""" % locals())
test.run_sconsign(arguments = "-t -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ timestamp: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ timestamp: \d+
=== sub1:
+hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
=== sub2:
+hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
-""")
+inc1.h:
+ timestamp: \d+
+inc2.h:
+ timestamp: \d+
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+=== %(CC_dir)s:
=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals(),
+ stderr = r"""sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+=== %(CC_dir)s:
=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals(),
+ stderr = r"""sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.exe' in `\.'
+sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+sconsign: no entry `hello.exe' in `%(CC_dir)s'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+""" % locals())
#test.run_sconsign(arguments = "-i -v .sconsign",
-# stdout = """\
-#=== sub1:
+# stdout = r"""=== sub1:
#hello.exe:
# implicit:
-# hello.obj: \S+
+# hello.obj: %(sig_re)s
#hello.obj:
# implicit:
-# hello.c: \S+
+# hello.c: %(sig_re)s
#=== sub2:
#hello.exe:
# implicit:
-# hello.obj: \S+
+# hello.obj: %(sig_re)s
#hello.obj:
# implicit:
-# hello.c: \S+
-# inc1.h: \S+
-# inc2.h: \S+
-#""")
+# hello.c: %(sig_re)s
+# inc1.h: %(sig_re)s
+# inc2.h: %(sig_re)s
+#inc1.h: %(sig_re)s
+#inc2.h: %(sig_re)s
+#""" % locals())
test.pass_test()
diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py
index 9a3ce62..fc85133 100644
--- a/test/sconsign/script/Signatures.py
+++ b/test/sconsign/script/Signatures.py
@@ -35,6 +35,17 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+
def re_sep(*args):
import os.path
import re
@@ -90,20 +101,29 @@ test.sleep()
test.run(arguments = '. --max-drift=1')
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
test.run_sconsign(arguments = "-e hello.exe -e hello.obj sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: None \d+ \d+
+ %(CC)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \S+
-hello.obj: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.exe: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+
+ %(LINK)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_c)s: None '%(date_re)s' \d+
+ %(CC)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.pass_test()
diff --git a/test/sconsign/script/dblite.py b/test/sconsign/script/dblite.py
index fe49df6..1b359e2 100644
--- a/test/sconsign/script/dblite.py
+++ b/test/sconsign/script/dblite.py
@@ -33,8 +33,19 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+
test.write('SConstruct', """
SConsignFile('my_sconsign')
SourceSignatures('timestamp')
@@ -83,21 +94,30 @@ test.sleep()
test.run(arguments = '. --max-drift=1')
-expect = """\
-=== sub1:
-hello.exe: \d+ None \d+ \d+
- hello.obj: \d+
-hello.obj: \d+ None \d+ \d+
- hello.c: \d+
-"""
-
-expect_r = """\
-=== sub1:
-hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \d+
-hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \d+
-"""
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
+expect = r"""=== sub1:
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: None \d+ \d+
+ %(CC)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals()
+
+expect_r = """=== sub1:
+hello.exe: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+
+ %(LINK)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_c)s: None '%(date_re)s' \d+
+ %(CC)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+""" % locals()
common_flags = '-e hello.exe -e hello.obj -d sub1'
diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py
index b860770..1fcfbfd 100644
--- a/test/sconsign/script/no-SConsignFile.py
+++ b/test/sconsign/script/no-SConsignFile.py
@@ -33,13 +33,23 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
-def re_sep(*args):
- import os.path
- import re
- return re.escape(apply(os.path.join, args))
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+sub2_hello_c = 'sub2/hello.c'
+sub2_hello_obj = 'sub2/hello.obj'
+sub2_inc1_h = 'sub2/inc1.h'
+sub2_inc2_h = 'sub2/inc2.h'
+
test.write(['SConstruct'], """
SConsignFile(None)
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
@@ -82,124 +92,160 @@ test.write(['sub2', 'inc2.h'], r"""\
#define STRING2 "inc2.h"
""")
-test.run(arguments = '--implicit-cache .')
+test.run(arguments = '--implicit-cache --tree=prune .')
-test.run_sconsign(arguments = "sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+sig_re = r'[0-9a-fA-F]{32}'
+
+expect = r"""hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals()
+
+test.run_sconsign(arguments = "sub1/.sconsign", stdout=expect)
+#test.run_sconsign(arguments = "sub1/.sconsign")
+#print test.stdout()
test.run_sconsign(arguments = "--raw sub1/.sconsign",
- stdout = """\
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
-""")
+ stdout = r"""hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub1_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-b -v sub1/.sconsign",
- stdout = """\
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
+ %(sub1_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-c -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
-""")
+ csig: %(sig_re)s
+""" % locals())
test.run_sconsign(arguments = "-s -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
-""")
+""" % locals())
test.run_sconsign(arguments = "-t -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
-""")
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-# XXX NOT SURE IF THIS IS RIGHT!
-sub2_inc1_h = re_sep('sub2', 'inc1.h')
-sub2_inc2_h = re_sep('sub2', 'inc2.h')
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "sub2/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+ stdout = r"""hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+inc1.h: %(sig_re)s \d+ \d+
+inc2.h: %(sig_re)s \d+ \d+
+""" % locals())
#test.run_sconsign(arguments = "-i -v sub2/.sconsign",
-# stdout = """\
-#hello.exe:
+# stdout = r"""hello.c: %(sig_re)s \d+ \d+
+#hello.exe: %(sig_re)s \d+ \d+
# implicit:
-# hello.obj: \S+ None \d+ \d+
-#hello.obj:
+# hello.obj: %(sig_re)s \d+ \d+
+#hello.obj: %(sig_re)s \d+ \d+
# implicit:
-# hello.c: None \S+ \d+ \d+
-# inc1.h: None \S+ \d+ \d+
-# inc2.h: None \S+ \d+ \d+
-#""")
+# hello.c: %(sig_re)s \d+ \d+
+# inc1.h: %(sig_re)s \d+ \d+
+# inc2.h: %(sig_re)s \d+ \d+
+#""" % locals())
test.run_sconsign(arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.pass_test()
diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py
index 7576023..9d89d70 100644
--- a/test/timestamp-fallback.py
+++ b/test/timestamp-fallback.py
@@ -24,6 +24,11 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify falling back to 'timestamp' behavior if there is no native
+hashlib and no underlying md5 module available.
+"""
+
import imp
import os
import os.path
@@ -33,6 +38,15 @@ import TestSCons
test = TestSCons.TestSCons()
try:
+ file, name, desc = imp.find_module('hashlib')
+except ImportError:
+ pass
+else:
+ msg = "This version of Python has a 'hashlib' module.\n" + \
+ "Skipping test of falling back to timestamps.\n"
+ test.skip_test(msg)
+
+try:
file, name, desc = imp.find_module('md5')
except ImportError:
pass
diff --git a/test/up-to-date.py b/test/up-to-date.py
index cec5952..366d017 100644
--- a/test/up-to-date.py
+++ b/test/up-to-date.py
@@ -24,9 +24,12 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
+"""
+Verify appropriate printing of "is up to date" messages.
+"""
+
import string
-import sys
+
import TestSCons
_python_ = TestSCons._python_
@@ -66,5 +69,29 @@ scons: `f3.out' is up to date.
test.run(arguments = 'f1.out f2.out f3.out f4.out', stdout = expect)
-test.pass_test()
+# Make sure all of the "up to date" messages get printed even when -j
+# is used. This broke during signature refactoring development.
+expected_lines = [
+ "scons: `f1.out' is up to date.",
+ "scons: `f2.out' is up to date.",
+ "scons: `f3.out' is up to date.",
+ "scons: `f4.out' is up to date.",
+]
+test.run(options = '-j4 f1.out f2.out f3.out f4.out')
+stdout = test.stdout()
+
+missing = []
+for line in expected_lines:
+ if string.find(stdout, line) == -1:
+ missing.append(line)
+
+if missing:
+ print "Missing the following expected lines:"
+ for line in missing:
+ print line
+ print "STDOUT =========="
+ print stdout
+ test.fail_test()
+
+test.pass_test()