10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#! /usr/bin/env python
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""Test script for the bsddb C module by Roger E. Masse
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi   Adapted to unittest format and expanded scope by Raymond Hettinger
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os, sys
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport unittest
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test import test_support
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Skip test if _bsddb wasn't built.
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitest_support.import_module('_bsddb')
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yibsddb = test_support.import_module('bsddb', deprecated=True)
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Just so we know it's imported:
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitest_support.import_module('dbhash', deprecated=True)
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestBSDDB(unittest.TestCase):
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openflag = 'c'
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setUp(self):
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = self.openmethod[0](self.fname, self.openflag, cachesize=32768)
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.d = dict(q='Guido', w='van', e='Rossum', r='invented', t='Python', y='')
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k, v in self.d.iteritems():
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.f[k] = v
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def tearDown(self):
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.sync()
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.fname is None:
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.remove(self.fname)
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except os.error:
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            pass
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_getitem(self):
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k, v in self.d.iteritems():
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.f[k], v)
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_len(self):
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(self.f), len(self.d))
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_change(self):
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f['r'] = 'discovered'
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f['r'], 'discovered')
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn('r', self.f.keys())
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn('discovered', self.f.values())
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_close_and_reopen(self):
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.fname is None:
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # if we're using an in-memory only db, we can't reopen it
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # so finish here.
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = self.openmethod[0](self.fname, 'w')
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k, v in self.d.iteritems():
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.f[k], v)
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def assertSetEquals(self, seqn1, seqn2):
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(set(seqn1), set(seqn2))
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_mapping_iteration_methods(self):
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.f
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.d
650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d, f)
660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.keys(), f.keys())
670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.values(), f.values())
680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.items(), f.items())
690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.iterkeys(), f.iterkeys())
700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.itervalues(), f.itervalues())
710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(d.iteritems(), f.iteritems())
720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_iter_while_modifying_values(self):
740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        di = iter(self.d)
750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while 1:
760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                key = di.next()
780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.d[key] = 'modified '+key
790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except StopIteration:
800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # it should behave the same as a dict.  modifying values
830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # of existing keys should not break iteration.  (adding
840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # or removing keys should)
850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        loops_left = len(self.f)
860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fi = iter(self.f)
870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while 1:
880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                key = fi.next()
900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.f[key] = 'modified '+key
910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                loops_left -= 1
920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except StopIteration:
930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(loops_left, 0)
950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.test_mapping_iteration_methods()
970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_iter_abort_on_changed_size(self):
990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def DictIterAbort():
1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            di = iter(self.d)
1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while 1:
1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    di.next()
1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.d['newkey'] = 'SPAM'
1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    break
1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(RuntimeError, DictIterAbort)
1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def DbIterAbort():
1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fi = iter(self.f)
1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while 1:
1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    fi.next()
1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.f['newkey'] = 'SPAM'
1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    break
1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(RuntimeError, DbIterAbort)
1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_iteritems_abort_on_changed_size(self):
1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def DictIteritemsAbort():
1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            di = self.d.iteritems()
1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while 1:
1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    di.next()
1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.d['newkey'] = 'SPAM'
1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    break
1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(RuntimeError, DictIteritemsAbort)
1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def DbIteritemsAbort():
1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fi = self.f.iteritems()
1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while 1:
1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    key, value = fi.next()
1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    del self.f[key]
1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    break
1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(RuntimeError, DbIteritemsAbort)
1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_iteritems_while_modifying_values(self):
1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        di = self.d.iteritems()
1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while 1:
1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                k, v = di.next()
1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.d[k] = 'modified '+v
1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except StopIteration:
1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # it should behave the same as a dict.  modifying values
1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # of existing keys should not break iteration.  (adding
1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # or removing keys should)
1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        loops_left = len(self.f)
1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fi = self.f.iteritems()
1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        while 1:
1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                k, v = fi.next()
1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.f[k] = 'modified '+v
1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                loops_left -= 1
1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except StopIteration:
1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(loops_left, 0)
1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.test_mapping_iteration_methods()
1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_first_next_looping(self):
1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        items = [self.f.first()]
1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in xrange(1, len(self.f)):
1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            items.append(self.f.next())
1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(items, self.d.items())
1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_previous_last_looping(self):
1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        items = [self.f.last()]
1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in xrange(1, len(self.f)):
1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            items.append(self.f.previous())
1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertSetEquals(items, self.d.items())
1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_first_while_deleting(self):
1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test for bug 1725856
1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(len(self.d) >= 2, "test requires >=2 items")
1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for _ in self.d:
1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            key = self.f.first()[0]
1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self.f[key]
1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual([], self.f.items(), "expected empty db after test")
1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_last_while_deleting(self):
1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test for bug 1725856's evil twin
1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(len(self.d) >= 2, "test requires >=2 items")
1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for _ in self.d:
1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            key = self.f.last()[0]
1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            del self.f[key]
1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual([], self.f.items(), "expected empty db after test")
1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_set_location(self):
1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.set_location('e'), ('e', self.d['e']))
1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_contains(self):
1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k in self.d:
1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertIn(k, self.f)
1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertNotIn('not here', self.f)
2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_has_key(self):
2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k in self.d:
2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(self.f.has_key(k))
2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not self.f.has_key('not here'))
2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_clear(self):
2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.clear()
2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(self.f), 0)
2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test__no_deadlock_first(self, debug=0):
2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # do this so that testers can see what function we're in in
2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verbose mode when we deadlock.
2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        sys.stdout.flush()
2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # in pybsddb's _DBWithCursor this causes an internal DBCursor
2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # object is created.  Other test_ methods in this class could
2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # inadvertently cause the deadlock but an explicit test is needed.
2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if debug: print "A"
2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        k,v = self.f.first()
2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if debug: print "B", k
2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f[k] = "deadlock.  do not pass go.  do not collect $200."
2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if debug: print "C"
2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # if the bsddb implementation leaves the DBCursor open during
2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the database write and locking+threading support is enabled
2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the cursor's read lock will deadlock the write lock request..
2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # test the iterator interface
2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if True:
2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "D"
2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i = self.f.iteritems()
2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            k,v = i.next()
2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "E"
2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.f[k] = "please don't deadlock"
2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "F"
2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while 1:
2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    k,v = i.next()
2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    break
2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "F2"
2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i = iter(self.f)
2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "G"
2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            while i:
2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if debug: print "H"
2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    k = i.next()
2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if debug: print "I"
2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.f[k] = "deadlocks-r-us"
2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if debug: print "J"
2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except StopIteration:
2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    i = None
2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if debug: print "K"
2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # test the legacy cursor interface mixed with writes
2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn(self.f.first()[0], self.d)
2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        k = self.f.next()[0]
2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn(k, self.d)
2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f[k] = "be gone with ye deadlocks"
2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.f[k], "be gone with ye deadlocks")
2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_for_cursor_memleak(self):
2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # do the bsddb._DBWithCursor iterator internals leak cursors?
2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nc1 = len(self.f._cursor_refs)
2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # create iterator
2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = self.f.iteritems()
2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nc2 = len(self.f._cursor_refs)
2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # use the iterator (should run to the first yield, creating the cursor)
2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        k, v = i.next()
2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nc3 = len(self.f._cursor_refs)
2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # destroy the iterator; this should cause the weakref callback
2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # to remove the cursor object from self.f._cursor_refs
2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        del i
2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nc4 = len(self.f._cursor_refs)
2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nc1, nc2)
2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nc1, nc4)
2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(nc3 == nc1+1)
2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_popitem(self):
2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        k, v = self.f.popitem()
2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn(k, self.d)
2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn(v, self.d.values())
2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertNotIn(k, self.f)
2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(self.d)-1, len(self.f))
2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pop(self):
2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        k = 'w'
2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        v = self.f.pop(k)
2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(v, self.d[k])
2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertNotIn(k, self.f)
2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertNotIn(v, self.f.values())
2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(self.d)-1, len(self.f))
2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_get(self):
2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.get('NotHere'), None)
2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.get('NotHere', 'Default'), 'Default')
2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.get('q', 'Default'), self.d['q'])
2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_setdefault(self):
3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.setdefault('new', 'dog'), 'dog')
3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.setdefault('r', 'cat'), self.d['r'])
3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_update(self):
3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        new = dict(y='life', u='of', i='brian')
3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.update(new)
3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.d.update(new)
3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for k, v in self.d.iteritems():
3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.f[k], v)
3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_keyordering(self):
3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.openmethod[0] is not bsddb.btopen:
3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return
3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        keys = self.d.keys()
3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        keys.sort()
3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.first()[0], keys[0])
3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.next()[0], keys[1])
3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.last()[0], keys[-1])
3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.previous()[0], keys[-2])
3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(list(self.f), keys)
3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestBTree(TestBSDDB):
3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fname = test_support.TESTFN
3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openmethod = [bsddb.btopen]
3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestBTree_InMemory(TestBSDDB):
3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fname = None
3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openmethod = [bsddb.btopen]
3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestBTree_InMemory_Truncate(TestBSDDB):
3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fname = None
3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openflag = 'n'
3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openmethod = [bsddb.btopen]
3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestHashTable(TestBSDDB):
3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fname = test_support.TESTFN
3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openmethod = [bsddb.hashopen]
3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestHashTable_InMemory(TestBSDDB):
3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    fname = None
3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    openmethod = [bsddb.hashopen]
3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi##         # (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85
3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi##         #                                   appears broken... at least on
3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi##         #                                   Solaris Intel - rmasse 1/97
3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main(verbose=None):
3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    test_support.run_unittest(
3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        TestBTree,
3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        TestHashTable,
3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        TestBTree_InMemory,
3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        TestHashTable_InMemory,
3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        TestBTree_InMemory_Truncate,
3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    )
3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == "__main__":
3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    test_main(verbose=True)
358