home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / test_basics.py < prev    next >
Text File  |  2003-12-30  |  27KB  |  933 lines

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