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>
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')