summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2003-11-03 01:04:41 (GMT)
committerGregory P. Smith <greg@mad-scientist.com>2003-11-03 01:04:41 (GMT)
commita703a21b486b4eb47d9873fb1c7de7008530ae93 (patch)
tree2a1a6c82902e4a1058595ed53741f51079d60724 /Lib/test
parent83c187460ead750da62b5837512492332e3ad75a (diff)
downloadcpython-a703a21b486b4eb47d9873fb1c7de7008530ae93.zip
cpython-a703a21b486b4eb47d9873fb1c7de7008530ae93.tar.gz
cpython-a703a21b486b4eb47d9873fb1c7de7008530ae93.tar.bz2
* Use weakref's of DBCursor objects for the iterator cursors to avoid a
memory leak that would've occurred for all iterators that were destroyed before having iterated until they raised StopIteration. * Simplify some code. * Add new test cases to check for the memleak and ensure that mixing iteration with modification of the values for existing keys works.
Diffstat (limited to 'Lib/test')
-rwxr-xr-xLib/test/test_bsddb.py79
1 files changed, 76 insertions, 3 deletions
diff --git a/Lib/test/test_bsddb.py b/Lib/test/test_bsddb.py
index ff8c355..1ec4801 100755
--- a/Lib/test/test_bsddb.py
+++ b/Lib/test/test_bsddb.py
@@ -3,6 +3,7 @@
Adapted to unittest format and expanded scope by Raymond Hettinger
"""
import os, sys
+import copy
import bsddb
import dbhash # Just so we know it's imported
import unittest
@@ -64,6 +65,56 @@ class TestBSDDB(unittest.TestCase):
self.assertSetEquals(d.itervalues(), f.itervalues())
self.assertSetEquals(d.iteritems(), f.iteritems())
+ def test_iter_while_modifying_values(self):
+ if not hasattr(self.f, '__iter__'):
+ return
+
+ di = iter(self.d)
+ while 1:
+ try:
+ key = di.next()
+ self.d[key] = 'modified '+key
+ except StopIteration:
+ break
+
+ # it should behave the same as a dict. modifying values
+ # of existing keys should not break iteration. (adding
+ # or removing keys should)
+ fi = iter(self.f)
+ while 1:
+ try:
+ key = fi.next()
+ self.f[key] = 'modified '+key
+ except StopIteration:
+ break
+
+ self.test_mapping_iteration_methods()
+
+ def test_iteritems_while_modifying_values(self):
+ if not hasattr(self.f, 'iteritems'):
+ return
+
+ di = self.d.iteritems()
+ while 1:
+ try:
+ k, v = di.next()
+ self.d[k] = 'modified '+v
+ except StopIteration:
+ break
+
+ # it should behave the same as a dict. modifying values
+ # of existing keys should not break iteration. (adding
+ # or removing keys should)
+ fi = self.f.iteritems()
+ while 1:
+ try:
+ k, v = fi.next()
+ self.f[k] = 'modified '+v
+ except StopIteration:
+ break
+
+ self.test_mapping_iteration_methods()
+
def test_first_next_looping(self):
items = [self.f.first()]
for i in xrange(1, len(self.f)):
@@ -111,15 +162,16 @@ class TestBSDDB(unittest.TestCase):
# the cursor's read lock will deadlock the write lock request..
# test the iterator interface (if present)
- if hasattr(self, 'iteritems'):
+ if hasattr(self.f, 'iteritems'):
if debug: print "D"
- k,v = self.f.iteritems()
+ i = self.f.iteritems()
+ k,v = i.next()
if debug: print "E"
self.f[k] = "please don't deadlock"
if debug: print "F"
while 1:
try:
- k,v = self.f.iteritems()
+ k,v = i.next()
except StopIteration:
break
if debug: print "F2"
@@ -144,6 +196,27 @@ class TestBSDDB(unittest.TestCase):
self.f[k] = "be gone with ye deadlocks"
self.assert_(self.f[k], "be gone with ye deadlocks")
+ def test_for_cursor_memleak(self):
+ if not hasattr(self.f, 'iteritems'):
+ return
+
+ # do the bsddb._DBWithCursor _iter_mixin internals leak cursors?
+ nc1 = len(self.f._cursor_refs)
+ # create iterator
+ i = self.f.iteritems()
+ nc2 = len(self.f._cursor_refs)
+ # use the iterator (should run to the first yeild, creating the cursor)
+ k, v = i.next()
+ nc3 = len(self.f._cursor_refs)
+ # destroy the iterator; this should cause the weakref callback
+ # to remove the cursor object from self.f._cursor_refs
+ del i
+ nc4 = len(self.f._cursor_refs)
+
+ self.assertEqual(nc1, nc2)
+ self.assertEqual(nc1, nc4)
+ self.assert_(nc3 == nc1+1)
+
def test_popitem(self):
k, v = self.f.popitem()
self.assert_(k in self.d)