/Lib/bsddb/test/test_basics.py

http://unladen-swallow.googlecode.com/ · Python · 1073 lines · 773 code · 236 blank · 64 comment · 159 complexity · 31f86134313566c9cae4a0be87a3c9a5 MD5 · raw file

  1. """
  2. Basic TestCases for BTree and hash DBs, with and without a DBEnv, with
  3. various DB flags, etc.
  4. """
  5. import os
  6. import errno
  7. import string
  8. from pprint import pprint
  9. import unittest
  10. import time
  11. from test_all import db, test_support, verbose, get_new_environment_path, \
  12. get_new_database_path
  13. DASH = '-'
  14. #----------------------------------------------------------------------
  15. class VersionTestCase(unittest.TestCase):
  16. def test00_version(self):
  17. info = db.version()
  18. if verbose:
  19. print '\n', '-=' * 20
  20. print 'bsddb.db.version(): %s' % (info, )
  21. print db.DB_VERSION_STRING
  22. print '-=' * 20
  23. self.assertEqual(info, (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR,
  24. db.DB_VERSION_PATCH))
  25. #----------------------------------------------------------------------
  26. class BasicTestCase(unittest.TestCase):
  27. dbtype = db.DB_UNKNOWN # must be set in derived class
  28. dbopenflags = 0
  29. dbsetflags = 0
  30. dbmode = 0660
  31. dbname = None
  32. useEnv = 0
  33. envflags = 0
  34. envsetflags = 0
  35. _numKeys = 1002 # PRIVATE. NOTE: must be an even value
  36. def setUp(self):
  37. if self.useEnv:
  38. self.homeDir=get_new_environment_path()
  39. try:
  40. self.env = db.DBEnv()
  41. self.env.set_lg_max(1024*1024)
  42. self.env.set_tx_max(30)
  43. self.env.set_tx_timestamp(int(time.time()))
  44. self.env.set_flags(self.envsetflags, 1)
  45. self.env.open(self.homeDir, self.envflags | db.DB_CREATE)
  46. self.filename = "test"
  47. # Yes, a bare except is intended, since we're re-raising the exc.
  48. except:
  49. test_support.rmtree(self.homeDir)
  50. raise
  51. else:
  52. self.env = None
  53. self.filename = get_new_database_path()
  54. # create and open the DB
  55. self.d = db.DB(self.env)
  56. self.d.set_flags(self.dbsetflags)
  57. if self.dbname:
  58. self.d.open(self.filename, self.dbname, self.dbtype,
  59. self.dbopenflags|db.DB_CREATE, self.dbmode)
  60. else:
  61. self.d.open(self.filename, # try out keyword args
  62. mode = self.dbmode,
  63. dbtype = self.dbtype,
  64. flags = self.dbopenflags|db.DB_CREATE)
  65. self.populateDB()
  66. def tearDown(self):
  67. self.d.close()
  68. if self.env is not None:
  69. self.env.close()
  70. test_support.rmtree(self.homeDir)
  71. else:
  72. os.remove(self.filename)
  73. def populateDB(self, _txn=None):
  74. d = self.d
  75. for x in range(self._numKeys//2):
  76. key = '%04d' % (self._numKeys - x) # insert keys in reverse order
  77. data = self.makeData(key)
  78. d.put(key, data, _txn)
  79. d.put('empty value', '', _txn)
  80. for x in range(self._numKeys//2-1):
  81. key = '%04d' % x # and now some in forward order
  82. data = self.makeData(key)
  83. d.put(key, data, _txn)
  84. if _txn:
  85. _txn.commit()
  86. num = len(d)
  87. if verbose:
  88. print "created %d records" % num
  89. def makeData(self, key):
  90. return DASH.join([key] * 5)
  91. #----------------------------------------
  92. def test01_GetsAndPuts(self):
  93. d = self.d
  94. if verbose:
  95. print '\n', '-=' * 30
  96. print "Running %s.test01_GetsAndPuts..." % self.__class__.__name__
  97. for key in ['0001', '0100', '0400', '0700', '0999']:
  98. data = d.get(key)
  99. if verbose:
  100. print data
  101. self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321')
  102. # By default non-existent keys return None...
  103. self.assertEqual(d.get('abcd'), None)
  104. # ...but they raise exceptions in other situations. Call
  105. # set_get_returns_none() to change it.
  106. try:
  107. d.delete('abcd')
  108. except db.DBNotFoundError, val:
  109. import sys
  110. if sys.version_info[0] < 3 :
  111. self.assertEqual(val[0], db.DB_NOTFOUND)
  112. else :
  113. self.assertEqual(val.args[0], db.DB_NOTFOUND)
  114. if verbose: print val
  115. else:
  116. self.fail("expected exception")
  117. d.put('abcd', 'a new record')
  118. self.assertEqual(d.get('abcd'), 'a new record')
  119. d.put('abcd', 'same key')
  120. if self.dbsetflags & db.DB_DUP:
  121. self.assertEqual(d.get('abcd'), 'a new record')
  122. else:
  123. self.assertEqual(d.get('abcd'), 'same key')
  124. try:
  125. d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE)
  126. except db.DBKeyExistError, val:
  127. import sys
  128. if sys.version_info[0] < 3 :
  129. self.assertEqual(val[0], db.DB_KEYEXIST)
  130. else :
  131. self.assertEqual(val.args[0], db.DB_KEYEXIST)
  132. if verbose: print val
  133. else:
  134. self.fail("expected exception")
  135. if self.dbsetflags & db.DB_DUP:
  136. self.assertEqual(d.get('abcd'), 'a new record')
  137. else:
  138. self.assertEqual(d.get('abcd'), 'same key')
  139. d.sync()
  140. d.close()
  141. del d
  142. self.d = db.DB(self.env)
  143. if self.dbname:
  144. self.d.open(self.filename, self.dbname)
  145. else:
  146. self.d.open(self.filename)
  147. d = self.d
  148. self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321')
  149. if self.dbsetflags & db.DB_DUP:
  150. self.assertEqual(d.get('abcd'), 'a new record')
  151. else:
  152. self.assertEqual(d.get('abcd'), 'same key')
  153. rec = d.get_both('0555', '0555-0555-0555-0555-0555')
  154. if verbose:
  155. print rec
  156. self.assertEqual(d.get_both('0555', 'bad data'), None)
  157. # test default value
  158. data = d.get('bad key', 'bad data')
  159. self.assertEqual(data, 'bad data')
  160. # any object can pass through
  161. data = d.get('bad key', self)
  162. self.assertEqual(data, self)
  163. s = d.stat()
  164. self.assertEqual(type(s), type({}))
  165. if verbose:
  166. print 'd.stat() returned this dictionary:'
  167. pprint(s)
  168. #----------------------------------------
  169. def test02_DictionaryMethods(self):
  170. d = self.d
  171. if verbose:
  172. print '\n', '-=' * 30
  173. print "Running %s.test02_DictionaryMethods..." % \
  174. self.__class__.__name__
  175. for key in ['0002', '0101', '0401', '0701', '0998']:
  176. data = d[key]
  177. self.assertEqual(data, self.makeData(key))
  178. if verbose:
  179. print data
  180. self.assertEqual(len(d), self._numKeys)
  181. keys = d.keys()
  182. self.assertEqual(len(keys), self._numKeys)
  183. self.assertEqual(type(keys), type([]))
  184. d['new record'] = 'a new record'
  185. self.assertEqual(len(d), self._numKeys+1)
  186. keys = d.keys()
  187. self.assertEqual(len(keys), self._numKeys+1)
  188. d['new record'] = 'a replacement record'
  189. self.assertEqual(len(d), self._numKeys+1)
  190. keys = d.keys()
  191. self.assertEqual(len(keys), self._numKeys+1)
  192. if verbose:
  193. print "the first 10 keys are:"
  194. pprint(keys[:10])
  195. self.assertEqual(d['new record'], 'a replacement record')
  196. # We check also the positional parameter
  197. self.assertEqual(d.has_key('0001', None), 1)
  198. # We check also the keyword parameter
  199. self.assertEqual(d.has_key('spam', txn=None), 0)
  200. items = d.items()
  201. self.assertEqual(len(items), self._numKeys+1)
  202. self.assertEqual(type(items), type([]))
  203. self.assertEqual(type(items[0]), type(()))
  204. self.assertEqual(len(items[0]), 2)
  205. if verbose:
  206. print "the first 10 items are:"
  207. pprint(items[:10])
  208. values = d.values()
  209. self.assertEqual(len(values), self._numKeys+1)
  210. self.assertEqual(type(values), type([]))
  211. if verbose:
  212. print "the first 10 values are:"
  213. pprint(values[:10])
  214. #----------------------------------------
  215. def test03_SimpleCursorStuff(self, get_raises_error=0, set_raises_error=0):
  216. if verbose:
  217. print '\n', '-=' * 30
  218. print "Running %s.test03_SimpleCursorStuff (get_error %s, set_error %s)..." % \
  219. (self.__class__.__name__, get_raises_error, set_raises_error)
  220. if self.env and self.dbopenflags & db.DB_AUTO_COMMIT:
  221. txn = self.env.txn_begin()
  222. else:
  223. txn = None
  224. c = self.d.cursor(txn=txn)
  225. rec = c.first()
  226. count = 0
  227. while rec is not None:
  228. count = count + 1
  229. if verbose and count % 100 == 0:
  230. print rec
  231. try:
  232. rec = c.next()
  233. except db.DBNotFoundError, val:
  234. if get_raises_error:
  235. import sys
  236. if sys.version_info[0] < 3 :
  237. self.assertEqual(val[0], db.DB_NOTFOUND)
  238. else :
  239. self.assertEqual(val.args[0], db.DB_NOTFOUND)
  240. if verbose: print val
  241. rec = None
  242. else:
  243. self.fail("unexpected DBNotFoundError")
  244. self.assertEqual(c.get_current_size(), len(c.current()[1]),
  245. "%s != len(%r)" % (c.get_current_size(), c.current()[1]))
  246. self.assertEqual(count, self._numKeys)
  247. rec = c.last()
  248. count = 0
  249. while rec is not None:
  250. count = count + 1
  251. if verbose and count % 100 == 0:
  252. print rec
  253. try:
  254. rec = c.prev()
  255. except db.DBNotFoundError, val:
  256. if get_raises_error:
  257. import sys
  258. if sys.version_info[0] < 3 :
  259. self.assertEqual(val[0], db.DB_NOTFOUND)
  260. else :
  261. self.assertEqual(val.args[0], db.DB_NOTFOUND)
  262. if verbose: print val
  263. rec = None
  264. else:
  265. self.fail("unexpected DBNotFoundError")
  266. self.assertEqual(count, self._numKeys)
  267. rec = c.set('0505')
  268. rec2 = c.current()
  269. self.assertEqual(rec, rec2)
  270. self.assertEqual(rec[0], '0505')
  271. self.assertEqual(rec[1], self.makeData('0505'))
  272. self.assertEqual(c.get_current_size(), len(rec[1]))
  273. # make sure we get empty values properly
  274. rec = c.set('empty value')
  275. self.assertEqual(rec[1], '')
  276. self.assertEqual(c.get_current_size(), 0)
  277. try:
  278. n = c.set('bad key')
  279. except db.DBNotFoundError, val:
  280. import sys
  281. if sys.version_info[0] < 3 :
  282. self.assertEqual(val[0], db.DB_NOTFOUND)
  283. else :
  284. self.assertEqual(val.args[0], db.DB_NOTFOUND)
  285. if verbose: print val
  286. else:
  287. if set_raises_error:
  288. self.fail("expected exception")
  289. if n != None:
  290. self.fail("expected None: %r" % (n,))
  291. rec = c.get_both('0404', self.makeData('0404'))
  292. self.assertEqual(rec, ('0404', self.makeData('0404')))
  293. try:
  294. n = c.get_both('0404', 'bad data')
  295. except db.DBNotFoundError, val:
  296. import sys
  297. if sys.version_info[0] < 3 :
  298. self.assertEqual(val[0], db.DB_NOTFOUND)
  299. else :
  300. self.assertEqual(val.args[0], db.DB_NOTFOUND)
  301. if verbose: print val
  302. else:
  303. if get_raises_error:
  304. self.fail("expected exception")
  305. if n != None:
  306. self.fail("expected None: %r" % (n,))
  307. if self.d.get_type() == db.DB_BTREE:
  308. rec = c.set_range('011')
  309. if verbose:
  310. print "searched for '011', found: ", rec
  311. rec = c.set_range('011',dlen=0,doff=0)
  312. if verbose:
  313. print "searched (partial) for '011', found: ", rec
  314. if rec[1] != '': self.fail('expected empty data portion')
  315. ev = c.set_range('empty value')
  316. if verbose:
  317. print "search for 'empty value' returned", ev
  318. if ev[1] != '': self.fail('empty value lookup failed')
  319. c.set('0499')
  320. c.delete()
  321. try:
  322. rec = c.current()
  323. except db.DBKeyEmptyError, val:
  324. if get_raises_error:
  325. import sys
  326. if sys.version_info[0] < 3 :
  327. self.assertEqual(val[0], db.DB_KEYEMPTY)
  328. else :
  329. self.assertEqual(val.args[0], db.DB_KEYEMPTY)
  330. if verbose: print val
  331. else:
  332. self.fail("unexpected DBKeyEmptyError")
  333. else:
  334. if get_raises_error:
  335. self.fail('DBKeyEmptyError exception expected')
  336. c.next()
  337. c2 = c.dup(db.DB_POSITION)
  338. self.assertEqual(c.current(), c2.current())
  339. c2.put('', 'a new value', db.DB_CURRENT)
  340. self.assertEqual(c.current(), c2.current())
  341. self.assertEqual(c.current()[1], 'a new value')
  342. c2.put('', 'er', db.DB_CURRENT, dlen=0, doff=5)
  343. self.assertEqual(c2.current()[1], 'a newer value')
  344. c.close()
  345. c2.close()
  346. if txn:
  347. txn.commit()
  348. # time to abuse the closed cursors and hope we don't crash
  349. methods_to_test = {
  350. 'current': (),
  351. 'delete': (),
  352. 'dup': (db.DB_POSITION,),
  353. 'first': (),
  354. 'get': (0,),
  355. 'next': (),
  356. 'prev': (),
  357. 'last': (),
  358. 'put':('', 'spam', db.DB_CURRENT),
  359. 'set': ("0505",),
  360. }
  361. for method, args in methods_to_test.items():
  362. try:
  363. if verbose:
  364. print "attempting to use a closed cursor's %s method" % \
  365. method
  366. # a bug may cause a NULL pointer dereference...
  367. apply(getattr(c, method), args)
  368. except db.DBError, val:
  369. import sys
  370. if sys.version_info[0] < 3 :
  371. self.assertEqual(val[0], 0)
  372. else :
  373. self.assertEqual(val.args[0], 0)
  374. if verbose: print val
  375. else:
  376. self.fail("no exception raised when using a buggy cursor's"
  377. "%s method" % method)
  378. #
  379. # free cursor referencing a closed database, it should not barf:
  380. #
  381. oldcursor = self.d.cursor(txn=txn)
  382. self.d.close()
  383. # this would originally cause a segfault when the cursor for a
  384. # closed database was cleaned up. it should not anymore.
  385. # SF pybsddb bug id 667343
  386. del oldcursor
  387. def test03b_SimpleCursorWithoutGetReturnsNone0(self):
  388. # same test but raise exceptions instead of returning None
  389. if verbose:
  390. print '\n', '-=' * 30
  391. print "Running %s.test03b_SimpleCursorStuffWithoutGetReturnsNone..." % \
  392. self.__class__.__name__
  393. old = self.d.set_get_returns_none(0)
  394. self.assertEqual(old, 2)
  395. self.test03_SimpleCursorStuff(get_raises_error=1, set_raises_error=1)
  396. def test03b_SimpleCursorWithGetReturnsNone1(self):
  397. # same test but raise exceptions instead of returning None
  398. if verbose:
  399. print '\n', '-=' * 30
  400. print "Running %s.test03b_SimpleCursorStuffWithoutGetReturnsNone..." % \
  401. self.__class__.__name__
  402. old = self.d.set_get_returns_none(1)
  403. self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=1)
  404. def test03c_SimpleCursorGetReturnsNone2(self):
  405. # same test but raise exceptions instead of returning None
  406. if verbose:
  407. print '\n', '-=' * 30
  408. print "Running %s.test03c_SimpleCursorStuffWithoutSetReturnsNone..." % \
  409. self.__class__.__name__
  410. old = self.d.set_get_returns_none(1)
  411. self.assertEqual(old, 2)
  412. old = self.d.set_get_returns_none(2)
  413. self.assertEqual(old, 1)
  414. self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=0)
  415. #----------------------------------------
  416. def test04_PartialGetAndPut(self):
  417. d = self.d
  418. if verbose:
  419. print '\n', '-=' * 30
  420. print "Running %s.test04_PartialGetAndPut..." % \
  421. self.__class__.__name__
  422. key = "partialTest"
  423. data = "1" * 1000 + "2" * 1000
  424. d.put(key, data)
  425. self.assertEqual(d.get(key), data)
  426. self.assertEqual(d.get(key, dlen=20, doff=990),
  427. ("1" * 10) + ("2" * 10))
  428. d.put("partialtest2", ("1" * 30000) + "robin" )
  429. self.assertEqual(d.get("partialtest2", dlen=5, doff=30000), "robin")
  430. # There seems to be a bug in DB here... Commented out the test for
  431. # now.
  432. ##self.assertEqual(d.get("partialtest2", dlen=5, doff=30010), "")
  433. if self.dbsetflags != db.DB_DUP:
  434. # Partial put with duplicate records requires a cursor
  435. d.put(key, "0000", dlen=2000, doff=0)
  436. self.assertEqual(d.get(key), "0000")
  437. d.put(key, "1111", dlen=1, doff=2)
  438. self.assertEqual(d.get(key), "0011110")
  439. #----------------------------------------
  440. def test05_GetSize(self):
  441. d = self.d
  442. if verbose:
  443. print '\n', '-=' * 30
  444. print "Running %s.test05_GetSize..." % self.__class__.__name__
  445. for i in range(1, 50000, 500):
  446. key = "size%s" % i
  447. #print "before ", i,
  448. d.put(key, "1" * i)
  449. #print "after",
  450. self.assertEqual(d.get_size(key), i)
  451. #print "done"
  452. #----------------------------------------
  453. def test06_Truncate(self):
  454. d = self.d
  455. if verbose:
  456. print '\n', '-=' * 30
  457. print "Running %s.test99_Truncate..." % self.__class__.__name__
  458. d.put("abcde", "ABCDE");
  459. num = d.truncate()
  460. self.assert_(num >= 1, "truncate returned <= 0 on non-empty database")
  461. num = d.truncate()
  462. self.assertEqual(num, 0,
  463. "truncate on empty DB returned nonzero (%r)" % (num,))
  464. #----------------------------------------
  465. def test07_verify(self):
  466. # Verify bug solved in 4.7.3pre8
  467. self.d.close()
  468. d = db.DB(self.env)
  469. d.verify(self.filename)
  470. #----------------------------------------
  471. #----------------------------------------------------------------------
  472. class BasicBTreeTestCase(BasicTestCase):
  473. dbtype = db.DB_BTREE
  474. class BasicHashTestCase(BasicTestCase):
  475. dbtype = db.DB_HASH
  476. class BasicBTreeWithThreadFlagTestCase(BasicTestCase):
  477. dbtype = db.DB_BTREE
  478. dbopenflags = db.DB_THREAD
  479. class BasicHashWithThreadFlagTestCase(BasicTestCase):
  480. dbtype = db.DB_HASH
  481. dbopenflags = db.DB_THREAD
  482. class BasicWithEnvTestCase(BasicTestCase):
  483. dbopenflags = db.DB_THREAD
  484. useEnv = 1
  485. envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
  486. #----------------------------------------
  487. def test08_EnvRemoveAndRename(self):
  488. if not self.env:
  489. return
  490. if verbose:
  491. print '\n', '-=' * 30
  492. print "Running %s.test08_EnvRemoveAndRename..." % self.__class__.__name__
  493. # can't rename or remove an open DB
  494. self.d.close()
  495. newname = self.filename + '.renamed'
  496. self.env.dbrename(self.filename, None, newname)
  497. self.env.dbremove(newname)
  498. # dbremove and dbrename are in 4.1 and later
  499. if db.version() < (4,1):
  500. del test08_EnvRemoveAndRename
  501. #----------------------------------------
  502. class BasicBTreeWithEnvTestCase(BasicWithEnvTestCase):
  503. dbtype = db.DB_BTREE
  504. class BasicHashWithEnvTestCase(BasicWithEnvTestCase):
  505. dbtype = db.DB_HASH
  506. #----------------------------------------------------------------------
  507. class BasicTransactionTestCase(BasicTestCase):
  508. import sys
  509. if sys.version_info[:3] < (2, 4, 0):
  510. def assertTrue(self, expr, msg=None):
  511. self.failUnless(expr,msg=msg)
  512. dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
  513. useEnv = 1
  514. envflags = (db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
  515. db.DB_INIT_TXN)
  516. envsetflags = db.DB_AUTO_COMMIT
  517. def tearDown(self):
  518. self.txn.commit()
  519. BasicTestCase.tearDown(self)
  520. def populateDB(self):
  521. txn = self.env.txn_begin()
  522. BasicTestCase.populateDB(self, _txn=txn)
  523. self.txn = self.env.txn_begin()
  524. def test06_Transactions(self):
  525. d = self.d
  526. if verbose:
  527. print '\n', '-=' * 30
  528. print "Running %s.test06_Transactions..." % self.__class__.__name__
  529. self.assertEqual(d.get('new rec', txn=self.txn), None)
  530. d.put('new rec', 'this is a new record', self.txn)
  531. self.assertEqual(d.get('new rec', txn=self.txn),
  532. 'this is a new record')
  533. self.txn.abort()
  534. self.assertEqual(d.get('new rec'), None)
  535. self.txn = self.env.txn_begin()
  536. self.assertEqual(d.get('new rec', txn=self.txn), None)
  537. d.put('new rec', 'this is a new record', self.txn)
  538. self.assertEqual(d.get('new rec', txn=self.txn),
  539. 'this is a new record')
  540. self.txn.commit()
  541. self.assertEqual(d.get('new rec'), 'this is a new record')
  542. self.txn = self.env.txn_begin()
  543. c = d.cursor(self.txn)
  544. rec = c.first()
  545. count = 0
  546. while rec is not None:
  547. count = count + 1
  548. if verbose and count % 100 == 0:
  549. print rec
  550. rec = c.next()
  551. self.assertEqual(count, self._numKeys+1)
  552. c.close() # Cursors *MUST* be closed before commit!
  553. self.txn.commit()
  554. # flush pending updates
  555. try:
  556. self.env.txn_checkpoint (0, 0, 0)
  557. except db.DBIncompleteError:
  558. pass
  559. statDict = self.env.log_stat(0);
  560. self.assert_(statDict.has_key('magic'))
  561. self.assert_(statDict.has_key('version'))
  562. self.assert_(statDict.has_key('cur_file'))
  563. self.assert_(statDict.has_key('region_nowait'))
  564. # must have at least one log file present:
  565. logs = self.env.log_archive(db.DB_ARCH_ABS | db.DB_ARCH_LOG)
  566. self.assertNotEqual(logs, None)
  567. for log in logs:
  568. if verbose:
  569. print 'log file: ' + log
  570. if db.version() >= (4,2):
  571. logs = self.env.log_archive(db.DB_ARCH_REMOVE)
  572. self.assertTrue(not logs)
  573. self.txn = self.env.txn_begin()
  574. #----------------------------------------
  575. def test08_TxnTruncate(self):
  576. d = self.d
  577. if verbose:
  578. print '\n', '-=' * 30
  579. print "Running %s.test08_TxnTruncate..." % self.__class__.__name__
  580. d.put("abcde", "ABCDE");
  581. txn = self.env.txn_begin()
  582. num = d.truncate(txn)
  583. self.assert_(num >= 1, "truncate returned <= 0 on non-empty database")
  584. num = d.truncate(txn)
  585. self.assertEqual(num, 0,
  586. "truncate on empty DB returned nonzero (%r)" % (num,))
  587. txn.commit()
  588. #----------------------------------------
  589. def test09_TxnLateUse(self):
  590. txn = self.env.txn_begin()
  591. txn.abort()
  592. try:
  593. txn.abort()
  594. except db.DBError, e:
  595. pass
  596. else:
  597. raise RuntimeError, "DBTxn.abort() called after DB_TXN no longer valid w/o an exception"
  598. txn = self.env.txn_begin()
  599. txn.commit()
  600. try:
  601. txn.commit()
  602. except db.DBError, e:
  603. pass
  604. else:
  605. raise RuntimeError, "DBTxn.commit() called after DB_TXN no longer valid w/o an exception"
  606. class BTreeTransactionTestCase(BasicTransactionTestCase):
  607. dbtype = db.DB_BTREE
  608. class HashTransactionTestCase(BasicTransactionTestCase):
  609. dbtype = db.DB_HASH
  610. #----------------------------------------------------------------------
  611. class BTreeRecnoTestCase(BasicTestCase):
  612. dbtype = db.DB_BTREE
  613. dbsetflags = db.DB_RECNUM
  614. def test08_RecnoInBTree(self):
  615. d = self.d
  616. if verbose:
  617. print '\n', '-=' * 30
  618. print "Running %s.test08_RecnoInBTree..." % self.__class__.__name__
  619. rec = d.get(200)
  620. self.assertEqual(type(rec), type(()))
  621. self.assertEqual(len(rec), 2)
  622. if verbose:
  623. print "Record #200 is ", rec
  624. c = d.cursor()
  625. c.set('0200')
  626. num = c.get_recno()
  627. self.assertEqual(type(num), type(1))
  628. if verbose:
  629. print "recno of d['0200'] is ", num
  630. rec = c.current()
  631. self.assertEqual(c.set_recno(num), rec)
  632. c.close()
  633. class BTreeRecnoWithThreadFlagTestCase(BTreeRecnoTestCase):
  634. dbopenflags = db.DB_THREAD
  635. #----------------------------------------------------------------------
  636. class BasicDUPTestCase(BasicTestCase):
  637. dbsetflags = db.DB_DUP
  638. def test09_DuplicateKeys(self):
  639. d = self.d
  640. if verbose:
  641. print '\n', '-=' * 30
  642. print "Running %s.test09_DuplicateKeys..." % \
  643. self.__class__.__name__
  644. d.put("dup0", "before")
  645. for x in "The quick brown fox jumped over the lazy dog.".split():
  646. d.put("dup1", x)
  647. d.put("dup2", "after")
  648. data = d.get("dup1")
  649. self.assertEqual(data, "The")
  650. if verbose:
  651. print data
  652. c = d.cursor()
  653. rec = c.set("dup1")
  654. self.assertEqual(rec, ('dup1', 'The'))
  655. next_reg = c.next()
  656. self.assertEqual(next_reg, ('dup1', 'quick'))
  657. rec = c.set("dup1")
  658. count = c.count()
  659. self.assertEqual(count, 9)
  660. next_dup = c.next_dup()
  661. self.assertEqual(next_dup, ('dup1', 'quick'))
  662. rec = c.set('dup1')
  663. while rec is not None:
  664. if verbose:
  665. print rec
  666. rec = c.next_dup()
  667. c.set('dup1')
  668. rec = c.next_nodup()
  669. self.assertNotEqual(rec[0], 'dup1')
  670. if verbose:
  671. print rec
  672. c.close()
  673. class BTreeDUPTestCase(BasicDUPTestCase):
  674. dbtype = db.DB_BTREE
  675. class HashDUPTestCase(BasicDUPTestCase):
  676. dbtype = db.DB_HASH
  677. class BTreeDUPWithThreadTestCase(BasicDUPTestCase):
  678. dbtype = db.DB_BTREE
  679. dbopenflags = db.DB_THREAD
  680. class HashDUPWithThreadTestCase(BasicDUPTestCase):
  681. dbtype = db.DB_HASH
  682. dbopenflags = db.DB_THREAD
  683. #----------------------------------------------------------------------
  684. class BasicMultiDBTestCase(BasicTestCase):
  685. dbname = 'first'
  686. def otherType(self):
  687. if self.dbtype == db.DB_BTREE:
  688. return db.DB_HASH
  689. else:
  690. return db.DB_BTREE
  691. def test10_MultiDB(self):
  692. d1 = self.d
  693. if verbose:
  694. print '\n', '-=' * 30
  695. print "Running %s.test10_MultiDB..." % self.__class__.__name__
  696. d2 = db.DB(self.env)
  697. d2.open(self.filename, "second", self.dbtype,
  698. self.dbopenflags|db.DB_CREATE)
  699. d3 = db.DB(self.env)
  700. d3.open(self.filename, "third", self.otherType(),
  701. self.dbopenflags|db.DB_CREATE)
  702. for x in "The quick brown fox jumped over the lazy dog".split():
  703. d2.put(x, self.makeData(x))
  704. for x in string.letters:
  705. d3.put(x, x*70)
  706. d1.sync()
  707. d2.sync()
  708. d3.sync()
  709. d1.close()
  710. d2.close()
  711. d3.close()
  712. self.d = d1 = d2 = d3 = None
  713. self.d = d1 = db.DB(self.env)
  714. d1.open(self.filename, self.dbname, flags = self.dbopenflags)
  715. d2 = db.DB(self.env)
  716. d2.open(self.filename, "second", flags = self.dbopenflags)
  717. d3 = db.DB(self.env)
  718. d3.open(self.filename, "third", flags = self.dbopenflags)
  719. c1 = d1.cursor()
  720. c2 = d2.cursor()
  721. c3 = d3.cursor()
  722. count = 0
  723. rec = c1.first()
  724. while rec is not None:
  725. count = count + 1
  726. if verbose and (count % 50) == 0:
  727. print rec
  728. rec = c1.next()
  729. self.assertEqual(count, self._numKeys)
  730. count = 0
  731. rec = c2.first()
  732. while rec is not None:
  733. count = count + 1
  734. if verbose:
  735. print rec
  736. rec = c2.next()
  737. self.assertEqual(count, 9)
  738. count = 0
  739. rec = c3.first()
  740. while rec is not None:
  741. count = count + 1
  742. if verbose:
  743. print rec
  744. rec = c3.next()
  745. self.assertEqual(count, len(string.letters))
  746. c1.close()
  747. c2.close()
  748. c3.close()
  749. d2.close()
  750. d3.close()
  751. # Strange things happen if you try to use Multiple DBs per file without a
  752. # DBEnv with MPOOL and LOCKing...
  753. class BTreeMultiDBTestCase(BasicMultiDBTestCase):
  754. dbtype = db.DB_BTREE
  755. dbopenflags = db.DB_THREAD
  756. useEnv = 1
  757. envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
  758. class HashMultiDBTestCase(BasicMultiDBTestCase):
  759. dbtype = db.DB_HASH
  760. dbopenflags = db.DB_THREAD
  761. useEnv = 1
  762. envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK
  763. class PrivateObject(unittest.TestCase) :
  764. import sys
  765. if sys.version_info[:3] < (2, 4, 0):
  766. def assertTrue(self, expr, msg=None):
  767. self.failUnless(expr,msg=msg)
  768. def tearDown(self) :
  769. del self.obj
  770. def test01_DefaultIsNone(self) :
  771. self.assertEqual(self.obj.get_private(), None)
  772. def test02_assignment(self) :
  773. a = "example of private object"
  774. self.obj.set_private(a)
  775. b = self.obj.get_private()
  776. self.assertTrue(a is b) # Object identity
  777. def test03_leak_assignment(self) :
  778. import sys
  779. a = "example of private object"
  780. refcount = sys.getrefcount(a)
  781. self.obj.set_private(a)
  782. self.assertEqual(refcount+1, sys.getrefcount(a))
  783. self.obj.set_private(None)
  784. self.assertEqual(refcount, sys.getrefcount(a))
  785. def test04_leak_GC(self) :
  786. import sys
  787. a = "example of private object"
  788. refcount = sys.getrefcount(a)
  789. self.obj.set_private(a)
  790. self.obj = None
  791. self.assertEqual(refcount, sys.getrefcount(a))
  792. class DBEnvPrivateObject(PrivateObject) :
  793. def setUp(self) :
  794. self.obj = db.DBEnv()
  795. class DBPrivateObject(PrivateObject) :
  796. def setUp(self) :
  797. self.obj = db.DB()
  798. class CrashAndBurn(unittest.TestCase) :
  799. import sys
  800. if sys.version_info[:3] < (2, 4, 0):
  801. def assertTrue(self, expr, msg=None):
  802. self.failUnless(expr,msg=msg)
  803. #def test01_OpenCrash(self) :
  804. # # See http://bugs.python.org/issue3307
  805. # self.assertRaises(db.DBInvalidArgError, db.DB, None, 65535)
  806. def test02_DBEnv_dealloc(self):
  807. # http://bugs.python.org/issue3885
  808. import gc
  809. self.assertRaises(db.DBInvalidArgError, db.DBEnv, ~db.DB_RPCCLIENT)
  810. gc.collect()
  811. #----------------------------------------------------------------------
  812. #----------------------------------------------------------------------
  813. def test_suite():
  814. suite = unittest.TestSuite()
  815. suite.addTest(unittest.makeSuite(VersionTestCase))
  816. suite.addTest(unittest.makeSuite(BasicBTreeTestCase))
  817. suite.addTest(unittest.makeSuite(BasicHashTestCase))
  818. suite.addTest(unittest.makeSuite(BasicBTreeWithThreadFlagTestCase))
  819. suite.addTest(unittest.makeSuite(BasicHashWithThreadFlagTestCase))
  820. suite.addTest(unittest.makeSuite(BasicBTreeWithEnvTestCase))
  821. suite.addTest(unittest.makeSuite(BasicHashWithEnvTestCase))
  822. suite.addTest(unittest.makeSuite(BTreeTransactionTestCase))
  823. suite.addTest(unittest.makeSuite(HashTransactionTestCase))
  824. suite.addTest(unittest.makeSuite(BTreeRecnoTestCase))
  825. suite.addTest(unittest.makeSuite(BTreeRecnoWithThreadFlagTestCase))
  826. suite.addTest(unittest.makeSuite(BTreeDUPTestCase))
  827. suite.addTest(unittest.makeSuite(HashDUPTestCase))
  828. suite.addTest(unittest.makeSuite(BTreeDUPWithThreadTestCase))
  829. suite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase))
  830. suite.addTest(unittest.makeSuite(BTreeMultiDBTestCase))
  831. suite.addTest(unittest.makeSuite(HashMultiDBTestCase))
  832. suite.addTest(unittest.makeSuite(DBEnvPrivateObject))
  833. suite.addTest(unittest.makeSuite(DBPrivateObject))
  834. suite.addTest(unittest.makeSuite(CrashAndBurn))
  835. return suite
  836. if __name__ == '__main__':
  837. unittest.main(defaultTest='test_suite')