From 81e49da9da4df0dab0041dbc2d499048f38ed4f4 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 5 Mar 2005 15:25:36 +0000 Subject: Fix a regression in handling CPPPATH='.' when using a BuildDir with subdirectories in the search path. --- src/engine/SCons/Node/FS.py | 4 - src/engine/SCons/Node/FSTests.py | 136 ++++++++---- test/BuildDir-errors.py | 171 --------------- test/BuildDir.py | 393 ---------------------------------- test/BuildDir/BuildDir.py | 393 ++++++++++++++++++++++++++++++++++ test/BuildDir/CPPPATH-subdir.py | 70 ++++++ test/BuildDir/Sconscript-build_dir.py | 263 +++++++++++++++++++++++ test/BuildDir/errors.py | 171 +++++++++++++++ test/BuildDir/reflect.py | 136 ++++++++++++ test/SConscript-build_dir.py | 263 ----------------------- test/builddir-reflect.py | 136 ------------ 11 files changed, 1128 insertions(+), 1008 deletions(-) delete mode 100644 test/BuildDir-errors.py delete mode 100644 test/BuildDir.py create mode 100644 test/BuildDir/BuildDir.py create mode 100644 test/BuildDir/CPPPATH-subdir.py create mode 100644 test/BuildDir/Sconscript-build_dir.py create mode 100644 test/BuildDir/errors.py create mode 100644 test/BuildDir/reflect.py delete mode 100644 test/SConscript-build_dir.py delete mode 100644 test/builddir-reflect.py diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index df974de..9dfd355 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1084,10 +1084,6 @@ class FS(LocalFS): else: if not must_exist or node.exists(): result.append(node) - if isinstance(node, Dir): - result.extend(filter(select, node.getRepositories())) - if node: - dir = node.get_dir() fname = '.' while dir: for rep in dir.getRepositories(): diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 5034d16..1d7d926 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1494,57 +1494,87 @@ class EntryTestCase(unittest.TestCase): -class RepositoryTestCase(unittest.TestCase): - def runTest(self): - """Test FS (file system) Repository operations +class RepositoryTestCase(_tempdirTestCase): - """ - fs = SCons.Node.FS.FS() + def setUp(self): + _tempdirTestCase.setUp(self) - fs.Repository('foo') - fs.Repository(os.path.join('foo', 'bar')) - fs.Repository(os.path.join('bar', 'foo')) - fs.Repository('bar') + self.test.subdir('rep1', 'rep2', 'rep3', 'work') - rep = fs.Dir('#').getRepositories() - assert len(rep) == 4, map(str, rep) - r = map(lambda x, np=os.path.normpath: np(str(x)), rep) - assert r == ['foo', - os.path.join('foo', 'bar'), - os.path.join('bar', 'foo'), - 'bar'], r + self.rep1 = self.test.workpath('rep1') + self.rep2 = self.test.workpath('rep2') + self.rep3 = self.test.workpath('rep3') - test = TestCmd(workdir = '') - test.subdir('rep1', 'rep2', 'rep3', 'work') + os.chdir(self.test.workpath('work')) - rep1 = test.workpath('rep1') - rep2 = test.workpath('rep2') - rep3 = test.workpath('rep3') + self.fs = SCons.Node.FS.FS() + self.fs.Repository(self.rep1, self.rep2, self.rep3) + + def test_getRepositories(self): + """Test the Dir.getRepositories() method""" + self.fs.Repository('foo') + self.fs.Repository(os.path.join('foo', 'bar')) + self.fs.Repository('bar/foo') + self.fs.Repository('bar') + + expect = [ + self.rep1, + self.rep2, + self.rep3, + 'foo', + os.path.join('foo', 'bar'), + os.path.join('bar', 'foo'), + 'bar' + ] - os.chdir(test.workpath('work')) + rep = self.fs.Dir('#').getRepositories() + r = map(lambda x, np=os.path.normpath: np(str(x)), rep) + assert r == expect, r - fs = SCons.Node.FS.FS() - fs.Repository(rep1, rep2, rep3) + def test_rfile(self): + """Test the File.rfile() method""" + f1 = self.fs.File('f1') + f2 = self.fs.File('f2') + f3 = self.fs.File('f3') + + self.test.write([self.rep1, 'f2'], "") + self.test.subdir([self.rep2, 'f3']) + self.test.write([self.rep3, 'f3'], "") - f1 = fs.File(os.path.join('f1')) assert f1.rfile() is f1 - test.write([rep1, 'f2'], "") + r = f2.rfile() + assert not r is f2, r + assert str(r) == os.path.join(self.rep1, 'f2'), str(r) - f2 = fs.File('f2') - assert not f2.rfile() is f2, f2.rfile() - assert str(f2.rfile()) == os.path.join(rep1, 'f2'), str(f2.rfile()) + r = f3.rfile() + assert not r is f3, r + r = f3.rstr() + assert r == os.path.join(self.rep3, 'f3'), r + + def test_Rsearches(self): + """Test the Rsearch() methods""" + fs = self.fs + test = self.test - test.subdir([rep2, 'f3']) - test.write([rep3, 'f3'], "") + test.write([self.rep1, 'f2'], "") + test.subdir([self.rep2, 'f3']) + test.write([self.rep3, 'f3'], "") + + r = fs.Rsearch('f1') + assert r is None, r + + r = fs.Rsearch('f2') + assert r, r f3 = fs.File('f3') - assert not f3.rfile() is f3, f3.rfile() - assert f3.rstr() == os.path.join(rep3, 'f3'), f3.rstr() + r = fs.Rsearch(f3) + assert r is f3, r - assert fs.Rsearch('f1') is None - assert fs.Rsearch('f2') - assert fs.Rsearch(f3) is f3 + def test_Rsearchall(self): + """Test the Rsearchall() methods""" + fs = self.fs + test = self.test list = fs.Rsearchall(fs.Dir('d1')) assert len(list) == 1, list @@ -1562,16 +1592,19 @@ class RepositoryTestCase(unittest.TestCase): fs.File('d2').built() # Clear exists cache test.subdir(['work', 'd2']) + list = fs.Rsearchall('d2') assert map(str, list) == ['d2'], list fs.File('../rep2/d2').built() # Clear exists cache test.subdir(['rep2', 'd2']) + list = fs.Rsearchall('d2') assert map(str, list) == ['d2', test.workpath('rep2', 'd2')], list fs.File('../rep1/d2').built() # Clear exists cache test.subdir(['rep1', 'd2']) + list = fs.Rsearchall('d2') assert map(str, list) == ['d2', test.workpath('rep1', 'd2'), @@ -1582,11 +1615,13 @@ class RepositoryTestCase(unittest.TestCase): fs.File('d3').built() # Clear exists cache test.subdir(['work', 'd3']) + list = map(str, fs.Rsearchall(['d3', 'd4'])) assert list == ['d3'], list fs.File('../rep3/d4').built() # Clear exists cache test.subdir(['rep3', 'd4']) + list = map(str, fs.Rsearchall(['d3', 'd4'])) assert list == ['d3', test.workpath('rep3', 'd4')], list @@ -1594,6 +1629,7 @@ class RepositoryTestCase(unittest.TestCase): assert list == ['d3', test.workpath('rep3', 'd4')], list work_d4 = fs.File(os.path.join('work', 'd4')) + list = map(str, fs.Rsearchall(['d3', work_d4])) assert list == ['d3', str(work_d4)], list @@ -1606,12 +1642,19 @@ class RepositoryTestCase(unittest.TestCase): list = fs.Rsearchall(['']) assert list == [], list + def test_rexists(self): + """Test the Entry.rexists() method""" + fs = self.fs + test = self.test + + test.write([self.rep1, 'f2'], "") + fs.BuildDir('build', '.') f = fs.File(test.workpath("work", "i_do_not_exist")) assert not f.rexists() - test.write(["rep2", "i_exist"], "\n") + test.write([self.rep2, "i_exist"], "\n") f = fs.File(test.workpath("work", "i_exist")) assert f.rexists() @@ -1625,6 +1668,11 @@ class RepositoryTestCase(unittest.TestCase): f2 = fs.File(os.path.join('build', 'f2')) assert f2.rexists() + def test_FAT_timestamps(self): + """Test repository timestamps on FAT file systems""" + fs = self.fs + test = self.test + test.write(["rep2", "tstamp"], "tstamp\n") try: # Okay, *this* manipulation accomodates Windows FAT file systems @@ -1640,7 +1688,11 @@ class RepositoryTestCase(unittest.TestCase): finally: test.unlink(["rep2", "tstamp"]) - # Make sure get_contents() returns the binary contents. + def test_get_contents(self): + """Ensure get_contents() returns binary contents from Repositories""" + fs = self.fs + test = self.test + test.write(["rep3", "contents"], "Con\x1aTents\n") try: c = fs.File("contents").get_contents() @@ -1648,9 +1700,11 @@ class RepositoryTestCase(unittest.TestCase): finally: test.unlink(["rep3", "contents"]) - # XXX test calc_signature() + #def test calc_signature(self): + + #def test current(self): + - # XXX test current() class find_fileTestCase(unittest.TestCase): def runTest(self): @@ -2372,7 +2426,6 @@ if __name__ == "__main__": suite.addTest(FSTestCase()) suite.addTest(BuildDirTestCase()) suite.addTest(EntryTestCase()) - suite.addTest(RepositoryTestCase()) suite.addTest(find_fileTestCase()) suite.addTest(StringDirTestCase()) suite.addTest(stored_infoTestCase()) @@ -2387,6 +2440,7 @@ if __name__ == "__main__": suite.addTest(SaveStringsTestCase()) tclasses = [ DirTestCase, + RepositoryTestCase, ] for tclass in tclasses: names = unittest.getTestCaseNames(tclass, 'test_') diff --git a/test/BuildDir-errors.py b/test/BuildDir-errors.py deleted file mode 100644 index 93cd3ec..0000000 --- a/test/BuildDir-errors.py +++ /dev/null @@ -1,171 +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__" - -""" -Validate successful handling of errors when duplicating things in -BuildDirs. This is generally when the BuildDir, or something in it, -is read-only. -""" - -import os -import os.path -import stat -import sys -import TestSCons - -test = TestSCons.TestSCons() - -for dir in ['normal', 'ro-dir', 'ro-SConscript', 'ro-src']: - test.subdir(dir, [dir, 'src']) - - test.write([dir, 'SConstruct'], """\ -import os.path -BuildDir('build', 'src') -SConscript(os.path.join('build', 'SConscript')) -""") - - test.write([dir, 'src', 'SConscript'], """\ -def fake_scan(node, env, target): - # We fetch the contents here, even though we don't examine - # them, because get_contents() will cause the engine to - # try to link the source file into the build directory, - # potentially triggering a different failure case. - contents = node.get_contents() - return [] - -def cat(env, source, target): - target = str(target[0]) - source = map(str, source) - f = open(target, "wb") - for src in source: - f.write(open(src, "rb").read()) - f.close() - -env = Environment(BUILDERS={'Build':Builder(action=cat)}, - SCANNERS=[Scanner(fake_scan, skeys = ['.in'])]) - -# 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') -""") - - test.write([dir, 'src', 'file.in'], dir + "/src/file.in\n") - -# Just verify that the normal case works fine. -test.run(chdir = 'normal', arguments = ".") - -test.fail_test(test.read(['normal', 'build', 'file.out']) != "normal/src/file.in\n") - -# Verify the error when the BuildDir itself is read-only. Don't bother -# to test this on Win32, because the ACL (I think) still allows the -# owner to create files in the directory even when it's read-only. -if sys.platform != 'win32': - dir = os.path.join('ro-dir', 'build') - test.subdir(dir) - os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) - - test.run(chdir = 'ro-dir', - arguments = ".", - status = 2, - stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) - -# Verify the error when the SConscript file within the BuildDir is -# read-only. Note that we have to make the directory read-only too, -# because otherwise our duplication logic will be able to unlink -# the read-only SConscript and duplicate the new one. -dir = os.path.join('ro-SConscript', 'build') -test.subdir(dir) -SConscript = test.workpath(dir, 'SConscript') -test.write(SConscript, '') -os.chmod(SConscript, os.stat(SConscript)[stat.ST_MODE] & ~stat.S_IWUSR) -f = open(SConscript, 'r') -os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) - -test.run(chdir = 'ro-SConscript', - arguments = ".", - status = 2, - stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) - -os.chmod('ro-SConscript', os.stat('ro-SConscript')[stat.ST_MODE] | stat.S_IWUSR) -f.close() - -test.run(chdir = 'ro-SConscript', - arguments = ".", - status = 2, - stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) - -# Verify the error when the source file within the BuildDir is -# read-only. Note that we have to make the directory read-only too, -# because otherwise our duplication logic will be able to unlink the -# read-only source file and duplicate the new one. But because we've -# made the BuildDir read-only, we must also create a writable SConscript -# file there so it can be duplicated from the source directory. -dir = os.path.join('ro-src', 'build') -test.subdir(dir) -test.write([dir, 'SConscript'], '') -file_in = test.workpath(dir, 'file.in') -test.write(file_in, '') -os.chmod(file_in, os.stat(file_in)[stat.ST_MODE] & ~stat.S_IWUSR) -f = open(file_in, 'r') -os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) - -test.run(chdir = 'ro-src', - arguments = ".", - status = 2, - stderr = """\ -scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop. -""" % (os.path.join('src', 'file.in'))) - -test.run(chdir = 'ro-src', - arguments = "-k .", - status = 2, - stderr = """\ -scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop. -""" % (os.path.join('src', 'file.in'))) - -f.close() - -# ensure that specifying multiple source directories for one -# build directory results in an error message, rather -# than just silently failing. -test.subdir('duplicate', ['duplicate', 'src1'], ['duplicate', 'src2']) -test.write(['duplicate', 'SConstruct'], """\ -BuildDir('build', 'src1') -BuildDir('build', 'src2') -""") - -test.run(chdir = 'duplicate', - arguments = ".", - status = 2, - stderr = """ -scons: *** 'build' already has a source directory: 'src1'. -File "SConstruct", line 2, in ? -""") - -test.pass_test() diff --git a/test/BuildDir.py b/test/BuildDir.py deleted file mode 100644 index 181d8aa..0000000 --- a/test/BuildDir.py +++ /dev/null @@ -1,393 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os.path -import string -import sys -import time -import TestSCons - -_exe = TestSCons._exe -fortran_runtime = TestSCons.fortran_lib - -test = TestSCons.TestSCons() - -fortran = test.detect('FORTRAN') - -foo11 = test.workpath('work1', 'build', 'var1', 'foo1' + _exe) -foo12 = test.workpath('work1', 'build', 'var1', 'foo2' + _exe) -foo21 = test.workpath('work1', 'build', 'var2', 'foo1' + _exe) -foo22 = test.workpath('work1', 'build', 'var2', 'foo2' + _exe) -foo31 = test.workpath('work1', 'build', 'var3', 'foo1' + _exe) -foo32 = test.workpath('work1', 'build', 'var3', 'foo2' + _exe) -foo41 = test.workpath('work1', 'build', 'var4', 'foo1' + _exe) -foo42 = test.workpath('work1', 'build', 'var4', 'foo2' + _exe) -foo51 = test.workpath('build', 'var5', 'foo1' + _exe) -foo52 = test.workpath('build', 'var5', 'foo2' + _exe) - -bar11 = test.workpath('work1', 'build', 'var1', 'bar1' + _exe) -bar12 = test.workpath('work1', 'build', 'var1', 'bar2' + _exe) -bar21 = test.workpath('work1', 'build', 'var2', 'bar1' + _exe) -bar22 = test.workpath('work1', 'build', 'var2', 'bar2' + _exe) -bar31 = test.workpath('work1', 'build', 'var3', 'bar1' + _exe) -bar32 = test.workpath('work1', 'build', 'var3', 'bar2' + _exe) -bar41 = test.workpath('work1', 'build', 'var4', 'bar1' + _exe) -bar42 = test.workpath('work1', 'build', 'var4', 'bar2' + _exe) -bar51 = test.workpath('build', 'var5', 'bar1' + _exe) -bar52 = test.workpath('build', 'var5', 'bar2' + _exe) - -test.subdir('work1', 'work2', 'work3') - -test.write(['work1', 'SConstruct'], """ -src = Dir('src') -var2 = Dir('build/var2') -var3 = Dir('build/var3') -var4 = Dir('build/var4') -var5 = Dir('../build/var5') -var6 = Dir('../build/var6') - -env = Environment(BUILD = 'build', SRC = 'src') - -BuildDir('build/var1', src) -BuildDir(var2, src) -BuildDir(var3, src, duplicate=0) -env.BuildDir("$BUILD/var4", "$SRC", duplicate=0) -BuildDir(var5, src, duplicate=0) -BuildDir(var6, src) - -env = Environment(CPPPATH='#src', FORTRANPATH='#src') -SConscript('build/var1/SConscript', "env") -SConscript('build/var2/SConscript', "env") - -env = Environment(CPPPATH=src, FORTRANPATH=src) -SConscript('build/var3/SConscript', "env") -SConscript(File('SConscript', var4), "env") - -env = Environment(CPPPATH='.', FORTRANPATH='.') -SConscript('../build/var5/SConscript', "env") -SConscript('../build/var6/SConscript', "env") -""") - -test.subdir(['work1', 'src']) -test.write(['work1', 'src', 'SConscript'], """ -import os -import os.path - -def buildIt(target, source, env): - if not os.path.exists('build'): - os.mkdir('build') - f1=open(str(source[0]), 'r') - f2=open(str(target[0]), 'w') - f2.write(f1.read()) - f2.close() - f1.close() - return 0 -Import("env") -env.Command(target='f2.c', source='f2.in', action=buildIt) -env.Program(target='foo2', source='f2.c') -env.Program(target='foo1', source='f1.c') -env.Command(target='f3.h', source='f3h.in', action=buildIt) -env.Command(target='f4.h', source='f4h.in', action=buildIt) -env.Command(target='f4.c', source='f4.in', action=buildIt) - -env2=env.Copy(CPPPATH='.') -env2.Program(target='foo3', source='f3.c') -env2.Program(target='foo4', source='f4.c') - -try: - fortran = env.subst('$FORTRAN') -except: - fortran = None - -if fortran and env.Detect(fortran): - env.Command(target='b2.f', source='b2.in', action=buildIt) - env.Copy(LIBS = %s).Program(target='bar2', source='b2.f') - env.Copy(LIBS = %s).Program(target='bar1', source='b1.f') -""" % (fortran_runtime, fortran_runtime)) - -test.write(['work1', 'src', 'f1.c'], r""" -#include "f1.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F1_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f2.in'], r""" -#include "f2.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F2_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f3.c'], r""" -#include "f3.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F3_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f4.in'], r""" -#include "f4.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F4_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f1.h'], r""" -#define F1_STR "f1.c\n" -""") - -test.write(['work1', 'src', 'f2.h'], r""" -#define F2_STR "f2.c\n" -""") - -test.write(['work1', 'src', 'f3h.in'], r""" -#define F3_STR "f3.c\n" -""") - -test.write(['work1', 'src', 'f4h.in'], r""" -#define F4_STR "f4.c\n" -""") - -test.write(['work1', 'src', 'b1.f'], r""" - PROGRAM FOO - INCLUDE 'b1.for' - STOP - END -""") - -test.write(['work1', 'src', 'b2.in'], r""" - PROGRAM FOO - INCLUDE 'b2.for' - STOP - END -""") - -test.write(['work1', 'src', 'b1.for'], r""" - PRINT *, 'b1.for' -""") - -test.write(['work1', 'src', 'b2.for'], r""" - PRINT *, 'b2.for' -""") - -# Some releases of freeBSD seem to have library complaints about -# tempnam(). Filter out these annoying messages before checking for -# error output. -def blank_output(err): - if not err: - return 1 - stderrlines = filter(lambda l: l, string.split(err, '\n')) - msg = "warning: tempnam() possibly used unsafely" - stderrlines = filter(lambda l, msg=msg: string.find(l, msg) == -1, - stderrlines) - return len(stderrlines) == 0 - -test.run(chdir='work1', arguments = '. ../build', stderr=None) - -test.fail_test(not blank_output(test.stderr())) - -test.run(program = foo11, stdout = "f1.c\n") -test.run(program = foo12, stdout = "f2.c\n") -test.run(program = foo21, stdout = "f1.c\n") -test.run(program = foo22, stdout = "f2.c\n") -test.run(program = foo31, stdout = "f1.c\n") -test.run(program = foo32, stdout = "f2.c\n") -test.run(program = foo41, stdout = "f1.c\n") -test.run(program = foo42, stdout = "f2.c\n") -test.run(program = foo51, stdout = "f1.c\n") -test.run(program = foo52, stdout = "f2.c\n") - -if fortran: - test.run(program = bar11, stdout = " b1.for\n") - test.run(program = bar12, stdout = " b2.for\n") - test.run(program = bar21, stdout = " b1.for\n") - test.run(program = bar22, stdout = " b2.for\n") - test.run(program = bar31, stdout = " b1.for\n") - test.run(program = bar32, stdout = " b2.for\n") - test.run(program = bar41, stdout = " b1.for\n") - test.run(program = bar42, stdout = " b2.for\n") - test.run(program = bar51, stdout = " b1.for\n") - test.run(program = bar52, stdout = " b2.for\n") - -test.run(chdir='work1', arguments='. ../build', stdout=test.wrap_stdout("""\ -scons: `.' is up to date. -scons: `%s' is up to date. -""" % test.workpath('build'))) - -import os -import stat -def equal_stats(x,y): - x = os.stat(x) - y = os.stat(y) - return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and - x[stat.ST_MTIME] == y[stat.ST_MTIME]) - -# Make sure we did duplicate the source files in build/var2, -# and that their stats are the same: -test.must_exist(['work1', 'build', 'var2', 'f1.c']) -test.must_exist(['work1', 'build', 'var2', 'f2.in']) -test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f1.c'), test.workpath('work1', 'src', 'f1.c'))) -test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f2.in'), test.workpath('work1', 'src', 'f2.in'))) - -# Make sure we didn't duplicate the source files in build/var3. -test.must_not_exist(['work1', 'build', 'var3', 'f1.c']) -test.must_not_exist(['work1', 'build', 'var3', 'f2.in']) -test.must_not_exist(['work1', 'build', 'var3', 'b1.f']) -test.must_not_exist(['work1', 'build', 'var3', 'b2.in']) - -# Make sure we didn't duplicate the source files in build/var4. -test.must_not_exist(['work1', 'build', 'var4', 'f1.c']) -test.must_not_exist(['work1', 'build', 'var4', 'f2.in']) -test.must_not_exist(['work1', 'build', 'var4', 'b1.f']) -test.must_not_exist(['work1', 'build', 'var4', 'b2.in']) - -# Make sure we didn't duplicate the source files in build/var5. -test.must_not_exist(['build', 'var5', 'f1.c']) -test.must_not_exist(['build', 'var5', 'f2.in']) -test.must_not_exist(['build', 'var5', 'b1.f']) -test.must_not_exist(['build', 'var5', 'b2.in']) - -# verify that header files in the source directory are scanned properly: -test.write(['work1', 'src', 'f1.h'], r""" -#define F1_STR "f1.c 2\n" -""") - -test.write(['work1', 'src', 'f3h.in'], r""" -#define F3_STR "f3.c 2\n" -""") - -test.write(['work1', 'src', 'f4h.in'], r""" -#define F4_STR "f4.c 2\n" -""") - -test.run(chdir='work1', arguments = '../build/var5', stderr=None) - -test.fail_test(not blank_output(test.stderr())) - -test.run(program = foo51, stdout = "f1.c 2\n") -test.run(program = test.workpath('build', 'var5', 'foo3' + _exe), - stdout = "f3.c 2\n") -test.run(program = test.workpath('build', 'var5', 'foo4' + _exe), - stdout = "f4.c 2\n") - -test.run(chdir='work1', arguments='../build/var5', stdout=test.wrap_stdout("""\ -scons: `%s' is up to date. -""" % test.workpath('build', 'var5'))) - -# -test.write(['work2', 'SConstruct'], """\ -env = Environment() -env.Program('prog.c') -""") - -test.write(['work2', 'prog.c'], r""" -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("work2/prog.c\n"); - exit (0); -} -""") - -test.run(chdir='work2', arguments='.') - -test.up_to_date(chdir='work2', arguments='.') - -# -test.write(['work2', 'SConstruct'], """\ -env = Environment() -BuildDir('build', '.') -Export('env') -SConscript('build/SConscript') -""") - -test.write(['work2', 'SConscript'], """\ -Import('env') -env.Program('prog.c') -""") - -test.run(chdir='work2', arguments='.', stderr=None) - -test.fail_test(not blank_output(test.stderr())) - -test.run(chdir='work2', arguments='.', - stdout=test.wrap_stdout("""\ -scons: building associated BuildDir targets: build -scons: `.' is up to date. -""")) - -test.write( ['work3', 'SConstruct'], """\ -SConscriptChdir(0) -BuildDir('build', '.', duplicate=1 ) -SConscript( 'build/SConscript' ) -""") - -test.write( ['work3', 'SConscript'], """\ -import sys -headers = ['existing.h', 'non_existing.h'] -for header in headers: - h = File( header ) - contents = h.get_contents() - sys.stderr.write( '%s:%s\\n' % (header, contents)) -""") - -test.write( ['work3', 'existing.h'], """\ -/* a header file */\ -""") - -test.run(chdir='work3', - stdout=test.wrap_stdout("""\ -scons: building associated BuildDir targets: build -scons: `.' is up to date. -"""), - stderr="""\ -existing.h:/* a header file */ -non_existing.h: -""") - -test.pass_test() diff --git a/test/BuildDir/BuildDir.py b/test/BuildDir/BuildDir.py new file mode 100644 index 0000000..181d8aa --- /dev/null +++ b/test/BuildDir/BuildDir.py @@ -0,0 +1,393 @@ +#!/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.path +import string +import sys +import time +import TestSCons + +_exe = TestSCons._exe +fortran_runtime = TestSCons.fortran_lib + +test = TestSCons.TestSCons() + +fortran = test.detect('FORTRAN') + +foo11 = test.workpath('work1', 'build', 'var1', 'foo1' + _exe) +foo12 = test.workpath('work1', 'build', 'var1', 'foo2' + _exe) +foo21 = test.workpath('work1', 'build', 'var2', 'foo1' + _exe) +foo22 = test.workpath('work1', 'build', 'var2', 'foo2' + _exe) +foo31 = test.workpath('work1', 'build', 'var3', 'foo1' + _exe) +foo32 = test.workpath('work1', 'build', 'var3', 'foo2' + _exe) +foo41 = test.workpath('work1', 'build', 'var4', 'foo1' + _exe) +foo42 = test.workpath('work1', 'build', 'var4', 'foo2' + _exe) +foo51 = test.workpath('build', 'var5', 'foo1' + _exe) +foo52 = test.workpath('build', 'var5', 'foo2' + _exe) + +bar11 = test.workpath('work1', 'build', 'var1', 'bar1' + _exe) +bar12 = test.workpath('work1', 'build', 'var1', 'bar2' + _exe) +bar21 = test.workpath('work1', 'build', 'var2', 'bar1' + _exe) +bar22 = test.workpath('work1', 'build', 'var2', 'bar2' + _exe) +bar31 = test.workpath('work1', 'build', 'var3', 'bar1' + _exe) +bar32 = test.workpath('work1', 'build', 'var3', 'bar2' + _exe) +bar41 = test.workpath('work1', 'build', 'var4', 'bar1' + _exe) +bar42 = test.workpath('work1', 'build', 'var4', 'bar2' + _exe) +bar51 = test.workpath('build', 'var5', 'bar1' + _exe) +bar52 = test.workpath('build', 'var5', 'bar2' + _exe) + +test.subdir('work1', 'work2', 'work3') + +test.write(['work1', 'SConstruct'], """ +src = Dir('src') +var2 = Dir('build/var2') +var3 = Dir('build/var3') +var4 = Dir('build/var4') +var5 = Dir('../build/var5') +var6 = Dir('../build/var6') + +env = Environment(BUILD = 'build', SRC = 'src') + +BuildDir('build/var1', src) +BuildDir(var2, src) +BuildDir(var3, src, duplicate=0) +env.BuildDir("$BUILD/var4", "$SRC", duplicate=0) +BuildDir(var5, src, duplicate=0) +BuildDir(var6, src) + +env = Environment(CPPPATH='#src', FORTRANPATH='#src') +SConscript('build/var1/SConscript', "env") +SConscript('build/var2/SConscript', "env") + +env = Environment(CPPPATH=src, FORTRANPATH=src) +SConscript('build/var3/SConscript', "env") +SConscript(File('SConscript', var4), "env") + +env = Environment(CPPPATH='.', FORTRANPATH='.') +SConscript('../build/var5/SConscript', "env") +SConscript('../build/var6/SConscript', "env") +""") + +test.subdir(['work1', 'src']) +test.write(['work1', 'src', 'SConscript'], """ +import os +import os.path + +def buildIt(target, source, env): + if not os.path.exists('build'): + os.mkdir('build') + f1=open(str(source[0]), 'r') + f2=open(str(target[0]), 'w') + f2.write(f1.read()) + f2.close() + f1.close() + return 0 +Import("env") +env.Command(target='f2.c', source='f2.in', action=buildIt) +env.Program(target='foo2', source='f2.c') +env.Program(target='foo1', source='f1.c') +env.Command(target='f3.h', source='f3h.in', action=buildIt) +env.Command(target='f4.h', source='f4h.in', action=buildIt) +env.Command(target='f4.c', source='f4.in', action=buildIt) + +env2=env.Copy(CPPPATH='.') +env2.Program(target='foo3', source='f3.c') +env2.Program(target='foo4', source='f4.c') + +try: + fortran = env.subst('$FORTRAN') +except: + fortran = None + +if fortran and env.Detect(fortran): + env.Command(target='b2.f', source='b2.in', action=buildIt) + env.Copy(LIBS = %s).Program(target='bar2', source='b2.f') + env.Copy(LIBS = %s).Program(target='bar1', source='b1.f') +""" % (fortran_runtime, fortran_runtime)) + +test.write(['work1', 'src', 'f1.c'], r""" +#include "f1.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F1_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f2.in'], r""" +#include "f2.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F2_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f3.c'], r""" +#include "f3.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F3_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f4.in'], r""" +#include "f4.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F4_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f1.h'], r""" +#define F1_STR "f1.c\n" +""") + +test.write(['work1', 'src', 'f2.h'], r""" +#define F2_STR "f2.c\n" +""") + +test.write(['work1', 'src', 'f3h.in'], r""" +#define F3_STR "f3.c\n" +""") + +test.write(['work1', 'src', 'f4h.in'], r""" +#define F4_STR "f4.c\n" +""") + +test.write(['work1', 'src', 'b1.f'], r""" + PROGRAM FOO + INCLUDE 'b1.for' + STOP + END +""") + +test.write(['work1', 'src', 'b2.in'], r""" + PROGRAM FOO + INCLUDE 'b2.for' + STOP + END +""") + +test.write(['work1', 'src', 'b1.for'], r""" + PRINT *, 'b1.for' +""") + +test.write(['work1', 'src', 'b2.for'], r""" + PRINT *, 'b2.for' +""") + +# Some releases of freeBSD seem to have library complaints about +# tempnam(). Filter out these annoying messages before checking for +# error output. +def blank_output(err): + if not err: + return 1 + stderrlines = filter(lambda l: l, string.split(err, '\n')) + msg = "warning: tempnam() possibly used unsafely" + stderrlines = filter(lambda l, msg=msg: string.find(l, msg) == -1, + stderrlines) + return len(stderrlines) == 0 + +test.run(chdir='work1', arguments = '. ../build', stderr=None) + +test.fail_test(not blank_output(test.stderr())) + +test.run(program = foo11, stdout = "f1.c\n") +test.run(program = foo12, stdout = "f2.c\n") +test.run(program = foo21, stdout = "f1.c\n") +test.run(program = foo22, stdout = "f2.c\n") +test.run(program = foo31, stdout = "f1.c\n") +test.run(program = foo32, stdout = "f2.c\n") +test.run(program = foo41, stdout = "f1.c\n") +test.run(program = foo42, stdout = "f2.c\n") +test.run(program = foo51, stdout = "f1.c\n") +test.run(program = foo52, stdout = "f2.c\n") + +if fortran: + test.run(program = bar11, stdout = " b1.for\n") + test.run(program = bar12, stdout = " b2.for\n") + test.run(program = bar21, stdout = " b1.for\n") + test.run(program = bar22, stdout = " b2.for\n") + test.run(program = bar31, stdout = " b1.for\n") + test.run(program = bar32, stdout = " b2.for\n") + test.run(program = bar41, stdout = " b1.for\n") + test.run(program = bar42, stdout = " b2.for\n") + test.run(program = bar51, stdout = " b1.for\n") + test.run(program = bar52, stdout = " b2.for\n") + +test.run(chdir='work1', arguments='. ../build', stdout=test.wrap_stdout("""\ +scons: `.' is up to date. +scons: `%s' is up to date. +""" % test.workpath('build'))) + +import os +import stat +def equal_stats(x,y): + x = os.stat(x) + y = os.stat(y) + return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and + x[stat.ST_MTIME] == y[stat.ST_MTIME]) + +# Make sure we did duplicate the source files in build/var2, +# and that their stats are the same: +test.must_exist(['work1', 'build', 'var2', 'f1.c']) +test.must_exist(['work1', 'build', 'var2', 'f2.in']) +test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f1.c'), test.workpath('work1', 'src', 'f1.c'))) +test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f2.in'), test.workpath('work1', 'src', 'f2.in'))) + +# Make sure we didn't duplicate the source files in build/var3. +test.must_not_exist(['work1', 'build', 'var3', 'f1.c']) +test.must_not_exist(['work1', 'build', 'var3', 'f2.in']) +test.must_not_exist(['work1', 'build', 'var3', 'b1.f']) +test.must_not_exist(['work1', 'build', 'var3', 'b2.in']) + +# Make sure we didn't duplicate the source files in build/var4. +test.must_not_exist(['work1', 'build', 'var4', 'f1.c']) +test.must_not_exist(['work1', 'build', 'var4', 'f2.in']) +test.must_not_exist(['work1', 'build', 'var4', 'b1.f']) +test.must_not_exist(['work1', 'build', 'var4', 'b2.in']) + +# Make sure we didn't duplicate the source files in build/var5. +test.must_not_exist(['build', 'var5', 'f1.c']) +test.must_not_exist(['build', 'var5', 'f2.in']) +test.must_not_exist(['build', 'var5', 'b1.f']) +test.must_not_exist(['build', 'var5', 'b2.in']) + +# verify that header files in the source directory are scanned properly: +test.write(['work1', 'src', 'f1.h'], r""" +#define F1_STR "f1.c 2\n" +""") + +test.write(['work1', 'src', 'f3h.in'], r""" +#define F3_STR "f3.c 2\n" +""") + +test.write(['work1', 'src', 'f4h.in'], r""" +#define F4_STR "f4.c 2\n" +""") + +test.run(chdir='work1', arguments = '../build/var5', stderr=None) + +test.fail_test(not blank_output(test.stderr())) + +test.run(program = foo51, stdout = "f1.c 2\n") +test.run(program = test.workpath('build', 'var5', 'foo3' + _exe), + stdout = "f3.c 2\n") +test.run(program = test.workpath('build', 'var5', 'foo4' + _exe), + stdout = "f4.c 2\n") + +test.run(chdir='work1', arguments='../build/var5', stdout=test.wrap_stdout("""\ +scons: `%s' is up to date. +""" % test.workpath('build', 'var5'))) + +# +test.write(['work2', 'SConstruct'], """\ +env = Environment() +env.Program('prog.c') +""") + +test.write(['work2', 'prog.c'], r""" +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("work2/prog.c\n"); + exit (0); +} +""") + +test.run(chdir='work2', arguments='.') + +test.up_to_date(chdir='work2', arguments='.') + +# +test.write(['work2', 'SConstruct'], """\ +env = Environment() +BuildDir('build', '.') +Export('env') +SConscript('build/SConscript') +""") + +test.write(['work2', 'SConscript'], """\ +Import('env') +env.Program('prog.c') +""") + +test.run(chdir='work2', arguments='.', stderr=None) + +test.fail_test(not blank_output(test.stderr())) + +test.run(chdir='work2', arguments='.', + stdout=test.wrap_stdout("""\ +scons: building associated BuildDir targets: build +scons: `.' is up to date. +""")) + +test.write( ['work3', 'SConstruct'], """\ +SConscriptChdir(0) +BuildDir('build', '.', duplicate=1 ) +SConscript( 'build/SConscript' ) +""") + +test.write( ['work3', 'SConscript'], """\ +import sys +headers = ['existing.h', 'non_existing.h'] +for header in headers: + h = File( header ) + contents = h.get_contents() + sys.stderr.write( '%s:%s\\n' % (header, contents)) +""") + +test.write( ['work3', 'existing.h'], """\ +/* a header file */\ +""") + +test.run(chdir='work3', + stdout=test.wrap_stdout("""\ +scons: building associated BuildDir targets: build +scons: `.' is up to date. +"""), + stderr="""\ +existing.h:/* a header file */ +non_existing.h: +""") + +test.pass_test() diff --git a/test/BuildDir/CPPPATH-subdir.py b/test/BuildDir/CPPPATH-subdir.py new file mode 100644 index 0000000..2ae50b5 --- /dev/null +++ b/test/BuildDir/CPPPATH-subdir.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__" + +""" +Test handling of the current directory (.) in CPPPATH when +the include path contains a subdirectory. + +This tests for a regression found in 0.96.90 by Chad Austin. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('src', ['src', 'glscry']) + +test.write('SConstruct', """\ +env = Environment() +Export('env') +SConscript(dirs=['src'], build_dir='build', duplicate=0) +""") + + +test.write(['src', 'SConscript'], """\ +SConscript(dirs=['glscry']) +""") + + +test.write(['src', 'glscry', 'SConscript'], """\ +Import('*') +env = env.Copy() +env.Append(CPPPATH=['.']) +env.Library('foo', 'foo.c') +""") + +test.write(['src', 'glscry', 'foo.c'], """\ +#include +""") + + +test.write(['src', 'glscry', 'foo.h'], "\n") + +test.run(arguments = '.', + stderr = TestSCons.noisy_ar, + match = TestSCons.match_re_dotall) + +test.pass_test() diff --git a/test/BuildDir/Sconscript-build_dir.py b/test/BuildDir/Sconscript-build_dir.py new file mode 100644 index 0000000..298eb9b --- /dev/null +++ b/test/BuildDir/Sconscript-build_dir.py @@ -0,0 +1,263 @@ +#!/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 specifying a build_dir argument to SConscript works properly. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +all1 = test.workpath('test', 'build', 'var1', 'all') +all2 = test.workpath('test', 'build', 'var2', 'all') +all3 = test.workpath('test', 'build', 'var3', 'all') +all4 = test.workpath('test', 'build', 'var4', 'all') +all5 = test.workpath('build', 'var5', 'all') +all6 = test.workpath('build', 'var6', 'all') +all7 = test.workpath('build', 'var7', 'all') +all8 = test.workpath('build', 'var8', 'all') +all9 = test.workpath('test', 'build', 'var9', 'src', 'all') + +test.subdir('test') + +test.write(['test', 'SConstruct'], """ +src = Dir('src') +alt = Dir('alt') +var1 = Dir('build/var1') +var2 = Dir('build/var2') +var3 = Dir('build/var3') +var4 = Dir('build/var4') +var5 = Dir('../build/var5') +var6 = Dir('../build/var6') +var7 = Dir('../build/var7') +var8 = Dir('../build/var8') +var9 = Dir('../build/var9') + +def cat(env, source, target): + target = str(target[0]) + source = map(str, source) + f = open(target, "wb") + for src in source: + f.write(open(src, "rb").read()) + f.close() + +env = Environment(BUILDERS={'Cat':Builder(action=cat)}, + BUILD='build') + +Export("env") + +SConscript('src/SConscript', build_dir=var1) +SConscript('src/SConscript', build_dir='build/var2', src_dir=src) + +SConscript('src/SConscript', build_dir='build/var3', duplicate=0) + +#XXX We can't support var4 and var5 yet, because our BuildDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX SConscript('src/SConscript', build_dir=var4, src_dir=alt, duplicate=0) + +#XXX SConscript('src/SConscript', build_dir='../build/var5', src_dir='alt') +SConscript('src/SConscript', build_dir=var6) + +SConscript('src/SConscript', build_dir=var7, src_dir=src, duplicate=0) +env.SConscript('src/SConscript', build_dir='../$BUILD/var8', duplicate=0) + +# This tests the fact that if you specify a src_dir that is above +# the dir a SConscript is in, that we do the intuitive thing, i.e., +# we set the path of the SConscript accordingly. The below is +# equivalent to saying: +# +# BuildDir('build/var9', '.') +# SConscript('build/var9/src/SConscript') +SConscript('src/SConscript', build_dir='build/var9', src_dir='.') +""") + +test.subdir(['test', 'src'], ['test', 'alt']) + +test.write(['test', 'src', 'SConscript'], """ +Import("env") +env.Cat('aaa.out', 'aaa.in') +env.Cat('bbb.out', 'bbb.in') +env.Cat('ccc.out', 'ccc.in') +env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) +""") + +test.write('test/src/aaa.in', "test/src/aaa.in\n") +test.write('test/src/bbb.in', "test/src/bbb.in\n") +test.write('test/src/ccc.in', "test/src/ccc.in\n") + +test.write('test/alt/aaa.in', "test/alt/aaa.in\n") +test.write('test/alt/bbb.in', "test/alt/bbb.in\n") +test.write('test/alt/ccc.in', "test/alt/ccc.in\n") + +test.run(chdir='test', arguments = '. ../build') + +all_src = "test/src/aaa.in\ntest/src/bbb.in\ntest/src/ccc.in\n" +all_alt = "test/alt/aaa.in\ntest/alt/bbb.in\ntest/alt/ccc.in\n" + +test.must_match(all1, all_src) +test.must_match(all2, all_src) +test.must_match(all3, all_src) +#XXX We can't support var4 and var5 yet, because our BuildDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX test.must_match(all4, all_alt) +#XXX test.must_match(all5, all_alt) +test.must_match(all6, all_src) +test.must_match(all7, all_src) +test.must_match(all8, all_src) +test.must_match(all9, all_src) + +import os +import stat +def equal_stats(x,y): + x = os.stat(x) + y = os.stat(y) + return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and + x[stat.ST_MTIME] == y[stat.ST_MTIME]) + +# Make sure we did duplicate the source files in build/var1, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('test', 'build', 'var1', file)) + test.fail_test(not equal_stats(test.workpath('test', 'build', 'var1', file), + test.workpath('test', 'src', file))) + +# Make sure we did duplicate the source files in build/var2, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('test', 'build', 'var2', file)) + test.fail_test(not equal_stats(test.workpath('test', 'build', 'var2', file), + test.workpath('test', 'src', file))) + +# Make sure we didn't duplicate the source files in build/var3. +test.must_not_exist(test.workpath('test', 'build', 'var3', 'aaa.in')) +test.must_not_exist(test.workpath('test', 'build', 'var3', 'bbb.in')) +test.must_not_exist(test.workpath('test', 'build', 'var3', 'ccc.in')) + +#XXX We can't support var4 and var5 yet, because our BuildDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX Make sure we didn't duplicate the source files in build/var4. +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'aaa.in')) +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'bbb.in')) +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'ccc.in')) + +#XXX We can't support var4 and var5 yet, because our BuildDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX Make sure we did duplicate the source files in build/var5, +#XXX and that their stats are the same: +#XXXfor file in ['aaa.in', 'bbb.in', 'ccc.in']: +#XXX test.must_exist(test.workpath('build', 'var5', file)) +#XXX test.fail_test(not equal_stats(test.workpath('build', 'var5', file), +#XXX test.workpath('test', 'src', file))) + +# Make sure we did duplicate the source files in build/var6, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('build', 'var6', file)) + test.fail_test(not equal_stats(test.workpath('build', 'var6', file), + test.workpath('test', 'src', file))) + +# Make sure we didn't duplicate the source files in build/var7. +test.must_not_exist(test.workpath('build', 'var7', 'aaa.in')) +test.must_not_exist(test.workpath('build', 'var7', 'bbb.in')) +test.must_not_exist(test.workpath('build', 'var7', 'ccc.in')) + +# Make sure we didn't duplicate the source files in build/var8. +test.must_not_exist(test.workpath('build', 'var8', 'aaa.in')) +test.must_not_exist(test.workpath('build', 'var8', 'bbb.in')) +test.must_not_exist(test.workpath('build', 'var8', 'ccc.in')) + +################### +test.subdir('test2') + +test.write(['test2', 'SConstruct'], """\ +SConscript('SConscript', build_dir='Build', src_dir='.', duplicate=0) +""") + +test.write(['test2', 'SConscript'], """\ +env = Environment() +foo_obj = env.Object('foo.c') +env.Program('foo', [foo_obj, 'bar.c']) +""") + +test.write(['test2', 'bar.c'], r""" +void +bar(void) { + printf("bar.c\n"); +} +""") + +test.write(['test2', 'foo.c'], r""" +int +main(int argc, char *argv[]) { + bar(); + printf("foo.c\n"); +} +""") + +test.run(chdir="test2") + +_obj = TestSCons._obj + +test.must_not_exist(test.workpath('test2', 'foo' + _obj)) +test.must_not_exist(test.workpath('test2', 'bar' + _obj)) +test.must_exist(test.workpath('test2', 'Build', 'foo' + _obj)) +test.must_exist(test.workpath('test2', 'Build', 'bar' + _obj)) + +################### +# Make sure that directories for subsidiary SConscript() calls +# in a build_dir get created if they don't already exist. +test.subdir('test3') + +test.subdir(['test3', 'src'], ['test3', 'src', '_glscry']) + +test.write(['test3', 'SConstruct'], """\ +SConscript(dirs=['src'], build_dir='build', duplicate=0) +""") + +test.write(['test3', 'src', 'SConscript'], """\ +SConscript(dirs=['_glscry']) +""") + +test.write(['test3', 'src', '_glscry', 'SConscript'], """\ +""") + +test.write(['test3', 'src', 'file.in'], "file.in\n") + +test.write(['test3', 'src', '_glscry', 'file.in'], "file.in\n") + +test.run(chdir='test3') + + +test.pass_test() diff --git a/test/BuildDir/errors.py b/test/BuildDir/errors.py new file mode 100644 index 0000000..93cd3ec --- /dev/null +++ b/test/BuildDir/errors.py @@ -0,0 +1,171 @@ +#!/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 successful handling of errors when duplicating things in +BuildDirs. This is generally when the BuildDir, or something in it, +is read-only. +""" + +import os +import os.path +import stat +import sys +import TestSCons + +test = TestSCons.TestSCons() + +for dir in ['normal', 'ro-dir', 'ro-SConscript', 'ro-src']: + test.subdir(dir, [dir, 'src']) + + test.write([dir, 'SConstruct'], """\ +import os.path +BuildDir('build', 'src') +SConscript(os.path.join('build', 'SConscript')) +""") + + test.write([dir, 'src', 'SConscript'], """\ +def fake_scan(node, env, target): + # We fetch the contents here, even though we don't examine + # them, because get_contents() will cause the engine to + # try to link the source file into the build directory, + # potentially triggering a different failure case. + contents = node.get_contents() + return [] + +def cat(env, source, target): + target = str(target[0]) + source = map(str, source) + f = open(target, "wb") + for src in source: + f.write(open(src, "rb").read()) + f.close() + +env = Environment(BUILDERS={'Build':Builder(action=cat)}, + SCANNERS=[Scanner(fake_scan, skeys = ['.in'])]) + +# 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') +""") + + test.write([dir, 'src', 'file.in'], dir + "/src/file.in\n") + +# Just verify that the normal case works fine. +test.run(chdir = 'normal', arguments = ".") + +test.fail_test(test.read(['normal', 'build', 'file.out']) != "normal/src/file.in\n") + +# Verify the error when the BuildDir itself is read-only. Don't bother +# to test this on Win32, because the ACL (I think) still allows the +# owner to create files in the directory even when it's read-only. +if sys.platform != 'win32': + dir = os.path.join('ro-dir', 'build') + test.subdir(dir) + os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) + + test.run(chdir = 'ro-dir', + arguments = ".", + status = 2, + stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) + +# Verify the error when the SConscript file within the BuildDir is +# read-only. Note that we have to make the directory read-only too, +# because otherwise our duplication logic will be able to unlink +# the read-only SConscript and duplicate the new one. +dir = os.path.join('ro-SConscript', 'build') +test.subdir(dir) +SConscript = test.workpath(dir, 'SConscript') +test.write(SConscript, '') +os.chmod(SConscript, os.stat(SConscript)[stat.ST_MODE] & ~stat.S_IWUSR) +f = open(SConscript, 'r') +os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) + +test.run(chdir = 'ro-SConscript', + arguments = ".", + status = 2, + stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) + +os.chmod('ro-SConscript', os.stat('ro-SConscript')[stat.ST_MODE] | stat.S_IWUSR) +f.close() + +test.run(chdir = 'ro-SConscript', + arguments = ".", + status = 2, + stderr = "scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop.\n" % os.path.join('src', 'SConscript')) + +# Verify the error when the source file within the BuildDir is +# read-only. Note that we have to make the directory read-only too, +# because otherwise our duplication logic will be able to unlink the +# read-only source file and duplicate the new one. But because we've +# made the BuildDir read-only, we must also create a writable SConscript +# file there so it can be duplicated from the source directory. +dir = os.path.join('ro-src', 'build') +test.subdir(dir) +test.write([dir, 'SConscript'], '') +file_in = test.workpath(dir, 'file.in') +test.write(file_in, '') +os.chmod(file_in, os.stat(file_in)[stat.ST_MODE] & ~stat.S_IWUSR) +f = open(file_in, 'r') +os.chmod(dir, os.stat(dir)[stat.ST_MODE] & ~stat.S_IWUSR) + +test.run(chdir = 'ro-src', + arguments = ".", + status = 2, + stderr = """\ +scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop. +""" % (os.path.join('src', 'file.in'))) + +test.run(chdir = 'ro-src', + arguments = "-k .", + status = 2, + stderr = """\ +scons: *** Cannot duplicate `%s' in `build': Permission denied. Stop. +""" % (os.path.join('src', 'file.in'))) + +f.close() + +# ensure that specifying multiple source directories for one +# build directory results in an error message, rather +# than just silently failing. +test.subdir('duplicate', ['duplicate', 'src1'], ['duplicate', 'src2']) +test.write(['duplicate', 'SConstruct'], """\ +BuildDir('build', 'src1') +BuildDir('build', 'src2') +""") + +test.run(chdir = 'duplicate', + arguments = ".", + status = 2, + stderr = """ +scons: *** 'build' already has a source directory: 'src1'. +File "SConstruct", line 2, in ? +""") + +test.pass_test() diff --git a/test/BuildDir/reflect.py b/test/BuildDir/reflect.py new file mode 100644 index 0000000..beb7df0 --- /dev/null +++ b/test/BuildDir/reflect.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +This test validates the correct operation of a BuildDir specification +in avoiding reflection: reflection is the case where the build_dir is +located under the corresponding source dir, and trying to use elements +in the build_dir as sources for that same build dir. + +Test based on bug #1055521 filed by Gary Oberbrunner. +""" + +import os.path +import re + +import TestSCons + +test = TestSCons.TestSCons() +python = TestSCons.python +re_python = re.escape(python) + +test.write("mycc.py", """ +print 'Compile' +""") + +test.write("mylink.py", """ +print 'Link' +""") + +sconstruct = """ +env = Environment(CC = r'%(python)s mycc.py', + LINK = r'%(python)s mylink.py', + INCPREFIX = 'INC_', + INCSUFFIX = '_CNI', + CPPPATH='%(cpppath)s') # note no leading '#' +Export("env") +SConscript('SConscript', build_dir="dir1/dir2", src_dir=".") +""" + +test.write('SConscript', """\ +Import("env") +env.Program("foo", "src1/foo.c") +Default(".") +""") + +test.write('foo.h', '#define HI_STR "hello, there!"\n') + +test.subdir('src1') + +test.write(['src1', 'foo.c'], """\ +#include +#include "foo.h" +main() { printf(HI_STR);} +""") + +# Test the bad cpppath; make sure it doesn't reflect dir1/dir2/foo.h +# into dir1/dir2/dir1/dir2/foo.h, and make sure the target/message for +# builds is correct. + +cpppath = 'dir1/dir2' # note, no leading '#' +test.write('SConstruct', sconstruct % locals() ) + +targets = re.escape(os.path.join('dir1', 'dir2')) +INC_CNI = re.escape(os.path.join('INC_dir1', 'dir2', 'dir1', 'dir2_CNI')) + +# The .* after mycc\\.py below handles /nologo flags from Visual C/C++. +test.run(arguments = '', + stdout=test.wrap_stdout("""\ +scons: building associated BuildDir targets: %(targets)s +%(re_python)s mycc\\.py.* %(INC_CNI)s .+ +Compile +%(re_python)s mylink\\.py .+ +Link +""" % locals()), + match=TestSCons.match_re, + ) + +# Note that we don't check for the existence of dir1/dir2/foo.h, because +# this bad cpppath will expand to dir1/dir2/dir1/dir2, which means it +# won't pick up the srcdir copy of dir/dir2/foo.h. That's all right, +# we just need to make sure it doesn't create dir1/dir2/dir1/dir2/foo.h. +test.must_exist(['dir1', 'dir2', 'src1', 'foo.c']) +test.must_not_exist(['dir1', 'dir2', 'dir1', 'dir2', 'foo.h']) + +import shutil +shutil.rmtree('dir1', ignore_errors=1) +test.must_not_exist('dir1') + +# Now test the good cpppath and make sure everything looks right. + +cpppath = '#dir1/dir2' # note leading '#' +test.write('SConstruct', sconstruct % locals() ) + +INC_CNI = re.escape(os.path.join('INC_dir1', 'dir2_CNI')) + +# The .* after mycc\\.py below handles /nologo flags from Visual C/C++. +test.run(arguments = '', + stdout=test.wrap_stdout("""\ +scons: building associated BuildDir targets: %(targets)s +%(re_python)s mycc\\.py.* %(INC_CNI)s .+ +Compile +%(re_python)s mylink\\.py .+ +Link +""" % locals()), + match=TestSCons.match_re, + ) + +test.must_exist(['dir1', 'dir2', 'foo.h']) +test.must_exist(['dir1', 'dir2', 'src1', 'foo.c']) +test.must_not_exist(['dir1', 'dir2', 'dir1', 'dir2', 'foo.h']) + + +test.pass_test() diff --git a/test/SConscript-build_dir.py b/test/SConscript-build_dir.py deleted file mode 100644 index 298eb9b..0000000 --- a/test/SConscript-build_dir.py +++ /dev/null @@ -1,263 +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__" - -""" -Verify that specifying a build_dir argument to SConscript works properly. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -all1 = test.workpath('test', 'build', 'var1', 'all') -all2 = test.workpath('test', 'build', 'var2', 'all') -all3 = test.workpath('test', 'build', 'var3', 'all') -all4 = test.workpath('test', 'build', 'var4', 'all') -all5 = test.workpath('build', 'var5', 'all') -all6 = test.workpath('build', 'var6', 'all') -all7 = test.workpath('build', 'var7', 'all') -all8 = test.workpath('build', 'var8', 'all') -all9 = test.workpath('test', 'build', 'var9', 'src', 'all') - -test.subdir('test') - -test.write(['test', 'SConstruct'], """ -src = Dir('src') -alt = Dir('alt') -var1 = Dir('build/var1') -var2 = Dir('build/var2') -var3 = Dir('build/var3') -var4 = Dir('build/var4') -var5 = Dir('../build/var5') -var6 = Dir('../build/var6') -var7 = Dir('../build/var7') -var8 = Dir('../build/var8') -var9 = Dir('../build/var9') - -def cat(env, source, target): - target = str(target[0]) - source = map(str, source) - f = open(target, "wb") - for src in source: - f.write(open(src, "rb").read()) - f.close() - -env = Environment(BUILDERS={'Cat':Builder(action=cat)}, - BUILD='build') - -Export("env") - -SConscript('src/SConscript', build_dir=var1) -SConscript('src/SConscript', build_dir='build/var2', src_dir=src) - -SConscript('src/SConscript', build_dir='build/var3', duplicate=0) - -#XXX We can't support var4 and var5 yet, because our BuildDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX SConscript('src/SConscript', build_dir=var4, src_dir=alt, duplicate=0) - -#XXX SConscript('src/SConscript', build_dir='../build/var5', src_dir='alt') -SConscript('src/SConscript', build_dir=var6) - -SConscript('src/SConscript', build_dir=var7, src_dir=src, duplicate=0) -env.SConscript('src/SConscript', build_dir='../$BUILD/var8', duplicate=0) - -# This tests the fact that if you specify a src_dir that is above -# the dir a SConscript is in, that we do the intuitive thing, i.e., -# we set the path of the SConscript accordingly. The below is -# equivalent to saying: -# -# BuildDir('build/var9', '.') -# SConscript('build/var9/src/SConscript') -SConscript('src/SConscript', build_dir='build/var9', src_dir='.') -""") - -test.subdir(['test', 'src'], ['test', 'alt']) - -test.write(['test', 'src', 'SConscript'], """ -Import("env") -env.Cat('aaa.out', 'aaa.in') -env.Cat('bbb.out', 'bbb.in') -env.Cat('ccc.out', 'ccc.in') -env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) -""") - -test.write('test/src/aaa.in', "test/src/aaa.in\n") -test.write('test/src/bbb.in', "test/src/bbb.in\n") -test.write('test/src/ccc.in', "test/src/ccc.in\n") - -test.write('test/alt/aaa.in', "test/alt/aaa.in\n") -test.write('test/alt/bbb.in', "test/alt/bbb.in\n") -test.write('test/alt/ccc.in', "test/alt/ccc.in\n") - -test.run(chdir='test', arguments = '. ../build') - -all_src = "test/src/aaa.in\ntest/src/bbb.in\ntest/src/ccc.in\n" -all_alt = "test/alt/aaa.in\ntest/alt/bbb.in\ntest/alt/ccc.in\n" - -test.must_match(all1, all_src) -test.must_match(all2, all_src) -test.must_match(all3, all_src) -#XXX We can't support var4 and var5 yet, because our BuildDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX test.must_match(all4, all_alt) -#XXX test.must_match(all5, all_alt) -test.must_match(all6, all_src) -test.must_match(all7, all_src) -test.must_match(all8, all_src) -test.must_match(all9, all_src) - -import os -import stat -def equal_stats(x,y): - x = os.stat(x) - y = os.stat(y) - return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and - x[stat.ST_MTIME] == y[stat.ST_MTIME]) - -# Make sure we did duplicate the source files in build/var1, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('test', 'build', 'var1', file)) - test.fail_test(not equal_stats(test.workpath('test', 'build', 'var1', file), - test.workpath('test', 'src', file))) - -# Make sure we did duplicate the source files in build/var2, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('test', 'build', 'var2', file)) - test.fail_test(not equal_stats(test.workpath('test', 'build', 'var2', file), - test.workpath('test', 'src', file))) - -# Make sure we didn't duplicate the source files in build/var3. -test.must_not_exist(test.workpath('test', 'build', 'var3', 'aaa.in')) -test.must_not_exist(test.workpath('test', 'build', 'var3', 'bbb.in')) -test.must_not_exist(test.workpath('test', 'build', 'var3', 'ccc.in')) - -#XXX We can't support var4 and var5 yet, because our BuildDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX Make sure we didn't duplicate the source files in build/var4. -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'aaa.in')) -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'bbb.in')) -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'ccc.in')) - -#XXX We can't support var4 and var5 yet, because our BuildDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX Make sure we did duplicate the source files in build/var5, -#XXX and that their stats are the same: -#XXXfor file in ['aaa.in', 'bbb.in', 'ccc.in']: -#XXX test.must_exist(test.workpath('build', 'var5', file)) -#XXX test.fail_test(not equal_stats(test.workpath('build', 'var5', file), -#XXX test.workpath('test', 'src', file))) - -# Make sure we did duplicate the source files in build/var6, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('build', 'var6', file)) - test.fail_test(not equal_stats(test.workpath('build', 'var6', file), - test.workpath('test', 'src', file))) - -# Make sure we didn't duplicate the source files in build/var7. -test.must_not_exist(test.workpath('build', 'var7', 'aaa.in')) -test.must_not_exist(test.workpath('build', 'var7', 'bbb.in')) -test.must_not_exist(test.workpath('build', 'var7', 'ccc.in')) - -# Make sure we didn't duplicate the source files in build/var8. -test.must_not_exist(test.workpath('build', 'var8', 'aaa.in')) -test.must_not_exist(test.workpath('build', 'var8', 'bbb.in')) -test.must_not_exist(test.workpath('build', 'var8', 'ccc.in')) - -################### -test.subdir('test2') - -test.write(['test2', 'SConstruct'], """\ -SConscript('SConscript', build_dir='Build', src_dir='.', duplicate=0) -""") - -test.write(['test2', 'SConscript'], """\ -env = Environment() -foo_obj = env.Object('foo.c') -env.Program('foo', [foo_obj, 'bar.c']) -""") - -test.write(['test2', 'bar.c'], r""" -void -bar(void) { - printf("bar.c\n"); -} -""") - -test.write(['test2', 'foo.c'], r""" -int -main(int argc, char *argv[]) { - bar(); - printf("foo.c\n"); -} -""") - -test.run(chdir="test2") - -_obj = TestSCons._obj - -test.must_not_exist(test.workpath('test2', 'foo' + _obj)) -test.must_not_exist(test.workpath('test2', 'bar' + _obj)) -test.must_exist(test.workpath('test2', 'Build', 'foo' + _obj)) -test.must_exist(test.workpath('test2', 'Build', 'bar' + _obj)) - -################### -# Make sure that directories for subsidiary SConscript() calls -# in a build_dir get created if they don't already exist. -test.subdir('test3') - -test.subdir(['test3', 'src'], ['test3', 'src', '_glscry']) - -test.write(['test3', 'SConstruct'], """\ -SConscript(dirs=['src'], build_dir='build', duplicate=0) -""") - -test.write(['test3', 'src', 'SConscript'], """\ -SConscript(dirs=['_glscry']) -""") - -test.write(['test3', 'src', '_glscry', 'SConscript'], """\ -""") - -test.write(['test3', 'src', 'file.in'], "file.in\n") - -test.write(['test3', 'src', '_glscry', 'file.in'], "file.in\n") - -test.run(chdir='test3') - - -test.pass_test() diff --git a/test/builddir-reflect.py b/test/builddir-reflect.py deleted file mode 100644 index beb7df0..0000000 --- a/test/builddir-reflect.py +++ /dev/null @@ -1,136 +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__" - -""" -This test validates the correct operation of a BuildDir specification -in avoiding reflection: reflection is the case where the build_dir is -located under the corresponding source dir, and trying to use elements -in the build_dir as sources for that same build dir. - -Test based on bug #1055521 filed by Gary Oberbrunner. -""" - -import os.path -import re - -import TestSCons - -test = TestSCons.TestSCons() -python = TestSCons.python -re_python = re.escape(python) - -test.write("mycc.py", """ -print 'Compile' -""") - -test.write("mylink.py", """ -print 'Link' -""") - -sconstruct = """ -env = Environment(CC = r'%(python)s mycc.py', - LINK = r'%(python)s mylink.py', - INCPREFIX = 'INC_', - INCSUFFIX = '_CNI', - CPPPATH='%(cpppath)s') # note no leading '#' -Export("env") -SConscript('SConscript', build_dir="dir1/dir2", src_dir=".") -""" - -test.write('SConscript', """\ -Import("env") -env.Program("foo", "src1/foo.c") -Default(".") -""") - -test.write('foo.h', '#define HI_STR "hello, there!"\n') - -test.subdir('src1') - -test.write(['src1', 'foo.c'], """\ -#include -#include "foo.h" -main() { printf(HI_STR);} -""") - -# Test the bad cpppath; make sure it doesn't reflect dir1/dir2/foo.h -# into dir1/dir2/dir1/dir2/foo.h, and make sure the target/message for -# builds is correct. - -cpppath = 'dir1/dir2' # note, no leading '#' -test.write('SConstruct', sconstruct % locals() ) - -targets = re.escape(os.path.join('dir1', 'dir2')) -INC_CNI = re.escape(os.path.join('INC_dir1', 'dir2', 'dir1', 'dir2_CNI')) - -# The .* after mycc\\.py below handles /nologo flags from Visual C/C++. -test.run(arguments = '', - stdout=test.wrap_stdout("""\ -scons: building associated BuildDir targets: %(targets)s -%(re_python)s mycc\\.py.* %(INC_CNI)s .+ -Compile -%(re_python)s mylink\\.py .+ -Link -""" % locals()), - match=TestSCons.match_re, - ) - -# Note that we don't check for the existence of dir1/dir2/foo.h, because -# this bad cpppath will expand to dir1/dir2/dir1/dir2, which means it -# won't pick up the srcdir copy of dir/dir2/foo.h. That's all right, -# we just need to make sure it doesn't create dir1/dir2/dir1/dir2/foo.h. -test.must_exist(['dir1', 'dir2', 'src1', 'foo.c']) -test.must_not_exist(['dir1', 'dir2', 'dir1', 'dir2', 'foo.h']) - -import shutil -shutil.rmtree('dir1', ignore_errors=1) -test.must_not_exist('dir1') - -# Now test the good cpppath and make sure everything looks right. - -cpppath = '#dir1/dir2' # note leading '#' -test.write('SConstruct', sconstruct % locals() ) - -INC_CNI = re.escape(os.path.join('INC_dir1', 'dir2_CNI')) - -# The .* after mycc\\.py below handles /nologo flags from Visual C/C++. -test.run(arguments = '', - stdout=test.wrap_stdout("""\ -scons: building associated BuildDir targets: %(targets)s -%(re_python)s mycc\\.py.* %(INC_CNI)s .+ -Compile -%(re_python)s mylink\\.py .+ -Link -""" % locals()), - match=TestSCons.match_re, - ) - -test.must_exist(['dir1', 'dir2', 'foo.h']) -test.must_exist(['dir1', 'dir2', 'src1', 'foo.c']) -test.must_not_exist(['dir1', 'dir2', 'dir1', 'dir2', 'foo.h']) - - -test.pass_test() -- cgit v0.12