summaryrefslogtreecommitdiffstats
path: root/test/Alias
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2015-09-21 17:03:12 (GMT)
committerWilliam Deegan <bill@baddogconsulting.com>2015-09-21 17:03:12 (GMT)
commit0941093e0e5a030faa49968457638a3a6aee7ad8 (patch)
tree6d33513c14eb6eac0531dd050de0ecca4c39bd79 /test/Alias
downloadSCons-2.4.0.zip
SCons-2.4.0.tar.gz
SCons-2.4.0.tar.bz2
release 2.4.02.4.0
Diffstat (limited to 'test/Alias')
-rw-r--r--test/Alias/Alias.py175
-rw-r--r--test/Alias/Depends.py168
-rw-r--r--test/Alias/Dir-order.py49
-rw-r--r--test/Alias/action.py140
-rw-r--r--test/Alias/errors.py49
-rw-r--r--test/Alias/scanner.py63
-rw-r--r--test/Alias/srcdir.py106
7 files changed, 750 insertions, 0 deletions
diff --git a/test/Alias/Alias.py b/test/Alias/Alias.py
new file mode 100644
index 0000000..a5dd903
--- /dev/null
+++ b/test/Alias/Alias.py
@@ -0,0 +1,175 @@
+#!/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 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')
+
+assert Alias('foo') == foo
+assert Alias('bar') == bar
+
+""" % 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.fail_test(os.path.exists(test.workpath('f1.out')))
+test.fail_test(not os.path.exists(test.workpath('f2.out')))
+test.fail_test(os.path.exists(test.workpath('f3.out')))
+
+test.fail_test(not os.path.exists(test.workpath('sub1', 'f4.out')))
+test.fail_test(not os.path.exists(test.workpath('sub1', 'f5.out')))
+test.fail_test(not os.path.exists(test.workpath('sub1', 'f6.out')))
+
+test.fail_test(os.path.exists(test.workpath('sub2', 'f7.out')))
+test.fail_test(os.path.exists(test.workpath('sub2', 'f8.out')))
+test.fail_test(os.path.exists(test.workpath('sub2', 'f9.out')))
+
+test.up_to_date(arguments = 'foo')
+
+test.run(arguments = 'f1.out')
+
+test.fail_test(not os.path.exists(test.workpath('f1.out')))
+test.fail_test(not os.path.exists(test.workpath('f3.out')))
+
+test.fail_test(not os.path.exists(test.workpath('sub2', 'f7.out')))
+test.fail_test(not os.path.exists(test.workpath('sub2', 'f8.out')))
+test.fail_test(not os.path.exists(test.workpath('sub2', 'f9.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.fail_test(not os.path.exists(test.workpath('f2.out')))
+test.fail_test(not os.path.exists(test.workpath('f3.out')))
+
+test.write('f3.in', "f3.in 2 \n")
+
+test.run(arguments = 'f1.out',
+ stdout = test.wrap_stdout(".* build.py f3.out f3.in\n.* build.py f1.out f1.in\n"))
+
+test.up_to_date(arguments = 'f1.out')
+
+test.write('SConstruct', """
+Decider('content')
+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")
+env.Alias('foo', ['f2.out', 'sub1'])
+env.Alias('bar', ['sub2', 'f3.out'])
+env.Alias('blat', ['sub2', 'f3.out'])
+env.Alias('blat', ['f2.out', 'sub1'])
+env.Depends('f1.out', 'bar')
+""" % locals())
+
+os.unlink(test.workpath('f1.out'))
+
+test.run(arguments = 'f1.out')
+
+test.fail_test(not os.path.exists(test.workpath('f1.out')))
+
+test.write('f3.in', "f3.in 3 \n")
+
+expect = test.wrap_stdout("""\
+%(_python_)s build.py f3.out f3.in
+%(_python_)s build.py f1.out f1.in
+""" % locals())
+
+test.run(arguments = 'f1.out', match = TestCmd.match_exact, stdout = expect)
+
+test.up_to_date(arguments = 'f1.out')
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Alias/Depends.py b/test/Alias/Depends.py
new file mode 100644
index 0000000..a1129e4
--- /dev/null
+++ b/test/Alias/Depends.py
@@ -0,0 +1,168 @@
+#!/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 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()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Alias/Dir-order.py b/test/Alias/Dir-order.py
new file mode 100644
index 0000000..f0eaa0c
--- /dev/null
+++ b/test/Alias/Dir-order.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Validate that calling Dir() for a string after we've used it as an
+Alias() expansion works.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+Alias('afoo', 'foo')
+f = Dir('foo')
+""")
+
+test.run(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/Alias/action.py b/test/Alias/action.py
new file mode 100644
index 0000000..74eb6f9
--- /dev/null
+++ b/test/Alias/action.py
@@ -0,0 +1,140 @@
+#!/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.
+#
+
+"""
+Test that Aliases with actions work.
+"""
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+def cat(target, source, env):
+ target = str(target[0])
+ f = open(target, "wb")
+ for src in source:
+ f.write(open(str(src), "rb").read())
+ f.close()
+
+def foo(target, source, env):
+ target = list(map(str, target))
+ source = list(map(str, source))
+ open('foo', 'wb').write("foo(%s, %s)\\n" % (target, source))
+
+def bar(target, source, env):
+ target = list(map(str, target))
+ source = list(map(str, source))
+ open('bar', 'wb').write("bar(%s, %s)\\n" % (target, source))
+
+env = Environment(BUILDERS = {'Cat':Builder(action=cat)})
+env.Alias(target = ['build-f1'], source = 'f1.out', action = foo)
+f1 = env.Cat('f1.out', 'f1.in')
+f2 = env.Cat('f2.out', 'f2.in')
+f3 = env.Cat('f3.out', 'f3.in')
+f4 = env.Cat('f4.out', 'f4.in')
+f5 = env.Cat('f5.out', 'f5.in')
+f6 = env.Cat('f6.out', 'f6.in')
+env.Alias('build-all', [f1, f2, f3], foo)
+env.Alias('build-add1', f3, foo)
+env.Alias('build-add1', f2)
+env.Alias('build-add2a', f4)
+env.Alias('build-add2b', f5)
+env.Alias(['build-add2a', 'build-add2b'], action=foo)
+env.Alias('build-add3', f6)
+env.Alias('build-add3', action=foo)
+env.Alias('build-add3', action=bar)
+""")
+
+test.write('f1.in', "f1.in 1\n")
+test.write('f2.in', "f2.in 1\n")
+test.write('f3.in', "f3.in 1\n")
+test.write('f4.in', "f4.in 1\n")
+test.write('f5.in', "f5.in 1\n")
+test.write('f6.in', "f6.in 1\n")
+
+test.run(arguments = 'build-f1')
+
+test.must_match('f1.out', "f1.in 1\n")
+test.must_match('foo', "foo(['build-f1'], ['f1.out'])\n")
+
+test.up_to_date(arguments = 'build-f1')
+
+test.write('f1.in', "f1.in 2\n")
+test.unlink('foo')
+
+test.run(arguments = 'build-f1')
+
+test.must_match('f1.out', "f1.in 2\n")
+test.must_match('foo', "foo(['build-f1'], ['f1.out'])\n")
+
+test.run(arguments = 'build-all')
+
+test.must_match('f1.out', "f1.in 2\n")
+test.must_match('f2.out', "f2.in 1\n")
+test.must_match('f3.out', "f3.in 1\n")
+test.must_match('foo', "foo(['build-all'], ['f1.out', 'f2.out', 'f3.out'])\n")
+
+test.up_to_date(arguments = 'build-all')
+test.up_to_date(arguments = 'build-add1')
+
+test.write('f1.in', "f1.in 3\n")
+test.write('f3.in', "f3.in 2\n")
+test.unlink('foo')
+
+test.run(arguments = 'build-add1')
+
+test.must_match('f1.out', "f1.in 2\n")
+test.must_match('f2.out', "f2.in 1\n")
+test.must_match('f3.out', "f3.in 2\n")
+test.must_match('foo', "foo(['build-add1'], ['f3.out', 'f2.out'])\n")
+
+test.up_to_date(arguments = 'build-add1')
+
+test.run(arguments = 'build-add2a')
+
+test.must_match('f4.out', "f4.in 1\n")
+test.must_not_exist('f5.out')
+test.must_match('foo', "foo(['build-add2a'], ['f4.out'])\n")
+
+test.run(arguments = 'build-add2b')
+
+test.must_match('f5.out', "f5.in 1\n")
+test.must_match('foo', "foo(['build-add2b'], ['f5.out'])\n")
+
+test.run(arguments = 'build-add3')
+
+test.must_match('f6.out', "f6.in 1\n")
+test.must_match('foo', "foo(['build-add3'], ['f6.out'])\n")
+test.must_match('bar', "bar(['build-add3'], ['f6.out'])\n")
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Alias/errors.py b/test/Alias/errors.py
new file mode 100644
index 0000000..1334f4e
--- /dev/null
+++ b/test/Alias/errors.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+env=Environment()
+Decider('content')
+env.Alias('C', 'D')
+env.Alias('B', 'C')
+env.Alias('A', 'B')
+""")
+
+test.run(arguments='A',
+ stderr="scons: *** [C] Source `D' not found, needed by target `C'.\n",
+ status=2)
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Alias/scanner.py b/test/Alias/scanner.py
new file mode 100644
index 0000000..fc78546
--- /dev/null
+++ b/test/Alias/scanner.py
@@ -0,0 +1,63 @@
+#!/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.
+#
+
+"""
+Test that an Alias of a node with a Scanner works.
+"""
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+def cat(env, source, target):
+ target = str(target[0])
+ f = open(target, "wb")
+ for src in source:
+ f.write(open(str(src), "rb").read())
+ f.close()
+
+XBuilder = Builder(action = cat, src_suffix = '.x', suffix = '.c')
+env = Environment()
+env.Append(BUILDERS = { 'XBuilder': XBuilder })
+f = env.XBuilder(source = ['file.x'], target = ['file.c'])
+env.Alias(target = ['cfiles'], source = f)
+Default(['cfiles'])
+""")
+
+test.write('file.x', "file.x\n")
+
+test.run()
+
+test.fail_test(test.read('file.c') != "file.x\n")
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Alias/srcdir.py b/test/Alias/srcdir.py
new file mode 100644
index 0000000..4a0de43
--- /dev/null
+++ b/test/Alias/srcdir.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that an Alias for a VariantDir()'s source directory works as
+expected.
+
+This tests for a 0.96.93 bug uncovered by the LilyPond project's build.
+
+The specific problem is that, in 0.96.93, the simple act of trying to
+disambiguate a target file in the VariantDir() would call srcnode(), which
+would create a "phantom" Node for the target in the *source* directory:
+
+ +-minimal
+ +-python
+ +-foo <= this doesn't belong!
+ +-foo.py
+ +-out-scons
+ +-foo <= this is all right
+ +-foo.py
+
+As part of deciding if the 'minimal' Alias is up-to-date, the 'python'
+source directory would get scanned for files, including the "phantom"
+'python/foo' target Node. Since this didn't exist, the build would die:
+
+ scons: *** Source `python/foo' not found, needed by target `minimal'. Stop.
+
+The specific 0.96.94 solution was to make the Node.FS.Entry.disambiguate()
+smarter about looking on disk. Future versions may solve this in other
+ways as the architecture evolves, of course, but this will still make
+for good test case regardless.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('python')
+
+test.write('SConstruct', """\
+import os.path
+
+env = Environment ()
+
+def at_copy_ext (target, source, env):
+ n = str (source[0])
+ s = open (n, 'rb').read ()
+ e = os.path.splitext (n)[1]
+ t = str (target[0]) + e
+ open (t, 'wb').write (s)
+
+AT_COPY_EXT = Builder (action = at_copy_ext, src_suffix=['.py', '.sh',])
+env.Append (BUILDERS = {'AT_COPY_EXT': AT_COPY_EXT})
+
+env.Alias ('minimal', ['python'])
+
+Export ('env')
+
+b = 'python/out-scons'
+
+env.VariantDir(b, 'python', duplicate=0)
+
+SConscript(b + '/SConscript')
+""")
+
+test.write(['python', 'SConscript'], """\
+Import ('env')
+env.AT_COPY_EXT('foo.py')
+""")
+
+test.write(['python', 'foo.py'], 'python/foo.py\n')
+
+test.run('minimal')
+
+test.must_match(['python', 'out-scons', 'foo.py'], "python/foo.py\n")
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: