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