blob: 3a62f9c1c7f6314f25897ee73b8f06842eaf7a0e [file] [log] [blame]
Roger E. Masse352e1861997-01-16 22:04:10 +00001#! /usr/bin/env python
Raymond Hettingerd55111f2003-09-13 05:51:09 +00002"""Test script for the bsddb C module by Roger E. Masse
3 Adapted to unittest format and expanded scope by Raymond Hettinger
Roger E. Masse352e1861997-01-16 22:04:10 +00004"""
Gregory P. Smithdc113a82003-11-02 09:10:16 +00005import os, sys
Gregory P. Smitha703a212003-11-03 01:04:41 +00006import copy
Roger E. Masse352e1861997-01-16 22:04:10 +00007import bsddb
Guido van Rossuma35e2ce2001-12-07 16:43:19 +00008import dbhash # Just so we know it's imported
Raymond Hettingerd55111f2003-09-13 05:51:09 +00009import unittest
10from test import test_support
Roger E. Masse352e1861997-01-16 22:04:10 +000011
Raymond Hettingerd55111f2003-09-13 05:51:09 +000012class TestBSDDB(unittest.TestCase):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000013 openflag = 'c'
Roger E. Masse352e1861997-01-16 22:04:10 +000014
Raymond Hettingerd55111f2003-09-13 05:51:09 +000015 def setUp(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000016 self.f = self.openmethod[0](self.fname, self.openflag, cachesize=32768)
Raymond Hettingerd55111f2003-09-13 05:51:09 +000017 self.d = dict(q='Guido', w='van', e='Rossum', r='invented', t='Python', y='')
Guido van Rossumcc2b0162007-02-11 06:12:03 +000018 for k, v in self.d.items():
Raymond Hettingerd55111f2003-09-13 05:51:09 +000019 self.f[k] = v
Fred Drake004d5e62000-10-23 17:22:08 +000020
Raymond Hettingerd55111f2003-09-13 05:51:09 +000021 def tearDown(self):
22 self.f.sync()
23 self.f.close()
24 if self.fname is None:
25 return
Anthony Baxter83888952002-04-23 02:11:05 +000026 try:
Raymond Hettingerd55111f2003-09-13 05:51:09 +000027 os.remove(self.fname)
Anthony Baxter83888952002-04-23 02:11:05 +000028 except os.error:
29 pass
Roger E. Masse352e1861997-01-16 22:04:10 +000030
Raymond Hettingerd55111f2003-09-13 05:51:09 +000031 def test_getitem(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000032 for k, v in self.d.items():
Raymond Hettingerd55111f2003-09-13 05:51:09 +000033 self.assertEqual(self.f[k], v)
Roger E. Masse352e1861997-01-16 22:04:10 +000034
Raymond Hettingerd55111f2003-09-13 05:51:09 +000035 def test_len(self):
36 self.assertEqual(len(self.f), len(self.d))
37
38 def test_change(self):
39 self.f['r'] = 'discovered'
40 self.assertEqual(self.f['r'], 'discovered')
41 self.assert_('r' in self.f.keys())
42 self.assert_('discovered' in self.f.values())
43
44 def test_close_and_reopen(self):
45 if self.fname is None:
46 # if we're using an in-memory only db, we can't reopen it
47 # so finish here.
48 return
49 self.f.close()
50 self.f = self.openmethod[0](self.fname, 'w')
Guido van Rossumcc2b0162007-02-11 06:12:03 +000051 for k, v in self.d.items():
Raymond Hettingerd55111f2003-09-13 05:51:09 +000052 self.assertEqual(self.f[k], v)
53
54 def assertSetEquals(self, seqn1, seqn2):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000055 self.assertEqual(set(seqn1), set(seqn2))
Raymond Hettingerd55111f2003-09-13 05:51:09 +000056
57 def test_mapping_iteration_methods(self):
58 f = self.f
59 d = self.d
60 self.assertSetEquals(d, f)
61 self.assertSetEquals(d.keys(), f.keys())
62 self.assertSetEquals(d.values(), f.values())
63 self.assertSetEquals(d.items(), f.items())
Guido van Rossumcc2b0162007-02-11 06:12:03 +000064 self.assertSetEquals(d.keys(), f.keys())
65 self.assertSetEquals(d.values(), f.values())
66 self.assertSetEquals(d.items(), f.items())
Raymond Hettingerd55111f2003-09-13 05:51:09 +000067
Gregory P. Smitha703a212003-11-03 01:04:41 +000068 def test_iter_while_modifying_values(self):
69 if not hasattr(self.f, '__iter__'):
70 return
71
72 di = iter(self.d)
73 while 1:
74 try:
75 key = di.next()
76 self.d[key] = 'modified '+key
77 except StopIteration:
78 break
79
80 # it should behave the same as a dict. modifying values
81 # of existing keys should not break iteration. (adding
82 # or removing keys should)
83 fi = iter(self.f)
84 while 1:
85 try:
86 key = fi.next()
87 self.f[key] = 'modified '+key
88 except StopIteration:
89 break
90
91 self.test_mapping_iteration_methods()
92
93 def test_iteritems_while_modifying_values(self):
94 if not hasattr(self.f, 'iteritems'):
95 return
96
Brett Cannon5b8d24a2007-02-22 06:12:19 +000097 di = iter(self.d.items())
Gregory P. Smitha703a212003-11-03 01:04:41 +000098 while 1:
99 try:
100 k, v = di.next()
101 self.d[k] = 'modified '+v
102 except StopIteration:
103 break
104
105 # it should behave the same as a dict. modifying values
106 # of existing keys should not break iteration. (adding
107 # or removing keys should)
Brett Cannon5b8d24a2007-02-22 06:12:19 +0000108 fi = iter(self.f.items())
Gregory P. Smitha703a212003-11-03 01:04:41 +0000109 while 1:
110 try:
111 k, v = fi.next()
112 self.f[k] = 'modified '+v
113 except StopIteration:
114 break
115
116 self.test_mapping_iteration_methods()
117
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000118 def test_first_next_looping(self):
119 items = [self.f.first()]
120 for i in xrange(1, len(self.f)):
121 items.append(self.f.next())
122 self.assertSetEquals(items, self.d.items())
123
124 def test_previous_last_looping(self):
125 items = [self.f.last()]
126 for i in xrange(1, len(self.f)):
127 items.append(self.f.previous())
128 self.assertSetEquals(items, self.d.items())
129
130 def test_set_location(self):
131 self.assertEqual(self.f.set_location('e'), ('e', self.d['e']))
132
133 def test_contains(self):
134 for k in self.d:
135 self.assert_(k in self.f)
136 self.assert_('not here' not in self.f)
137
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000138 def test_clear(self):
139 self.f.clear()
140 self.assertEqual(len(self.f), 0)
141
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000142 def test__no_deadlock_first(self, debug=0):
143 # do this so that testers can see what function we're in in
144 # verbose mode when we deadlock.
145 sys.stdout.flush()
146
147 # in pybsddb's _DBWithCursor this causes an internal DBCursor
148 # object is created. Other test_ methods in this class could
149 # inadvertently cause the deadlock but an explicit test is needed.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000150 if debug: print("A")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000151 k,v = self.f.first()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000152 if debug: print("B", k)
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000153 self.f[k] = "deadlock. do not pass go. do not collect $200."
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000154 if debug: print("C")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000155 # if the bsddb implementation leaves the DBCursor open during
156 # the database write and locking+threading support is enabled
157 # the cursor's read lock will deadlock the write lock request..
158
159 # test the iterator interface (if present)
Gregory P. Smitha703a212003-11-03 01:04:41 +0000160 if hasattr(self.f, 'iteritems'):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000161 if debug: print("D")
Brett Cannon5b8d24a2007-02-22 06:12:19 +0000162 i = iter(self.f.items())
Gregory P. Smitha703a212003-11-03 01:04:41 +0000163 k,v = i.next()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000164 if debug: print("E")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000165 self.f[k] = "please don't deadlock"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000166 if debug: print("F")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000167 while 1:
168 try:
Gregory P. Smitha703a212003-11-03 01:04:41 +0000169 k,v = i.next()
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000170 except StopIteration:
171 break
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000172 if debug: print("F2")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000173
174 i = iter(self.f)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000175 if debug: print("G")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000176 while i:
177 try:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000178 if debug: print("H")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000179 k = i.next()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000180 if debug: print("I")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000181 self.f[k] = "deadlocks-r-us"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000182 if debug: print("J")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000183 except StopIteration:
184 i = None
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000185 if debug: print("K")
Gregory P. Smithdc113a82003-11-02 09:10:16 +0000186
187 # test the legacy cursor interface mixed with writes
188 self.assert_(self.f.first()[0] in self.d)
189 k = self.f.next()[0]
190 self.assert_(k in self.d)
191 self.f[k] = "be gone with ye deadlocks"
192 self.assert_(self.f[k], "be gone with ye deadlocks")
193
Gregory P. Smitha703a212003-11-03 01:04:41 +0000194 def test_for_cursor_memleak(self):
195 if not hasattr(self.f, 'iteritems'):
196 return
197
198 # do the bsddb._DBWithCursor _iter_mixin internals leak cursors?
199 nc1 = len(self.f._cursor_refs)
200 # create iterator
Guido van Rossum63eecc72007-02-22 23:55:25 +0000201 i = iter(self.f.iteritems())
Gregory P. Smitha703a212003-11-03 01:04:41 +0000202 nc2 = len(self.f._cursor_refs)
Guido van Rossum63eecc72007-02-22 23:55:25 +0000203 # use the iterator (should run to the first yield, creating the cursor)
Gregory P. Smitha703a212003-11-03 01:04:41 +0000204 k, v = i.next()
205 nc3 = len(self.f._cursor_refs)
206 # destroy the iterator; this should cause the weakref callback
207 # to remove the cursor object from self.f._cursor_refs
208 del i
209 nc4 = len(self.f._cursor_refs)
210
211 self.assertEqual(nc1, nc2)
212 self.assertEqual(nc1, nc4)
Guido van Rossum63eecc72007-02-22 23:55:25 +0000213 self.assertEqual(nc3, nc1+1)
Gregory P. Smitha703a212003-11-03 01:04:41 +0000214
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000215 def test_popitem(self):
216 k, v = self.f.popitem()
217 self.assert_(k in self.d)
218 self.assert_(v in self.d.values())
219 self.assert_(k not in self.f)
220 self.assertEqual(len(self.d)-1, len(self.f))
221
222 def test_pop(self):
223 k = 'w'
224 v = self.f.pop(k)
225 self.assertEqual(v, self.d[k])
226 self.assert_(k not in self.f)
227 self.assert_(v not in self.f.values())
228 self.assertEqual(len(self.d)-1, len(self.f))
229
230 def test_get(self):
231 self.assertEqual(self.f.get('NotHere'), None)
232 self.assertEqual(self.f.get('NotHere', 'Default'), 'Default')
233 self.assertEqual(self.f.get('q', 'Default'), self.d['q'])
234
235 def test_setdefault(self):
236 self.assertEqual(self.f.setdefault('new', 'dog'), 'dog')
237 self.assertEqual(self.f.setdefault('r', 'cat'), self.d['r'])
238
239 def test_update(self):
240 new = dict(y='life', u='of', i='brian')
241 self.f.update(new)
242 self.d.update(new)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000243 for k, v in self.d.items():
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000244 self.assertEqual(self.f[k], v)
245
246 def test_keyordering(self):
247 if self.openmethod[0] is not bsddb.btopen:
248 return
Brett Cannon5b8d24a2007-02-22 06:12:19 +0000249 keys = sorted(self.d.keys())
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000250 self.assertEqual(self.f.first()[0], keys[0])
251 self.assertEqual(self.f.next()[0], keys[1])
252 self.assertEqual(self.f.last()[0], keys[-1])
253 self.assertEqual(self.f.previous()[0], keys[-2])
254 self.assertEqual(list(self.f), keys)
255
256class TestBTree(TestBSDDB):
257 fname = test_support.TESTFN
258 openmethod = [bsddb.btopen]
259
260class TestBTree_InMemory(TestBSDDB):
261 fname = None
262 openmethod = [bsddb.btopen]
263
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000264class TestBTree_InMemory_Truncate(TestBSDDB):
265 fname = None
266 openflag = 'n'
267 openmethod = [bsddb.btopen]
268
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000269class TestHashTable(TestBSDDB):
270 fname = test_support.TESTFN
271 openmethod = [bsddb.hashopen]
272
273class TestHashTable_InMemory(TestBSDDB):
274 fname = None
275 openmethod = [bsddb.hashopen]
276
277## # (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85
278## # appears broken... at least on
279## # Solaris Intel - rmasse 1/97
280
281def test_main(verbose=None):
282 test_support.run_unittest(
283 TestBTree,
284 TestHashTable,
285 TestBTree_InMemory,
286 TestHashTable_InMemory,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000287 TestBTree_InMemory_Truncate,
Raymond Hettingerd55111f2003-09-13 05:51:09 +0000288 )
289
290if __name__ == "__main__":
291 test_main(verbose=True)