diff options
author | William Deegan <bill@baddogconsulting.com> | 2018-04-22 21:30:21 (GMT) |
---|---|---|
committer | William Deegan <bill@baddogconsulting.com> | 2018-11-12 16:42:44 (GMT) |
commit | da31f2954ae37e1c07a408bccbbf39a9c14b2446 (patch) | |
tree | e0228bd3e370543ae801673aa655c13797276670 | |
parent | 140cea983b9d9e02cc76b1ebcb47c0fb4a88b367 (diff) | |
download | SCons-da31f2954ae37e1c07a408bccbbf39a9c14b2446.zip SCons-da31f2954ae37e1c07a408bccbbf39a9c14b2446.tar.gz SCons-da31f2954ae37e1c07a408bccbbf39a9c14b2446.tar.bz2 |
Create test to verify fix for issue #2980
There are still possible errors due to timestamp-MD5 + cachedir + changed implicit or regular dependencies (but the same # of such as the previous build).
These are not yet handled as the fix being used for changed number of such breaks a number of tests.
This fix doe reduce the number of possible issues.
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 137 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 7 |
2 files changed, 140 insertions, 4 deletions
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 63a1ba4..0b57e2a 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -41,6 +41,7 @@ import SCons.Errors import SCons.Node.FS import SCons.Util import SCons.Warnings +import SCons.Environment built_it = None @@ -2460,6 +2461,142 @@ class FileTestCase(_tempdirTestCase): assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1) assert not os.path.exists(build_f1.get_abspath()), "%s did not get removed after %s was removed" % (build_f1, src_f1) + def test_changed(self): + """ + Verify that changes between BuildInfo's list of souces, depends, and implicit + dependencies do not corrupt content signiture values written to .SConsign + when using CacheDir and Timestamp-MD5 decider. + This is for issue #2980 + """ + # node should have + # 1 source (for example main.cpp) + # 0 depends + # N implicits (for example ['alpha.h', 'beta.h', 'gamma.h', '/usr/bin/g++']) + + class ChangedNode(SCons.Node.FS.File): + def __init__(self, name, directory=None, fs=None): + SCons.Node.FS.File.__init__(self, name, directory, fs) + self.name = name + self.Tag('found_includes', []) + self.stored_info = None + self.build_env = None + self.changed_since_last_build = 4 + self.timestamp = 1 + + def get_stored_info(self): + return self.stored_info + + def get_build_env(self): + return self.build_env + + def get_timestamp(self): + """ Fake timestamp so they always match""" + return self.timestamp + + def get_contents(self): + return self.name + + def get_ninfo(self): + """ mocked to ensure csig will equal the filename""" + try: + return self.ninfo + except AttributeError: + self.ninfo = FakeNodeInfo(self.name, self.timestamp) + return self.ninfo + + def get_csig(self): + ninfo = self.get_ninfo() + try: + return ninfo.csig + except AttributeError: + pass + + return "Should Never Happen" + + class ChangedEnvironment(SCons.Environment.Base): + + def __init__(self): + SCons.Environment.Base.__init__(self) + self.decide_source = self._changed_timestamp_then_content + + class FakeNodeInfo(object): + def __init__(self, csig, timestamp): + self.csig = csig + self.timestamp = timestamp + + + #Create nodes + fs = SCons.Node.FS.FS() + d = self.fs.Dir('.') + + node = ChangedNode('main.o',d,fs) # main.o + s1 = ChangedNode('main.cpp',d,fs) # main.cpp + s1.timestamp = 2 # this changed + i1 = ChangedNode('alpha.h',d,fs) # alpha.h - The bug is caused because the second build adds this file + i1.timestamp = 2 # This is the new file. + i2 = ChangedNode('beta.h',d,fs) # beta.h + i3 = ChangedNode('gamma.h',d,fs) # gamma.h - In the bug beta.h's csig from binfo overwrites this ones + i4 = ChangedNode('/usr/bin/g++',d,fs) # /usr/bin/g++ + + + + node.add_source([s1]) + node.add_dependency([]) + node.implicit = [i1, i2, i3, i4] + node.implicit_set = set() + # node._add_child(node.implicit, node.implicit_set, [n7, n8, n9]) + # node._add_child(node.implicit, node.implicit_set, [n10, n11, n12]) + + # Mock out node's scan method + # node.scan = lambda *args: None + + # Mock out nodes' children() ? + # Should return Node's. + # All those nodes should have changed_since_last_build set to match Timestamp-MD5's + # decider method... + + # Generate sconsign entry needed + sconsign_entry = SCons.SConsign.SConsignEntry() + sconsign_entry.binfo = node.new_binfo() + sconsign_entry.ninfo = node.new_ninfo() + + # mock out loading info from sconsign + # This will cause node.get_stored_info() to return our freshly created sconsign_entry + node.stored_info = sconsign_entry + + # binfo = information from previous build (from sconsign) + # We'll set the following attributes (which are lists): "bsources", "bsourcesigs", + # "bdepends","bdependsigs", "bimplicit", "bimplicitsigs" + bi = sconsign_entry.binfo + bi.bsources = ['main.cpp'] + bi.bsourcesigs=[FakeNodeInfo('main.cpp',1),] + + bi.bdepends = [] + bi.bdependsigs = [] + + bi.bimplicit = ['beta.h','gamma.h'] + bi.bimplicitsigs = [FakeNodeInfo('beta.h',1), FakeNodeInfo('gamma.h',1)] + + ni = sconsign_entry.ninfo + # We'll set the following attributes (which are lists): sources, depends, implicit lists + + #Set timestamp-md5 + #Call changed + #Check results + node.build_env = ChangedEnvironment() + + changed = node.changed() + + # change to true to debug + if False: + print("Changed:%s"%changed) + print("%15s -> csig:%s"%(s1.name, s1.ninfo.csig)) + print("%15s -> csig:%s"%(i1.name, i1.ninfo.csig)) + print("%15s -> csig:%s"%(i2.name, i2.ninfo.csig)) + print("%15s -> csig:%s"%(i3.name, i3.ninfo.csig)) + print("%15s -> csig:%s"%(i4.name, i4.ninfo.csig)) + + self.assertEqual(i2.name,i2.ninfo.csig, "gamma.h's fake csig should equal gamma.h but equals:%s"%i2.ninfo.csig) class GlobTestCase(_tempdirTestCase): diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index b02c84d..ce2a4e3 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -1458,8 +1458,6 @@ class Node(object, with_metaclass(NoSlotsPyPy)): prev.append(dmap.get(c)) return prev - - def changed(self, node=None, allowcache=False): """ Returns if the node is up-to-date with respect to the BuildInfo @@ -1492,7 +1490,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): bi = node.get_stored_info().binfo previous_children = bi.bsourcesigs + bi.bdependsigs + bi.bimplicitsigs - # TODO: Can we move this into the if diff below? + children = self.children() diff = len(children) - len(previous_children) @@ -1515,6 +1513,8 @@ class Node(object, with_metaclass(NoSlotsPyPy)): result = True + # TODO: There are still possible errors due to timestamp-MD5 + cachedir + changed implicit or regular dependencies (but the same # of such as the previous build). + for child, prev_ni in zip(children, previous_children): if _decider_map[child.changed_since_last_build](child, self, prev_ni): @@ -1524,7 +1524,6 @@ class Node(object, with_metaclass(NoSlotsPyPy)): if self.has_builder(): contents = self.get_executor().get_contents() - import SCons.Util newsig = SCons.Util.MD5signature(contents) if bi.bactsig != newsig: if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig)) |