test = TestSCons.TestSCons()
-test.subdir('cache', 'src')
+test.subdir('cache1', 'cache2', 'cache3', 'src', 'subdir')
-test.write(['src', 'SConstruct'], """
+test.write(['src', 'SConstruct'], """\
+CacheDir(r'%s')
+SConscript('SConscript')
+""" % test.workpath('cache1'))
+
+test.write(['src', 'SConscript'], """\
def cat(env, source, target):
target = str(target[0])
open('cat.out', 'ab').write(target + "\\n")
env.Cat('bbb.out', 'bbb.in')
env.Cat('ccc.out', 'ccc.in')
env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
-CacheDir(r'%s')
-""" % test.workpath('cache'))
+""")
test.write(['src', 'aaa.in'], "aaa.in\n")
test.write(['src', 'bbb.in'], "bbb.in\n")
test.write(['src', 'ccc.in'], "ccc.in\n")
+#############################################################################
# Verify that a normal build works correctly, and clean up.
# This should populate the cache with our derived files.
test.run(chdir = 'src', arguments = '.')
test.up_to_date(chdir = 'src', arguments = '.')
+#############################################################################
+# Now we try out BuildDir() functionality.
+# This is largely cut-and-paste of the above,
+# with appropriate directory modifications.
+
+build_aaa_out = os.path.join('build', 'aaa.out')
+build_bbb_out = os.path.join('build', 'bbb.out')
+build_ccc_out = os.path.join('build', 'ccc.out')
+build_all = os.path.join('build', 'all')
+
+# First, clean up the source directory and start over with fresh files.
+test.run(chdir = 'src', arguments = '-c .')
+
+test.write(['src', 'aaa.in'], "aaa.in\n")
+test.write(['src', 'bbb.in'], "bbb.in\n")
+test.write(['src', 'ccc.in'], "ccc.in\n")
+
+#
+test.write('SConstruct', """\
+CacheDir(r'%s')
+BuildDir('build', 'src', duplicate=0)
+SConscript('build/SConscript')
+""" % test.workpath('cache2'))
+
+# Verify that a normal build works correctly, and clean up.
+# This should populate the cache with our derived files.
+test.run()
+
+test.fail_test(test.read(['build', 'all']) != "aaa.in\nbbb.in\nccc.in\n")
+test.fail_test(test.read('cat.out') != "%s\n%s\n%s\n%s\n" % (build_aaa_out, build_bbb_out, build_ccc_out, build_all))
+
+test.up_to_date(arguments = '.')
+
+test.run(arguments = '-c .')
+test.unlink('cat.out')
+
+# Verify that we now retrieve the derived files from cache,
+# not rebuild them. Then clean up.
+test.run(stdout = test.wrap_stdout("""\
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+""" % (build_aaa_out, build_bbb_out, build_ccc_out, build_all)))
+
+test.fail_test(os.path.exists(test.workpath('cat.out')))
+
+test.up_to_date(arguments = '.')
+
+test.run(arguments = '-c .')
+
+# Verify that rebuilding with -n reports that everything was retrieved
+# from the cache, but that nothing really was.
+test.run(arguments = '-n .', stdout = test.wrap_stdout("""\
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+Retrieved `%s' from cache
+""" % (build_aaa_out, build_bbb_out, build_ccc_out, build_all)))
+
+test.fail_test(os.path.exists(test.workpath('build', 'aaa.out')))
+test.fail_test(os.path.exists(test.workpath('build', 'bbb.out')))
+test.fail_test(os.path.exists(test.workpath('build', 'ccc.out')))
+test.fail_test(os.path.exists(test.workpath('build', 'all')))
+
+# Verify that rebuilding with -s retrieves everything from the cache
+# even though it doesn't report anything.
+test.run(arguments = '-s .', stdout = "")
+
+test.fail_test(test.read(['build', 'all']) != "aaa.in\nbbb.in\nccc.in\n")
+test.fail_test(os.path.exists(test.workpath('cat.out')))
+
+test.up_to_date(arguments = '.')
+
+test.run(arguments = '-c .')
+
+# Verify that updating one input file builds its derived file and
+# dependency but that the other files are retrieved from cache.
+test.write(['src', 'bbb.in'], "bbb.in 2\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Retrieved `%s' from cache
+cat("%s", "%s")
+Retrieved `%s' from cache
+cat("%s", ["%s", "%s", "%s"])
+""" % (build_aaa_out,
+ build_bbb_out, os.path.join('src', 'bbb.in'),
+ build_ccc_out,
+ build_all, build_aaa_out, build_bbb_out, build_ccc_out)))
+
+test.fail_test(test.read(['build', 'all']) != "aaa.in\nbbb.in 2\nccc.in\n")
+test.fail_test(test.read('cat.out') != "%s\n%s\n" % (build_bbb_out, build_all))
+
+test.up_to_date(arguments = '.')
+
+#############################################################################
+# 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).
+
+test.write(['subdir', 'SConstruct'], """\
+import SCons
+
+CacheDir(r'%s')
+
+def docopy(target,source,env):
+ data = source[0].get_contents()
+ f = open(target[0].rfile().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('cache3'))
+
+test.write(['subdir', 'file.ma'], "subdir/file.ma\n")
+
+test.run(chdir = 'subdir')
+
+test.fail_test(os.path.exists(test.workpath('cache3', 'N', 'None')))
+
# All done.
test.pass_test()