summaryrefslogtreecommitdiffstats
path: root/test/Decider
diff options
context:
space:
mode:
Diffstat (limited to 'test/Decider')
-rw-r--r--test/Decider/Environment.py67
-rw-r--r--test/Decider/MD5-timestamp.py87
-rw-r--r--test/Decider/Node.py67
-rw-r--r--test/Decider/default.py65
-rw-r--r--test/Decider/mixed.py121
-rw-r--r--test/Decider/switch-rebuild.py93
-rw-r--r--test/Decider/timestamp.py119
-rw-r--r--test/Decider/unknown.py52
8 files changed, 671 insertions, 0 deletions
diff --git a/test/Decider/Environment.py b/test/Decider/Environment.py
new file mode 100644
index 0000000..7c609ee
--- /dev/null
+++ b/test/Decider/Environment.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 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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/MD5-timestamp.py b/test/Decider/MD5-timestamp.py
new file mode 100644
index 0000000..f8776c3
--- /dev/null
+++ b/test/Decider/MD5-timestamp.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 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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/Node.py b/test/Decider/Node.py
new file mode 100644
index 0000000..cdd3e35
--- /dev/null
+++ b/test/Decider/Node.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 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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/default.py b/test/Decider/default.py
new file mode 100644
index 0000000..f05e869
--- /dev/null
+++ b/test/Decider/default.py
@@ -0,0 +1,65 @@
+#!/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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/mixed.py b/test/Decider/mixed.py
new file mode 100644
index 0000000..5598468
--- /dev/null
+++ b/test/Decider/mixed.py
@@ -0,0 +1,121 @@
+#!/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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/switch-rebuild.py b/test/Decider/switch-rebuild.py
new file mode 100644
index 0000000..45becbe
--- /dev/null
+++ b/test/Decider/switch-rebuild.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__"
+
+"""
+Test that switching Decider() types between MD5 and timestamp-match
+does not cause unnecessary rebuilds.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match=TestSCons.match_re_dotall)
+
+base_sconstruct_contents = """\
+Decider('%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)
+
+
+# Build first MD5 checksums.
+write_SConstruct(test, 'MD5')
+
+test.write('switch.in', "switch.in\n")
+
+switch_out_switch_in = test.wrap_stdout(r'build\(\["switch.out"\], \["switch.in"\]\)\n')
+
+test.run(arguments='switch.out', stdout=switch_out_switch_in)
+
+test.up_to_date(arguments='switch.out')
+
+
+# Now rebuild with timestamp-match. Because we always store timestamps,
+# even when making the decision based on MD5 checksums, the build is
+# still up to date.
+write_SConstruct(test, 'timestamp-match')
+
+test.up_to_date(arguments='switch.out')
+
+
+# Now switch back to MD5 checksums. When we rebuilt with the timestamp,
+# it wiped out the MD5 value (because the point of timestamps is to not
+# open up and checksum the contents), so the file is considered *not*
+# up to date and must be rebuilt to generate a checksum.
+write_SConstruct(test, 'MD5')
+
+test.not_up_to_date(arguments='switch.out')
+
+
+# And just for good measure, make sure that we now rebuild in response
+# to a content change.
+test.write('switch.in', "switch.in 2\n")
+
+test.run(arguments='switch.out', stdout=switch_out_switch_in)
+
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/timestamp.py b/test/Decider/timestamp.py
new file mode 100644
index 0000000..8389745
--- /dev/null
+++ b/test/Decider/timestamp.py
@@ -0,0 +1,119 @@
+#!/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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Decider/unknown.py b/test/Decider/unknown.py
new file mode 100644
index 0000000..ec24eff
--- /dev/null
+++ b/test/Decider/unknown.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__"
+
+"""
+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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: