Move setting of ioready 'wait' earlier in call chain, to
[python/dscho.git] / Lib / bsddb / test / test_associate.py
blob3061e4591a7690b4edd47d04b0b2d622dec9b265
1 """
2 TestCases for multi-threaded access to a DB.
3 """
5 import sys, os, string
6 import tempfile
7 import time
8 from pprint import pprint
10 try:
11 from threading import Thread, currentThread
12 have_threads = 1
13 except ImportError:
14 have_threads = 0
16 import unittest
17 from test_all import verbose
19 try:
20 # For Python 2.3
21 from bsddb import db, dbshelve
22 except ImportError:
23 # For earlier Pythons w/distutils pybsddb
24 from bsddb3 import db, dbshelve
27 #----------------------------------------------------------------------
30 musicdata = {
31 1 : ("Bad English", "The Price Of Love", "Rock"),
32 2 : ("DNA featuring Suzanne Vega", "Tom's Diner", "Rock"),
33 3 : ("George Michael", "Praying For Time", "Rock"),
34 4 : ("Gloria Estefan", "Here We Are", "Rock"),
35 5 : ("Linda Ronstadt", "Don't Know Much", "Rock"),
36 6 : ("Michael Bolton", "How Am I Supposed To Live Without You", "Blues"),
37 7 : ("Paul Young", "Oh Girl", "Rock"),
38 8 : ("Paula Abdul", "Opposites Attract", "Rock"),
39 9 : ("Richard Marx", "Should've Known Better", "Rock"),
40 10: ("Rod Stewart", "Forever Young", "Rock"),
41 11: ("Roxette", "Dangerous", "Rock"),
42 12: ("Sheena Easton", "The Lover In Me", "Rock"),
43 13: ("Sinead O'Connor", "Nothing Compares 2 U", "Rock"),
44 14: ("Stevie B.", "Because I Love You", "Rock"),
45 15: ("Taylor Dayne", "Love Will Lead You Back", "Rock"),
46 16: ("The Bangles", "Eternal Flame", "Rock"),
47 17: ("Wilson Phillips", "Release Me", "Rock"),
48 18: ("Billy Joel", "Blonde Over Blue", "Rock"),
49 19: ("Billy Joel", "Famous Last Words", "Rock"),
50 20: ("Billy Joel", "Lullabye (Goodnight, My Angel)", "Rock"),
51 21: ("Billy Joel", "The River Of Dreams", "Rock"),
52 22: ("Billy Joel", "Two Thousand Years", "Rock"),
53 23: ("Janet Jackson", "Alright", "Rock"),
54 24: ("Janet Jackson", "Black Cat", "Rock"),
55 25: ("Janet Jackson", "Come Back To Me", "Rock"),
56 26: ("Janet Jackson", "Escapade", "Rock"),
57 27: ("Janet Jackson", "Love Will Never Do (Without You)", "Rock"),
58 28: ("Janet Jackson", "Miss You Much", "Rock"),
59 29: ("Janet Jackson", "Rhythm Nation", "Rock"),
60 30: ("Janet Jackson", "State Of The World", "Rock"),
61 31: ("Janet Jackson", "The Knowledge", "Rock"),
62 32: ("Spyro Gyra", "End of Romanticism", "Jazz"),
63 33: ("Spyro Gyra", "Heliopolis", "Jazz"),
64 34: ("Spyro Gyra", "Jubilee", "Jazz"),
65 35: ("Spyro Gyra", "Little Linda", "Jazz"),
66 36: ("Spyro Gyra", "Morning Dance", "Jazz"),
67 37: ("Spyro Gyra", "Song for Lorraine", "Jazz"),
68 38: ("Yes", "Owner Of A Lonely Heart", "Rock"),
69 39: ("Yes", "Rhythm Of Love", "Rock"),
70 40: ("Cusco", "Dream Catcher", "New Age"),
71 41: ("Cusco", "Geronimos Laughter", "New Age"),
72 42: ("Cusco", "Ghost Dance", "New Age"),
73 43: ("Blue Man Group", "Drumbone", "New Age"),
74 44: ("Blue Man Group", "Endless Column", "New Age"),
75 45: ("Blue Man Group", "Klein Mandelbrot", "New Age"),
76 46: ("Kenny G", "Silhouette", "Jazz"),
77 47: ("Sade", "Smooth Operator", "Jazz"),
78 48: ("David Arkenstone", "Papillon (On The Wings Of The Butterfly)",
79 "New Age"),
80 49: ("David Arkenstone", "Stepping Stars", "New Age"),
81 50: ("David Arkenstone", "Carnation Lily Lily Rose", "New Age"),
82 51: ("David Lanz", "Behind The Waterfall", "New Age"),
83 52: ("David Lanz", "Cristofori's Dream", "New Age"),
84 53: ("David Lanz", "Heartsounds", "New Age"),
85 54: ("David Lanz", "Leaves on the Seine", "New Age"),
88 #----------------------------------------------------------------------
91 class AssociateTestCase(unittest.TestCase):
92 keytype = ''
94 def setUp(self):
95 self.filename = self.__class__.__name__ + '.db'
96 homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home')
97 self.homeDir = homeDir
98 try: os.mkdir(homeDir)
99 except os.error: pass
100 self.env = db.DBEnv()
101 self.env.open(homeDir, db.DB_CREATE | db.DB_INIT_MPOOL |
102 db.DB_INIT_LOCK | db.DB_THREAD)
104 def tearDown(self):
105 self.closeDB()
106 self.env.close()
107 import glob
108 files = glob.glob(os.path.join(self.homeDir, '*'))
109 for file in files:
110 os.remove(file)
112 def addDataToDB(self, d):
113 for key, value in musicdata.items():
114 if type(self.keytype) == type(''):
115 key = "%02d" % key
116 d.put(key, string.join(value, '|'))
118 def createDB(self):
119 self.primary = db.DB(self.env)
120 self.primary.open(self.filename, "primary", self.dbtype,
121 db.DB_CREATE | db.DB_THREAD)
123 def closeDB(self):
124 self.primary.close()
126 def getDB(self):
127 return self.primary
129 def test01_associateWithDB(self):
130 if verbose:
131 print '\n', '-=' * 30
132 print "Running %s.test01_associateWithDB..." % \
133 self.__class__.__name__
135 self.createDB()
137 secDB = db.DB(self.env)
138 secDB.set_flags(db.DB_DUP)
139 secDB.open(self.filename, "secondary", db.DB_BTREE,
140 db.DB_CREATE | db.DB_THREAD)
141 self.getDB().associate(secDB, self.getGenre)
143 self.addDataToDB(self.getDB())
145 self.finish_test(secDB)
148 def test02_associateAfterDB(self):
149 if verbose:
150 print '\n', '-=' * 30
151 print "Running %s.test02_associateAfterDB..." % \
152 self.__class__.__name__
154 self.createDB()
155 self.addDataToDB(self.getDB())
157 secDB = db.DB(self.env)
158 secDB.set_flags(db.DB_DUP)
159 secDB.open(self.filename, "secondary", db.DB_BTREE,
160 db.DB_CREATE | db.DB_THREAD)
162 # adding the DB_CREATE flag will cause it to index existing records
163 self.getDB().associate(secDB, self.getGenre, db.DB_CREATE)
165 self.finish_test(secDB)
168 def finish_test(self, secDB):
169 if verbose:
170 print "Primary key traversal:"
171 c = self.getDB().cursor()
172 count = 0
173 rec = c.first()
174 while rec is not None:
175 if type(self.keytype) == type(''):
176 assert string.atoi(rec[0]) # for primary db, key is a number
177 else:
178 assert rec[0] and type(rec[0]) == type(0)
179 count = count + 1
180 if verbose:
181 print rec
182 rec = c.next()
183 assert count == len(musicdata) # all items accounted for
186 if verbose:
187 print "Secondary key traversal:"
188 c = secDB.cursor()
189 count = 0
190 rec = c.first()
191 assert rec[0] == "Jazz"
192 while rec is not None:
193 count = count + 1
194 if verbose:
195 print rec
196 rec = c.next()
197 # all items accounted for EXCEPT for 1 with "Blues" genre
198 assert count == len(musicdata)-1
200 def getGenre(self, priKey, priData):
201 assert type(priData) == type("")
202 if verbose:
203 print 'getGenre key:', `priKey`, 'data:', `priData`
204 genre = string.split(priData, '|')[2]
205 if genre == 'Blues':
206 return db.DB_DONOTINDEX
207 else:
208 return genre
211 #----------------------------------------------------------------------
214 class AssociateHashTestCase(AssociateTestCase):
215 dbtype = db.DB_HASH
217 class AssociateBTreeTestCase(AssociateTestCase):
218 dbtype = db.DB_BTREE
220 class AssociateRecnoTestCase(AssociateTestCase):
221 dbtype = db.DB_RECNO
222 keytype = 0
225 #----------------------------------------------------------------------
227 class ShelveAssociateTestCase(AssociateTestCase):
229 def createDB(self):
230 self.primary = dbshelve.open(self.filename,
231 dbname="primary",
232 dbenv=self.env,
233 filetype=self.dbtype)
235 def addDataToDB(self, d):
236 for key, value in musicdata.items():
237 if type(self.keytype) == type(''):
238 key = "%02d" % key
239 d.put(key, value) # save the value as is this time
242 def getGenre(self, priKey, priData):
243 assert type(priData) == type(())
244 if verbose:
245 print 'getGenre key:', `priKey`, 'data:', `priData`
246 genre = priData[2]
247 if genre == 'Blues':
248 return db.DB_DONOTINDEX
249 else:
250 return genre
253 class ShelveAssociateHashTestCase(ShelveAssociateTestCase):
254 dbtype = db.DB_HASH
256 class ShelveAssociateBTreeTestCase(ShelveAssociateTestCase):
257 dbtype = db.DB_BTREE
259 class ShelveAssociateRecnoTestCase(ShelveAssociateTestCase):
260 dbtype = db.DB_RECNO
261 keytype = 0
264 #----------------------------------------------------------------------
266 class ThreadedAssociateTestCase(AssociateTestCase):
268 def addDataToDB(self, d):
269 t1 = Thread(target = self.writer1,
270 args = (d, ))
271 t2 = Thread(target = self.writer2,
272 args = (d, ))
274 t1.start()
275 t2.start()
276 t1.join()
277 t2.join()
279 def writer1(self, d):
280 for key, value in musicdata.items():
281 if type(self.keytype) == type(''):
282 key = "%02d" % key
283 d.put(key, string.join(value, '|'))
285 def writer2(self, d):
286 for x in range(100, 600):
287 key = 'z%2d' % x
288 value = [key] * 4
289 d.put(key, string.join(value, '|'))
292 class ThreadedAssociateHashTestCase(ShelveAssociateTestCase):
293 dbtype = db.DB_HASH
295 class ThreadedAssociateBTreeTestCase(ShelveAssociateTestCase):
296 dbtype = db.DB_BTREE
298 class ThreadedAssociateRecnoTestCase(ShelveAssociateTestCase):
299 dbtype = db.DB_RECNO
300 keytype = 0
303 #----------------------------------------------------------------------
305 def test_suite():
306 suite = unittest.TestSuite()
308 if db.version() >= (3, 3, 11):
309 suite.addTest(unittest.makeSuite(AssociateHashTestCase))
310 suite.addTest(unittest.makeSuite(AssociateBTreeTestCase))
311 suite.addTest(unittest.makeSuite(AssociateRecnoTestCase))
313 suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase))
314 suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase))
315 suite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase))
317 if have_threads:
318 suite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase))
319 suite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase))
320 suite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase))
322 return suite
325 if __name__ == '__main__':
326 unittest.main(defaultTest='test_suite')