From 730081593efc2ac5c17def1650ad0b39c4d0e72a Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 7 May 2005 19:19:41 +0000 Subject: Make SConsignFile() behavior the default. --- doc/man/scons.1 | 33 ++- src/CHANGES.txt | 5 + src/RELEASE.txt | 28 +- src/engine/SCons/Environment.py | 7 +- src/engine/SCons/EnvironmentTests.py | 4 + src/engine/SCons/Node/FS.py | 14 + src/engine/SCons/SConfTests.py | 27 +- src/engine/SCons/SConsign.py | 110 ++++++-- src/engine/SCons/SConsignTests.py | 89 +++--- src/engine/SCons/dblite.py | 5 +- test/Configure.py | 1 + test/Repository/SConsignFile.py | 61 ++++ test/old-sconsign.py | 192 ------------- test/option-n.py | 2 +- test/sconsign-script.py | 519 ---------------------------------- test/sconsign.py | 99 ------- test/sconsign/corrupt.py | 100 +++++++ test/sconsign/nonwritable.py | 104 +++++++ test/sconsign/old.py | 197 +++++++++++++ test/sconsign/script.py | 520 +++++++++++++++++++++++++++++++++++ test/subdivide.py | 7 +- 21 files changed, 1237 insertions(+), 887 deletions(-) create mode 100644 test/Repository/SConsignFile.py delete mode 100644 test/old-sconsign.py delete mode 100644 test/sconsign-script.py delete mode 100644 test/sconsign.py create mode 100644 test/sconsign/corrupt.py create mode 100644 test/sconsign/nonwritable.py create mode 100644 test/sconsign/old.py create mode 100644 test/sconsign/script.py diff --git a/doc/man/scons.1 b/doc/man/scons.1 index cb1334b..33c7a19 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -3983,13 +3983,17 @@ SConscript('bar/SConscript') # will chdir to bar This tells .B scons to store all file signatures -in the specified +in the specified database .IR file . If the .I file -is omitted, -.B .sconsign.dbm +name is omitted, +.B .sconsign is used by default. +(The actual file name(s) stored on disk +may have an appropriated suffix appended +by the +.IR dbm_module .) If .I file is not an absolute path name, @@ -3997,6 +4001,20 @@ the file is placed in the same directory as the top-level .B SConstruct file. +If +.I file +is +.BR None , +then +.B scons +will store file signatures +in a separate +.B .sconsign +file in each directory, +not in one global database file. +(This was the default behavior +prior to SCons 0.96.91 and 0.97.) + The optional .I dbm_module argument can be used to specify @@ -4010,8 +4028,9 @@ and which works on all Python versions from 1.5.2 on. Examples: .ES -# Stores signatures in ".sconsign.dbm" -# in the top-level SConstruct directory. +# Explicitly stores signatures in ".sconsign.dblite" +# in the top-level SConstruct directory (the +# default behavior). SConsignFile() # Stores signatures in the file "etc/scons-signatures" @@ -4020,6 +4039,10 @@ SConsignFile("etc/scons-signatures") # Stores signatures in the specified absolute file name. SConsignFile("/home/me/SCons/signatures") + +# Stores signatures in a separate .sconsign file +# in each directory. +SConsignFile(None) .EE '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/src/CHANGES.txt b/src/CHANGES.txt index cfd7097..5513057 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -266,6 +266,11 @@ RELEASE 0.97 - XXX that accomodate parser generators that write header files to a different suffix than the hard-coded .hpp when the -d option is used. + - The default behavior is now to store signature information in a + single .sconsign.dblite file in the top-level SConstruct directory. + The old behavior of a separate .sconsign file in each directory can + be specified by calling SConsignFile(None). + From Wayne Lee: - Avoid "maximum recursion limit" errors when removing $(-$) pairs diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 9c09e60..47b0031 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -58,7 +58,33 @@ RELEASE 0.97 - XXX or /usr/local was passed as the source to a Builder or Command() call, in which case SCons would scan the entire directory tree. - -- SIGNATURE CHANGES WILL CAUSE LIKELY REBUILDS AFTER UPGRADE + -- SIGNATURES ARE NOW STORED IN AN SConsignFile() BY DEFAULT, + CAUSING LIKELY REBUILDS; SPECIAL NOTE CONCERNING INTERACTION + WITH REPOSITORIES + + The default behavior has been changed to store signature + information in a single .sconsign.dblite file in the top-level + SConstruct file. This will cause rebuilds on upgrade to 0.97, + unless you were already calling the SConsignFile() function in + your SConscript files. + + The previous default behavior was to store signature information + in a .sconsign file in each directory that contained target + files that SCons knew about. The old behavior may be preserved + by specifying: + + SConsignFile(None) + + in any SConscript file. + + If you are using the Repository feature, are not already using + the SConsignFile() function in your build, you *must* add + SConsignFile(None) to your build to keep interoperating with an + existing Repository that uses the old behavior of a .sconsign + file in each directory. Alternatively, you can rebuild the + Repository with the new default behavior. + + -- OTHER SIGNATURE CHANGES WILL CAUSE LIKELY REBUILDS AFTER UPGRADE This release adds several changes to the signature mechanism that will cause SCons to rebuild most configurations after upgrading diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index b813cf1..58440d6 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1367,9 +1367,10 @@ class Base(SubstitutionEnvironment): return apply(SCons.Scanner.Scanner, nargs, nkw) def SConsignFile(self, name=".sconsign", dbm_module=None): - name = self.subst(name) - if not os.path.isabs(name): - name = os.path.join(str(self.fs.SConstruct_dir), name) + if not name is None: + name = self.subst(name) + if not os.path.isabs(name): + name = os.path.join(str(self.fs.SConstruct_dir), name) SCons.SConsign.File(name, dbm_module) def SideEffect(self, side_effect, target): diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index fcd0fee..495fab0 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -2568,6 +2568,10 @@ def generate(env): env.SConsignFile() assert fnames[5] == os.path.join(os.sep, 'dir', '.sconsign'), fnames assert dbms[5] == None, dbms + + env.SConsignFile(None) + assert fnames[6] == None, fnames + assert dbms[6] == None, dbms finally: SCons.SConsign.File = save_SConsign_File diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 75efc15..9d7086c 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -422,6 +422,10 @@ class Base(SCons.Node.Node): self.path = name else: self.path = directory.entry_path(name) + if directory.tpath == '.': + self.tpath = name + else: + self.tpath = directory.entry_tpath(name) self.path_elements = directory.path_elements + [self] self.dir = directory @@ -732,6 +736,7 @@ class FS(LocalFS): self.Top = self._doLookup(Dir, os.path.normpath(self.pathTop)) self.Top.path = '.' + self.Top.tpath = '.' self._cwd = self.Top def clear_cache(self): @@ -1102,6 +1107,7 @@ class Dir(Base): def addRepository(self, dir): if dir != self and not dir in self.repositories: self.repositories.append(dir) + dir.tpath = '.' self.__clearRepositoryCache() def up(self): @@ -1284,6 +1290,9 @@ class Dir(Base): def entry_path(self, name): return self.path + os.sep + name + def entry_tpath(self, name): + return self.tpath + os.sep + name + def must_be_a_Dir(self): """Called to make sure a Node is a Dir. Since we're already one, this is a no-op for us.""" @@ -1389,6 +1398,7 @@ class RootDir(Dir): # won't gag won't it calls some of our methods. self.abspath = '' self.path = '' + self.tpath = '' self.path_elements = [] self.duplicate = 0 Base.__init__(self, name, self, fs) @@ -1397,6 +1407,7 @@ class RootDir(Dir): # initial drive letter (the name) plus the directory separator. self.abspath = name + os.sep self.path = name + os.sep + self.tpath = name + os.sep self._morph() def __str__(self): @@ -1408,6 +1419,9 @@ class RootDir(Dir): def entry_path(self, name): return self.path + name + def entry_tpath(self, name): + return self.tpath + name + def is_under(self, dir): if self is dir: return 1 diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index a5e0700..2685c2b 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -44,10 +44,15 @@ class SConfTestCase(unittest.TestCase): def setUp(self): # we always want to start with a clean directory + self.save_cwd = os.getcwd() self.test = TestCmd.TestCmd(workdir = '') + os.chdir(self.test.workpath('')) def tearDown(self): self.test.cleanup() + import SCons.SConsign + SCons.SConsign.Reset() + os.chdir(self.save_cwd) def _resetSConfState(self): # Ok, this is tricky, and i do not know, if everything is sane. @@ -104,7 +109,7 @@ class SConfTestCase(unittest.TestCase): log_file=self.test.workpath('config.log')) try: res = checks( self, sconf, TryFunc ) - assert res[0] and not res[1] + assert res[0] and not res[1], res finally: sconf.Finish() @@ -115,7 +120,7 @@ class SConfTestCase(unittest.TestCase): log_file=self.test.workpath('config.log')) try: res = checks( self, sconf, TryFunc ) - assert res[0] and not res[1] + assert res[0] and not res[1], res finally: sconf.Finish() # we should have exactly one one error cached @@ -136,7 +141,7 @@ class SConfTestCase(unittest.TestCase): try: res = checks( self, sconf, TryFunc ) log = self.test.read( self.test.workpath('config.log') ) - assert res[0] and res[1] + assert res[0] and res[1], res finally: sconf.Finish() @@ -231,8 +236,8 @@ int main() { log_file=self.test.workpath('config.log')) try: res = checks(sconf) - assert res[0][0] and res[0][1] == "Hello" - assert not res[1][0] and res[1][1] == "" + assert res[0][0] and res[0][1] == "Hello", res + assert not res[1][0] and res[1][1] == "", res finally: sconf.Finish() log = self.test.read( self.test.workpath('config.log') ) @@ -244,8 +249,8 @@ int main() { log_file=self.test.workpath('config.log')) try: res = checks(sconf) - assert res[0][0] and res[0][1] == "Hello" - assert not res[1][0] and res[1][1] == "" + assert res[0][0] and res[0][1] == "Hello", res + assert not res[1][0] and res[1][1] == "", res finally: sconf.Finish() # we should have exactly one error cached @@ -271,9 +276,9 @@ int main() { log_file=self.test.workpath('config.log')) try: (ret, output) = sconf.TryAction(action=actionOK) - assert ret and output == "RUN OK" + assert ret and output == "RUN OK", (ret, output) (ret, output) = sconf.TryAction(action=actionFAIL) - assert not ret and output == "" + assert not ret and output == "", (ret, output) finally: sconf.Finish() @@ -514,7 +519,7 @@ int main() { """ (ret, output) = test.TryRun( prog, ".c" ) test.Result( ret ) - assert ret and output == "Hello" + assert ret and output == "Hello", (ret, output) return ret @@ -525,7 +530,7 @@ int main() { log_file=self.test.workpath('config.log')) try: ret = sconf.CheckCustom() - assert ret + assert ret, ret finally: sconf.Finish() diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 212ec8d..9b5c420 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -35,15 +35,68 @@ import os.path import string import time +import SCons.dblite import SCons.Node import SCons.Sig import SCons.Warnings +from SCons.Debug import Trace + +def corrupt_dblite_warning(filename): + SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, + "Ignoring corrupt .sconsign file: %s"%filename) + +SCons.dblite.ignore_corrupt_dbfiles = 1 +SCons.dblite.corruption_warning = corrupt_dblite_warning + #XXX Get rid of the global array so this becomes re-entrant. sig_files = [] -# Handle to open database object if using the DB SConsign implementation. -database = None +# Info for the database SConsign implementation (now the default): +# "DataBase" is a dictionary that maps top-level SConstruct directories +# to open database handles. +# "DB_Module" is the Python database module to create the handles. +# "DB_Name" is the base name of the database file (minus any +# extension the underlying DB module will add). +DataBase = {} +DB_Module = SCons.dblite +DB_Name = ".sconsign" +DB_sync_list = [] + +def Get_DataBase(dir): + global DataBase, DB_Module, DB_Name + top = dir.fs.Top + if not os.path.isabs(DB_Name) and top.repositories: + mode = "c" + for d in [top] + top.repositories: + if dir.is_under(d): + try: + return DataBase[d], mode + except KeyError: + path = d.entry_abspath(DB_Name) + try: db = DataBase[d] = DB_Module.open(path, mode) + except (IOError, OSError): pass + else: + if mode != "r": + DB_sync_list.append(db) + return db, mode + mode = "r" + try: + return DataBase[top], "c" + except KeyError: + db = DataBase[top] = DB_Module.open(DB_Name, "c") + DB_sync_list.append(db) + return db, "c" + except TypeError: + print "DataBase =", DataBase + raise + +def Reset(): + """Reset global state. Used by unit tests that end up using + SConsign multiple times to get a clean slate for each test.""" + global sig_files, DB_sync_list + sig_files = [] + DB_sync_list = [] if os.sep == '/': norm_entry = lambda s: s @@ -55,9 +108,9 @@ def write(): global sig_files for sig_file in sig_files: sig_file.write(sync=0) - if database: + for db in DB_sync_list: try: - syncmethod = database.sync + syncmethod = db.sync except AttributeError: pass # Not all anydbm modules have sync() methods. else: @@ -94,19 +147,25 @@ class Base: self.entries[filename] = obj self.dirty = 1 + def do_not_set_entry(self, filename, obj): + pass + class DB(Base): """ A Base subclass that reads and writes signature information - from a global .sconsign.dbm file. + from a global .sconsign.db* file--the actual file suffix is + determined by the specified database module. """ def __init__(self, dir, module=None): Base.__init__(self, module) self.dir = dir + db, mode = Get_DataBase(dir) + + tpath = norm_entry(dir.tpath) try: - global database - rawentries = database[norm_entry(self.dir.path)] + rawentries = db[tpath] except KeyError: pass else: @@ -119,18 +178,25 @@ class DB(Base): raise except: SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt sconsign entry : %s"%self.dir.path) + "Ignoring corrupt sconsign entry : %s"%self.dir.tpath) + + if mode == "r": + # This directory is actually under a repository, which means + # likely they're reaching in directly for a dependency on + # a file there. Don't actually set any entry info, so we + # won't try to write to that .sconsign.dblite file. + self.set_entry = self.do_not_set_entry global sig_files sig_files.append(self) def write(self, sync=1): if self.dirty: - global database - database[norm_entry(self.dir.path)] = cPickle.dumps(self.entries, 1) + db, mode = Get_DataBase(self.dir) + db[norm_entry(self.dir.tpath)] = cPickle.dumps(self.entries, 1) if sync: try: - syncmethod = database.sync + syncmethod = db.sync except AttributeError: # Not all anydbm modules have sync() methods. pass @@ -223,19 +289,19 @@ class DirFile(Dir): except OSError: pass -ForDirectory = DirFile +ForDirectory = DB def File(name, dbm_module=None): """ - Arrange for all signatures to be stored in a global .sconsign.dbm + Arrange for all signatures to be stored in a global .sconsign.db* file. """ - global database - if database is None: - if dbm_module is None: - import SCons.dblite - dbm_module = SCons.dblite - database = dbm_module.open(name, "c") - - global ForDirectory - ForDirectory = DB + global ForDirectory, DB_Name, DB_Module + if name is None: + ForDirectory = DirFile + DB_Module = None + else: + ForDirectory = DB + DB_Name = name + if not dbm_module is None: + DB_Module = dbm_module diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py index c2f40bd..025ad8e 100644 --- a/src/engine/SCons/SConsignTests.py +++ b/src/engine/SCons/SConsignTests.py @@ -28,6 +28,8 @@ import sys import TestCmd import unittest +import SCons.dblite + import SCons.SConsign class BuildInfo: @@ -41,12 +43,30 @@ class DummyModule: def from_string(self, sig): return int(sig) -class BaseTestCase(unittest.TestCase): +class FS: + def __init__(self, top): + self.Top = top + self.Top.repositories = [] + +class DummyNode: + def __init__(self, path='not_a_valid_path'): + self.path = path + self.tpath = path + self.fs = FS(self) + +class SConsignTestCase(unittest.TestCase): + def setUp(self): + self.save_cwd = os.getcwd() + self.test = TestCmd.TestCmd(workdir = '') + os.chdir(self.test.workpath('')) + def tearDown(self): + self.test.cleanup() + SCons.SConsign.Reset() + os.chdir(self.save_cwd) + +class BaseTestCase(SConsignTestCase): def runTest(self): - class DummyNode: - path = 'not_a_valid_path' - aaa = BuildInfo('aaa') bbb = BuildInfo('bbb') bbb.arg1 = 'bbb arg1' @@ -96,14 +116,11 @@ class BaseTestCase(unittest.TestCase): assert e.name == 'fff', e.name assert e.arg == 'fff arg', e.arg -class SConsignDBTestCase(unittest.TestCase): +class SConsignDBTestCase(SConsignTestCase): def runTest(self): - class DummyNode: - def __init__(self, path): - self.path = path - save_database = SCons.SConsign.database - SCons.SConsign.database = {} + save_DataBase = SCons.SConsign.DataBase + SCons.SConsign.DataBase = {} try: d1 = SCons.SConsign.DB(DummyNode('dir1')) d1.set_entry('aaa', BuildInfo('aaa name')) @@ -137,14 +154,11 @@ class SConsignDBTestCase(unittest.TestCase): hhh = d32.get_entry('hhh') assert hhh.name == 'hhh name' finally: - SCons.SConsign.database = save_database + SCons.SConsign.DataBase = save_DataBase -class SConsignDirFileTestCase(unittest.TestCase): +class SConsignDirFileTestCase(SConsignTestCase): def runTest(self): - class DummyNode: - path = 'not_a_valid_path' - foo = BuildInfo('foo') bar = BuildInfo('bar') @@ -169,52 +183,65 @@ class SConsignDirFileTestCase(unittest.TestCase): assert e.arg == 'bbb arg', e.arg -class SConsignFileTestCase(unittest.TestCase): +class SConsignFileTestCase(SConsignTestCase): def runTest(self): - test = TestCmd.TestCmd(workdir = '') + test = self.test file = test.workpath('sconsign_file') - assert SCons.SConsign.database is None, SCons.SConsign.database + assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase + assert SCons.SConsign.DB_Name == ".sconsign", SCons.SConsign.DB_Name + assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module SCons.SConsign.File(file) - assert not SCons.SConsign.database is SCons.dblite, SCons.SConsign.database + assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase + assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name + assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module + + SCons.SConsign.File(None) + + assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase + assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name + assert SCons.SConsign.DB_Module is None, SCons.SConsign.DB_Module class Fake_DBM: def open(self, name, mode): self.name = name self.mode = mode return self + def __getitem__(self, key): + pass + def __setitem__(self, key, value): + pass fake_dbm = Fake_DBM() SCons.SConsign.File(file, fake_dbm) - assert not SCons.SConsign.database is None, SCons.SConsign.database + assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase + assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name + assert SCons.SConsign.DB_Module is fake_dbm, SCons.SConsign.DB_Module assert not hasattr(fake_dbm, 'name'), fake_dbm assert not hasattr(fake_dbm, 'mode'), fake_dbm - SCons.SConsign.database = None - - SCons.SConsign.File(file, fake_dbm) + SCons.SConsign.ForDirectory(DummyNode(test.workpath('dir'))) - assert not SCons.SConsign.database is None, SCons.SConsign.database + assert not SCons.SConsign.DataBase is None, SCons.SConsign.DataBase assert fake_dbm.name == file, fake_dbm.name assert fake_dbm.mode == "c", fake_dbm.mode -class writeTestCase(unittest.TestCase): +class writeTestCase(SConsignTestCase): def runTest(self): - class DummyNode: - path = 'not_a_valid_path' - - test = TestCmd.TestCmd(workdir = '') + test = self.test file = test.workpath('sconsign_file') class Fake_DBM: + def __getitem__(self, key): + return None def __setitem__(self, key, value): pass def open(self, name, mode): @@ -225,10 +252,10 @@ class writeTestCase(unittest.TestCase): fake_dbm = Fake_DBM() - SCons.SConsign.database = None + SCons.SConsign.DataBase = {} SCons.SConsign.File(file, fake_dbm) - f = SCons.SConsign.DirFile(DummyNode(), DummyModule()) + f = SCons.SConsign.DB(DummyNode(), DummyModule()) f.set_entry('foo', BuildInfo('foo')) f.set_entry('bar', BuildInfo('bar')) diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 00f8274..637e503 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -14,6 +14,9 @@ _open = __builtin__.open # avoid name clash keep_all_files = 00000 ignore_corrupt_dbfiles = 0 +def corruption_warning(filename): + print "Warning: Discarding corrupt database:", filename + if hasattr(types, 'UnicodeType'): def is_string(s): t = type(s) @@ -64,7 +67,7 @@ class dblite: except cPickle.UnpicklingError: if (ignore_corrupt_dbfiles == 0): raise if (ignore_corrupt_dbfiles == 1): - print "Warning: Discarding corrupt database:", self._file_name + corruption_warning(self._file_name) def __del__(self): if (self._needs_sync): diff --git a/test/Configure.py b/test/Configure.py index 515ae70..83155bb 100644 --- a/test/Configure.py +++ b/test/Configure.py @@ -509,6 +509,7 @@ int main() { os.path.join("build", "sub", "SConscript")) shutil.rmtree(test.workpath(work_dir, ".sconf_temp")) + os.unlink(test.workpath(work_dir, ".sconsign.dblite")) # now with SConscriptChdir(1) test.run(chdir=work_dir, arguments='chdir=yes') diff --git a/test/Repository/SConsignFile.py b/test/Repository/SConsignFile.py new file mode 100644 index 0000000..9643cb8 --- /dev/null +++ b/test/Repository/SConsignFile.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the Repository option works when recording signature +information in an SConsignFile(). +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('repository', 'work') + +SConstruct_contents = """\ +SConsignFile('sconsignfile') +env = Environment() +result = env.Command('file.out', 'file.in', Copy("$TARGET", "$SOURCE")) +Default(result) +""" + +test.write(['repository', 'SConstruct'], SConstruct_contents) + +test.write(['repository', 'file.in'], "repository/file.in\n") + +test.run(chdir='repository') + +test.must_match(['repository', 'file.out'], "repository/file.in\n") + +test.write(['work', 'SConstruct'], SConstruct_contents) + +test.run(chdir='work', + arguments='-Y ../repository -n --debug=explain', + stdout=test.wrap_stdout("scons: `file.out' is up to date.\n")) + +test.must_not_exist(['work', 'file.out']) + +test.pass_test() diff --git a/test/old-sconsign.py b/test/old-sconsign.py deleted file mode 100644 index 6c057dd..0000000 --- a/test/old-sconsign.py +++ /dev/null @@ -1,192 +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__" - -""" -Test the transition from the old .sconsign format(s). -""" - -import os -import os.path -import string -import sys -import TestSCons - -python = TestSCons.python - -test = TestSCons.TestSCons() - -test.subdir('src1', ['src1', 'subdir'], - 'src2', ['src2', 'subdir']) - -convert = test.workpath('convert.py') -convert_dblite = test.workpath('convert_dblite.py') - -test.write(convert, """\ -import cPickle -import sys -import SCons.SConsign -import SCons.Sig - -try: - SConsignEntry = SCons.Sig.SConsignEntry -except AttributeError: - class SConsignEntry: - timestamp = None - bsig = None - csig = None - implicit = None - -filename = sys.argv[1] - -sconsign = SCons.SConsign.Dir(open(filename, 'rb')) - -old_entries = {} -for name, entry in sconsign.entries.items(): - oe = SConsignEntry() - for attr in ['timestamp', 'bsig', 'csig', 'implicit']: - try: setattr(oe, attr, getattr(entry, attr)) - except AttributeError: pass - old_entries[name] = oe - -cPickle.dump(old_entries, open(filename, 'wb'), 1) -""") - -test.write(convert_dblite, """\ -import cPickle -import SCons.dblite -import sys -import SCons.SConsign -import SCons.Sig - -try: - SConsignEntry = SCons.Sig.SConsignEntry -except AttributeError: - class SConsignEntry: - timestamp = None - bsig = None - csig = None - implicit = None - -filename = sys.argv[1] - -db = SCons.dblite.open(filename, "r") - -old_db = {} -for dir in db.keys(): - #self.printentries(dir, db[dir]) - - new_entries = cPickle.loads(db[dir]) - old_db[dir] = old_entries = {} - for name, entry in new_entries.items(): - oe = SConsignEntry() - for attr in ['timestamp', 'bsig', 'csig', 'implicit']: - try: setattr(oe, attr, getattr(entry, attr)) - except AttributeError: pass - old_entries[name] = oe - -db = SCons.dblite.open(filename, "c") -for key, val in old_db.items(): - db[key] = cPickle.dumps(val) -db.sync() -""") - -# Now generate a simple .sconsign file for a simple build. -test.write(['src1', 'SConstruct'], """\ -import os -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() -env.Append(BUILDERS={'Cat':Builder(action=cat)}) - -Export("env") -SConscript('SConscript') -""") - -test.write(['src1', 'SConscript'], """\ -Import("env") -env.Cat('file1', 'file1.in') -env.Cat('subdir/file2', 'subdir/file2.in') -""") - -test.write(['src1', 'file1.in'], "file1.in 1\n") -test.write(['src1', 'subdir', 'file2.in'], "subdir/file2.in 1\n") - -test.run(chdir='src1', arguments='.') - -test.up_to_date(chdir='src1', arguments='.') - -sconsign_list = [ - test.workpath('src1', '.sconsign'), - test.workpath('src1', 'subdir', '.sconsign'), -] - -for sconsign in sconsign_list: - test.run(interpreter=python, program=convert, arguments=sconsign) - -test.up_to_date(chdir='src1', arguments='.') - -# Now do the same with SConsignFile(). -test.write(['src2', 'SConstruct'], """\ -SConsignFile() - -import os -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() -env.Append(BUILDERS={'Cat':Builder(action=cat)}) -env.Cat('file1', 'file1.in') -env.Cat('subdir/file2', 'subdir/file2.in') -""") - -test.write(['src2', 'file1.in'], "file1.in 1\n") -test.write(['src2', 'subdir', 'file2.in'], "subdir/file2.in 1\n") - -test.run(chdir='src2', arguments='.') - -test.up_to_date(chdir='src2', arguments='.') - -sconsign_list = [ - test.workpath('src2', '.sconsign'), -] - -for sconsign in sconsign_list: - test.run(interpreter=python, program=convert_dblite, arguments=sconsign) - -test.up_to_date(chdir='src2', arguments='.') - -test.pass_test() diff --git a/test/option-n.py b/test/option-n.py index aa0b8f2..769c4dd 100644 --- a/test/option-n.py +++ b/test/option-n.py @@ -120,7 +120,7 @@ test.fail_test(not os.path.exists(test.workpath('f1.out'))) expect = test.wrap_stdout("""\ %s build.py f1.out """ % python) -test.unlink('.sconsign') +test.unlink('.sconsign.dblite') test.write('f1.out', "X1.out\n") test.run(arguments = '-n f1.out', stdout = expect) test.run(arguments = '-n f1.out', stdout = expect) diff --git a/test/sconsign-script.py b/test/sconsign-script.py deleted file mode 100644 index 7a24aef..0000000 --- a/test/sconsign-script.py +++ /dev/null @@ -1,519 +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 time - -import TestCmd -import TestSCons - -# Check for the sconsign script before we instantiate TestSCons(), -# because that will change directory on us. -if os.path.exists('sconsign.py'): - sconsign = 'sconsign.py' -elif os.path.exists('sconsign'): - sconsign = 'sconsign' -else: - print "Can find neither 'sconsign.py' nor 'sconsign' scripts." - test.no_result(1) - -def sort_match(test, lines, expect): - lines = string.split(lines, '\n') - lines.sort() - expect = string.split(expect, '\n') - expect.sort() - return test.match_re(lines, expect) - -def re_sep(*args): - return string.replace(apply(os.path.join, args), '\\', '\\\\') - - - -class MyTestSCons(TestSCons.TestSCons): - # subclass with a method for running the sconsign script - def __init__(self, *args, **kw): - apply(TestSCons.TestSCons.__init__, (self,)+args, kw) - self.my_kw = { - 'interpreter' : TestSCons.python, - 'program' : sconsign, - } - def run_sconsign(self, *args, **kw): - kw.update(self.my_kw) - return apply(self.run, args, kw) - -test = MyTestSCons(match = TestCmd.match_re) - - - - -test.subdir('work1', ['work1', 'sub1'], ['work1', 'sub2'], - 'work2', ['work2', 'sub1'], ['work2', 'sub2']) - -test.write(['work1', 'SConstruct'], """ -env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') -env1.Program('sub1/hello.c') -env2 = env1.Copy(CPPPATH = ['sub2']) -env2.Program('sub2/hello.c') -""") - -test.write(['work1', 'sub1', 'hello.c'], r"""\ -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("sub1/hello.c\n"); - exit (0); -} -""") - -test.write(['work1', 'sub2', 'hello.c'], r"""\ -#include -#include -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("sub2/goodbye.c\n"); - exit (0); -} -""") - -test.write(['work1', 'sub2', 'inc1.h'], r"""\ -#define STRING1 "inc1.h" -""") - -test.write(['work1', 'sub2', 'inc2.h'], r"""\ -#define STRING2 "inc2.h" -""") - -test.run(chdir = 'work1', arguments = '--debug=stacktrace --implicit-cache .') - -test.run_sconsign(arguments = "work1/sub1/.sconsign", - stdout = """\ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-v work1/sub1/.sconsign", - stdout = """\ -hello.exe: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.obj: \S+ -hello.obj: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-b -v work1/sub1/.sconsign", - stdout = """\ -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -""") - -test.run_sconsign(arguments = "-c -v work1/sub1/.sconsign", - stdout = """\ -hello.exe: - csig: None -hello.obj: - csig: None -""") - -test.run_sconsign(arguments = "-e hello.obj work1/sub1/.sconsign", - stdout = """\ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work1/sub1/.sconsign", - stdout = """\ -hello.obj: None \S+ None - hello.c: \S+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -# XXX NOT SURE IF THIS IS RIGHT! -sub2_inc1_h = re_sep('sub2', 'inc1.h') -sub2_inc2_h = re_sep('sub2', 'inc2.h') - -test.run_sconsign(arguments = "work1/sub2/.sconsign", - stdout = """\ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-i -v work1/sub2/.sconsign", - stdout = """\ -hello.exe: - implicit: - hello.obj: \S+ -hello.obj: - implicit: - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-e hello.obj work1/sub2/.sconsign work1/sub1/.sconsign", - stdout = """\ -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run(chdir = 'work1', arguments = '--clean .') - -test.write(['work1', 'SConstruct'], """ -SourceSignatures('timestamp') -TargetSignatures('content') -env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') -env1.Program('sub1/hello.c') -env2 = env1.Copy(CPPPATH = ['sub2']) -env2.Program('sub2/hello.c') -""") - -time.sleep(1) - -test.run(chdir = 'work1', arguments = '. --max-drift=1 --debug=stacktrace') - -test.run_sconsign(arguments = "-e hello.exe -e hello.obj work1/sub1/.sconsign", - stdout = """\ -hello.exe: None \d+ None - hello.obj: \d+ -hello.obj: None \d+ None - hello.c: \d+ -""") - -test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r work1/sub1/.sconsign", - stdout = """\ -hello.exe: None \d+ None - hello.obj: \d+ -hello.obj: None \d+ None - hello.c: \d+ -""") - - -############################################################################## - -test.write(['work2', 'SConstruct'], """ -SConsignFile() -env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') -env1.Program('sub1/hello.c') -env2 = env1.Copy(CPPPATH = ['sub2']) -env2.Program('sub2/hello.c') -""") - -test.write(['work2', 'sub1', 'hello.c'], r"""\ -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("sub1/hello.c\n"); - exit (0); -} -""") - -test.write(['work2', 'sub2', 'hello.c'], r"""\ -#include -#include -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("sub2/goodbye.c\n"); - exit (0); -} -""") - -test.write(['work2', 'sub2', 'inc1.h'], r"""\ -#define STRING1 "inc1.h" -""") - -test.write(['work2', 'sub2', 'inc2.h'], r"""\ -#define STRING2 "inc2.h" -""") - -test.run(chdir = 'work2', arguments = '--implicit-cache .') - -test.run_sconsign(arguments = "work2/.sconsign") - -test.run_sconsign(arguments = "work2/.sconsign", - stdout = """\ -=== sub1: -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -=== sub2: -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-v work2/.sconsign", - stdout = """\ -=== sub1: -hello.exe: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.obj: \S+ -hello.obj: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.c: \S+ -=== sub2: -hello.exe: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.obj: \S+ -hello.obj: - timestamp: None - bsig: \S+ - csig: None - implicit: - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-b -v work2/.sconsign", - stdout = """\ -=== sub1: -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -=== sub2: -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -""") - -test.run_sconsign(arguments = "-c -v work2/.sconsign", - stdout = """\ -=== sub1: -hello.exe: - csig: None -hello.obj: - csig: None -=== sub2: -hello.exe: - csig: None -hello.obj: - csig: None -""") - -test.run_sconsign(arguments = "-e hello.obj work2/.sconsign", - stdout = """\ -=== sub1: -hello.obj: None \S+ None - hello.c: \S+ -=== sub2: -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work2/.sconsign", - stdout = """\ -=== sub1: -hello.obj: None \S+ None - hello.c: \S+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -=== sub2: -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run_sconsign(arguments = "-i -v work2/.sconsign", - stdout = """\ -=== sub1: -hello.exe: - implicit: - hello.obj: \S+ -hello.obj: - implicit: - hello.c: \S+ -=== sub2: -hello.exe: - implicit: - hello.obj: \S+ -hello.obj: - implicit: - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") - -test.run(chdir = 'work2', arguments = '--clean .') - -test.write(['work2','SConstruct'], """ -SConsignFile('my_sconsign') -SourceSignatures('timestamp') -TargetSignatures('content') -env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') -env1.Program('sub1/hello.c') -env2 = env1.Copy(CPPPATH = ['sub2']) -env2.Program('sub2/hello.c') -""") - -time.sleep(1) - -test.run(chdir = 'work2', arguments = '. --max-drift=1') - -expect = """\ -=== sub1: -hello.c: \d+ None \d+ -""" - -test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign", - stdout = """\ -=== sub1: -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite", - stdout = """\ -=== sub1: -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign", - stdout = """\ -=== sub1: -hello.c: \d+ None \d+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite", - stdout = """\ -=== sub1: -hello.c: \d+ None \d+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign", - stdout = """\ -=== sub1: -hello.c: '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' None \d+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign.dblite", - stdout = """\ -=== sub1: -hello.c: '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' None \d+ -hello.exe: None \S+ None - hello.obj: \S+ -hello.obj: None \S+ None - hello.c: \S+ -""") - -############################################################################## - -test.write('bad1', "bad1\n") -test.write('bad2.dblite', "bad2.dblite\n") -test.write('bad3', "bad3\n") - -test.run_sconsign(arguments = "-f dblite no_sconsign", - stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n") - -test.run_sconsign(arguments = "-f dblite bad1", - stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n") - -test.run_sconsign(arguments = "-f dblite bad1.dblite", - stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n") - -test.run_sconsign(arguments = "-f dblite bad2", - stderr = "sconsign: ignoring invalid `dblite' file `bad2'\n") - -test.run_sconsign(arguments = "-f dblite bad2.dblite", - stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'\n") - -test.run_sconsign(arguments = "-f sconsign no_sconsign", - stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n") - -test.run_sconsign(arguments = "-f sconsign bad3", - stderr = "sconsign: ignoring invalid .sconsign file `bad3'\n") - -test.pass_test() diff --git a/test/sconsign.py b/test/sconsign.py deleted file mode 100644 index e9a6609..0000000 --- a/test/sconsign.py +++ /dev/null @@ -1,99 +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 -import TestSCons -import TestCmd -import cPickle - -test = TestSCons.TestSCons(match = TestCmd.match_re) - -test.subdir('sub1', 'sub2', 'sub3') - -test.write('SConstruct', """ -def build1(target, source, env): - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) - return None - -def build2(target, source, env): - import os - import os.path - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) - dir, file = os.path.split(str(target[0])) - os.chmod(dir, 0555) - return None - -B1 = Builder(action = build1) -B2 = Builder(action = build2) -env = Environment(BUILDERS = { 'B1' : B1, 'B2' : B2 }) -env.B1(target = 'sub1/foo.out', source = 'foo.in') -env.B2(target = 'sub2/foo.out', source = 'foo.in') -env.B2(target = 'sub3/foo.out', source = 'foo.in') -""") - -test.write('foo.in', "foo.in\n") - -sub1__sconsign = test.workpath('sub1', '.sconsign') -sub2__sconsign = test.workpath('sub2', '.sconsign') -sub3__sconsign = test.workpath('sub3', '.sconsign') - -cPickle.dump({}, open(sub1__sconsign, 'wb'), 1) -cPickle.dump({}, open(sub2__sconsign, 'wb'), 1) - -os.chmod(sub1__sconsign, 0444) - -test.run(arguments = '.') - -test.fail_test(test.read(sub1__sconsign) == "") -test.fail_test(test.read(sub2__sconsign) == "") - -os.chmod(sub1__sconsign, 0666) - -test.write('SConstruct', """ -def build1(target, source, env): - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) - return None - -B1 = Builder(action = build1) -env = Environment(BUILDERS = { 'B1' : B1}) -env.B1(target = 'sub1/foo.out', source = 'foo.in') -""") - -stderr = ''' -scons: warning: Ignoring corrupt .sconsign file: sub1.\.sconsign -.* -''' - -stdout = test.wrap_stdout('build1\(\["sub1.foo\.out"\], \["foo\.in"\]\)\n') - -test.write(sub1__sconsign, 'not:a:sconsign:file') -test.run(arguments = '.', stderr=stderr, stdout=stdout) - -test.write(sub1__sconsign, '\0\0\0\0\0\0\0\0\0\0\0\0\0\0') -test.run(arguments = '.', stderr=stderr, stdout=stdout) - - -test.pass_test() diff --git a/test/sconsign/corrupt.py b/test/sconsign/corrupt.py new file mode 100644 index 0000000..fd46de4 --- /dev/null +++ b/test/sconsign/corrupt.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that we get proper warnings when .sconsign* files are corrupt. +""" + +import os +import TestSCons +import TestCmd +import cPickle + +test = TestSCons.TestSCons(match = TestCmd.match_re) + +test.subdir('work1', ['work1', 'sub'], + 'work2', ['work2', 'sub']) + +work1__sconsign_dblite = test.workpath('work1', '.sconsign.dblite') +work2_sub__sconsign = test.workpath('work2', 'sub', '.sconsign') + +SConstruct_contents = """\ +def build1(target, source, env): + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + return None + +B1 = Builder(action = build1) +env = Environment(BUILDERS = { 'B1' : B1}) +env.B1(target = 'sub/foo.out', source = 'foo.in') +""" + + + +test.write(['work1', 'SConstruct'], SConstruct_contents) + +test.write(['work1', 'foo.in'], "work1/foo.in\n") + +stderr = ''' +scons: warning: Ignoring corrupt .sconsign file: \.sconsign\.dblite +.* +''' + +stdout = test.wrap_stdout('build1\(\["sub.foo\.out"\], \["foo\.in"\]\)\n') + +test.write(work1__sconsign_dblite, 'not:a:sconsign:file') +test.run(chdir='work1', arguments='.', stderr=stderr, stdout=stdout) + +test.write(work1__sconsign_dblite, '\0\0\0\0\0\0\0\0\0\0\0\0\0\0') +test.run(chdir='work1', arguments='.', stderr=stderr, stdout=stdout) + + + +# Test explicitly using a .sconsign file in each directory. + +SConstruct_contents = """\ +SConsignFile(None) +""" + SConstruct_contents + +test.write(['work2', 'SConstruct'], SConstruct_contents) + +test.write(['work2', 'foo.in'], "work2/foo.in\n") + +stderr = ''' +scons: warning: Ignoring corrupt .sconsign file: sub.\.sconsign +.* +''' + +stdout = test.wrap_stdout('build1\(\["sub.foo\.out"\], \["foo\.in"\]\)\n') + +test.write(work2_sub__sconsign, 'not:a:sconsign:file') +test.run(chdir='work2', arguments='.', stderr=stderr, stdout=stdout) + +test.write(work2_sub__sconsign, '\0\0\0\0\0\0\0\0\0\0\0\0\0\0') +test.run(chdir='work2', arguments='.', stderr=stderr, stdout=stdout) + + + +test.pass_test() diff --git a/test/sconsign/nonwritable.py b/test/sconsign/nonwritable.py new file mode 100644 index 0000000..9ad679c --- /dev/null +++ b/test/sconsign/nonwritable.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that things still work when a .sconsign* file is not writable. +""" + +import os +import TestSCons +import TestCmd +import cPickle + +test = TestSCons.TestSCons(match = TestCmd.match_re) + +test.subdir('work1', + ['work1', 'sub1'], + ['work1', 'sub2'], + ['work1', 'sub3'], + 'work2', + ['work2', 'sub1'], + ['work2', 'sub2'], + ['work2', 'sub3']) + +work1__sconsign_dblite = test.workpath('work1', '.sconsign.dblite') +work2_sub1__sconsign = test.workpath('work2', 'sub1', '.sconsign') +work2_sub2__sconsign = test.workpath('work2', 'sub2', '.sconsign') +work2_sub3__sconsign = test.workpath('work2', 'sub3', '.sconsign') + +SConstruct_contents = """\ +def build1(target, source, env): + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + return None + +def build2(target, source, env): + import os + import os.path + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + dir, file = os.path.split(str(target[0])) + os.chmod(dir, 0555) + return None + +B1 = Builder(action = build1) +B2 = Builder(action = build2) +env = Environment(BUILDERS = { 'B1' : B1, 'B2' : B2 }) +env.B1(target = 'sub1/foo.out', source = 'foo.in') +env.B2(target = 'sub2/foo.out', source = 'foo.in') +env.B2(target = 'sub3/foo.out', source = 'foo.in') +""" + + + +test.write(['work1', 'SConstruct'], SConstruct_contents) + +test.write(['work1', 'foo.in'], "work1/foo.in\n") + +test.write(work1__sconsign_dblite, "") + +os.chmod(work1__sconsign_dblite, 0444) + +test.run(chdir='work1', arguments='.') + + + +SConstruct_contents = """\ +SConsignFile(None) +""" + SConstruct_contents + +test.write(['work2', 'SConstruct'], SConstruct_contents) + +test.write(['work2', 'foo.in'], "work2/foo.in\n") + +cPickle.dump({}, open(work2_sub1__sconsign, 'wb'), 1) +cPickle.dump({}, open(work2_sub2__sconsign, 'wb'), 1) + +os.chmod(work2_sub1__sconsign, 0444) + +test.run(chdir='work2', arguments='.') + + + +test.pass_test() diff --git a/test/sconsign/old.py b/test/sconsign/old.py new file mode 100644 index 0000000..703a924 --- /dev/null +++ b/test/sconsign/old.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the transition from the old .sconsign format(s). +""" + +import os +import os.path +import string +import sys +import TestSCons + +python = TestSCons.python + +test = TestSCons.TestSCons() + +test.subdir('src1', ['src1', 'subdir'], + 'src2', ['src2', 'subdir']) + +convert = test.workpath('convert.py') +convert_dblite = test.workpath('convert_dblite.py') + +test.write(convert, """\ +import cPickle +import sys +import SCons.SConsign +import SCons.Sig + +try: + SConsignEntry = SCons.Sig.SConsignEntry +except AttributeError: + class SConsignEntry: + timestamp = None + bsig = None + csig = None + implicit = None + +filename = sys.argv[1] + +sconsign = SCons.SConsign.Dir(open(filename, 'rb')) + +old_entries = {} +for name, entry in sconsign.entries.items(): + oe = SConsignEntry() + for attr in ['timestamp', 'bsig', 'csig', 'implicit']: + try: setattr(oe, attr, getattr(entry, attr)) + except AttributeError: pass + old_entries[name] = oe + +cPickle.dump(old_entries, open(filename, 'wb'), 1) +""") + +test.write(convert_dblite, """\ +import cPickle +import SCons.dblite +import sys +import SCons.SConsign +import SCons.Sig + +try: + SConsignEntry = SCons.Sig.SConsignEntry +except AttributeError: + class SConsignEntry: + timestamp = None + bsig = None + csig = None + implicit = None + +filename = sys.argv[1] + +db = SCons.dblite.open(filename, "r") + +old_db = {} +for dir in db.keys(): + #self.printentries(dir, db[dir]) + + new_entries = cPickle.loads(db[dir]) + old_db[dir] = old_entries = {} + for name, entry in new_entries.items(): + oe = SConsignEntry() + for attr in ['timestamp', 'bsig', 'csig', 'implicit']: + try: setattr(oe, attr, getattr(entry, attr)) + except AttributeError: pass + old_entries[name] = oe + +db = SCons.dblite.open(filename, "c") +for key, val in old_db.items(): + db[key] = cPickle.dumps(val) +db.sync() +""") + + + +# Now generate a simple .sconsign file for a simple build. +test.write(['src1', 'SConstruct'], """\ +SConsignFile(None) +import os +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() +env.Append(BUILDERS={'Cat':Builder(action=cat)}) + +Export("env") +SConscript('SConscript') +""") + +test.write(['src1', 'SConscript'], """\ +Import("env") +env.Cat('file1', 'file1.in') +env.Cat('subdir/file2', 'subdir/file2.in') +""") + +test.write(['src1', 'file1.in'], "file1.in 1\n") +test.write(['src1', 'subdir', 'file2.in'], "subdir/file2.in 1\n") + +test.run(chdir='src1', arguments='.') + +test.up_to_date(chdir='src1', arguments='.') + +sconsign_list = [ + test.workpath('src1', '.sconsign'), + test.workpath('src1', 'subdir', '.sconsign'), +] + +for sconsign in sconsign_list: + test.run(interpreter=python, program=convert, arguments=sconsign) + +test.up_to_date(chdir='src1', arguments='.') + + + +# Now do the same with SConsignFile(). +test.write(['src2', 'SConstruct'], """\ +import os +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() +env.Append(BUILDERS={'Cat':Builder(action=cat)}) +env.Cat('file1', 'file1.in') +env.Cat('subdir/file2', 'subdir/file2.in') +""") + +test.write(['src2', 'file1.in'], "file1.in 1\n") +test.write(['src2', 'subdir', 'file2.in'], "subdir/file2.in 1\n") + +test.run(chdir='src2', arguments='.') + +test.up_to_date(chdir='src2', arguments='.') + +sconsign_list = [ + test.workpath('src2', '.sconsign'), +] + +for sconsign in sconsign_list: + test.run(interpreter=python, program=convert_dblite, arguments=sconsign) + +test.up_to_date(chdir='src2', arguments='.') + + + +test.pass_test() diff --git a/test/sconsign/script.py b/test/sconsign/script.py new file mode 100644 index 0000000..9758d5a --- /dev/null +++ b/test/sconsign/script.py @@ -0,0 +1,520 @@ +#!/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 time + +import TestCmd +import TestSCons + +# Check for the sconsign script before we instantiate TestSCons(), +# because that will change directory on us. +if os.path.exists('sconsign.py'): + sconsign = 'sconsign.py' +elif os.path.exists('sconsign'): + sconsign = 'sconsign' +else: + print "Can find neither 'sconsign.py' nor 'sconsign' scripts." + test.no_result(1) + +def sort_match(test, lines, expect): + lines = string.split(lines, '\n') + lines.sort() + expect = string.split(expect, '\n') + expect.sort() + return test.match_re(lines, expect) + +def re_sep(*args): + return string.replace(apply(os.path.join, args), '\\', '\\\\') + + + +class MyTestSCons(TestSCons.TestSCons): + # subclass with a method for running the sconsign script + def __init__(self, *args, **kw): + apply(TestSCons.TestSCons.__init__, (self,)+args, kw) + self.my_kw = { + 'interpreter' : TestSCons.python, + 'program' : sconsign, + } + def run_sconsign(self, *args, **kw): + kw.update(self.my_kw) + return apply(self.run, args, kw) + +test = MyTestSCons(match = TestCmd.match_re) + + + + +test.subdir('work1', ['work1', 'sub1'], ['work1', 'sub2'], + 'work2', ['work2', 'sub1'], ['work2', 'sub2']) + +test.write(['work1', 'SConstruct'], """ +SConsignFile(None) +env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') +env1.Program('sub1/hello.c') +env2 = env1.Copy(CPPPATH = ['sub2']) +env2.Program('sub2/hello.c') +""") + +test.write(['work1', 'sub1', 'hello.c'], r"""\ +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub1/hello.c\n"); + exit (0); +} +""") + +test.write(['work1', 'sub2', 'hello.c'], r"""\ +#include +#include +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub2/goodbye.c\n"); + exit (0); +} +""") + +test.write(['work1', 'sub2', 'inc1.h'], r"""\ +#define STRING1 "inc1.h" +""") + +test.write(['work1', 'sub2', 'inc2.h'], r"""\ +#define STRING2 "inc2.h" +""") + +test.run(chdir = 'work1', arguments = '--debug=stacktrace --implicit-cache .') + +test.run_sconsign(arguments = "work1/sub1/.sconsign", + stdout = """\ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-v work1/sub1/.sconsign", + stdout = """\ +hello.exe: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.obj: \S+ +hello.obj: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-b -v work1/sub1/.sconsign", + stdout = """\ +hello.exe: + bsig: \S+ +hello.obj: + bsig: \S+ +""") + +test.run_sconsign(arguments = "-c -v work1/sub1/.sconsign", + stdout = """\ +hello.exe: + csig: None +hello.obj: + csig: None +""") + +test.run_sconsign(arguments = "-e hello.obj work1/sub1/.sconsign", + stdout = """\ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work1/sub1/.sconsign", + stdout = """\ +hello.obj: None \S+ None + hello.c: \S+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +# XXX NOT SURE IF THIS IS RIGHT! +sub2_inc1_h = re_sep('sub2', 'inc1.h') +sub2_inc2_h = re_sep('sub2', 'inc2.h') + +test.run_sconsign(arguments = "work1/sub2/.sconsign", + stdout = """\ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-i -v work1/sub2/.sconsign", + stdout = """\ +hello.exe: + implicit: + hello.obj: \S+ +hello.obj: + implicit: + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-e hello.obj work1/sub2/.sconsign work1/sub1/.sconsign", + stdout = """\ +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run(chdir = 'work1', arguments = '--clean .') + +test.write(['work1', 'SConstruct'], """ +SourceSignatures('timestamp') +TargetSignatures('content') +env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') +env1.Program('sub1/hello.c') +env2 = env1.Copy(CPPPATH = ['sub2']) +env2.Program('sub2/hello.c') +""") + +time.sleep(1) + +test.run(chdir = 'work1', arguments = '. --max-drift=1 --debug=stacktrace') + +test.run_sconsign(arguments = "-e hello.exe -e hello.obj work1/sub1/.sconsign", + stdout = """\ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r work1/sub1/.sconsign", + stdout = """\ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + + +############################################################################## + +test.write(['work2', 'SConstruct'], """ +SConsignFile() +env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') +env1.Program('sub1/hello.c') +env2 = env1.Copy(CPPPATH = ['sub2']) +env2.Program('sub2/hello.c') +""") + +test.write(['work2', 'sub1', 'hello.c'], r"""\ +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub1/hello.c\n"); + exit (0); +} +""") + +test.write(['work2', 'sub2', 'hello.c'], r"""\ +#include +#include +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub2/goodbye.c\n"); + exit (0); +} +""") + +test.write(['work2', 'sub2', 'inc1.h'], r"""\ +#define STRING1 "inc1.h" +""") + +test.write(['work2', 'sub2', 'inc2.h'], r"""\ +#define STRING2 "inc2.h" +""") + +test.run(chdir = 'work2', arguments = '--implicit-cache .') + +test.run_sconsign(arguments = "work2/.sconsign") + +test.run_sconsign(arguments = "work2/.sconsign", + stdout = """\ +=== sub1: +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +=== sub2: +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-v work2/.sconsign", + stdout = """\ +=== sub1: +hello.exe: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.obj: \S+ +hello.obj: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.c: \S+ +=== sub2: +hello.exe: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.obj: \S+ +hello.obj: + timestamp: None + bsig: \S+ + csig: None + implicit: + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-b -v work2/.sconsign", + stdout = """\ +=== sub1: +hello.exe: + bsig: \S+ +hello.obj: + bsig: \S+ +=== sub2: +hello.exe: + bsig: \S+ +hello.obj: + bsig: \S+ +""") + +test.run_sconsign(arguments = "-c -v work2/.sconsign", + stdout = """\ +=== sub1: +hello.exe: + csig: None +hello.obj: + csig: None +=== sub2: +hello.exe: + csig: None +hello.obj: + csig: None +""") + +test.run_sconsign(arguments = "-e hello.obj work2/.sconsign", + stdout = """\ +=== sub1: +hello.obj: None \S+ None + hello.c: \S+ +=== sub2: +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work2/.sconsign", + stdout = """\ +=== sub1: +hello.obj: None \S+ None + hello.c: \S+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +=== sub2: +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run_sconsign(arguments = "-i -v work2/.sconsign", + stdout = """\ +=== sub1: +hello.exe: + implicit: + hello.obj: \S+ +hello.obj: + implicit: + hello.c: \S+ +=== sub2: +hello.exe: + implicit: + hello.obj: \S+ +hello.obj: + implicit: + hello.c: \S+ + inc1.h: \S+ + inc2.h: \S+ +""") + +test.run(chdir = 'work2', arguments = '--clean .') + +test.write(['work2','SConstruct'], """ +SConsignFile('my_sconsign') +SourceSignatures('timestamp') +TargetSignatures('content') +env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') +env1.Program('sub1/hello.c') +env2 = env1.Copy(CPPPATH = ['sub2']) +env2.Program('sub2/hello.c') +""") + +time.sleep(1) + +test.run(chdir = 'work2', arguments = '. --max-drift=1') + +expect = """\ +=== sub1: +hello.c: \d+ None \d+ +""" + +test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign", + stdout = """\ +=== sub1: +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite", + stdout = """\ +=== sub1: +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign", + stdout = """\ +=== sub1: +hello.c: \d+ None \d+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite", + stdout = """\ +=== sub1: +hello.c: \d+ None \d+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign", + stdout = """\ +=== sub1: +hello.c: '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' None \d+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +test.run_sconsign(arguments = "-e hello.c -e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign.dblite", + stdout = """\ +=== sub1: +hello.c: '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' None \d+ +hello.exe: None \S+ None + hello.obj: \S+ +hello.obj: None \S+ None + hello.c: \S+ +""") + +############################################################################## + +test.write('bad1', "bad1\n") +test.write('bad2.dblite', "bad2.dblite\n") +test.write('bad3', "bad3\n") + +test.run_sconsign(arguments = "-f dblite no_sconsign", + stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n") + +test.run_sconsign(arguments = "-f dblite bad1", + stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n") + +test.run_sconsign(arguments = "-f dblite bad1.dblite", + stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n") + +test.run_sconsign(arguments = "-f dblite bad2", + stderr = "sconsign: ignoring invalid `dblite' file `bad2'\n") + +test.run_sconsign(arguments = "-f dblite bad2.dblite", + stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'\n") + +test.run_sconsign(arguments = "-f sconsign no_sconsign", + stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n") + +test.run_sconsign(arguments = "-f sconsign bad3", + stderr = "sconsign: ignoring invalid .sconsign file `bad3'\n") + +test.pass_test() diff --git a/test/subdivide.py b/test/subdivide.py index f6aa4f1..18219bf 100644 --- a/test/subdivide.py +++ b/test/subdivide.py @@ -25,8 +25,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Verify that rebuilds do not occur when TargetSignatures() -content is used to subdivide a dependency tree. +Verify that rebuilds do not occur when SConsignFile(None) is used to +put a .sconsign file in each directory, and TargetSignatures('content') +is used to subdivide a dependency tree. """ import os.path @@ -46,6 +47,7 @@ test = TestSCons.TestSCons() test.subdir('src', ['src', 'sub']) test.write('SConstruct', """\ +SConsignFile(None) TargetSignatures('content') env = Environment() env.SConscript('src/SConstruct', exports=['env']) @@ -53,6 +55,7 @@ env.Object('foo.c') """) test.write(['src', 'SConstruct'], """\ +SConsignFile(None) TargetSignatures('content') env = Environment() p = env.Program('prog', ['main.c', '../foo%s', 'sub/bar.c']) -- cgit v0.12