[Zope-CVS] CVS: Products/Ape/apelib/tests - teststorage.py:1.2 zope2testbase.py:1.3

Shane Hathaway shane@zope.com
Sat, 29 Mar 2003 14:45:27 -0500


Update of /cvs-repository/Products/Ape/apelib/tests
In directory cvs.zope.org:/tmp/cvs-serv13976/apelib/tests

Modified Files:
	teststorage.py zope2testbase.py 
Log Message:
Stopped using the _p_serial attribute of persistent objects.  ZODB
assumes that _p_serial is a transaction time stamp and uses it to
compute _p_mtime, but that assumption is not valid for Ape.  Until
now, Ape has monkey-patched PersistentExtra to make it so the Zope
application doesn't depend so much on _p_mtime.  But that patch wasn't
enough, since other parts of Zope depend on _p_mtime.

So now Ape stores the object hashes in a dictionary external to the
object and periodically prunes hashes no longer in use.  Once again
Ape got around the need to patch the C code, but only by a narrow
margin.  Hopefully, ZODB 4 already provides a better answer for this
dilemma.


=== Products/Ape/apelib/tests/teststorage.py 1.1.1.1 => 1.2 ===
--- Products/Ape/apelib/tests/teststorage.py:1.1.1.1	Sat Mar 15 18:44:40 2003
+++ Products/Ape/apelib/tests/teststorage.py	Sat Mar 29 14:44:56 2003
@@ -30,6 +30,7 @@
 
 
 def run_in_thread(f):
+    """Calls a function in another thread and waits for it to finish."""
     lock = allocate_lock()
     def run(f=f, lock=lock):
         try:
@@ -43,7 +44,7 @@
 
 
 class ApeStorageTests (SerialTestBase, unittest.TestCase):
-    # Tests of ApeStorage, not including ApeConnection.
+    # Tests of ApeStorage and ApeConnection.
 
     def setUp(self):
         SerialTestBase.setUp(self)
@@ -202,6 +203,18 @@
             conn1.close()
 
 
+    def _writeBasicObjects(self, conn):
+        ob = PersistentMapping()
+        ob.strdata = 'abc'
+        dummy = PersistentMapping()
+        root = conn.root()
+        get_transaction().begin()
+        root['TestRoot'] = ob
+        root['TestRoot2'] = dummy
+        get_transaction().commit()
+        return ob, dummy
+
+
     def _changeTestRoot(self):
         conn2 = self.db.open()
         try:
@@ -213,18 +226,9 @@
 
 
     def testConflictDetection(self):
-        ob1 = PersistentMapping()
-        ob1.strdata = 'abc'
-
-        dummy = PersistentMapping()
-
         conn1 = self.db.open()
         try:
-            root = conn1.root()
-            get_transaction().begin()
-            root['TestRoot'] = ob1
-            root['TestRoot2'] = dummy
-            get_transaction().commit()
+            ob1, dummy = self._writeBasicObjects(conn1)
             ob1.strdata = 'def'
             run_in_thread(self._changeTestRoot)
             # Verify that "def" doesn't get written, since it
@@ -238,20 +242,11 @@
 
     def testNewObjectConflictDetection(self):
         # Verify a new object won't overwrite existing objects by accident
-        ob1 = PersistentMapping()
-        ob1.strdata = 'abc'
-
-        dummy = PersistentMapping()
-
         conn1 = self.db.open()
         try:
-            root = conn1.root()
-            get_transaction().begin()
-            root['TestRoot'] = ob1
-            root['TestRoot2'] = dummy
-            get_transaction().commit()
+            ob1, dummy = self._writeBasicObjects(conn1)
             ob1.strdata = 'def'
-            ob1._p_serial = '\0' * 8  # Pretend that it's new
+            conn1.setSerial(ob1, '\0' * 8)  # Pretend that it's new
             self.assertRaises(ZODB.POSException.ConflictError,
                               get_transaction().commit)
         finally:
@@ -318,6 +313,67 @@
         self.assert_(ob2 is not ob1)
         self.assert_(ob2['fishy'] is not ob1['fishy'])
         self.assert_(ob2['fishy'].__class__ is weird_class)
+
+
+    def test_p_serial_untouched(self):
+        # _p_serial isn't safe to use for hashes, since _p_mtime
+        # interprets it as a date stamp.  Verify Ape doesn't
+        # use _p_serial for hashes.
+        conn1 = self.db.open()
+        try:
+            ob1, dummy = self._writeBasicObjects(conn1)
+            self.assertEqual(ob1._p_serial, "\0" * 8)
+            self.assertEqual(dummy._p_serial, "\0" * 8)
+        finally:
+            conn1.close()
+
+
+    def testGetSerial(self):
+        # Verifies the behavior of getSerial().
+        conn1 = self.db.open()
+        try:
+            new_ob = PersistentMapping()
+            self.assertEqual(conn1.getSerial(new_ob), '\0' * 8)
+            ob1, dummy = self._writeBasicObjects(conn1)
+            self.assertNotEqual(conn1.getSerial(ob1), '\0' * 8)
+        finally:
+            conn1.close()
+
+
+    def testGetSerialDetectsNewObjects(self):
+        # Verifies the behavior of getSerial() and setSerial().
+        conn1 = self.db.open()
+        try:
+            ob1, dummy = self._writeBasicObjects(conn1)
+            self.assertNotEqual(conn1.getSerial(ob1), '\0' * 8)
+            # Replace the object and verify it gets a new serial.
+            ob1 = PersistentMapping()
+            ob1.strdata = 'cba'
+            ob1._p_oid = conn1.root()['TestRoot']._p_oid
+            conn1.root()['TestRoot'] = ob1
+            self.assertEqual(conn1.getSerial(ob1), '\0' * 8)
+        finally:
+            conn1.close()
+
+
+    def testSerialCleanup(self):
+        # Verify that setSerial() cleans up.
+        conn1 = self.db.open()
+        try:
+            conn1.SERIAL_CLEANUP_THRESHOLD = 10
+            for n in range(conn1.SERIAL_CLEANUP_THRESHOLD + 1):
+                new_ob = PersistentMapping()
+                new_ob._p_oid = 'fake_oid_' + str(n)
+                old_size = len(conn1._serials or ())
+                conn1.setSerial(new_ob, '01234567')
+                new_size = len(conn1._serials)
+                if new_size < old_size:
+                    # Cleaned up.  Success.
+                    break
+            else:
+                self.fail("setSerial() did not clean up")
+        finally:
+            conn1.close()
 
 
 if __name__ == '__main__':


=== Products/Ape/apelib/tests/zope2testbase.py 1.2 => 1.3 ===
--- Products/Ape/apelib/tests/zope2testbase.py:1.2	Sat Mar 15 20:13:46 2003
+++ Products/Ape/apelib/tests/zope2testbase.py	Sat Mar 29 14:44:56 2003
@@ -313,7 +313,7 @@
         try:
             app = conn.root()['Application']
             app.some_attr = 'stuff'
-            app._p_serial = '\0' * 8  # Pretend that it's new
+            conn.setSerial(app, '\0' * 8)  # Pretend that it's new
             self.assertRaises(POSException.ConflictError,
                               get_transaction().commit)
         finally: