diff options
author | Steven Knight <knight@baldmt.com> | 2004-05-30 19:17:38 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2004-05-30 19:17:38 (GMT) |
commit | 78b110985d41c80a1803e95f3f9fe7280a0c1cb1 (patch) | |
tree | 965379d611026b1b16b9b7e0d78bc130c1f664ae /src/engine/SCons/Sig | |
parent | d941bfd4f886fc6b2a3f70d3f2f8e76b88bb4c9b (diff) | |
download | SCons-78b110985d41c80a1803e95f3f9fe7280a0c1cb1.zip SCons-78b110985d41c80a1803e95f3f9fe7280a0c1cb1.tar.gz SCons-78b110985d41c80a1803e95f3f9fe7280a0c1cb1.tar.bz2 |
Eliminate the refactored-out-of-existence Sig.Calculator methods (whose jobs are now handled by Node methods). Stop tying calculators to Taskmaster objects, and eliminate the unused Taskmaster.Calc class.
Diffstat (limited to 'src/engine/SCons/Sig')
-rw-r--r-- | src/engine/SCons/Sig/SigTests.py | 372 | ||||
-rw-r--r-- | src/engine/SCons/Sig/__init__.py | 127 |
2 files changed, 7 insertions, 492 deletions
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index 4390a60..8964c5c 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -24,393 +24,31 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import unittest -import TestCmd import SCons.Sig -import SCons.Sig.MD5 -import SCons.Sig.TimeStamp import sys - -class DummyFile: - """A class that simulates a file for testing purposes""" - def __init__(self, path, contents, timestamp, builder): - self.path = path - self.contents = contents - self.timestamp = timestamp - self.builder = builder - - def modify(self, contents, timestamp): - self.contents = contents - self.timestamp = timestamp - -class DummyNode: - """A node workalike for testing purposes""" - - def __init__(self, file): - self.file = file - self.path = file.path - self.builder = file.builder - self.depends = [] - self.ignore = [] - self.use_signature = 1 - self.bsig = None - self.csig = None - self.oldtime = 0 - self.oldbsig = 0 - self.oldcsig = 0 - self.always_build = 0 - - def has_builder(self): - return self.builder - - def get_contents(self): - # a file that doesn't exist has no contents: - assert self.exists() - - return self.file.contents - - def get_timestamp(self): - # a file that doesn't exist has no timestamp: - assert self.exists() - - return self.file.timestamp - - def exists(self): - return not self.file.contents is None - - def cached_exists(self): - try: - return self.exists_cache - except AttributeError: - self.exists_cache = self.exists() - return self.exists_cache - - def rexists(self): - return not self.file.contents is None - - def children(self): - return filter(lambda x, i=self.ignore: x not in i, - self.sources + self.depends) - - def all_children(self): - return self.sources + self.depends - - def current(self): - if not self.exists(): - return 0 - return None - - def calc_signature(self, calc): - if self.has_builder(): - return calc.bsig(self) - else: - return calc.csig(self) - - def set_binfo(self, bsig, bkids, bkidsigs, bact, bactsig): - self.bsig = bsig - self.bkids = bkids - self.bkidsigs = bkidsigs - self.bact = bact - self.bactsig = bactsig - - def get_bsig(self): - return self.bsig - - def store_bsig(self): - pass - - def set_csig(self, csig): - self.csig = csig - - def get_csig(self): - return self.csig - - def store_csig(self): - pass - - def get_prevsiginfo(self): - return (self.oldtime, self.oldbsig, self.oldcsig) - - def get_stored_implicit(self): - return None - - def store_timestamp(self): - pass - - def get_executor(self): - class Adapter: - def get_contents(self): - return 111 - def get_timestamp(self): - return 222 - return Adapter() - - -def create_files(test): - args = [(test.workpath('f1.c'), 'blah blah', 111, 0), #0 - (test.workpath('f1'), None, 0, 1), #1 - (test.workpath('d1/f1.c'), 'blah blah', 111, 0), #2 - (test.workpath('d1/f1.h'), 'blah blah', 111, 0), #3 - (test.workpath('d1/f2.c'), 'blah blah', 111, 0), #4 - (test.workpath('d1/f3.h'), 'blah blah', 111, 0), #5 - (test.workpath('d1/f4.h'), 'blah blah', 111, 0), #6 - (test.workpath('d1/f1'), None, 0, 1), #7 - (test.workpath('d1/test.c'), 'blah blah', 111, 0),#8 - (test.workpath('d1/test.o'), None, 0, 1), #9 - (test.workpath('d1/test'), None, 0, 1)] #10 - - files = map(lambda x: apply(DummyFile, x), args) - - return files - -def create_nodes(files): - nodes = map(DummyNode, files) - - nodes[0].sources = [] - nodes[1].sources = [nodes[0]] - nodes[2].sources = [] - nodes[3].sources = [] - nodes[4].sources = [] - nodes[5].sources = [nodes[6]] - nodes[6].sources = [nodes[5]] - nodes[7].sources = [nodes[2], nodes[4], nodes[3], nodes[5]] - nodes[8].sources = [] - nodes[9].sources = [nodes[8]] - nodes[10].sources = [nodes[9]] - - return nodes - -def current(calc, node): - return calc.current(node, node.calc_signature(calc)) - -def write(calc, nodes): - for node in nodes: - node.oldtime = node.file.timestamp - node.oldbsig = calc.bsig(node) - node.oldcsig = calc.csig(node) - -def clear(nodes): - for node in nodes: - node.csig = None - node.bsig = None - class SConsignEntryTestCase(unittest.TestCase): def runTest(self): - se = SCons.Sig.SConsignEntry() assert hasattr(se, 'timestamp'), "no timestamp attribute" assert hasattr(se, 'bsig'), "no bsig attribute" assert hasattr(se, 'csig'), "no csig attribute" assert hasattr(se, 'implicit'), "no implicit attribute" -class SigTestBase: - - def runTest(self): - - test = TestCmd.TestCmd(workdir = '') - test.subdir('d1') - - self.files = create_files(test) - self.test_initial() - self.test_built() - self.test_modify() - self.test_modify_same_time() - - def test_initial(self): - - nodes = create_nodes(self.files) - calc = SCons.Sig.Calculator(self.module) - - for node in nodes: - self.failUnless(not current(calc, node), - "node %s should not be current" % node.path) - - # simulate a build: - self.files[1].modify('built', 222) - self.files[7].modify('built', 222) - self.files[9].modify('built', 222) - self.files[10].modify('built', 222) - - def test_built(self): - - nodes = create_nodes(self.files) - - calc = SCons.Sig.Calculator(self.module) - - write(calc, nodes) - - for node in nodes: - self.failUnless(current(calc, node), - "node %s should be current" % node.path) - - def test_modify(self): - - nodes = create_nodes(self.files) - - calc = SCons.Sig.Calculator(self.module) - - write(calc, nodes) - - #simulate a modification of some files - self.files[0].modify('blah blah blah', 333) - self.files[3].modify('blah blah blah', 333) - self.files[6].modify('blah blah blah', 333) - self.files[8].modify('blah blah blah', 333) - - clear(nodes) - - self.failUnless(not current(calc, nodes[0]), "modified directly") - self.failUnless(not current(calc, nodes[1]), "direct source modified") - self.failUnless(current(calc, nodes[2])) - self.failUnless(not current(calc, nodes[3]), "modified directly") - self.failUnless(current(calc, nodes[4])) - self.failUnless(current(calc, nodes[5])) - self.failUnless(not current(calc, nodes[6]), "modified directly") - self.failUnless(not current(calc, nodes[7]), "indirect source modified") - self.failUnless(not current(calc, nodes[8]), "modified directory") - self.failUnless(not current(calc, nodes[9]), "direct source modified") - self.failUnless(not current(calc, nodes[10]), "indirect source modified") - - def test_modify_same_time(self): - - nodes = create_nodes(self.files) - - calc = SCons.Sig.Calculator(self.module, 0) - - write(calc, nodes) - - #simulate a modification of some files without changing the timestamp: - self.files[0].modify('blah blah blah blah', 333) - self.files[3].modify('blah blah blah blah', 333) - self.files[6].modify('blah blah blah blah', 333) - self.files[8].modify('blah blah blah blah', 333) - - clear(nodes) - - for node in nodes: - self.failUnless(current(calc, node), - "node %s should be current" % node.path) - - -class MD5TestCase(unittest.TestCase, SigTestBase): - """Test MD5 signatures""" - - module = SCons.Sig.MD5 - -class TimeStampTestCase(unittest.TestCase, SigTestBase): - """Test timestamp signatures""" - - module = SCons.Sig.TimeStamp - -class CalcTestCase(unittest.TestCase): +class CalculatorTestCase(unittest.TestCase): def runTest(self): class MySigModule: - def collect(self, signatures): - return reduce(lambda x, y: x + y, signatures) - def current(self, newsig, oldsig): - return newsig == oldsig - def signature(self, node): - return node.get_csig() - - class MyNode: - def __init__(self, name, bsig, csig): - self.name = name - self.bsig = bsig - self.csig = csig - self.kids = [] - self.ignore = [] - self.builder = None - self.use_signature = 1 - def has_builder(self): - return not self.builder is None - def children(self): - return filter(lambda x, i=self.ignore: x not in i, self.kids) - def all_children(self): - return self.kids - def exists(self): - return 1 - def cached_exists(self): - return 1 - def get_bsig(self): - return self.bsig - def set_binfo(self, bsig, bkids, bkidsig, bact, bactsig): - self.bsig = bsig - self.bkids = bkids - self.bkidsigs = bkidsigs - self.bact = bact - self.bactsig = bactsig - def get_csig(self): - return self.csig - def set_csig(self, csig): - self.csig = csig - def store_csig(self): - pass - def store_timestamp(self): - pass - def get_prevsiginfo(self): - return 0, self.bsig, self.csig - def get_stored_implicit(self): - return None - def get_timestamp(self): - return 1 - def builder_sig_adapter(self): - class MyAdapter: - def get_csig(self): - return 333 - def get_timestamp(self): - return 444 - return MyAdapter() - - self.module = MySigModule() - self.nodeclass = MyNode - self.test_Calc___init__() - self.test_Calc_bsig() - self.test_Calc_current() - - def test_Calc___init__(self): - self.calc = SCons.Sig.Calculator(self.module) - assert self.calc.module == self.module - - def test_Calc_bsig(self): - n1 = self.nodeclass('n1', 11, 12) - n2 = self.nodeclass('n2', 22, 23) - n3 = self.nodeclass('n3', 33, 34) - n1.builder = 1 - n1.kids = [n2, n3] - - assert self.calc.bsig(n1) == 55 - - n1.ignore = [n2] - - assert self.calc.bsig(n1) == 33 - - def test_Calc_bsig(self): - n = self.nodeclass('n', 11, 12) - - assert self.calc.csig(n) == 12 - - def test_Calc_current(self): - class NN(self.nodeclass): - always_build = 0 - def current(self): - return None - - nn = NN('nn', 33, 34) - assert not self.calc.current(nn, 30) - assert self.calc.current(nn, 33) - nn.always_build = 1 - assert not self.calc.current(nn, 33) - + pass + calc = SCons.Sig.Calculator(MySigModule) + assert calc.module == MySigModule def suite(): suite = unittest.TestSuite() suite.addTest(SConsignEntryTestCase()) - suite.addTest(MD5TestCase()) - suite.addTest(TimeStampTestCase()) - suite.addTest(CalcTestCase()) + suite.addTest(CalculatorTestCase()) return suite if __name__ == "__main__": diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index 6626571..2a9680e 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -29,14 +29,6 @@ The Signature package for the scons software construction utility. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import cPickle -import os -import os.path -import time - -import SCons.Node -import SCons.Warnings - try: import MD5 default_module = MD5 @@ -44,6 +36,8 @@ except ImportError: import TimeStamp default_module = TimeStamp +# XXX We should move max_drift into Node/FS.py, +# since it's really something about files. default_max_drift = 2*24*60*60 class SConsignEntry: @@ -72,121 +66,4 @@ class Calculator: self.module = module self.max_drift = max_drift - def bsig(self, node, cache=None): - """ - Generate a node's build signature, the digested signatures - of its dependency files and build information. - - node - the node whose sources will be collected - cache - alternate node to use for the signature cache - returns - the build signature - - This no longer handles the recursive descent of the - node's children's signatures. We expect that they're - already built and updated by someone else, if that's - what's wanted. - """ - - if cache is None: cache = node - - bsig = cache.get_bsig() - if bsig is not None: - return bsig - - children = node.children() - bkids = map(str, children) - - # double check bsig, because the call to children() above may - # have set it: - bsig = cache.get_bsig() - if bsig is not None: - return bsig - - sigs = map(lambda n, c=self: n.calc_signature(c), children) - - if node.has_builder(): - executor = node.get_executor() - bact = str(executor) - bactsig = self.module.signature(executor) - sigs.append(bactsig) - else: - bact = "" - bactsig = "" - - bsig = self.module.collect(filter(None, sigs)) - - cache.set_binfo(bsig, bkids, sigs, bact, bactsig) - - # don't store the bsig here, because it isn't accurate until - # the node is actually built. - - return bsig - - def csig(self, node, cache=None): - """ - Generate a node's content signature, the digested signature - of its content. - - node - the node - cache - alternate node to use for the signature cache - returns - the content signature - """ - - if cache is None: cache = node - - csig = cache.get_csig() - if csig is not None: - return csig - - if self.max_drift >= 0: - oldtime, oldbsig, oldcsig = node.get_prevsiginfo() - else: - import SCons.SConsign - oldtime, oldbsig, oldcsig = SCons.SConsign.Base.null_siginfo - - mtime = node.get_timestamp() - - if (oldtime and oldcsig and oldtime == mtime): - # use the signature stored in the .sconsign file - csig = oldcsig - # Set the csig here so it doesn't get recalculated unnecessarily - # and so it's set when the .sconsign file gets written - cache.set_csig(csig) - else: - csig = self.module.signature(node) - # Set the csig here so it doesn't get recalculated unnecessarily - # and so it's set when the .sconsign file gets written - cache.set_csig(csig) - - if self.max_drift >= 0 and (time.time() - mtime) > self.max_drift: - node.store_csig() - node.store_timestamp() - - return csig - - def current(self, node, newsig): - """ - Check if a signature is up to date with respect to a node. - - node - the node whose signature will be checked - newsig - the (presumably current) signature of the file - - returns - 1 if the file is current with the specified signature, - 0 if it isn't - """ - - if node.always_build: - return 0 - - oldtime, oldbsig, oldcsig = node.get_prevsiginfo() - - if type(newsig) != type(oldbsig): - return 0 - - if not node.has_builder() and node.get_timestamp() == oldtime: - return 1 - - return self.module.current(newsig, oldbsig) - - default_calc = Calculator() |