3
#-----------------------------------------------------------------------
4
# A test suite for the table interface built on bsddb.db
5
#-----------------------------------------------------------------------
7
# Copyright (C) 2000, 2001 by Autonomous Zone Industries
8
# Copyright (C) 2002 Gregory P. Smith
12
# License: This is free software. You may use this software for any
13
# purpose including modification/redistribution, so long as
14
# this header remains intact and that you do not claim any
15
# rights of ownership or authorship of this software. This
16
# software has been tested, but no warranty is expressed or
19
# -- Gregory P. Smith <greg@electricrain.com>
21
# $Id: test_dbtables.py,v 1.7 2004/02/12 17:35:08 doerwalter Exp $
31
from test_all import verbose
34
# For Pythons w/distutils pybsddb
35
from bsddb3 import db, dbtables
38
from bsddb import db, dbtables
42
#----------------------------------------------------------------------
44
class TableDBTestCase(unittest.TestCase):
46
db_name = 'test-table.db'
49
homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home')
50
self.homeDir = homeDir
51
try: os.mkdir(homeDir)
53
self.tdb = dbtables.bsdTableDB(
54
filename='tabletest.db', dbhome=homeDir, create=1)
59
files = glob.glob(os.path.join(self.homeDir, '*'))
65
colname = 'cool numbers'
67
self.tdb.Drop(tabname)
68
except dbtables.TableDBError:
70
self.tdb.CreateTable(tabname, [colname])
71
self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)})
76
values = self.tdb.Select(
77
tabname, [colname], conditions={colname: None})
79
colval = pickle.loads(values[0][colname])
80
assert(colval > 3.141 and colval < 3.142)
85
col0 = 'coolness factor'
86
col1 = 'but can it fly?'
89
{col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'},
90
{col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'},
91
{col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'}
95
self.tdb.Drop(tabname)
96
except dbtables.TableDBError:
98
self.tdb.CreateTable(tabname, [col0, col1, col2])
100
self.tdb.Insert(tabname, row)
102
values = self.tdb.Select(tabname, [col2],
103
conditions={col0: lambda x: pickle.loads(x) >= 8})
105
assert len(values) == 2
106
if values[0]['Species'] == 'Penguin' :
107
assert values[1]['Species'] == 'SR-71A Blackbird'
108
elif values[0]['Species'] == 'SR-71A Blackbird' :
109
assert values[1]['Species'] == 'Penguin'
112
print "values= %r" % (values,)
113
raise "Wrong values returned!"
118
self.tdb.Drop(tabname)
119
except dbtables.TableDBError:
122
print '...before CreateTable...'
124
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
126
print '...after CreateTable...'
128
self.tdb.Drop(tabname)
130
print '...after Drop...'
132
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
135
self.tdb.Insert(tabname,
137
'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
140
except dbtables.TableDBError:
144
self.tdb.Select(tabname, [], conditions={'foo': '123'})
146
except dbtables.TableDBError:
149
self.tdb.Insert(tabname,
153
'e': 'Fuzzy wuzzy was a bear'})
154
self.tdb.Insert(tabname,
159
'e': 'fuzzy was here'})
160
self.tdb.Insert(tabname,
165
'e': 'Fuzzy wuzzy is a bear'})
170
# this should return two rows
171
values = self.tdb.Select(tabname, ['b', 'a', 'd'],
172
conditions={'e': re.compile('wuzzy').search,
173
'a': re.compile('^[0-9]+$').match})
174
assert len(values) == 2
176
# now lets delete one of them and try again
177
self.tdb.Delete(tabname, conditions={'b': dbtables.ExactCond('good')})
178
values = self.tdb.Select(
179
tabname, ['a', 'd', 'b'],
180
conditions={'e': dbtables.PrefixCond('Fuzzy')})
181
assert len(values) == 1
182
assert values[0]['d'] == None
184
values = self.tdb.Select(tabname, ['b'],
185
conditions={'c': lambda c: c == 'meep'})
186
assert len(values) == 1
187
assert values[0]['b'] == "bad"
190
def test04_MultiCondSelect(self):
191
tabname = "test04_MultiCondSelect"
193
self.tdb.Drop(tabname)
194
except dbtables.TableDBError:
196
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
199
self.tdb.Insert(tabname,
201
'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
204
except dbtables.TableDBError:
207
self.tdb.Insert(tabname, {'a': "A", 'b': "B", 'c': "C", 'd': "D",
209
self.tdb.Insert(tabname, {'a': "-A", 'b': "-B", 'c': "-C", 'd': "-D",
211
self.tdb.Insert(tabname, {'a': "A-", 'b': "B-", 'c': "C-", 'd': "D-",
217
# This select should return 0 rows. it is designed to test
218
# the bug identified and fixed in sourceforge bug # 590449
219
# (Big Thanks to "Rob Tillotson (n9mtb)" for tracking this down
220
# and supplying a fix!! This one caused many headaches to say
222
values = self.tdb.Select(tabname, ['b', 'a', 'd'],
223
conditions={'e': dbtables.ExactCond('E'),
224
'a': dbtables.ExactCond('A'),
225
'd': dbtables.PrefixCond('-')
227
assert len(values) == 0, values
230
def test_CreateOrExtend(self):
231
tabname = "test_CreateOrExtend"
233
self.tdb.CreateOrExtendTable(
234
tabname, ['name', 'taste', 'filling', 'alcohol content', 'price'])
236
self.tdb.Insert(tabname,
239
'is it Guinness?': 'no'})
240
assert 0, "Insert should've failed due to bad column name"
243
self.tdb.CreateOrExtendTable(tabname,
244
['name', 'taste', 'is it Guinness?'])
246
# these should both succeed as the table should contain the union of both sets of columns.
247
self.tdb.Insert(tabname, {'taste': 'crap', 'filling': 'no',
248
'is it Guinness?': 'no'})
249
self.tdb.Insert(tabname, {'taste': 'great', 'filling': 'yes',
250
'is it Guinness?': 'yes',
254
def test_CondObjs(self):
255
tabname = "test_CondObjs"
257
self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e', 'p'])
259
self.tdb.Insert(tabname, {'a': "the letter A",
261
'c': "is for cookie"})
262
self.tdb.Insert(tabname, {'a': "is for aardvark",
264
'c': "is for cookie",
266
self.tdb.Insert(tabname, {'a': "the letter A",
268
'c': "is for cookie",
269
'p': "is for Python"})
271
values = self.tdb.Select(
273
conditions={'e': dbtables.PrefixCond('the l')})
274
assert len(values) == 2, values
275
assert values[0]['e'] == values[1]['e'], values
276
assert values[0]['p'] != values[1]['p'], values
278
values = self.tdb.Select(
280
conditions={'a': dbtables.LikeCond('%aardvark%')})
281
assert len(values) == 1, values
282
assert values[0]['d'] == "is for dog", values
283
assert values[0]['a'] == "is for aardvark", values
285
values = self.tdb.Select(tabname, None,
286
{'b': dbtables.Cond(),
287
'e':dbtables.LikeCond('%letter%'),
288
'a':dbtables.PrefixCond('is'),
289
'd':dbtables.ExactCond('is for dog'),
290
'c':dbtables.PrefixCond('is for'),
291
'p':lambda s: not s})
292
assert len(values) == 1, values
293
assert values[0]['d'] == "is for dog", values
294
assert values[0]['a'] == "is for aardvark", values
296
def test_Delete(self):
297
tabname = "test_Delete"
298
self.tdb.CreateTable(tabname, ['x', 'y', 'z'])
300
# prior to 2001-05-09 there was a bug where Delete() would
301
# fail if it encountered any rows that did not have values in
303
# Hunted and Squashed by <Donwulff> (Jukka Santala - donwulff@nic.fi)
304
self.tdb.Insert(tabname, {'x': 'X1', 'y':'Y1'})
305
self.tdb.Insert(tabname, {'x': 'X2', 'y':'Y2', 'z': 'Z2'})
307
self.tdb.Delete(tabname, conditions={'x': dbtables.PrefixCond('X')})
308
values = self.tdb.Select(tabname, ['y'],
309
conditions={'x': dbtables.PrefixCond('X')})
310
assert len(values) == 0
312
def test_Modify(self):
313
tabname = "test_Modify"
314
self.tdb.CreateTable(tabname, ['Name', 'Type', 'Access'])
316
self.tdb.Insert(tabname, {'Name': 'Index to MP3 files.doc',
317
'Type': 'Word', 'Access': '8'})
318
self.tdb.Insert(tabname, {'Name': 'Nifty.MP3', 'Access': '1'})
319
self.tdb.Insert(tabname, {'Type': 'Unknown', 'Access': '0'})
326
def increment_access(count):
327
return str(int(count)+1)
329
def remove_value(value):
332
self.tdb.Modify(tabname,
333
conditions={'Access': dbtables.ExactCond('0')},
334
mappings={'Access': remove_value})
335
self.tdb.Modify(tabname,
336
conditions={'Name': dbtables.LikeCond('%MP3%')},
337
mappings={'Type': set_type})
338
self.tdb.Modify(tabname,
339
conditions={'Name': dbtables.LikeCond('%')},
340
mappings={'Access': increment_access})
342
# Delete key in select conditions
343
values = self.tdb.Select(
345
conditions={'Type': dbtables.ExactCond('Unknown')})
346
assert len(values) == 1, values
347
assert values[0]['Name'] == None, values
348
assert values[0]['Access'] == None, values
350
# Modify value by select conditions
351
values = self.tdb.Select(
353
conditions={'Name': dbtables.ExactCond('Nifty.MP3')})
354
assert len(values) == 1, values
355
assert values[0]['Type'] == "MP3", values
356
assert values[0]['Access'] == "2", values
358
# Make sure change applied only to select conditions
359
values = self.tdb.Select(
360
tabname, None, conditions={'Name': dbtables.LikeCond('%doc%')})
361
assert len(values) == 1, values
362
assert values[0]['Type'] == "Word", values
363
assert values[0]['Access'] == "9", values
367
suite = unittest.TestSuite()
368
suite.addTest(unittest.makeSuite(TableDBTestCase))
372
if __name__ == '__main__':
373
unittest.main(defaultTest='test_suite')