SVN: ZODB/branches/3.9/src/ Bug fix: DemoStorage.loadBefore returned invalid data when

Patrick Strawderman <[email protected]>
Newsgroups gmane.comp.python.zope.zodb.cvs
Message-ID <20091211203646.36EFD9417F__11552.7696595111$1260563820$gmane$org@cvs.zope.org>
Log message for revision 106428:
  Bug fix: DemoStorage.loadBefore returned invalid data when
  passed a tid older than anything in changes but newer than
  anything in base.
  

Changed:
  U   ZODB/branches/3.9/src/CHANGES.txt
  U   ZODB/branches/3.9/src/ZODB/DemoStorage.py
  U   ZODB/branches/3.9/src/ZODB/tests/testDemoStorage.py

-=-
Modified: ZODB/branches/3.9/src/CHANGES.txt
===================================================================
--- ZODB/branches/3.9/src/CHANGES.txt	2009-12-11 20:12:44 UTC (rev 106427)
+++ ZODB/branches/3.9/src/CHANGES.txt	2009-12-11 20:36:45 UTC (rev 106428)
@@ -8,6 +8,9 @@
 Bugs Fixed
 ----------
 
+- DemoStorage.loadBefore sometimes returned invalid data which
+  would trigger AssertionErrors in ZODB.Connection.
+
 - History support was broken when using stprages that work with ZODB
   3.8 and 3.9.
 

Modified: ZODB/branches/3.9/src/ZODB/DemoStorage.py
===================================================================
--- ZODB/branches/3.9/src/ZODB/DemoStorage.py	2009-12-11 20:12:44 UTC (rev 106427)
+++ ZODB/branches/3.9/src/ZODB/DemoStorage.py	2009-12-11 20:36:45 UTC (rev 106428)
@@ -153,11 +153,18 @@
             # The oid *was* in the changes, but there aren't any
             # earlier records. Maybe there are in the base.
             try:
-                return self.base.loadBefore(oid, tid)
+                result = self.base.loadBefore(oid, tid)
             except ZODB.POSException.POSKeyError:
                 # The oid isn't in the base, so None will be the right result
                 pass
-
+            else:
+                if result and not result[-1]:
+                    end_tid = None
+                    t = self.changes.load(oid)
+                    while t:
+                        end_tid = t[1]
+                        t = self.changes.loadBefore(oid, end_tid)
+                    result = result[:2] + (end_tid,)
         return result
 
     def loadBlob(self, oid, serial):

Modified: ZODB/branches/3.9/src/ZODB/tests/testDemoStorage.py
===================================================================
--- ZODB/branches/3.9/src/ZODB/tests/testDemoStorage.py	2009-12-11 20:12:44 UTC (rev 106427)
+++ ZODB/branches/3.9/src/ZODB/tests/testDemoStorage.py	2009-12-11 20:36:45 UTC (rev 106428)
@@ -171,7 +171,54 @@
 
     """
 
+def load_before_base_storage_current():
+    """
+    Here we'll exercise that DemoStorage's loadBefore method works
+    properly when deferring to a record that is current in the
+    base storage.
 
+    >>> import transaction
+    >>> import ZODB.DB
+    >>> import ZODB.DemoStorage
+    >>> import ZODB.MappingStorage
+    >>> import ZODB.utils
+
+    >>> base = ZODB.MappingStorage.MappingStorage()
+    >>> basedb = ZODB.DB(base)
+    >>> conn = basedb.open()
+    >>> conn.root()['foo'] = 'bar'
+    >>> transaction.commit()
+    >>> conn.close()
+    >>> storage = ZODB.DemoStorage.DemoStorage(base=base)
+    >>> db = ZODB.DB(storage)
+    >>> conn = db.open()
+    >>> conn.root()['foo'] = 'baz'
+    >>> transaction.commit()
+
+    >>> oid = ZODB.utils.z64
+    >>> base_current = storage.base.load(oid)
+    >>> tid = ZODB.utils.p64(ZODB.utils.u64(base_current[1]) + 1)
+    >>> base_record = storage.base.loadBefore(oid, tid)
+    >>> base_record[-1] is None
+    True
+    >>> base_current == base_record[:2]
+    True
+
+    >>> t = storage.loadBefore(oid, tid)
+
+    The data and tid are the values from the base storage, but the
+    next tid is from changes.
+
+    >>> t[:2] == base_record[:2]
+    True
+    >>> t[-1] == storage.changes.load(oid)[1]
+    True
+
+    >>> conn.close()
+    >>> db.close()
+    >>> base.close()
+    """
+
 def test_suite():
     suite = unittest.TestSuite((
         doctest.DocTestSuite(
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.