ยปCore Development>Code coverage>Lib/bsddb/test/test_basics.py

Python code coverage for Lib/bsddb/test/test_basics.py

#countcontent
1n/a"""
2n/aBasic TestCases for BTree and hash DBs, with and without a DBEnv, with
3n/avarious DB flags, etc.
4n/a"""
5n/a
6n/aimport os
7n/aimport errno
8n/aimport string
9n/afrom pprint import pprint
10n/aimport unittest
11n/aimport time
12n/a
13n/afrom test_all import db, test_support, verbose, get_new_environment_path, \
14n/a get_new_database_path
15n/a
16n/aDASH = '-'
17n/a
18n/a
19n/a#----------------------------------------------------------------------
20n/a
21n/aclass VersionTestCase(unittest.TestCase):
22n/a def test00_version(self):
23n/a info = db.version()
24n/a if verbose:
25n/a print '\n', '-=' * 20
26n/a print 'bsddb.db.version(): %s' % (info, )
27n/a print db.DB_VERSION_STRING
28n/a print '-=' * 20
29n/a self.assertEqual(info, (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR,
30n/a db.DB_VERSION_PATCH))
31n/a
32n/a#----------------------------------------------------------------------
33n/a
34n/aclass BasicTestCase(unittest.TestCase):
35n/a dbtype = db.DB_UNKNOWN # must be set in derived class
36n/a cachesize = (0, 1024*1024, 1)
37n/a dbopenflags = 0
38n/a dbsetflags = 0
39n/a dbmode = 0660
40n/a dbname = None
41n/a useEnv = 0
42n/a envflags = 0
43n/a envsetflags = 0
44n/a
45n/a _numKeys = 1002 # PRIVATE. NOTE: must be an even value
46n/a
47n/a import sys
48n/a if sys.version_info < (2, 4):
49n/a def assertTrue(self, expr, msg=None):
50n/a self.failUnless(expr,msg=msg)
51n/a def assertFalse(self, expr, msg=None):
52n/a self.failIf(expr,msg=msg)
53n/a
54n/a def setUp(self):
55n/a if self.useEnv:
56n/a self.homeDir=get_new_environment_path()
57n/a try:
58n/a self.env = db.DBEnv()
59n/a self.env.set_lg_max(1024*1024)
60n/a self.env.set_tx_max(30)
61n/a self._t = int(time.time())
62n/a self.env.set_tx_timestamp(self._t)
63n/a self.env.set_flags(self.envsetflags, 1)
64n/a self.env.open(self.homeDir, self.envflags | db.DB_CREATE)
65n/a self.filename = "test"
66n/a # Yes, a bare except is intended, since we're re-raising the exc.
67n/a except:
68n/a test_support.rmtree(self.homeDir)
69n/a raise
70n/a else:
71n/a self.env = None
72n/a self.filename = get_new_database_path()
73n/a
74n/a # create and open the DB
75n/a self.d = db.DB(self.env)
76n/a if not self.useEnv :
77n/a if db.version() >= (4, 2) :
78n/a self.d.set_cachesize(*self.cachesize)
79n/a cachesize = self.d.get_cachesize()
80n/a self.assertEqual(cachesize[0], self.cachesize[0])
81n/a self.assertEqual(cachesize[2], self.cachesize[2])
82n/a # Berkeley DB expands the cache 25% accounting overhead,
83n/a # if the cache is small.
84n/a self.assertEqual(125, int(100.0*cachesize[1]/self.cachesize[1]))
85n/a self.d.set_flags(self.dbsetflags)
86n/a if self.dbname:
87n/a self.d.open(self.filename, self.dbname, self.dbtype,
88n/a self.dbopenflags|db.DB_CREATE, self.dbmode)
89n/a else:
90n/a self.d.open(self.filename, # try out keyword args
91n/a mode = self.dbmode,
92n/a dbtype = self.dbtype,
93n/a flags = self.dbopenflags|db.DB_CREATE)
94n/a
95n/a if not self.useEnv:
96n/a self.assertRaises(db.DBInvalidArgError,
97n/a self.d.set_cachesize, *self.cachesize)
98n/a
99n/a self.populateDB()
100n/a
101n/a
102n/a def tearDown(self):
103n/a self.d.close()
104n/a if self.env is not None:
105n/a self.env.close()
106n/a test_support.rmtree(self.homeDir)
107n/a else:
108n/a os.remove(self.filename)
109n/a
110n/a
111n/a
112n/a def populateDB(self, _txn=None):
113n/a d = self.d
114n/a
115n/a for x in range(self._numKeys//2):
116n/a key = '%04d' % (self._numKeys - x) # insert keys in reverse order
117n/a data = self.makeData(key)
118n/a d.put(key, data, _txn)
119n/a
120n/a d.put('empty value', '', _txn)
121n/a
122n/a for x in range(self._numKeys//2-1):
123n/a key = '%04d' % x # and now some in forward order
124n/a data = self.makeData(key)
125n/a d.put(key, data, _txn)
126n/a
127n/a if _txn:
128n/a _txn.commit()
129n/a
130n/a num = len(d)
131n/a if verbose:
132n/a print "created %d records" % num
133n/a
134n/a
135n/a def makeData(self, key):
136n/a return DASH.join([key] * 5)
137n/a
138n/a
139n/a
140n/a #----------------------------------------
141n/a
142n/a def test01_GetsAndPuts(self):
143n/a d = self.d
144n/a
145n/a if verbose:
146n/a print '\n', '-=' * 30
147n/a print "Running %s.test01_GetsAndPuts..." % self.__class__.__name__
148n/a
149n/a for key in ['0001', '0100', '0400', '0700', '0999']:
150n/a data = d.get(key)
151n/a if verbose:
152n/a print data
153n/a
154n/a self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321')
155n/a
156n/a # By default non-existent keys return None...
157n/a self.assertEqual(d.get('abcd'), None)
158n/a
159n/a # ...but they raise exceptions in other situations. Call
160n/a # set_get_returns_none() to change it.
161n/a try:
162n/a d.delete('abcd')
163n/a except db.DBNotFoundError, val:
164n/a import sys
165n/a if sys.version_info < (2, 6) :
166n/a self.assertEqual(val[0], db.DB_NOTFOUND)
167n/a else :
168n/a self.assertEqual(val.args[0], db.DB_NOTFOUND)
169n/a if verbose: print val
170n/a else:
171n/a self.fail("expected exception")
172n/a
173n/a
174n/a d.put('abcd', 'a new record')
175n/a self.assertEqual(d.get('abcd'), 'a new record')
176n/a
177n/a d.put('abcd', 'same key')
178n/a if self.dbsetflags & db.DB_DUP:
179n/a self.assertEqual(d.get('abcd'), 'a new record')
180n/a else:
181n/a self.assertEqual(d.get('abcd'), 'same key')
182n/a
183n/a
184n/a try:
185n/a d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE)
186n/a except db.DBKeyExistError, val:
187n/a import sys
188n/a if sys.version_info < (2, 6) :
189n/a self.assertEqual(val[0], db.DB_KEYEXIST)
190n/a else :
191n/a self.assertEqual(val.args[0], db.DB_KEYEXIST)
192n/a if verbose: print val
193n/a else:
194n/a self.fail("expected exception")
195n/a
196n/a if self.dbsetflags & db.DB_DUP:
197n/a self.assertEqual(d.get('abcd'), 'a new record')
198n/a else:
199n/a self.assertEqual(d.get('abcd'), 'same key')
200n/a
201n/a
202n/a d.sync()
203n/a d.close()
204n/a del d
205n/a
206n/a self.d = db.DB(self.env)
207n/a if self.dbname:
208n/a self.d.open(self.filename, self.dbname)
209n/a else:
210n/a self.d.open(self.filename)
211n/a d = self.d
212n/a
213n/a self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321')
214n/a if self.dbsetflags & db.DB_DUP:
215n/a self.assertEqual(d.get('abcd'), 'a new record')
216n/a else:
217n/a self.assertEqual(d.get('abcd'), 'same key')
218n/a
219n/a rec = d.get_both('0555', '0555-0555-0555-0555-0555')
220n/a if verbose:
221n/a print rec
222n/a
223n/a self.assertEqual(d.get_both('0555', 'bad data'), None)
224n/a
225n/a # test default value
226n/a data = d.get('bad key', 'bad data')
227n/a self.assertEqual(data, 'bad data')
228n/a
229n/a # any object can pass through
230n/a data = d.get('bad key', self)
231n/a self.assertEqual(data, self)
232n/a
233n/a s = d.stat()
234n/a self.assertEqual(type(s), type({}))
235n/a if verbose:
236n/a print 'd.stat() returned this dictionary:'
237n/a pprint(s)
238n/a
239n/a
240n/a #----------------------------------------
241n/a
242n/a def test02_DictionaryMethods(self):
243n/a d = self.d
244n/a
245n/a if verbose:
246n/a print '\n', '-=' * 30
247n/a print "Running %s.test02_DictionaryMethods..." % \
248n/a self.__class__.__name__
249n/a
250n/a for key in ['0002', '0101', '0401', '0701', '0998']:
251n/a data = d[key]
252n/a self.assertEqual(data, self.makeData(key))
253n/a if verbose:
254n/a print data
255n/a
256n/a self.assertEqual(len(d), self._numKeys)
257n/a keys = d.keys()
258n/a self.assertEqual(len(keys), self._numKeys)
259n/a self.assertEqual(type(keys), type([]))
260n/a
261n/a d['new record'] = 'a new record'
262n/a self.assertEqual(len(d), self._numKeys+1)
263n/a keys = d.keys()
264n/a self.assertEqual(len(keys), self._numKeys+1)
265n/a
266n/a d['new record'] = 'a replacement record'
267n/a self.assertEqual(len(d), self._numKeys+1)
268n/a keys = d.keys()
269n/a self.assertEqual(len(keys), self._numKeys+1)
270n/a
271n/a if verbose:
272n/a print "the first 10 keys are:"
273n/a pprint(keys[:10])
274n/a
275n/a self.assertEqual(d['new record'], 'a replacement record')
276n/a
277n/a# We check also the positional parameter
278n/a self.assertEqual(d.has_key('0001', None), 1)
279n/a# We check also the keyword parameter
280n/a self.assertEqual(d.has_key('spam', txn=None), 0)
281n/a
282n/a items = d.items()
283n/a self.assertEqual(len(items), self._numKeys+1)
284n/a self.assertEqual(type(items), type([]))
285n/a self.assertEqual(type(items[0]), type(()))
286n/a self.assertEqual(len(items[0]), 2)
287n/a
288n/a if verbose:
289n/a print "the first 10 items are:"
290n/a pprint(items[:10])
291n/a
292n/a values = d.values()
293n/a self.assertEqual(len(values), self._numKeys+1)
294n/a self.assertEqual(type(values), type([]))
295n/a
296n/a if verbose:
297n/a print "the first 10 values are:"
298n/a pprint(values[:10])
299n/a
300n/a
301n/a #----------------------------------------
302n/a
303n/a def test02b_SequenceMethods(self):
304n/a d = self.d
305n/a
306n/a for key in ['0002', '0101', '0401', '0701', '0998']:
307n/a data = d[key]
308n/a self.assertEqual(data, self.makeData(key))
309n/a if verbose:
310n/a print data
311n/a
312n/a self.assertTrue(hasattr(d, "__contains__"))
313n/a self.assertTrue("0401" in d)
314n/a self.assertFalse("1234" in d)
315n/a
316n/a
317n/a #----------------------------------------
318n/a
319n/a def test03_SimpleCursorStuff(self, get_raises_error=0, set_raises_error=0):
320n/a if verbose:
321n/a print '\n', '-=' * 30
322n/a print "Running %s.test03_SimpleCursorStuff (get_error %s, set_error %s)..." % \
323n/a (self.__class__.__name__, get_raises_error, set_raises_error)
324n/a
325n/a if self.env and self.dbopenflags & db.DB_AUTO_COMMIT:
326n/a txn = self.env.txn_begin()
327n/a else:
328n/a txn = None
329n/a c = self.d.cursor(txn=txn)
330n/a
331n/a rec = c.first()
332n/a count = 0
333n/a while rec is not None:
334n/a count = count + 1
335n/a if verbose and count % 100 == 0:
336n/a print rec
337n/a try:
338n/a rec = c.next()
339n/a except db.DBNotFoundError, val:
340n/a if get_raises_error:
341n/a import sys
342n/a if sys.version_info < (2, 6) :
343n/a self.assertEqual(val[0], db.DB_NOTFOUND)
344n/a else :
345n/a self.assertEqual(val.args[0], db.DB_NOTFOUND)
346n/a if verbose: print val
347n/a rec = None
348n/a else:
349n/a self.fail("unexpected DBNotFoundError")
350n/a self.assertEqual(c.get_current_size(), len(c.current()[1]),
351n/a "%s != len(%r)" % (c.get_current_size(), c.current()[1]))
352n/a
353n/a self.assertEqual(count, self._numKeys)
354n/a
355n/a
356n/a rec = c.last()
357n/a count = 0
358n/a while rec is not None:
359n/a count = count + 1
360n/a if verbose and count % 100 == 0:
361n/a print rec
362n/a try:
363n/a rec = c.prev()
364n/a except db.DBNotFoundError, val:
365n/a if get_raises_error:
366n/a import sys
367n/a if sys.version_info < (2, 6) :
368n/a self.assertEqual(val[0], db.DB_NOTFOUND)
369n/a else :
370n/a self.assertEqual(val.args[0], db.DB_NOTFOUND)
371n/a if verbose: print val
372n/a rec = None
373n/a else:
374n/a self.fail("unexpected DBNotFoundError")
375n/a
376n/a self.assertEqual(count, self._numKeys)
377n/a
378n/a rec = c.set('0505')
379n/a rec2 = c.current()
380n/a self.assertEqual(rec, rec2)
381n/a self.assertEqual(rec[0], '0505')
382n/a self.assertEqual(rec[1], self.makeData('0505'))
383n/a self.assertEqual(c.get_current_size(), len(rec[1]))
384n/a
385n/a # make sure we get empty values properly
386n/a rec = c.set('empty value')
387n/a self.assertEqual(rec[1], '')
388n/a self.assertEqual(c.get_current_size(), 0)
389n/a
390n/a try:
391n/a n = c.set('bad key')
392n/a except db.DBNotFoundError, val:
393n/a import sys
394n/a if sys.version_info < (2, 6) :
395n/a self.assertEqual(val[0], db.DB_NOTFOUND)
396n/a else :
397n/a self.assertEqual(val.args[0], db.DB_NOTFOUND)
398n/a if verbose: print val
399n/a else:
400n/a if set_raises_error:
401n/a self.fail("expected exception")
402n/a if n is not None:
403n/a self.fail("expected None: %r" % (n,))
404n/a
405n/a rec = c.get_both('0404', self.makeData('0404'))
406n/a self.assertEqual(rec, ('0404', self.makeData('0404')))
407n/a
408n/a try:
409n/a n = c.get_both('0404', 'bad data')
410n/a except db.DBNotFoundError, val:
411n/a import sys
412n/a if sys.version_info < (2, 6) :
413n/a self.assertEqual(val[0], db.DB_NOTFOUND)
414n/a else :
415n/a self.assertEqual(val.args[0], db.DB_NOTFOUND)
416n/a if verbose: print val
417n/a else:
418n/a if get_raises_error:
419n/a self.fail("expected exception")
420n/a if n is not None:
421n/a self.fail("expected None: %r" % (n,))
422n/a
423n/a if self.d.get_type() == db.DB_BTREE:
424n/a rec = c.set_range('011')
425n/a if verbose:
426n/a print "searched for '011', found: ", rec
427n/a
428n/a rec = c.set_range('011',dlen=0,doff=0)
429n/a if verbose:
430n/a print "searched (partial) for '011', found: ", rec
431n/a if rec[1] != '': self.fail('expected empty data portion')
432n/a
433n/a ev = c.set_range('empty value')
434n/a if verbose:
435n/a print "search for 'empty value' returned", ev
436n/a if ev[1] != '': self.fail('empty value lookup failed')
437n/a
438n/a c.set('0499')
439n/a c.delete()
440n/a try:
441n/a rec = c.current()
442n/a except db.DBKeyEmptyError, val:
443n/a if get_raises_error:
444n/a import sys
445n/a if sys.version_info < (2, 6) :
446n/a self.assertEqual(val[0], db.DB_KEYEMPTY)
447n/a else :
448n/a self.assertEqual(val.args[0], db.DB_KEYEMPTY)
449n/a if verbose: print val
450n/a else:
451n/a self.fail("unexpected DBKeyEmptyError")
452n/a else:
453n/a if get_raises_error:
454n/a self.fail('DBKeyEmptyError exception expected')
455n/a
456n/a c.next()
457n/a c2 = c.dup(db.DB_POSITION)
458n/a self.assertEqual(c.current(), c2.current())
459n/a
460n/a c2.put('', 'a new value', db.DB_CURRENT)
461n/a self.assertEqual(c.current(), c2.current())
462n/a self.assertEqual(c.current()[1], 'a new value')
463n/a
464n/a c2.put('', 'er', db.DB_CURRENT, dlen=0, doff=5)
465n/a self.assertEqual(c2.current()[1], 'a newer value')
466n/a
467n/a c.close()
468n/a c2.close()
469n/a if txn:
470n/a txn.commit()
471n/a
472n/a # time to abuse the closed cursors and hope we don't crash
473n/a methods_to_test = {
474n/a 'current': (),
475n/a 'delete': (),
476n/a 'dup': (db.DB_POSITION,),
477n/a 'first': (),
478n/a 'get': (0,),
479n/a 'next': (),
480n/a 'prev': (),
481n/a 'last': (),
482n/a 'put':('', 'spam', db.DB_CURRENT),
483n/a 'set': ("0505",),
484n/a }
485n/a for method, args in methods_to_test.items():
486n/a try:
487n/a if verbose:
488n/a print "attempting to use a closed cursor's %s method" % \
489n/a method
490n/a # a bug may cause a NULL pointer dereference...
491n/a getattr(c, method)(*args)
492n/a except db.DBError, val:
493n/a import sys
494n/a if sys.version_info < (2, 6) :
495n/a self.assertEqual(val[0], 0)
496n/a else :
497n/a self.assertEqual(val.args[0], 0)
498n/a if verbose: print val
499n/a else:
500n/a self.fail("no exception raised when using a buggy cursor's"
501n/a "%s method" % method)
502n/a
503n/a #
504n/a # free cursor referencing a closed database, it should not barf:
505n/a #
506n/a oldcursor = self.d.cursor(txn=txn)
507n/a self.d.close()
508n/a
509n/a # this would originally cause a segfault when the cursor for a
510n/a # closed database was cleaned up. it should not anymore.
511n/a # SF pybsddb bug id 667343
512n/a del oldcursor
513n/a
514n/a def test03b_SimpleCursorWithoutGetReturnsNone0(self):
515n/a # same test but raise exceptions instead of returning None
516n/a if verbose:
517n/a print '\n', '-=' * 30
518n/a print "Running %s.test03b_SimpleCursorStuffWithoutGetReturnsNone..." % \
519n/a self.__class__.__name__
520n/a
521n/a old = self.d.set_get_returns_none(0)
522n/a self.assertEqual(old, 2)
523n/a self.test03_SimpleCursorStuff(get_raises_error=1, set_raises_error=1)
524n/a
525n/a def test03b_SimpleCursorWithGetReturnsNone1(self):
526n/a # same test but raise exceptions instead of returning None
527n/a if verbose:
528n/a print '\n', '-=' * 30
529n/a print "Running %s.test03b_SimpleCursorStuffWithoutGetReturnsNone..." % \
530n/a self.__class__.__name__
531n/a
532n/a old = self.d.set_get_returns_none(1)
533n/a self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=1)
534n/a
535n/a
536n/a def test03c_SimpleCursorGetReturnsNone2(self):
537n/a # same test but raise exceptions instead of returning None
538n/a if verbose:
539n/a print '\n', '-=' * 30
540n/a print "Running %s.test03c_SimpleCursorStuffWithoutSetReturnsNone..." % \
541n/a self.__class__.__name__
542n/a
543n/a old = self.d.set_get_returns_none(1)
544n/a self.assertEqual(old, 2)
545n/a old = self.d.set_get_returns_none(2)
546n/a self.assertEqual(old, 1)
547n/a self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=0)
548n/a
549n/a if db.version() >= (4, 6):
550n/a def test03d_SimpleCursorPriority(self) :
551n/a c = self.d.cursor()
552n/a c.set_priority(db.DB_PRIORITY_VERY_LOW) # Positional
553n/a self.assertEqual(db.DB_PRIORITY_VERY_LOW, c.get_priority())
554n/a c.set_priority(priority=db.DB_PRIORITY_HIGH) # Keyword
555n/a self.assertEqual(db.DB_PRIORITY_HIGH, c.get_priority())
556n/a c.close()
557n/a
558n/a #----------------------------------------
559n/a
560n/a def test04_PartialGetAndPut(self):
561n/a d = self.d
562n/a if verbose:
563n/a print '\n', '-=' * 30
564n/a print "Running %s.test04_PartialGetAndPut..." % \
565n/a self.__class__.__name__
566n/a
567n/a key = "partialTest"
568n/a data = "1" * 1000 + "2" * 1000
569n/a d.put(key, data)
570n/a self.assertEqual(d.get(key), data)
571n/a self.assertEqual(d.get(key, dlen=20, doff=990),
572n/a ("1" * 10) + ("2" * 10))
573n/a
574n/a d.put("partialtest2", ("1" * 30000) + "robin" )
575n/a self.assertEqual(d.get("partialtest2", dlen=5, doff=30000), "robin")
576n/a
577n/a # There seems to be a bug in DB here... Commented out the test for
578n/a # now.
579n/a ##self.assertEqual(d.get("partialtest2", dlen=5, doff=30010), "")
580n/a
581n/a if self.dbsetflags != db.DB_DUP:
582n/a # Partial put with duplicate records requires a cursor
583n/a d.put(key, "0000", dlen=2000, doff=0)
584n/a self.assertEqual(d.get(key), "0000")
585n/a
586n/a d.put(key, "1111", dlen=1, doff=2)
587n/a self.assertEqual(d.get(key), "0011110")
588n/a
589n/a #----------------------------------------
590n/a
591n/a def test05_GetSize(self):
592n/a d = self.d
593n/a if verbose:
594n/a print '\n', '-=' * 30
595n/a print "Running %s.test05_GetSize..." % self.__class__.__name__
596n/a
597n/a for i in range(1, 50000, 500):
598n/a key = "size%s" % i
599n/a #print "before ", i,
600n/a d.put(key, "1" * i)
601n/a #print "after",
602n/a self.assertEqual(d.get_size(key), i)
603n/a #print "done"
604n/a
605n/a #----------------------------------------
606n/a
607n/a def test06_Truncate(self):
608n/a d = self.d
609n/a if verbose:
610n/a print '\n', '-=' * 30
611n/a print "Running %s.test06_Truncate..." % self.__class__.__name__
612n/a
613n/a d.put("abcde", "ABCDE");
614n/a num = d.truncate()
615n/a self.assert_(num >= 1, "truncate returned <= 0 on non-empty database")
616n/a num = d.truncate()
617n/a self.assertEqual(num, 0,
618n/a "truncate on empty DB returned nonzero (%r)" % (num,))
619n/a
620n/a #----------------------------------------
621n/a
622n/a def test07_verify(self):
623n/a # Verify bug solved in 4.7.3pre8
624n/a self.d.close()
625n/a d = db.DB(self.env)
626n/a d.verify(self.filename)
627n/a
628n/a
629n/a #----------------------------------------
630n/a
631n/a if db.version() >= (4, 6):
632n/a def test08_exists(self) :
633n/a self.d.put("abcde", "ABCDE")
634n/a self.assert_(self.d.exists("abcde") == True,
635n/a "DB->exists() returns wrong value")
636n/a self.assert_(self.d.exists("x") == False,
637n/a "DB->exists() returns wrong value")
638n/a
639n/a #----------------------------------------
640n/a
641n/a if db.version() >= (4, 7):
642n/a def test_compact(self) :
643n/a d = self.d
644n/a self.assertEqual(0, d.compact(flags=db.DB_FREELIST_ONLY))
645n/a self.assertEqual(0, d.compact(flags=db.DB_FREELIST_ONLY))
646n/a d.put("abcde", "ABCDE");
647n/a d.put("bcde", "BCDE");
648n/a d.put("abc", "ABC");
649n/a d.put("monty", "python");
650n/a d.delete("abc")
651n/a d.delete("bcde")
652n/a d.compact(start='abcde', stop='monty', txn=None,
653n/a compact_fillpercent=42, compact_pages=1,
654n/a compact_timeout=50000000,
655n/a flags=db.DB_FREELIST_ONLY|db.DB_FREE_SPACE)
656n/a
657n/a #----------------------------------------
658n/a
659n/a#----------------------------------------------------------------------
660n/a
661n/a
662n/aclass BasicBTreeTestCase(BasicTestCase):
663n/a dbtype = db.DB_BTREE
664n/a
665n/a
666n/aclass BasicHashTestCase(BasicTestCase):
667n/a dbtype = db.DB_HASH
668n/a
669n/a
670n/aclass BasicBTreeWithThreadFlagTestCase(BasicTestCase):
671n/a dbtype = db.DB_BTREE
672n/a dbopenflags = db.DB_THREAD
673n/a
674n/a
675n/aclass BasicHashWithThreadFlagTestCase(BasicTestCase):
676n/a dbtype = db.DB_HASH
677n/a dbopenflags = db.DB_THREAD
678n/a
679n/a
680n/aclass BasicWithEnvTestCase(BasicTestCase):
681n/a dbopenflags = db.DB_THREAD
682n/a useEnv = 1
683n/a envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
684n/a
685n/a #----------------------------------------
686n/a
687n/a def test09_EnvRemoveAndRename(self):
688n/a if not self.env:
689n/a return
690n/a
691n/a if verbose:
692n/a print '\n', '-=' * 30
693n/a print "Running %s.test09_EnvRemoveAndRename..." % self.__class__.__name__
694n/a
695n/a # can't rename or remove an open DB
696n/a self.d.close()
697n/a
698n/a newname = self.filename + '.renamed'
699n/a self.env.dbrename(self.filename, None, newname)
700n/a self.env.dbremove(newname)
701n/a
702n/a #----------------------------------------
703n/a
704n/aclass BasicBTreeWithEnvTestCase(BasicWithEnvTestCase):
705n/a dbtype = db.DB_BTREE
706n/a
707n/a
708n/aclass BasicHashWithEnvTestCase(BasicWithEnvTestCase):
709n/a dbtype = db.DB_HASH
710n/a
711n/a
712n/a#----------------------------------------------------------------------
713n/a
714n/aclass BasicTransactionTestCase(BasicTestCase):
715n/a import sys
716n/a if sys.version_info < (2, 4):
717n/a def assertTrue(self, expr, msg=None):
718n/a return self.failUnless(expr,msg=msg)
719n/a
720n/a if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
721n/a (sys.version_info < (3, 2))) :
722n/a def assertIn(self, a, b, msg=None) :
723n/a return self.assertTrue(a in b, msg=msg)
724n/a
725n/a dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
726n/a useEnv = 1
727n/a envflags = (db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
728n/a db.DB_INIT_TXN)
729n/a envsetflags = db.DB_AUTO_COMMIT
730n/a
731n/a
732n/a def tearDown(self):
733n/a self.txn.commit()
734n/a BasicTestCase.tearDown(self)
735n/a
736n/a
737n/a def populateDB(self):
738n/a txn = self.env.txn_begin()
739n/a BasicTestCase.populateDB(self, _txn=txn)
740n/a
741n/a self.txn = self.env.txn_begin()
742n/a
743n/a
744n/a def test06_Transactions(self):
745n/a d = self.d
746n/a if verbose:
747n/a print '\n', '-=' * 30
748n/a print "Running %s.test06_Transactions..." % self.__class__.__name__
749n/a
750n/a self.assertEqual(d.get('new rec', txn=self.txn), None)
751n/a d.put('new rec', 'this is a new record', self.txn)
752n/a self.assertEqual(d.get('new rec', txn=self.txn),
753n/a 'this is a new record')
754n/a self.txn.abort()
755n/a self.assertEqual(d.get('new rec'), None)
756n/a
757n/a self.txn = self.env.txn_begin()
758n/a
759n/a self.assertEqual(d.get('new rec', txn=self.txn), None)
760n/a d.put('new rec', 'this is a new record', self.txn)
761n/a self.assertEqual(d.get('new rec', txn=self.txn),
762n/a 'this is a new record')
763n/a self.txn.commit()
764n/a self.assertEqual(d.get('new rec'), 'this is a new record')
765n/a
766n/a self.txn = self.env.txn_begin()
767n/a c = d.cursor(self.txn)
768n/a rec = c.first()
769n/a count = 0
770n/a while rec is not None:
771n/a count = count + 1
772n/a if verbose and count % 100 == 0:
773n/a print rec
774n/a rec = c.next()
775n/a self.assertEqual(count, self._numKeys+1)
776n/a
777n/a c.close() # Cursors *MUST* be closed before commit!
778n/a self.txn.commit()
779n/a
780n/a # flush pending updates
781n/a self.env.txn_checkpoint (0, 0, 0)
782n/a
783n/a statDict = self.env.log_stat(0);
784n/a self.assertIn('magic', statDict)
785n/a self.assertIn('version', statDict)
786n/a self.assertIn('cur_file', statDict)
787n/a self.assertIn('region_nowait', statDict)
788n/a
789n/a # must have at least one log file present:
790n/a logs = self.env.log_archive(db.DB_ARCH_ABS | db.DB_ARCH_LOG)
791n/a self.assertNotEqual(logs, None)
792n/a for log in logs:
793n/a if verbose:
794n/a print 'log file: ' + log
795n/a if db.version() >= (4,2):
796n/a logs = self.env.log_archive(db.DB_ARCH_REMOVE)
797n/a self.assertTrue(not logs)
798n/a
799n/a self.txn = self.env.txn_begin()
800n/a
801n/a #----------------------------------------
802n/a
803n/a if db.version() >= (4, 6):
804n/a def test08_exists(self) :
805n/a txn = self.env.txn_begin()
806n/a self.d.put("abcde", "ABCDE", txn=txn)
807n/a txn.commit()
808n/a txn = self.env.txn_begin()
809n/a self.assert_(self.d.exists("abcde", txn=txn) == True,
810n/a "DB->exists() returns wrong value")
811n/a self.assert_(self.d.exists("x", txn=txn) == False,
812n/a "DB->exists() returns wrong value")
813n/a txn.abort()
814n/a
815n/a #----------------------------------------
816n/a
817n/a def test09_TxnTruncate(self):
818n/a d = self.d
819n/a if verbose:
820n/a print '\n', '-=' * 30
821n/a print "Running %s.test09_TxnTruncate..." % self.__class__.__name__
822n/a
823n/a d.put("abcde", "ABCDE");
824n/a txn = self.env.txn_begin()
825n/a num = d.truncate(txn)
826n/a self.assert_(num >= 1, "truncate returned <= 0 on non-empty database")
827n/a num = d.truncate(txn)
828n/a self.assertEqual(num, 0,
829n/a "truncate on empty DB returned nonzero (%r)" % (num,))
830n/a txn.commit()
831n/a
832n/a #----------------------------------------
833n/a
834n/a def test10_TxnLateUse(self):
835n/a txn = self.env.txn_begin()
836n/a txn.abort()
837n/a try:
838n/a txn.abort()
839n/a except db.DBError, e:
840n/a pass
841n/a else:
842n/a raise RuntimeError, "DBTxn.abort() called after DB_TXN no longer valid w/o an exception"
843n/a
844n/a txn = self.env.txn_begin()
845n/a txn.commit()
846n/a try:
847n/a txn.commit()
848n/a except db.DBError, e:
849n/a pass
850n/a else:
851n/a raise RuntimeError, "DBTxn.commit() called after DB_TXN no longer valid w/o an exception"
852n/a
853n/a
854n/a #----------------------------------------
855n/a
856n/a
857n/a if db.version() >= (4, 4):
858n/a def test_txn_name(self) :
859n/a txn=self.env.txn_begin()
860n/a self.assertEqual(txn.get_name(), "")
861n/a txn.set_name("XXYY")
862n/a self.assertEqual(txn.get_name(), "XXYY")
863n/a txn.set_name("")
864n/a self.assertEqual(txn.get_name(), "")
865n/a txn.abort()
866n/a
867n/a #----------------------------------------
868n/a
869n/a
870n/a def test_txn_set_timeout(self) :
871n/a txn=self.env.txn_begin()
872n/a txn.set_timeout(1234567, db.DB_SET_LOCK_TIMEOUT)
873n/a txn.set_timeout(2345678, flags=db.DB_SET_TXN_TIMEOUT)
874n/a txn.abort()
875n/a
876n/a #----------------------------------------
877n/a
878n/a if db.version() >= (4, 2) :
879n/a def test_get_tx_max(self) :
880n/a self.assertEqual(self.env.get_tx_max(), 30)
881n/a
882n/a def test_get_tx_timestamp(self) :
883n/a self.assertEqual(self.env.get_tx_timestamp(), self._t)
884n/a
885n/a
886n/a
887n/aclass BTreeTransactionTestCase(BasicTransactionTestCase):
888n/a dbtype = db.DB_BTREE
889n/a
890n/aclass HashTransactionTestCase(BasicTransactionTestCase):
891n/a dbtype = db.DB_HASH
892n/a
893n/a
894n/a
895n/a#----------------------------------------------------------------------
896n/a
897n/aclass BTreeRecnoTestCase(BasicTestCase):
898n/a dbtype = db.DB_BTREE
899n/a dbsetflags = db.DB_RECNUM
900n/a
901n/a def test09_RecnoInBTree(self):
902n/a d = self.d
903n/a if verbose:
904n/a print '\n', '-=' * 30
905n/a print "Running %s.test09_RecnoInBTree..." % self.__class__.__name__
906n/a
907n/a rec = d.get(200)
908n/a self.assertEqual(type(rec), type(()))
909n/a self.assertEqual(len(rec), 2)
910n/a if verbose:
911n/a print "Record #200 is ", rec
912n/a
913n/a c = d.cursor()
914n/a c.set('0200')
915n/a num = c.get_recno()
916n/a self.assertEqual(type(num), type(1))
917n/a if verbose:
918n/a print "recno of d['0200'] is ", num
919n/a
920n/a rec = c.current()
921n/a self.assertEqual(c.set_recno(num), rec)
922n/a
923n/a c.close()
924n/a
925n/a
926n/a
927n/aclass BTreeRecnoWithThreadFlagTestCase(BTreeRecnoTestCase):
928n/a dbopenflags = db.DB_THREAD
929n/a
930n/a#----------------------------------------------------------------------
931n/a
932n/aclass BasicDUPTestCase(BasicTestCase):
933n/a dbsetflags = db.DB_DUP
934n/a
935n/a def test10_DuplicateKeys(self):
936n/a d = self.d
937n/a if verbose:
938n/a print '\n', '-=' * 30
939n/a print "Running %s.test10_DuplicateKeys..." % \
940n/a self.__class__.__name__
941n/a
942n/a d.put("dup0", "before")
943n/a for x in "The quick brown fox jumped over the lazy dog.".split():
944n/a d.put("dup1", x)
945n/a d.put("dup2", "after")
946n/a
947n/a data = d.get("dup1")
948n/a self.assertEqual(data, "The")
949n/a if verbose:
950n/a print data
951n/a
952n/a c = d.cursor()
953n/a rec = c.set("dup1")
954n/a self.assertEqual(rec, ('dup1', 'The'))
955n/a
956n/a next_reg = c.next()
957n/a self.assertEqual(next_reg, ('dup1', 'quick'))
958n/a
959n/a rec = c.set("dup1")
960n/a count = c.count()
961n/a self.assertEqual(count, 9)
962n/a
963n/a next_dup = c.next_dup()
964n/a self.assertEqual(next_dup, ('dup1', 'quick'))
965n/a
966n/a rec = c.set('dup1')
967n/a while rec is not None:
968n/a if verbose:
969n/a print rec
970n/a rec = c.next_dup()
971n/a
972n/a c.set('dup1')
973n/a rec = c.next_nodup()
974n/a self.assertNotEqual(rec[0], 'dup1')
975n/a if verbose:
976n/a print rec
977n/a
978n/a c.close()
979n/a
980n/a
981n/a
982n/aclass BTreeDUPTestCase(BasicDUPTestCase):
983n/a dbtype = db.DB_BTREE
984n/a
985n/aclass HashDUPTestCase(BasicDUPTestCase):
986n/a dbtype = db.DB_HASH
987n/a
988n/aclass BTreeDUPWithThreadTestCase(BasicDUPTestCase):
989n/a dbtype = db.DB_BTREE
990n/a dbopenflags = db.DB_THREAD
991n/a
992n/aclass HashDUPWithThreadTestCase(BasicDUPTestCase):
993n/a dbtype = db.DB_HASH
994n/a dbopenflags = db.DB_THREAD
995n/a
996n/a
997n/a#----------------------------------------------------------------------
998n/a
999n/aclass BasicMultiDBTestCase(BasicTestCase):
1000n/a dbname = 'first'
1001n/a
1002n/a def otherType(self):
1003n/a if self.dbtype == db.DB_BTREE:
1004n/a return db.DB_HASH
1005n/a else:
1006n/a return db.DB_BTREE
1007n/a
1008n/a def test11_MultiDB(self):
1009n/a d1 = self.d
1010n/a if verbose:
1011n/a print '\n', '-=' * 30
1012n/a print "Running %s.test11_MultiDB..." % self.__class__.__name__
1013n/a
1014n/a d2 = db.DB(self.env)
1015n/a d2.open(self.filename, "second", self.dbtype,
1016n/a self.dbopenflags|db.DB_CREATE)
1017n/a d3 = db.DB(self.env)
1018n/a d3.open(self.filename, "third", self.otherType(),
1019n/a self.dbopenflags|db.DB_CREATE)
1020n/a
1021n/a for x in "The quick brown fox jumped over the lazy dog".split():
1022n/a d2.put(x, self.makeData(x))
1023n/a
1024n/a for x in string.letters:
1025n/a d3.put(x, x*70)
1026n/a
1027n/a d1.sync()
1028n/a d2.sync()
1029n/a d3.sync()
1030n/a d1.close()
1031n/a d2.close()
1032n/a d3.close()
1033n/a
1034n/a self.d = d1 = d2 = d3 = None
1035n/a
1036n/a self.d = d1 = db.DB(self.env)
1037n/a d1.open(self.filename, self.dbname, flags = self.dbopenflags)
1038n/a d2 = db.DB(self.env)
1039n/a d2.open(self.filename, "second", flags = self.dbopenflags)
1040n/a d3 = db.DB(self.env)
1041n/a d3.open(self.filename, "third", flags = self.dbopenflags)
1042n/a
1043n/a c1 = d1.cursor()
1044n/a c2 = d2.cursor()
1045n/a c3 = d3.cursor()
1046n/a
1047n/a count = 0
1048n/a rec = c1.first()
1049n/a while rec is not None:
1050n/a count = count + 1
1051n/a if verbose and (count % 50) == 0:
1052n/a print rec
1053n/a rec = c1.next()
1054n/a self.assertEqual(count, self._numKeys)
1055n/a
1056n/a count = 0
1057n/a rec = c2.first()
1058n/a while rec is not None:
1059n/a count = count + 1
1060n/a if verbose:
1061n/a print rec
1062n/a rec = c2.next()
1063n/a self.assertEqual(count, 9)
1064n/a
1065n/a count = 0
1066n/a rec = c3.first()
1067n/a while rec is not None:
1068n/a count = count + 1
1069n/a if verbose:
1070n/a print rec
1071n/a rec = c3.next()
1072n/a self.assertEqual(count, len(string.letters))
1073n/a
1074n/a
1075n/a c1.close()
1076n/a c2.close()
1077n/a c3.close()
1078n/a
1079n/a d2.close()
1080n/a d3.close()
1081n/a
1082n/a
1083n/a
1084n/a# Strange things happen if you try to use Multiple DBs per file without a
1085n/a# DBEnv with MPOOL and LOCKing...
1086n/a
1087n/aclass BTreeMultiDBTestCase(BasicMultiDBTestCase):
1088n/a dbtype = db.DB_BTREE
1089n/a dbopenflags = db.DB_THREAD
1090n/a useEnv = 1
1091n/a envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
1092n/a
1093n/aclass HashMultiDBTestCase(BasicMultiDBTestCase):
1094n/a dbtype = db.DB_HASH
1095n/a dbopenflags = db.DB_THREAD
1096n/a useEnv = 1
1097n/a envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
1098n/a
1099n/a
1100n/aclass PrivateObject(unittest.TestCase) :
1101n/a import sys
1102n/a if sys.version_info < (2, 4):
1103n/a def assertTrue(self, expr, msg=None):
1104n/a self.failUnless(expr,msg=msg)
1105n/a
1106n/a def tearDown(self) :
1107n/a del self.obj
1108n/a
1109n/a def test01_DefaultIsNone(self) :
1110n/a self.assertEqual(self.obj.get_private(), None)
1111n/a
1112n/a def test02_assignment(self) :
1113n/a a = "example of private object"
1114n/a self.obj.set_private(a)
1115n/a b = self.obj.get_private()
1116n/a self.assertTrue(a is b) # Object identity
1117n/a
1118n/a def test03_leak_assignment(self) :
1119n/a import sys
1120n/a a = "example of private object"
1121n/a refcount = sys.getrefcount(a)
1122n/a self.obj.set_private(a)
1123n/a self.assertEqual(refcount+1, sys.getrefcount(a))
1124n/a self.obj.set_private(None)
1125n/a self.assertEqual(refcount, sys.getrefcount(a))
1126n/a
1127n/a def test04_leak_GC(self) :
1128n/a import sys
1129n/a a = "example of private object"
1130n/a refcount = sys.getrefcount(a)
1131n/a self.obj.set_private(a)
1132n/a self.obj = None
1133n/a self.assertEqual(refcount, sys.getrefcount(a))
1134n/a
1135n/aclass DBEnvPrivateObject(PrivateObject) :
1136n/a def setUp(self) :
1137n/a self.obj = db.DBEnv()
1138n/a
1139n/aclass DBPrivateObject(PrivateObject) :
1140n/a def setUp(self) :
1141n/a self.obj = db.DB()
1142n/a
1143n/aclass CrashAndBurn(unittest.TestCase) :
1144n/a import sys
1145n/a if sys.version_info < (2, 4):
1146n/a def assertTrue(self, expr, msg=None):
1147n/a self.failUnless(expr,msg=msg)
1148n/a
1149n/a #def test01_OpenCrash(self) :
1150n/a # # See http://bugs.python.org/issue3307
1151n/a # self.assertRaises(db.DBInvalidArgError, db.DB, None, 65535)
1152n/a
1153n/a if db.version() < (4, 8) :
1154n/a def test02_DBEnv_dealloc(self):
1155n/a # http://bugs.python.org/issue3885
1156n/a import gc
1157n/a self.assertRaises(db.DBInvalidArgError, db.DBEnv, ~db.DB_RPCCLIENT)
1158n/a gc.collect()
1159n/a
1160n/a
1161n/a#----------------------------------------------------------------------
1162n/a#----------------------------------------------------------------------
1163n/a
1164n/adef test_suite():
1165n/a suite = unittest.TestSuite()
1166n/a
1167n/a suite.addTest(unittest.makeSuite(VersionTestCase))
1168n/a suite.addTest(unittest.makeSuite(BasicBTreeTestCase))
1169n/a suite.addTest(unittest.makeSuite(BasicHashTestCase))
1170n/a suite.addTest(unittest.makeSuite(BasicBTreeWithThreadFlagTestCase))
1171n/a suite.addTest(unittest.makeSuite(BasicHashWithThreadFlagTestCase))
1172n/a suite.addTest(unittest.makeSuite(BasicBTreeWithEnvTestCase))
1173n/a suite.addTest(unittest.makeSuite(BasicHashWithEnvTestCase))
1174n/a suite.addTest(unittest.makeSuite(BTreeTransactionTestCase))
1175n/a suite.addTest(unittest.makeSuite(HashTransactionTestCase))
1176n/a suite.addTest(unittest.makeSuite(BTreeRecnoTestCase))
1177n/a suite.addTest(unittest.makeSuite(BTreeRecnoWithThreadFlagTestCase))
1178n/a suite.addTest(unittest.makeSuite(BTreeDUPTestCase))
1179n/a suite.addTest(unittest.makeSuite(HashDUPTestCase))
1180n/a suite.addTest(unittest.makeSuite(BTreeDUPWithThreadTestCase))
1181n/a suite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase))
1182n/a suite.addTest(unittest.makeSuite(BTreeMultiDBTestCase))
1183n/a suite.addTest(unittest.makeSuite(HashMultiDBTestCase))
1184n/a suite.addTest(unittest.makeSuite(DBEnvPrivateObject))
1185n/a suite.addTest(unittest.makeSuite(DBPrivateObject))
1186n/a suite.addTest(unittest.makeSuite(CrashAndBurn))
1187n/a
1188n/a return suite
1189n/a
1190n/a
1191n/aif __name__ == '__main__':
1192n/a unittest.main(defaultTest='test_suite')