[Zope3-checkins] CVS: Zope3/src/zodb/btrees/tests - test_conflict.py:1.9
Tim Peters
tim.one@comcast.net
Sun, 12 Jan 2003 14:54:49 -0500
Update of /cvs-repository/Zope3/src/zodb/btrees/tests
In directory cvs.zope.org:/tmp/cvs-serv21899/src/zodb/btrees/tests
Modified Files:
test_conflict.py
Log Message:
New testEmptyBucketConflict *should* raise ConflictError, but currently
creates an insane BTree instead. Conflict resolution doesn't know enough
to empty a bucket correctly all on its own.
New test testEmptyBucketNoConflict shouldn't raise ConflictError, and
doesn't -- an empty bucket coming *into* ConflictResolution isn't
necessarily a problem. This test is here mostly to ensure that the
eventual fix for testEmptyBucketConflict doesn't complain about too much.
=== Zope3/src/zodb/btrees/tests/test_conflict.py 1.8 => 1.9 ===
--- Zope3/src/zodb/btrees/tests/test_conflict.py:1.8 Sat Jan 11 01:59:59 2003
+++ Zope3/src/zodb/btrees/tests/test_conflict.py Sun Jan 12 14:54:46 2003
@@ -523,6 +523,153 @@
self.assertRaises(ConflictError, get_transaction().commit)
get_transaction().abort() # horrible things happen w/o this
+ def testEmptyBucketConflict(self):
+ # Tests that an emptied bucket *created by* conflict resolution is
+ # viewed as a conflict: conflict resolution doesn't have enough
+ # info to unlink the empty bucket from the BTree correctly.
+ b = self.t
+ for i in range(0, 200, 4):
+ b[i] = i
+ # bucket 0 has 15 values: 0, 4 .. 56
+ # bucket 1 has 15 values: 60, 64 .. 116
+ # bucket 2 has 20 values: 120, 124 .. 196
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+ # If these fail, the *preconditions* for running the test aren't
+ # satisfied -- the test itself hasn't been run yet.
+ self.assertEqual(len(state), 2)
+ self.assertEqual(len(state[0]), 5)
+ self.assertEqual(state[0][1], 60)
+ self.assertEqual(state[0][3], 120)
+
+ # Invoke conflict resolution by committing a transaction.
+ self.openDB()
+
+ r1 = self.db.open().root()
+ r1["t"] = self.t
+ get_transaction().commit()
+
+ r2 = self.db.open().root()
+ copy = r2["t"]
+ # Make sure all of copy is loaded.
+ list(copy.values())
+
+ self.assertEqual(self.t._p_serial, copy._p_serial)
+
+ # In one transaction, delete half of bucket 1.
+ b = self.t
+ for k in 60, 64, 68, 72, 76, 80, 84, 88:
+ del b[k]
+ # bucket 0 has 15 values: 0, 4 .. 56
+ # bucket 1 has 7 values: 92, 96, 100, 104, 108, 112, 116
+ # bucket 2 has 20 values: 120, 124 .. 196
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+ # The next block is still verifying preconditions.
+ self.assertEqual(len(state) , 2)
+ self.assertEqual(len(state[0]), 5)
+ self.assertEqual(state[0][1], 60)
+ self.assertEqual(state[0][3], 120)
+
+ get_transaction().commit()
+
+ # In the other transaction, delete the other half of bucket 1.
+ b = copy
+ for k in 92, 96, 100, 104, 108, 112, 116:
+ del b[k]
+ # bucket 0 has 15 values: 0, 4 .. 56
+ # bucket 1 has 8 values: 60, 64, 68, 72, 76, 80, 84, 88
+ # bucket 2 has 20 values: 120, 124 .. 196
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+ # The next block is still verifying preconditions.
+ self.assertEqual(len(state), 2)
+ self.assertEqual(len(state[0]), 5)
+ self.assertEqual(state[0][1], 60)
+ self.assertEqual(state[0][3], 120)
+
+ # Conflict resolution empties bucket1 entirely.
+
+ # XXX This is broken: it doesn't raise ConflictError now.
+ ### XXX The ConflictError imported at the top of this module isn't
+ ### XXX the ConflictError that gets raised here.
+ ##from zodb.interfaces import ConflictError
+ ##self.assertRaises(ConflictError, get_transaction().commit)
+ ##get_transaction().abort() # horrible things happen w/o this
+
+ # XXX Instead it creates an insane BTree (with an empty bucket
+ # XXX still linked in. Remove the remaining lines and uncomment
+ # XXX the lines above when this is fixed.
+ # XXX AssertionError: Bucket length < 1
+ get_transaction().commit()
+ self.assertRaises(AssertionError, b._check)
+
+
+ def testEmptyBucketNoConflict(self):
+ # Tests that a plain empty bucket (on input) is not viewed as a
+ # conflict.
+ b = self.t
+ for i in range(0, 200, 4):
+ b[i] = i
+ # bucket 0 has 15 values: 0, 4 .. 56
+ # bucket 1 has 15 values: 60, 64 .. 116
+ # bucket 2 has 20 values: 120, 124 .. 196
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+ # If these fail, the *preconditions* for running the test aren't
+ # satisfied -- the test itself hasn't been run yet.
+ self.assertEqual(len(state), 2)
+ self.assertEqual(len(state[0]), 5)
+ self.assertEqual(state[0][1], 60)
+ self.assertEqual(state[0][3], 120)
+
+ # Invoke conflict resolution by committing a transaction.
+ self.openDB()
+
+ r1 = self.db.open().root()
+ r1["t"] = self.t
+ get_transaction().commit()
+
+ r2 = self.db.open().root()
+ copy = r2["t"]
+ # Make sure all of copy is loaded.
+ list(copy.values())
+
+ self.assertEqual(self.t._p_serial, copy._p_serial)
+
+ # In one transaction, just add a key.
+ b = self.t
+ b[1] = 1
+ # bucket 0 has 16 values: [0, 1] + [4, 8 .. 56]
+ # bucket 1 has 15 values: 60, 64 .. 116
+ # bucket 2 has 20 values: 120, 124 .. 196
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+ # The next block is still verifying preconditions.
+ self.assertEqual(len(state), 2)
+ self.assertEqual(len(state[0]), 5)
+ self.assertEqual(state[0][1], 60)
+ self.assertEqual(state[0][3], 120)
+
+ get_transaction().commit()
+
+ # In the other transaction, delete bucket 2.
+ b = copy
+ for k in range(120, 200, 4):
+ del b[k]
+ # bucket 0 has 15 values: 0, 4 .. 56
+ # bucket 1 has 15 values: 60, 64 .. 116
+ state = b.__getstate__()
+ # Looks like: ((bucket0, 60, bucket1), firstbucket)
+ # The next block is still verifying preconditions.
+ self.assertEqual(len(state), 2)
+ self.assertEqual(len(state[0]), 3)
+ self.assertEqual(state[0][1], 60)
+
+ # This shouldn't create a ConflictError.
+ get_transaction().commit()
+ # And the resulting BTree shouldn't have internal damage.
+ b._check()
def test_suite():
suite = TestSuite()