/Lib/bsddb/test/test_dbtables.py
Python | 405 lines | 354 code | 26 blank | 25 comment | 21 complexity | 88402054184fd61c395f6368f9ab3715 MD5 | raw file
1#!/usr/bin/env python 2# 3#----------------------------------------------------------------------- 4# A test suite for the table interface built on bsddb.db 5#----------------------------------------------------------------------- 6# 7# Copyright (C) 2000, 2001 by Autonomous Zone Industries 8# Copyright (C) 2002 Gregory P. Smith 9# 10# March 20, 2000 11# 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 17# implied. 18# 19# -- Gregory P. Smith <greg@krypto.org> 20# 21# $Id: test_dbtables.py 66088 2008-08-31 14:00:51Z jesus.cea $ 22 23import os, re 24try: 25 import cPickle 26 pickle = cPickle 27except ImportError: 28 import pickle 29 30import unittest 31from test_all import db, dbtables, test_support, verbose, \ 32 get_new_environment_path, get_new_database_path 33 34#---------------------------------------------------------------------- 35 36class TableDBTestCase(unittest.TestCase): 37 db_name = 'test-table.db' 38 39 def setUp(self): 40 import sys 41 if sys.version_info[0] >= 3 : 42 from test_all import do_proxy_db_py3k 43 self._flag_proxy_db_py3k = do_proxy_db_py3k(False) 44 45 self.testHomeDir = get_new_environment_path() 46 self.tdb = dbtables.bsdTableDB( 47 filename='tabletest.db', dbhome=self.testHomeDir, create=1) 48 49 def tearDown(self): 50 self.tdb.close() 51 import sys 52 if sys.version_info[0] >= 3 : 53 from test_all import do_proxy_db_py3k 54 do_proxy_db_py3k(self._flag_proxy_db_py3k) 55 test_support.rmtree(self.testHomeDir) 56 57 def test01(self): 58 tabname = "test01" 59 colname = 'cool numbers' 60 try: 61 self.tdb.Drop(tabname) 62 except dbtables.TableDBError: 63 pass 64 self.tdb.CreateTable(tabname, [colname]) 65 import sys 66 if sys.version_info[0] < 3 : 67 self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)}) 68 else : 69 self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 70 1).decode("iso8859-1")}) # 8 bits 71 72 if verbose: 73 self.tdb._db_print() 74 75 values = self.tdb.Select( 76 tabname, [colname], conditions={colname: None}) 77 78 import sys 79 if sys.version_info[0] < 3 : 80 colval = pickle.loads(values[0][colname]) 81 else : 82 colval = pickle.loads(bytes(values[0][colname], "iso8859-1")) 83 self.assert_(colval > 3.141) 84 self.assert_(colval < 3.142) 85 86 87 def test02(self): 88 tabname = "test02" 89 col0 = 'coolness factor' 90 col1 = 'but can it fly?' 91 col2 = 'Species' 92 93 import sys 94 if sys.version_info[0] < 3 : 95 testinfo = [ 96 {col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'}, 97 {col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'}, 98 {col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'} 99 ] 100 else : 101 testinfo = [ 102 {col0: pickle.dumps(8, 1).decode("iso8859-1"), 103 col1: 'no', col2: 'Penguin'}, 104 {col0: pickle.dumps(-1, 1).decode("iso8859-1"), 105 col1: 'no', col2: 'Turkey'}, 106 {col0: pickle.dumps(9, 1).decode("iso8859-1"), 107 col1: 'yes', col2: 'SR-71A Blackbird'} 108 ] 109 110 try: 111 self.tdb.Drop(tabname) 112 except dbtables.TableDBError: 113 pass 114 self.tdb.CreateTable(tabname, [col0, col1, col2]) 115 for row in testinfo : 116 self.tdb.Insert(tabname, row) 117 118 import sys 119 if sys.version_info[0] < 3 : 120 values = self.tdb.Select(tabname, [col2], 121 conditions={col0: lambda x: pickle.loads(x) >= 8}) 122 else : 123 values = self.tdb.Select(tabname, [col2], 124 conditions={col0: lambda x: 125 pickle.loads(bytes(x, "iso8859-1")) >= 8}) 126 127 self.assertEqual(len(values), 2) 128 if values[0]['Species'] == 'Penguin' : 129 self.assertEqual(values[1]['Species'], 'SR-71A Blackbird') 130 elif values[0]['Species'] == 'SR-71A Blackbird' : 131 self.assertEqual(values[1]['Species'], 'Penguin') 132 else : 133 if verbose: 134 print "values= %r" % (values,) 135 raise RuntimeError("Wrong values returned!") 136 137 def test03(self): 138 tabname = "test03" 139 try: 140 self.tdb.Drop(tabname) 141 except dbtables.TableDBError: 142 pass 143 if verbose: 144 print '...before CreateTable...' 145 self.tdb._db_print() 146 self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e']) 147 if verbose: 148 print '...after CreateTable...' 149 self.tdb._db_print() 150 self.tdb.Drop(tabname) 151 if verbose: 152 print '...after Drop...' 153 self.tdb._db_print() 154 self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e']) 155 156 try: 157 self.tdb.Insert(tabname, 158 {'a': "", 159 'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1), 160 'f': "Zero"}) 161 self.fail('Expected an exception') 162 except dbtables.TableDBError: 163 pass 164 165 try: 166 self.tdb.Select(tabname, [], conditions={'foo': '123'}) 167 self.fail('Expected an exception') 168 except dbtables.TableDBError: 169 pass 170 171 self.tdb.Insert(tabname, 172 {'a': '42', 173 'b': "bad", 174 'c': "meep", 175 'e': 'Fuzzy wuzzy was a bear'}) 176 self.tdb.Insert(tabname, 177 {'a': '581750', 178 'b': "good", 179 'd': "bla", 180 'c': "black", 181 'e': 'fuzzy was here'}) 182 self.tdb.Insert(tabname, 183 {'a': '800000', 184 'b': "good", 185 'd': "bla", 186 'c': "black", 187 'e': 'Fuzzy wuzzy is a bear'}) 188 189 if verbose: 190 self.tdb._db_print() 191 192 # this should return two rows 193 values = self.tdb.Select(tabname, ['b', 'a', 'd'], 194 conditions={'e': re.compile('wuzzy').search, 195 'a': re.compile('^[0-9]+$').match}) 196 self.assertEqual(len(values), 2) 197 198 # now lets delete one of them and try again 199 self.tdb.Delete(tabname, conditions={'b': dbtables.ExactCond('good')}) 200 values = self.tdb.Select( 201 tabname, ['a', 'd', 'b'], 202 conditions={'e': dbtables.PrefixCond('Fuzzy')}) 203 self.assertEqual(len(values), 1) 204 self.assertEqual(values[0]['d'], None) 205 206 values = self.tdb.Select(tabname, ['b'], 207 conditions={'c': lambda c: c == 'meep'}) 208 self.assertEqual(len(values), 1) 209 self.assertEqual(values[0]['b'], "bad") 210 211 212 def test04_MultiCondSelect(self): 213 tabname = "test04_MultiCondSelect" 214 try: 215 self.tdb.Drop(tabname) 216 except dbtables.TableDBError: 217 pass 218 self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e']) 219 220 try: 221 self.tdb.Insert(tabname, 222 {'a': "", 223 'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1), 224 'f': "Zero"}) 225 self.fail('Expected an exception') 226 except dbtables.TableDBError: 227 pass 228 229 self.tdb.Insert(tabname, {'a': "A", 'b': "B", 'c': "C", 'd': "D", 230 'e': "E"}) 231 self.tdb.Insert(tabname, {'a': "-A", 'b': "-B", 'c': "-C", 'd': "-D", 232 'e': "-E"}) 233 self.tdb.Insert(tabname, {'a': "A-", 'b': "B-", 'c': "C-", 'd': "D-", 234 'e': "E-"}) 235 236 if verbose: 237 self.tdb._db_print() 238 239 # This select should return 0 rows. it is designed to test 240 # the bug identified and fixed in sourceforge bug # 590449 241 # (Big Thanks to "Rob Tillotson (n9mtb)" for tracking this down 242 # and supplying a fix!! This one caused many headaches to say 243 # the least...) 244 values = self.tdb.Select(tabname, ['b', 'a', 'd'], 245 conditions={'e': dbtables.ExactCond('E'), 246 'a': dbtables.ExactCond('A'), 247 'd': dbtables.PrefixCond('-') 248 } ) 249 self.assertEqual(len(values), 0, values) 250 251 252 def test_CreateOrExtend(self): 253 tabname = "test_CreateOrExtend" 254 255 self.tdb.CreateOrExtendTable( 256 tabname, ['name', 'taste', 'filling', 'alcohol content', 'price']) 257 try: 258 self.tdb.Insert(tabname, 259 {'taste': 'crap', 260 'filling': 'no', 261 'is it Guinness?': 'no'}) 262 self.fail("Insert should've failed due to bad column name") 263 except: 264 pass 265 self.tdb.CreateOrExtendTable(tabname, 266 ['name', 'taste', 'is it Guinness?']) 267 268 # these should both succeed as the table should contain the union of both sets of columns. 269 self.tdb.Insert(tabname, {'taste': 'crap', 'filling': 'no', 270 'is it Guinness?': 'no'}) 271 self.tdb.Insert(tabname, {'taste': 'great', 'filling': 'yes', 272 'is it Guinness?': 'yes', 273 'name': 'Guinness'}) 274 275 276 def test_CondObjs(self): 277 tabname = "test_CondObjs" 278 279 self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e', 'p']) 280 281 self.tdb.Insert(tabname, {'a': "the letter A", 282 'b': "the letter B", 283 'c': "is for cookie"}) 284 self.tdb.Insert(tabname, {'a': "is for aardvark", 285 'e': "the letter E", 286 'c': "is for cookie", 287 'd': "is for dog"}) 288 self.tdb.Insert(tabname, {'a': "the letter A", 289 'e': "the letter E", 290 'c': "is for cookie", 291 'p': "is for Python"}) 292 293 values = self.tdb.Select( 294 tabname, ['p', 'e'], 295 conditions={'e': dbtables.PrefixCond('the l')}) 296 self.assertEqual(len(values), 2, values) 297 self.assertEqual(values[0]['e'], values[1]['e'], values) 298 self.assertNotEqual(values[0]['p'], values[1]['p'], values) 299 300 values = self.tdb.Select( 301 tabname, ['d', 'a'], 302 conditions={'a': dbtables.LikeCond('%aardvark%')}) 303 self.assertEqual(len(values), 1, values) 304 self.assertEqual(values[0]['d'], "is for dog", values) 305 self.assertEqual(values[0]['a'], "is for aardvark", values) 306 307 values = self.tdb.Select(tabname, None, 308 {'b': dbtables.Cond(), 309 'e':dbtables.LikeCond('%letter%'), 310 'a':dbtables.PrefixCond('is'), 311 'd':dbtables.ExactCond('is for dog'), 312 'c':dbtables.PrefixCond('is for'), 313 'p':lambda s: not s}) 314 self.assertEqual(len(values), 1, values) 315 self.assertEqual(values[0]['d'], "is for dog", values) 316 self.assertEqual(values[0]['a'], "is for aardvark", values) 317 318 def test_Delete(self): 319 tabname = "test_Delete" 320 self.tdb.CreateTable(tabname, ['x', 'y', 'z']) 321 322 # prior to 2001-05-09 there was a bug where Delete() would 323 # fail if it encountered any rows that did not have values in 324 # every column. 325 # Hunted and Squashed by <Donwulff> (Jukka Santala - donwulff@nic.fi) 326 self.tdb.Insert(tabname, {'x': 'X1', 'y':'Y1'}) 327 self.tdb.Insert(tabname, {'x': 'X2', 'y':'Y2', 'z': 'Z2'}) 328 329 self.tdb.Delete(tabname, conditions={'x': dbtables.PrefixCond('X')}) 330 values = self.tdb.Select(tabname, ['y'], 331 conditions={'x': dbtables.PrefixCond('X')}) 332 self.assertEqual(len(values), 0) 333 334 def test_Modify(self): 335 tabname = "test_Modify" 336 self.tdb.CreateTable(tabname, ['Name', 'Type', 'Access']) 337 338 self.tdb.Insert(tabname, {'Name': 'Index to MP3 files.doc', 339 'Type': 'Word', 'Access': '8'}) 340 self.tdb.Insert(tabname, {'Name': 'Nifty.MP3', 'Access': '1'}) 341 self.tdb.Insert(tabname, {'Type': 'Unknown', 'Access': '0'}) 342 343 def set_type(type): 344 if type == None: 345 return 'MP3' 346 return type 347 348 def increment_access(count): 349 return str(int(count)+1) 350 351 def remove_value(value): 352 return None 353 354 self.tdb.Modify(tabname, 355 conditions={'Access': dbtables.ExactCond('0')}, 356 mappings={'Access': remove_value}) 357 self.tdb.Modify(tabname, 358 conditions={'Name': dbtables.LikeCond('%MP3%')}, 359 mappings={'Type': set_type}) 360 self.tdb.Modify(tabname, 361 conditions={'Name': dbtables.LikeCond('%')}, 362 mappings={'Access': increment_access}) 363 364 try: 365 self.tdb.Modify(tabname, 366 conditions={'Name': dbtables.LikeCond('%')}, 367 mappings={'Access': 'What is your quest?'}) 368 except TypeError: 369 # success, the string value in mappings isn't callable 370 pass 371 else: 372 raise RuntimeError, "why was TypeError not raised for bad callable?" 373 374 # Delete key in select conditions 375 values = self.tdb.Select( 376 tabname, None, 377 conditions={'Type': dbtables.ExactCond('Unknown')}) 378 self.assertEqual(len(values), 1, values) 379 self.assertEqual(values[0]['Name'], None, values) 380 self.assertEqual(values[0]['Access'], None, values) 381 382 # Modify value by select conditions 383 values = self.tdb.Select( 384 tabname, None, 385 conditions={'Name': dbtables.ExactCond('Nifty.MP3')}) 386 self.assertEqual(len(values), 1, values) 387 self.assertEqual(values[0]['Type'], "MP3", values) 388 self.assertEqual(values[0]['Access'], "2", values) 389 390 # Make sure change applied only to select conditions 391 values = self.tdb.Select( 392 tabname, None, conditions={'Name': dbtables.LikeCond('%doc%')}) 393 self.assertEqual(len(values), 1, values) 394 self.assertEqual(values[0]['Type'], "Word", values) 395 self.assertEqual(values[0]['Access'], "9", values) 396 397 398def test_suite(): 399 suite = unittest.TestSuite() 400 suite.addTest(unittest.makeSuite(TableDBTestCase)) 401 return suite 402 403 404if __name__ == '__main__': 405 unittest.main(defaultTest='test_suite')