[Zodb-checkins] SVN: ZODB/trunk/src/BTrees/tests/testBTrees.py Added test from issue 294788
Jim Fulton
jim at zope.com
Thu Aug 27 17:32:53 EDT 2009
Log message for revision 103325:
Added test from issue 294788
Changed:
U ZODB/trunk/src/BTrees/tests/testBTrees.py
-=-
Modified: ZODB/trunk/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/trunk/src/BTrees/tests/testBTrees.py 2009-08-27 21:28:42 UTC (rev 103324)
+++ ZODB/trunk/src/BTrees/tests/testBTrees.py 2009-08-27 21:32:52 UTC (rev 103325)
@@ -11,6 +11,7 @@
# FOR A PARTICULAR PURPOSE
#
##############################################################################
+import gc
import pickle
import random
import StringIO
@@ -1572,7 +1573,26 @@
# at some unrelated line.
del t # trigger destructor
+LP294788_ids = {}
+class ToBeDeleted(object):
+ def __init__(self, id):
+ assert type(id) is int #we don't want to store any object ref here
+ self.id = id
+
+ global LP294788_ids
+ LP294788_ids[id] = 1
+
+ def __del__(self):
+ global LP294788_ids
+ LP294788_ids.pop(self.id, None)
+
+ def __cmp__(self, other):
+ return cmp(self.id, other.id)
+
+ def __hash__(self):
+ return hash(self.id)
+
class BugFixes(TestCase):
# Collector 1843. Error returns were effectively ignored in
@@ -1585,7 +1605,161 @@
# This one used to segfault.
self.assertRaises(TypeError, t.keys, 0, "")
+ def test_LP294788(self):
+ # https://bugs.launchpad.net/bugs/294788
+ # BTree keeps some deleted objects referenced
+ # The logic here together with the ToBeDeleted class is that
+ # a separate reference dict is populated on object creation
+ # and removed in __del__
+ # That means what's left in the reference dict is never GC'ed
+ # therefore referenced somewhere
+ # To simulate real life, some random data is used to exercise the tree
+
+ t = OOBTree()
+
+ random.seed('OOBTree')
+
+ global LP294788_ids
+
+ # /// BTree keys are integers, value is an object
+ LP294788_ids = {}
+ ids = {}
+ for i in xrange(1024):
+ if random.random() > 0.1:
+ #add
+ id = None
+ while id is None or id in ids:
+ id = random.randint(0,1000000)
+
+ ids[id] = 1
+ t[id] = ToBeDeleted(id)
+ else:
+ #del
+ id = random.choice(ids.keys())
+ del t[id]
+ del ids[id]
+
+ ids = ids.keys()
+ random.shuffle(ids)
+ for id in ids:
+ del t[id]
+ ids = None
+
+ #to be on the safe side run a full GC
+ gc.collect()
+
+ #print LP294788_ids
+
+ self.assertEqual(len(t), 0)
+ self.assertEqual(len(LP294788_ids), 0)
+ # \\\
+
+ # /// BTree keys are integers, value is a tuple having an object
+ LP294788_ids = {}
+ ids = {}
+ for i in xrange(1024):
+ if random.random() > 0.1:
+ #add
+ id = None
+ while id is None or id in ids:
+ id = random.randint(0,1000000)
+
+ ids[id] = 1
+ t[id] = (id, ToBeDeleted(id), u'somename')
+ else:
+ #del
+ id = random.choice(ids.keys())
+ del t[id]
+ del ids[id]
+
+ ids = ids.keys()
+ random.shuffle(ids)
+ for id in ids:
+ del t[id]
+ ids = None
+
+ #to be on the safe side run a full GC
+ gc.collect()
+
+ #print LP294788_ids
+
+ self.assertEqual(len(t), 0)
+ self.assertEqual(len(LP294788_ids), 0)
+ # \\\
+
+
+ # /// BTree keys are objects, value is an int
+ t = OOBTree()
+ LP294788_ids = {}
+ ids = {}
+ for i in xrange(1024):
+ if random.random() > 0.1:
+ #add
+ id = None
+ while id is None or id in ids:
+ id = random.randint(0,1000000)
+
+ obj = ToBeDeleted(id)
+ ids[obj] = 1
+ t[obj] = 1
+ else:
+ #del
+ obj = random.choice(ids.keys())
+ del ids[obj]
+ del t[obj]
+
+ ids = ids.keys()
+ random.shuffle(ids)
+ for id in ids:
+ del t[id]
+ #release all refs
+ ids = obj = id = None
+
+ #to be on the safe side run a full GC
+ gc.collect()
+
+ #print LP294788_ids
+
+ self.assertEqual(len(t), 0)
+ self.assertEqual(len(LP294788_ids), 0)
+
+ # /// BTree keys are tuples having objects, value is an int
+ t = OOBTree()
+ LP294788_ids = {}
+ ids = {}
+ for i in xrange(1024):
+ if random.random() > 0.1:
+ #add
+ id = None
+ while id is None or id in ids:
+ id = random.randint(0,1000000)
+
+ key = (id, ToBeDeleted(id), u'somename')
+ ids[key] = 1
+ t[key] = 1
+ else:
+ #del
+ key = random.choice(ids.keys())
+ del ids[key]
+ del t[key]
+
+ ids = ids.keys()
+ random.shuffle(ids)
+ for id in ids:
+ del t[id]
+ #release all refs
+ ids = id = obj = key = None
+
+ #to be on the safe side run a full GC
+ gc.collect()
+
+ #print LP294788_ids
+
+ self.assertEqual(len(t), 0)
+ self.assertEqual(len(LP294788_ids), 0)
+
+
class IIBTreeTest(BTreeTests):
def setUp(self):
self.t = IIBTree()
@@ -1621,7 +1795,7 @@
self.t = OIBTree()
def getTwoKeys(self):
return object(), object()
-
+
class LLBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues):
def setUp(self):
self.t = LLBTree()
More information about the Zodb-checkins
mailing list