[Zodb-checkins] SVN: ZODB/branches/3.9/src/ Bug fix: DemoStorage.loadBefore returned invalid data when

Patrick Strawderman patrick at zope.com
Fri Dec 11 15:36:46 EST 2009


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(



More information about the Zodb-checkins mailing list