diff options
author | Gregory P. Smith <greg@mad-scientist.com> | 2003-11-03 01:04:41 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@mad-scientist.com> | 2003-11-03 01:04:41 (GMT) |
commit | a703a21b486b4eb47d9873fb1c7de7008530ae93 (patch) | |
tree | 2a1a6c82902e4a1058595ed53741f51079d60724 /Lib/test | |
parent | 83c187460ead750da62b5837512492332e3ad75a (diff) | |
download | cpython-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-x | Lib/test/test_bsddb.py | 79 |
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) |