2002-11-19 13:47:07 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
# A test suite for the table interface built on bsddb.db
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Copyright (C) 2000, 2001 by Autonomous Zone Industries
|
2002-11-23 07:26:07 -04:00
|
|
|
# Copyright (C) 2002 Gregory P. Smith
|
2002-11-19 13:47:07 -04:00
|
|
|
#
|
|
|
|
# March 20, 2000
|
|
|
|
#
|
|
|
|
# License: This is free software. You may use this software for any
|
|
|
|
# purpose including modification/redistribution, so long as
|
|
|
|
# this header remains intact and that you do not claim any
|
|
|
|
# rights of ownership or authorship of this software. This
|
|
|
|
# software has been tested, but no warranty is expressed or
|
|
|
|
# implied.
|
|
|
|
#
|
2007-09-09 17:25:00 -03:00
|
|
|
# -- Gregory P. Smith <greg@krypto.org>
|
2002-11-19 13:47:07 -04:00
|
|
|
#
|
|
|
|
# $Id$
|
|
|
|
|
2008-02-23 13:40:11 -04:00
|
|
|
import os, re
|
2002-11-19 13:47:07 -04:00
|
|
|
try:
|
|
|
|
import cPickle
|
|
|
|
pickle = cPickle
|
|
|
|
except ImportError:
|
|
|
|
import pickle
|
|
|
|
|
|
|
|
import unittest
|
2008-05-13 17:57:59 -03:00
|
|
|
from test_all import verbose, get_new_environment_path, get_new_database_path
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2003-01-28 13:20:44 -04:00
|
|
|
try:
|
2003-09-20 21:08:14 -03:00
|
|
|
# For Pythons w/distutils pybsddb
|
|
|
|
from bsddb3 import db, dbtables
|
|
|
|
except ImportError:
|
2003-01-28 13:20:44 -04:00
|
|
|
# For Python 2.3
|
|
|
|
from bsddb import db, dbtables
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2008-03-02 16:00:53 -04:00
|
|
|
try:
|
|
|
|
from bsddb3 import test_support
|
|
|
|
except ImportError:
|
|
|
|
from test import test_support
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
|
|
|
class TableDBTestCase(unittest.TestCase):
|
|
|
|
db_name = 'test-table.db'
|
|
|
|
|
|
|
|
def setUp(self):
|
2008-05-13 17:57:59 -03:00
|
|
|
self.testHomeDir = get_new_environment_path()
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb = dbtables.bsdTableDB(
|
2008-05-13 17:57:59 -03:00
|
|
|
filename='tabletest.db', dbhome=self.testHomeDir, create=1)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
self.tdb.close()
|
2008-02-24 14:47:03 -04:00
|
|
|
test_support.rmtree(self.testHomeDir)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
def test01(self):
|
|
|
|
tabname = "test01"
|
|
|
|
colname = 'cool numbers'
|
|
|
|
try:
|
|
|
|
self.tdb.Drop(tabname)
|
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
self.tdb.CreateTable(tabname, [colname])
|
|
|
|
self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)})
|
|
|
|
|
|
|
|
if verbose:
|
|
|
|
self.tdb._db_print()
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, [colname], conditions={colname: None})
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
colval = pickle.loads(values[0][colname])
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assert_(colval > 3.141)
|
|
|
|
self.assert_(colval < 3.142)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
def test02(self):
|
|
|
|
tabname = "test02"
|
|
|
|
col0 = 'coolness factor'
|
|
|
|
col1 = 'but can it fly?'
|
|
|
|
col2 = 'Species'
|
|
|
|
testinfo = [
|
|
|
|
{col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'},
|
|
|
|
{col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'},
|
|
|
|
{col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'}
|
|
|
|
]
|
|
|
|
|
|
|
|
try:
|
|
|
|
self.tdb.Drop(tabname)
|
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
self.tdb.CreateTable(tabname, [col0, col1, col2])
|
|
|
|
for row in testinfo :
|
|
|
|
self.tdb.Insert(tabname, row)
|
|
|
|
|
|
|
|
values = self.tdb.Select(tabname, [col2],
|
|
|
|
conditions={col0: lambda x: pickle.loads(x) >= 8})
|
|
|
|
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 2)
|
2002-11-19 13:47:07 -04:00
|
|
|
if values[0]['Species'] == 'Penguin' :
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(values[1]['Species'], 'SR-71A Blackbird')
|
2002-11-19 13:47:07 -04:00
|
|
|
elif values[0]['Species'] == 'SR-71A Blackbird' :
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(values[1]['Species'], 'Penguin')
|
2002-11-19 13:47:07 -04:00
|
|
|
else :
|
|
|
|
if verbose:
|
2004-02-12 13:35:32 -04:00
|
|
|
print "values= %r" % (values,)
|
2007-10-14 15:30:21 -03:00
|
|
|
raise RuntimeError("Wrong values returned!")
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
def test03(self):
|
|
|
|
tabname = "test03"
|
|
|
|
try:
|
|
|
|
self.tdb.Drop(tabname)
|
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
if verbose:
|
|
|
|
print '...before CreateTable...'
|
|
|
|
self.tdb._db_print()
|
|
|
|
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
|
|
|
|
if verbose:
|
|
|
|
print '...after CreateTable...'
|
|
|
|
self.tdb._db_print()
|
|
|
|
self.tdb.Drop(tabname)
|
|
|
|
if verbose:
|
|
|
|
print '...after Drop...'
|
|
|
|
self.tdb._db_print()
|
|
|
|
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
|
|
|
|
|
|
|
|
try:
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'a': "",
|
|
|
|
'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
|
|
|
|
'f': "Zero"})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.fail('Expected an exception')
|
2002-11-19 13:47:07 -04:00
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
|
|
|
self.tdb.Select(tabname, [], conditions={'foo': '123'})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.fail('Expected an exception')
|
2002-11-19 13:47:07 -04:00
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'a': '42',
|
|
|
|
'b': "bad",
|
|
|
|
'c': "meep",
|
|
|
|
'e': 'Fuzzy wuzzy was a bear'})
|
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'a': '581750',
|
|
|
|
'b': "good",
|
|
|
|
'd': "bla",
|
|
|
|
'c': "black",
|
|
|
|
'e': 'fuzzy was here'})
|
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'a': '800000',
|
|
|
|
'b': "good",
|
|
|
|
'd': "bla",
|
|
|
|
'c': "black",
|
|
|
|
'e': 'Fuzzy wuzzy is a bear'})
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
if verbose:
|
|
|
|
self.tdb._db_print()
|
|
|
|
|
|
|
|
# this should return two rows
|
|
|
|
values = self.tdb.Select(tabname, ['b', 'a', 'd'],
|
2002-12-30 16:53:52 -04:00
|
|
|
conditions={'e': re.compile('wuzzy').search,
|
|
|
|
'a': re.compile('^[0-9]+$').match})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 2)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
# now lets delete one of them and try again
|
|
|
|
self.tdb.Delete(tabname, conditions={'b': dbtables.ExactCond('good')})
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, ['a', 'd', 'b'],
|
|
|
|
conditions={'e': dbtables.PrefixCond('Fuzzy')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1)
|
|
|
|
self.assertEqual(values[0]['d'], None)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
values = self.tdb.Select(tabname, ['b'],
|
|
|
|
conditions={'c': lambda c: c == 'meep'})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1)
|
|
|
|
self.assertEqual(values[0]['b'], "bad")
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
|
2002-11-23 07:26:07 -04:00
|
|
|
def test04_MultiCondSelect(self):
|
|
|
|
tabname = "test04_MultiCondSelect"
|
|
|
|
try:
|
|
|
|
self.tdb.Drop(tabname)
|
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
|
|
|
|
|
|
|
|
try:
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'a': "",
|
|
|
|
'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
|
|
|
|
'f': "Zero"})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.fail('Expected an exception')
|
2002-11-23 07:26:07 -04:00
|
|
|
except dbtables.TableDBError:
|
|
|
|
pass
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname, {'a': "A", 'b': "B", 'c': "C", 'd': "D",
|
|
|
|
'e': "E"})
|
|
|
|
self.tdb.Insert(tabname, {'a': "-A", 'b': "-B", 'c': "-C", 'd': "-D",
|
|
|
|
'e': "-E"})
|
|
|
|
self.tdb.Insert(tabname, {'a': "A-", 'b': "B-", 'c': "C-", 'd': "D-",
|
|
|
|
'e': "E-"})
|
2002-11-23 07:26:07 -04:00
|
|
|
|
|
|
|
if verbose:
|
|
|
|
self.tdb._db_print()
|
|
|
|
|
|
|
|
# This select should return 0 rows. it is designed to test
|
|
|
|
# the bug identified and fixed in sourceforge bug # 590449
|
|
|
|
# (Big Thanks to "Rob Tillotson (n9mtb)" for tracking this down
|
|
|
|
# and supplying a fix!! This one caused many headaches to say
|
|
|
|
# the least...)
|
|
|
|
values = self.tdb.Select(tabname, ['b', 'a', 'd'],
|
|
|
|
conditions={'e': dbtables.ExactCond('E'),
|
|
|
|
'a': dbtables.ExactCond('A'),
|
|
|
|
'd': dbtables.PrefixCond('-')
|
|
|
|
} )
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 0, values)
|
2002-11-23 07:26:07 -04:00
|
|
|
|
|
|
|
|
2002-11-19 13:47:07 -04:00
|
|
|
def test_CreateOrExtend(self):
|
|
|
|
tabname = "test_CreateOrExtend"
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.CreateOrExtendTable(
|
|
|
|
tabname, ['name', 'taste', 'filling', 'alcohol content', 'price'])
|
2002-11-19 13:47:07 -04:00
|
|
|
try:
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname,
|
|
|
|
{'taste': 'crap',
|
|
|
|
'filling': 'no',
|
|
|
|
'is it Guinness?': 'no'})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.fail("Insert should've failed due to bad column name")
|
2002-11-19 13:47:07 -04:00
|
|
|
except:
|
|
|
|
pass
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.CreateOrExtendTable(tabname,
|
|
|
|
['name', 'taste', 'is it Guinness?'])
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
# these should both succeed as the table should contain the union of both sets of columns.
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname, {'taste': 'crap', 'filling': 'no',
|
|
|
|
'is it Guinness?': 'no'})
|
|
|
|
self.tdb.Insert(tabname, {'taste': 'great', 'filling': 'yes',
|
|
|
|
'is it Guinness?': 'yes',
|
|
|
|
'name': 'Guinness'})
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
def test_CondObjs(self):
|
|
|
|
tabname = "test_CondObjs"
|
|
|
|
|
|
|
|
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e', 'p'])
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname, {'a': "the letter A",
|
|
|
|
'b': "the letter B",
|
|
|
|
'c': "is for cookie"})
|
|
|
|
self.tdb.Insert(tabname, {'a': "is for aardvark",
|
|
|
|
'e': "the letter E",
|
|
|
|
'c': "is for cookie",
|
|
|
|
'd': "is for dog"})
|
|
|
|
self.tdb.Insert(tabname, {'a': "the letter A",
|
|
|
|
'e': "the letter E",
|
|
|
|
'c': "is for cookie",
|
|
|
|
'p': "is for Python"})
|
|
|
|
|
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, ['p', 'e'],
|
|
|
|
conditions={'e': dbtables.PrefixCond('the l')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 2, values)
|
|
|
|
self.assertEqual(values[0]['e'], values[1]['e'], values)
|
|
|
|
self.assertNotEqual(values[0]['p'], values[1]['p'], values)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, ['d', 'a'],
|
|
|
|
conditions={'a': dbtables.LikeCond('%aardvark%')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1, values)
|
|
|
|
self.assertEqual(values[0]['d'], "is for dog", values)
|
|
|
|
self.assertEqual(values[0]['a'], "is for aardvark", values)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(tabname, None,
|
|
|
|
{'b': dbtables.Cond(),
|
|
|
|
'e':dbtables.LikeCond('%letter%'),
|
|
|
|
'a':dbtables.PrefixCond('is'),
|
|
|
|
'd':dbtables.ExactCond('is for dog'),
|
|
|
|
'c':dbtables.PrefixCond('is for'),
|
|
|
|
'p':lambda s: not s})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1, values)
|
|
|
|
self.assertEqual(values[0]['d'], "is for dog", values)
|
|
|
|
self.assertEqual(values[0]['a'], "is for aardvark", values)
|
2002-11-23 22:35:35 -04:00
|
|
|
|
2002-11-19 13:47:07 -04:00
|
|
|
def test_Delete(self):
|
|
|
|
tabname = "test_Delete"
|
|
|
|
self.tdb.CreateTable(tabname, ['x', 'y', 'z'])
|
|
|
|
|
|
|
|
# prior to 2001-05-09 there was a bug where Delete() would
|
|
|
|
# fail if it encountered any rows that did not have values in
|
|
|
|
# every column.
|
|
|
|
# Hunted and Squashed by <Donwulff> (Jukka Santala - donwulff@nic.fi)
|
|
|
|
self.tdb.Insert(tabname, {'x': 'X1', 'y':'Y1'})
|
|
|
|
self.tdb.Insert(tabname, {'x': 'X2', 'y':'Y2', 'z': 'Z2'})
|
|
|
|
|
|
|
|
self.tdb.Delete(tabname, conditions={'x': dbtables.PrefixCond('X')})
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(tabname, ['y'],
|
|
|
|
conditions={'x': dbtables.PrefixCond('X')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 0)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
def test_Modify(self):
|
|
|
|
tabname = "test_Modify"
|
|
|
|
self.tdb.CreateTable(tabname, ['Name', 'Type', 'Access'])
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Insert(tabname, {'Name': 'Index to MP3 files.doc',
|
|
|
|
'Type': 'Word', 'Access': '8'})
|
2002-11-19 13:47:07 -04:00
|
|
|
self.tdb.Insert(tabname, {'Name': 'Nifty.MP3', 'Access': '1'})
|
|
|
|
self.tdb.Insert(tabname, {'Type': 'Unknown', 'Access': '0'})
|
|
|
|
|
|
|
|
def set_type(type):
|
2008-05-13 17:57:59 -03:00
|
|
|
if type == None:
|
2002-11-19 13:47:07 -04:00
|
|
|
return 'MP3'
|
|
|
|
return type
|
|
|
|
|
|
|
|
def increment_access(count):
|
|
|
|
return str(int(count)+1)
|
|
|
|
|
|
|
|
def remove_value(value):
|
|
|
|
return None
|
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
self.tdb.Modify(tabname,
|
|
|
|
conditions={'Access': dbtables.ExactCond('0')},
|
|
|
|
mappings={'Access': remove_value})
|
|
|
|
self.tdb.Modify(tabname,
|
|
|
|
conditions={'Name': dbtables.LikeCond('%MP3%')},
|
|
|
|
mappings={'Type': set_type})
|
|
|
|
self.tdb.Modify(tabname,
|
|
|
|
conditions={'Name': dbtables.LikeCond('%')},
|
|
|
|
mappings={'Access': increment_access})
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2006-06-08 02:38:11 -03:00
|
|
|
try:
|
|
|
|
self.tdb.Modify(tabname,
|
|
|
|
conditions={'Name': dbtables.LikeCond('%')},
|
|
|
|
mappings={'Access': 'What is your quest?'})
|
|
|
|
except TypeError:
|
|
|
|
# success, the string value in mappings isn't callable
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
raise RuntimeError, "why was TypeError not raised for bad callable?"
|
|
|
|
|
2002-11-19 13:47:07 -04:00
|
|
|
# Delete key in select conditions
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, None,
|
|
|
|
conditions={'Type': dbtables.ExactCond('Unknown')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1, values)
|
|
|
|
self.assertEqual(values[0]['Name'], None, values)
|
|
|
|
self.assertEqual(values[0]['Access'], None, values)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
# Modify value by select conditions
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, None,
|
|
|
|
conditions={'Name': dbtables.ExactCond('Nifty.MP3')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1, values)
|
|
|
|
self.assertEqual(values[0]['Type'], "MP3", values)
|
|
|
|
self.assertEqual(values[0]['Access'], "2", values)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
# Make sure change applied only to select conditions
|
2002-12-30 16:53:52 -04:00
|
|
|
values = self.tdb.Select(
|
|
|
|
tabname, None, conditions={'Name': dbtables.LikeCond('%doc%')})
|
2007-10-14 15:40:37 -03:00
|
|
|
self.assertEqual(len(values), 1, values)
|
|
|
|
self.assertEqual(values[0]['Type'], "Word", values)
|
|
|
|
self.assertEqual(values[0]['Access'], "9", values)
|
2002-11-19 13:47:07 -04:00
|
|
|
|
2002-12-30 16:53:52 -04:00
|
|
|
|
|
|
|
def test_suite():
|
|
|
|
suite = unittest.TestSuite()
|
|
|
|
suite.addTest(unittest.makeSuite(TableDBTestCase))
|
|
|
|
return suite
|
2002-11-19 13:47:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2002-12-30 16:53:52 -04:00
|
|
|
unittest.main(defaultTest='test_suite')
|