[Zodb-checkins] SVN: ZODB/branches/tim-deprecate-subtxn/src/ZODB/tests/testZODB.py New test checkSavepointDoesntGetInvalidations(), to

Tim Peters tim.one at comcast.net
Wed Jul 13 21:22:59 EDT 2005


Log message for revision 33309:
  New test checkSavepointDoesntGetInvalidations(), to
  verify that a old subtxn bug didn't reappear in savepoints.
  

Changed:
  U   ZODB/branches/tim-deprecate-subtxn/src/ZODB/tests/testZODB.py

-=-
Modified: ZODB/branches/tim-deprecate-subtxn/src/ZODB/tests/testZODB.py
===================================================================
--- ZODB/branches/tim-deprecate-subtxn/src/ZODB/tests/testZODB.py	2005-07-13 22:53:27 UTC (rev 33308)
+++ ZODB/branches/tim-deprecate-subtxn/src/ZODB/tests/testZODB.py	2005-07-14 01:22:58 UTC (rev 33309)
@@ -437,6 +437,72 @@
         finally:
             tm1.abort()
 
+    def checkSavepointDoesntGetInvalidations(self):
+        # Prior to ZODB 3.2.9 and 3.4, Connection.tpc_finish() processed
+        # invalidations even for a subtxn commit.  This could make
+        # inconsistent state visible after a subtxn commit.  There was a
+        # suspicion that POSKeyError was possible as a result, but I wasn't
+        # able to construct a case where that happened.
+        # Subtxns are deprecated now, but it's good to check that the
+        # same kind of thing doesn't happen when making savepoints either.
+
+        # Set up the database, to hold
+        # root --> "p" -> value = 1
+        #      --> "q" -> value = 2
+        tm1 = transaction.TransactionManager()
+        conn = self._db.open(transaction_manager=tm1)
+        r1 = conn.root()
+        p = P()
+        p.value = 1
+        r1["p"] = p
+        q = P()
+        q.value = 2
+        r1["q"] = q
+        tm1.commit()
+
+        # Now txn T1 changes p.value to 3 locally (subtxn commit).
+        p.value = 3
+        tm1.savepoint()
+
+        # Start new txn T2 with a new connection.
+        tm2 = transaction.TransactionManager()
+        cn2 = self._db.open(transaction_manager=tm2)
+        r2 = cn2.root()
+        p2 = r2["p"]
+        self.assertEqual(p._p_oid, p2._p_oid)
+        # T2 shouldn't see T1's change of p.value to 3, because T1 didn't
+        # commit yet.
+        self.assertEqual(p2.value, 1)
+        # Change p.value to 4, and q.value to 5.  Neither should be visible
+        # to T1, because T1 is still in progress.
+        p2.value = 4
+        q2 = r2["q"]
+        self.assertEqual(q._p_oid, q2._p_oid)
+        self.assertEqual(q2.value, 2)
+        q2.value = 5
+        tm2.commit()
+
+        # Back to T1.  p and q still have the expected values.
+        rt = conn.root()
+        self.assertEqual(rt["p"].value, 3)
+        self.assertEqual(rt["q"].value, 2)
+
+        # Now make another savepoint in T1.  This shouldn't change what
+        # T1 sees for p and q.
+        rt["r"] = P()
+        tm1.savepoint()
+
+        # Making that savepoint in T1 should not process invalidations
+        # from T2's commit.  p.value should still be 3 here (because that's
+        # what T1 savepointed earlier), and q.value should still be 2.
+        # Prior to ZODB 3.2.9 and 3.4, q.value was 5 here.
+        rt = conn.root()
+        try:
+            self.assertEqual(rt["p"].value, 3)
+            self.assertEqual(rt["q"].value, 2)
+        finally:
+            tm1.abort()
+
     def checkReadConflictErrorClearedDuringAbort(self):
         # When a transaction is aborted, the "memory" of which
         # objects were the cause of a ReadConflictError during



More information about the Zodb-checkins mailing list