[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: