blob: 37f4d11bc4e3e5d59587a07111ebbf1f4be0c0f2 [file] [log] [blame]
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +00001"""
2Basic TestCases for BTree and hash DBs, with and without a DBEnv, with
3various DB flags, etc.
4"""
5
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006import os
7import sys
8import errno
9import shutil
10import string
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000011import tempfile
12from pprint import pprint
13import unittest
14
15from bsddb import db
16
Barry Warsaw9a0d7792002-12-30 20:53:52 +000017from test_all import verbose
18
19DASH = '-'
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000020
21
22#----------------------------------------------------------------------
23
24class VersionTestCase(unittest.TestCase):
25 def test00_version(self):
26 info = db.version()
27 if verbose:
28 print '\n', '-=' * 20
29 print 'bsddb.db.version(): %s' % (info, )
30 print db.DB_VERSION_STRING
31 print '-=' * 20
Barry Warsaw9a0d7792002-12-30 20:53:52 +000032 assert info == (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR,
33 db.DB_VERSION_PATCH)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000034
35#----------------------------------------------------------------------
36
37class BasicTestCase(unittest.TestCase):
38 dbtype = db.DB_UNKNOWN # must be set in derived class
39 dbopenflags = 0
40 dbsetflags = 0
41 dbmode = 0660
42 dbname = None
43 useEnv = 0
44 envflags = 0
Barry Warsaw9a0d7792002-12-30 20:53:52 +000045 envsetflags = 0
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000046
47 def setUp(self):
48 if self.useEnv:
49 homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home')
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000050 self.homeDir = homeDir
Barry Warsaw9a0d7792002-12-30 20:53:52 +000051 try:
52 shutil.rmtree(homeDir)
53 except OSError, e:
54 # unix returns ENOENT, windows returns ESRCH
55 if e.errno not in (errno.ENOENT, errno.ESRCH): raise
56 os.mkdir(homeDir)
57 try:
58 self.env = db.DBEnv()
59 self.env.set_lg_max(1024*1024)
60 self.env.set_flags(self.envsetflags, 1)
61 self.env.open(homeDir, self.envflags | db.DB_CREATE)
62 tempfile.tempdir = homeDir
63 self.filename = os.path.split(tempfile.mktemp())[1]
64 tempfile.tempdir = None
65 # Yes, a bare except is intended, since we're re-raising the exc.
66 except:
67 shutil.rmtree(homeDir)
68 raise
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000069 else:
70 self.env = None
71 self.filename = tempfile.mktemp()
72
73 # create and open the DB
74 self.d = db.DB(self.env)
75 self.d.set_flags(self.dbsetflags)
76 if self.dbname:
77 self.d.open(self.filename, self.dbname, self.dbtype,
78 self.dbopenflags|db.DB_CREATE, self.dbmode)
79 else:
80 self.d.open(self.filename, # try out keyword args
81 mode = self.dbmode,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000082 dbtype = self.dbtype,
83 flags = self.dbopenflags|db.DB_CREATE)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000084
85 self.populateDB()
86
87
88 def tearDown(self):
89 self.d.close()
90 if self.env is not None:
91 self.env.close()
Barry Warsaw9a0d7792002-12-30 20:53:52 +000092 shutil.rmtree(self.homeDir)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000093 ## Make a new DBEnv to remove the env files from the home dir.
94 ## (It can't be done while the env is open, nor after it has been
95 ## closed, so we make a new one to do it.)
96 #e = db.DBEnv()
97 #e.remove(self.homeDir)
98 #os.remove(os.path.join(self.homeDir, self.filename))
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +000099 else:
100 os.remove(self.filename)
101
102
103
104 def populateDB(self):
105 d = self.d
106 for x in range(500):
107 key = '%04d' % (1000 - x) # insert keys in reverse order
108 data = self.makeData(key)
109 d.put(key, data)
110
111 for x in range(500):
112 key = '%04d' % x # and now some in forward order
113 data = self.makeData(key)
114 d.put(key, data)
115
116 num = len(d)
117 if verbose:
118 print "created %d records" % num
119
120
121 def makeData(self, key):
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000122 return DASH.join([key] * 5)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000123
124
125
126 #----------------------------------------
127
128 def test01_GetsAndPuts(self):
129 d = self.d
130
131 if verbose:
132 print '\n', '-=' * 30
133 print "Running %s.test01_GetsAndPuts..." % self.__class__.__name__
134
135 for key in ['0001', '0100', '0400', '0700', '0999']:
136 data = d.get(key)
137 if verbose:
138 print data
139
140 assert d.get('0321') == '0321-0321-0321-0321-0321'
141
142 # By default non-existant keys return None...
143 assert d.get('abcd') == None
144
145 # ...but they raise exceptions in other situations. Call
146 # set_get_returns_none() to change it.
147 try:
148 d.delete('abcd')
149 except db.DBNotFoundError, val:
150 assert val[0] == db.DB_NOTFOUND
151 if verbose: print val
152 else:
153 self.fail("expected exception")
154
155
156 d.put('abcd', 'a new record')
157 assert d.get('abcd') == 'a new record'
158
159 d.put('abcd', 'same key')
160 if self.dbsetflags & db.DB_DUP:
161 assert d.get('abcd') == 'a new record'
162 else:
163 assert d.get('abcd') == 'same key'
164
165
166 try:
167 d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE)
168 except db.DBKeyExistError, val:
169 assert val[0] == db.DB_KEYEXIST
170 if verbose: print val
171 else:
172 self.fail("expected exception")
173
174 if self.dbsetflags & db.DB_DUP:
175 assert d.get('abcd') == 'a new record'
176 else:
177 assert d.get('abcd') == 'same key'
178
179
180 d.sync()
181 d.close()
182 del d
183
184 self.d = db.DB(self.env)
185 if self.dbname:
186 self.d.open(self.filename, self.dbname)
187 else:
188 self.d.open(self.filename)
189 d = self.d
190
191 assert d.get('0321') == '0321-0321-0321-0321-0321'
192 if self.dbsetflags & db.DB_DUP:
193 assert d.get('abcd') == 'a new record'
194 else:
195 assert d.get('abcd') == 'same key'
196
197 rec = d.get_both('0555', '0555-0555-0555-0555-0555')
198 if verbose:
199 print rec
200
201 assert d.get_both('0555', 'bad data') == None
202
203 # test default value
204 data = d.get('bad key', 'bad data')
205 assert data == 'bad data'
206
207 # any object can pass through
208 data = d.get('bad key', self)
209 assert data == self
210
211 s = d.stat()
212 assert type(s) == type({})
213 if verbose:
214 print 'd.stat() returned this dictionary:'
215 pprint(s)
216
217
218 #----------------------------------------
219
220 def test02_DictionaryMethods(self):
221 d = self.d
222
223 if verbose:
224 print '\n', '-=' * 30
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000225 print "Running %s.test02_DictionaryMethods..." % \
226 self.__class__.__name__
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000227
228 for key in ['0002', '0101', '0401', '0701', '0998']:
229 data = d[key]
230 assert data == self.makeData(key)
231 if verbose:
232 print data
233
234 assert len(d) == 1000
235 keys = d.keys()
236 assert len(keys) == 1000
237 assert type(keys) == type([])
238
239 d['new record'] = 'a new record'
240 assert len(d) == 1001
241 keys = d.keys()
242 assert len(keys) == 1001
243
244 d['new record'] = 'a replacement record'
245 assert len(d) == 1001
246 keys = d.keys()
247 assert len(keys) == 1001
248
249 if verbose:
250 print "the first 10 keys are:"
251 pprint(keys[:10])
252
253 assert d['new record'] == 'a replacement record'
254
255 assert d.has_key('0001') == 1
256 assert d.has_key('spam') == 0
257
258 items = d.items()
259 assert len(items) == 1001
260 assert type(items) == type([])
261 assert type(items[0]) == type(())
262 assert len(items[0]) == 2
263
264 if verbose:
265 print "the first 10 items are:"
266 pprint(items[:10])
267
268 values = d.values()
269 assert len(values) == 1001
270 assert type(values) == type([])
271
272 if verbose:
273 print "the first 10 values are:"
274 pprint(values[:10])
275
276
277
278 #----------------------------------------
279
280 def test03_SimpleCursorStuff(self):
281 if verbose:
282 print '\n', '-=' * 30
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000283 print "Running %s.test03_SimpleCursorStuff..." % \
284 self.__class__.__name__
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000285
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000286 if self.env and self.dbopenflags & db.DB_AUTO_COMMIT:
287 txn = self.env.txn_begin()
288 else:
289 txn = None
290 c = self.d.cursor(txn=txn)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000291
292 rec = c.first()
293 count = 0
294 while rec is not None:
295 count = count + 1
296 if verbose and count % 100 == 0:
297 print rec
298 rec = c.next()
299
300 assert count == 1000
301
302
303 rec = c.last()
304 count = 0
305 while rec is not None:
306 count = count + 1
307 if verbose and count % 100 == 0:
308 print rec
309 rec = c.prev()
310
311 assert count == 1000
312
313 rec = c.set('0505')
314 rec2 = c.current()
315 assert rec == rec2
316 assert rec[0] == '0505'
317 assert rec[1] == self.makeData('0505')
318
319 try:
320 c.set('bad key')
321 except db.DBNotFoundError, val:
322 assert val[0] == db.DB_NOTFOUND
323 if verbose: print val
324 else:
325 self.fail("expected exception")
326
327 rec = c.get_both('0404', self.makeData('0404'))
328 assert rec == ('0404', self.makeData('0404'))
329
330 try:
331 c.get_both('0404', 'bad data')
332 except db.DBNotFoundError, val:
333 assert val[0] == db.DB_NOTFOUND
334 if verbose: print val
335 else:
336 self.fail("expected exception")
337
338 if self.d.get_type() == db.DB_BTREE:
339 rec = c.set_range('011')
340 if verbose:
341 print "searched for '011', found: ", rec
342
343 rec = c.set_range('011',dlen=0,doff=0)
344 if verbose:
345 print "searched (partial) for '011', found: ", rec
346 if rec[1] != '': set.fail('expected empty data portion')
347
348 c.set('0499')
349 c.delete()
350 try:
351 rec = c.current()
352 except db.DBKeyEmptyError, val:
353 assert val[0] == db.DB_KEYEMPTY
354 if verbose: print val
355 else:
356 self.fail('exception expected')
357
358 c.next()
359 c2 = c.dup(db.DB_POSITION)
360 assert c.current() == c2.current()
361
362 c2.put('', 'a new value', db.DB_CURRENT)
363 assert c.current() == c2.current()
364 assert c.current()[1] == 'a new value'
365
366 c2.put('', 'er', db.DB_CURRENT, dlen=0, doff=5)
367 assert c2.current()[1] == 'a newer value'
368
369 c.close()
370 c2.close()
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000371 if txn:
372 txn.commit()
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000373
374 # time to abuse the closed cursors and hope we don't crash
375 methods_to_test = {
376 'current': (),
377 'delete': (),
378 'dup': (db.DB_POSITION,),
379 'first': (),
380 'get': (0,),
381 'next': (),
382 'prev': (),
383 'last': (),
384 'put':('', 'spam', db.DB_CURRENT),
385 'set': ("0505",),
386 }
387 for method, args in methods_to_test.items():
388 try:
389 if verbose:
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000390 print "attempting to use a closed cursor's %s method" % \
391 method
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000392 # a bug may cause a NULL pointer dereference...
393 apply(getattr(c, method), args)
394 except db.DBError, val:
395 assert val[0] == 0
396 if verbose: print val
397 else:
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000398 self.fail("no exception raised when using a buggy cursor's"
399 "%s method" % method)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000400
401 #----------------------------------------
402
403 def test04_PartialGetAndPut(self):
404 d = self.d
405 if verbose:
406 print '\n', '-=' * 30
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 print "Running %s.test04_PartialGetAndPut..." % \
408 self.__class__.__name__
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000409
410 key = "partialTest"
411 data = "1" * 1000 + "2" * 1000
412 d.put(key, data)
413 assert d.get(key) == data
414 assert d.get(key, dlen=20, doff=990) == ("1" * 10) + ("2" * 10)
415
416 d.put("partialtest2", ("1" * 30000) + "robin" )
417 assert d.get("partialtest2", dlen=5, doff=30000) == "robin"
418
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000419 # There seems to be a bug in DB here... Commented out the test for
420 # now.
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000421 ##assert d.get("partialtest2", dlen=5, doff=30010) == ""
422
423 if self.dbsetflags != db.DB_DUP:
424 # Partial put with duplicate records requires a cursor
425 d.put(key, "0000", dlen=2000, doff=0)
426 assert d.get(key) == "0000"
427
428 d.put(key, "1111", dlen=1, doff=2)
429 assert d.get(key) == "0011110"
430
431 #----------------------------------------
432
433 def test05_GetSize(self):
434 d = self.d
435 if verbose:
436 print '\n', '-=' * 30
437 print "Running %s.test05_GetSize..." % self.__class__.__name__
438
439 for i in range(1, 50000, 500):
440 key = "size%s" % i
441 #print "before ", i,
442 d.put(key, "1" * i)
443 #print "after",
444 assert d.get_size(key) == i
445 #print "done"
446
447 #----------------------------------------
448
449 def test06_Truncate(self):
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000450 if db.version() < (3,3):
451 # truncate is a feature of BerkeleyDB 3.3 and above
452 return
453
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000454 d = self.d
455 if verbose:
456 print '\n', '-=' * 30
457 print "Running %s.test99_Truncate..." % self.__class__.__name__
458
459 d.put("abcde", "ABCDE");
460 num = d.truncate()
461 assert num >= 1, "truncate returned <= 0 on non-empty database"
462 num = d.truncate()
463 assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num`
464
465#----------------------------------------------------------------------
466
467
468class BasicBTreeTestCase(BasicTestCase):
469 dbtype = db.DB_BTREE
470
471
472class BasicHashTestCase(BasicTestCase):
473 dbtype = db.DB_HASH
474
475
476class BasicBTreeWithThreadFlagTestCase(BasicTestCase):
477 dbtype = db.DB_BTREE
478 dbopenflags = db.DB_THREAD
479
480
481class BasicHashWithThreadFlagTestCase(BasicTestCase):
482 dbtype = db.DB_HASH
483 dbopenflags = db.DB_THREAD
484
485
486class BasicBTreeWithEnvTestCase(BasicTestCase):
487 dbtype = db.DB_BTREE
488 dbopenflags = db.DB_THREAD
489 useEnv = 1
490 envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
491
492
493class BasicHashWithEnvTestCase(BasicTestCase):
494 dbtype = db.DB_HASH
495 dbopenflags = db.DB_THREAD
496 useEnv = 1
497 envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
498
499
500#----------------------------------------------------------------------
501
502class BasicTransactionTestCase(BasicTestCase):
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000503 dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000504 useEnv = 1
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000505 envflags = (db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
506 db.DB_INIT_TXN)
507 envsetflags = db.DB_AUTO_COMMIT
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000508
509
510 def tearDown(self):
511 self.txn.commit()
512 BasicTestCase.tearDown(self)
513
514
515 def populateDB(self):
516 d = self.d
517 txn = self.env.txn_begin()
518 for x in range(500):
519 key = '%04d' % (1000 - x) # insert keys in reverse order
520 data = self.makeData(key)
521 d.put(key, data, txn)
522
523 for x in range(500):
524 key = '%04d' % x # and now some in forward order
525 data = self.makeData(key)
526 d.put(key, data, txn)
527
528 txn.commit()
529
530 num = len(d)
531 if verbose:
532 print "created %d records" % num
533
534 self.txn = self.env.txn_begin()
535
536
537
538 def test06_Transactions(self):
539 d = self.d
540 if verbose:
541 print '\n', '-=' * 30
542 print "Running %s.test06_Transactions..." % self.__class__.__name__
543
544 assert d.get('new rec', txn=self.txn) == None
545 d.put('new rec', 'this is a new record', self.txn)
546 assert d.get('new rec', txn=self.txn) == 'this is a new record'
547 self.txn.abort()
548 assert d.get('new rec') == None
549
550 self.txn = self.env.txn_begin()
551
552 assert d.get('new rec', txn=self.txn) == None
553 d.put('new rec', 'this is a new record', self.txn)
554 assert d.get('new rec', txn=self.txn) == 'this is a new record'
555 self.txn.commit()
556 assert d.get('new rec') == 'this is a new record'
557
558 self.txn = self.env.txn_begin()
559 c = d.cursor(self.txn)
560 rec = c.first()
561 count = 0
562 while rec is not None:
563 count = count + 1
564 if verbose and count % 100 == 0:
565 print rec
566 rec = c.next()
567 assert count == 1001
568
569 c.close() # Cursors *MUST* be closed before commit!
570 self.txn.commit()
571
572 # flush pending updates
573 try:
574 self.env.txn_checkpoint (0, 0, 0)
575 except db.DBIncompleteError:
576 pass
577
578 # must have at least one log file present:
579 logs = self.env.log_archive(db.DB_ARCH_ABS | db.DB_ARCH_LOG)
580 assert logs != None
581 for log in logs:
582 if verbose:
583 print 'log file: ' + log
584
585 self.txn = self.env.txn_begin()
586
587 #----------------------------------------
588
589 def test07_TxnTruncate(self):
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000590 if db.version() < (3,3):
591 # truncate is a feature of BerkeleyDB 3.3 and above
592 return
593
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000594 d = self.d
595 if verbose:
596 print '\n', '-=' * 30
597 print "Running %s.test07_TxnTruncate..." % self.__class__.__name__
598
599 d.put("abcde", "ABCDE");
600 txn = self.env.txn_begin()
601 num = d.truncate(txn)
602 assert num >= 1, "truncate returned <= 0 on non-empty database"
603 num = d.truncate(txn)
604 assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num`
605 txn.commit()
606
607
608
609class BTreeTransactionTestCase(BasicTransactionTestCase):
610 dbtype = db.DB_BTREE
611
612class HashTransactionTestCase(BasicTransactionTestCase):
613 dbtype = db.DB_HASH
614
615
616
617#----------------------------------------------------------------------
618
619class BTreeRecnoTestCase(BasicTestCase):
620 dbtype = db.DB_BTREE
621 dbsetflags = db.DB_RECNUM
622
623 def test07_RecnoInBTree(self):
624 d = self.d
625 if verbose:
626 print '\n', '-=' * 30
627 print "Running %s.test07_RecnoInBTree..." % self.__class__.__name__
628
629 rec = d.get(200)
630 assert type(rec) == type(())
631 assert len(rec) == 2
632 if verbose:
633 print "Record #200 is ", rec
634
635 c = d.cursor()
636 c.set('0200')
637 num = c.get_recno()
638 assert type(num) == type(1)
639 if verbose:
640 print "recno of d['0200'] is ", num
641
642 rec = c.current()
643 assert c.set_recno(num) == rec
644
645 c.close()
646
647
648
649class BTreeRecnoWithThreadFlagTestCase(BTreeRecnoTestCase):
650 dbopenflags = db.DB_THREAD
651
652#----------------------------------------------------------------------
653
654class BasicDUPTestCase(BasicTestCase):
655 dbsetflags = db.DB_DUP
656
657 def test08_DuplicateKeys(self):
658 d = self.d
659 if verbose:
660 print '\n', '-=' * 30
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000661 print "Running %s.test08_DuplicateKeys..." % \
662 self.__class__.__name__
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000663
664 d.put("dup0", "before")
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000665 for x in "The quick brown fox jumped over the lazy dog.".split():
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000666 d.put("dup1", x)
667 d.put("dup2", "after")
668
669 data = d.get("dup1")
670 assert data == "The"
671 if verbose:
672 print data
673
674 c = d.cursor()
675 rec = c.set("dup1")
676 assert rec == ('dup1', 'The')
677
678 next = c.next()
679 assert next == ('dup1', 'quick')
680
681 rec = c.set("dup1")
682 count = c.count()
683 assert count == 9
684
685 next_dup = c.next_dup()
686 assert next_dup == ('dup1', 'quick')
687
688 rec = c.set('dup1')
689 while rec is not None:
690 if verbose:
691 print rec
692 rec = c.next_dup()
693
694 c.set('dup1')
695 rec = c.next_nodup()
696 assert rec[0] != 'dup1'
697 if verbose:
698 print rec
699
700 c.close()
701
702
703
704class BTreeDUPTestCase(BasicDUPTestCase):
705 dbtype = db.DB_BTREE
706
707class HashDUPTestCase(BasicDUPTestCase):
708 dbtype = db.DB_HASH
709
710class BTreeDUPWithThreadTestCase(BasicDUPTestCase):
711 dbtype = db.DB_BTREE
712 dbopenflags = db.DB_THREAD
713
714class HashDUPWithThreadTestCase(BasicDUPTestCase):
715 dbtype = db.DB_HASH
716 dbopenflags = db.DB_THREAD
717
718
719#----------------------------------------------------------------------
720
721class BasicMultiDBTestCase(BasicTestCase):
722 dbname = 'first'
723
724 def otherType(self):
725 if self.dbtype == db.DB_BTREE:
726 return db.DB_HASH
727 else:
728 return db.DB_BTREE
729
730 def test09_MultiDB(self):
731 d1 = self.d
732 if verbose:
733 print '\n', '-=' * 30
734 print "Running %s.test09_MultiDB..." % self.__class__.__name__
735
736 d2 = db.DB(self.env)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000737 d2.open(self.filename, "second", self.dbtype,
738 self.dbopenflags|db.DB_CREATE)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000739 d3 = db.DB(self.env)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000740 d3.open(self.filename, "third", self.otherType(),
741 self.dbopenflags|db.DB_CREATE)
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000742
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000743 for x in "The quick brown fox jumped over the lazy dog".split():
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000744 d2.put(x, self.makeData(x))
745
746 for x in string.letters:
747 d3.put(x, x*70)
748
749 d1.sync()
750 d2.sync()
751 d3.sync()
752 d1.close()
753 d2.close()
754 d3.close()
755
756 self.d = d1 = d2 = d3 = None
757
758 self.d = d1 = db.DB(self.env)
759 d1.open(self.filename, self.dbname, flags = self.dbopenflags)
760 d2 = db.DB(self.env)
761 d2.open(self.filename, "second", flags = self.dbopenflags)
762 d3 = db.DB(self.env)
763 d3.open(self.filename, "third", flags = self.dbopenflags)
764
765 c1 = d1.cursor()
766 c2 = d2.cursor()
767 c3 = d3.cursor()
768
769 count = 0
770 rec = c1.first()
771 while rec is not None:
772 count = count + 1
773 if verbose and (count % 50) == 0:
774 print rec
775 rec = c1.next()
776 assert count == 1000
777
778 count = 0
779 rec = c2.first()
780 while rec is not None:
781 count = count + 1
782 if verbose:
783 print rec
784 rec = c2.next()
785 assert count == 9
786
787 count = 0
788 rec = c3.first()
789 while rec is not None:
790 count = count + 1
791 if verbose:
792 print rec
793 rec = c3.next()
794 assert count == 52
795
796
797 c1.close()
798 c2.close()
799 c3.close()
800
801 d2.close()
802 d3.close()
803
804
805
806# Strange things happen if you try to use Multiple DBs per file without a
807# DBEnv with MPOOL and LOCKing...
808
809class BTreeMultiDBTestCase(BasicMultiDBTestCase):
810 dbtype = db.DB_BTREE
811 dbopenflags = db.DB_THREAD
812 useEnv = 1
813 envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
814
815class HashMultiDBTestCase(BasicMultiDBTestCase):
816 dbtype = db.DB_HASH
817 dbopenflags = db.DB_THREAD
818 useEnv = 1
819 envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
820
821
822#----------------------------------------------------------------------
823#----------------------------------------------------------------------
824
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000825def test_suite():
826 suite = unittest.TestSuite()
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000827
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000828 suite.addTest(unittest.makeSuite(VersionTestCase))
829 suite.addTest(unittest.makeSuite(BasicBTreeTestCase))
830 suite.addTest(unittest.makeSuite(BasicHashTestCase))
831 suite.addTest(unittest.makeSuite(BasicBTreeWithThreadFlagTestCase))
832 suite.addTest(unittest.makeSuite(BasicHashWithThreadFlagTestCase))
833 suite.addTest(unittest.makeSuite(BasicBTreeWithEnvTestCase))
834 suite.addTest(unittest.makeSuite(BasicHashWithEnvTestCase))
835 suite.addTest(unittest.makeSuite(BTreeTransactionTestCase))
836 suite.addTest(unittest.makeSuite(HashTransactionTestCase))
837 suite.addTest(unittest.makeSuite(BTreeRecnoTestCase))
838 suite.addTest(unittest.makeSuite(BTreeRecnoWithThreadFlagTestCase))
839 suite.addTest(unittest.makeSuite(BTreeDUPTestCase))
840 suite.addTest(unittest.makeSuite(HashDUPTestCase))
841 suite.addTest(unittest.makeSuite(BTreeDUPWithThreadTestCase))
842 suite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase))
843 suite.addTest(unittest.makeSuite(BTreeMultiDBTestCase))
844 suite.addTest(unittest.makeSuite(HashMultiDBTestCase))
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000845
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000846 return suite
Martin v. Löwis1c6b1a22002-11-19 17:47:07 +0000847
848
849if __name__ == '__main__':
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000850 unittest.main(defaultTest='test_suite')