ยปCore Development>Code coverage>Lib/bsddb/test/test_associate.py

Python code coverage for Lib/bsddb/test/test_associate.py

#countcontent
1n/a"""
2n/aTestCases for DB.associate.
3n/a"""
4n/a
5n/aimport sys, os, string
6n/aimport time
7n/afrom pprint import pprint
8n/a
9n/aimport unittest
10n/afrom test_all import db, dbshelve, test_support, verbose, have_threads, \
11n/a get_new_environment_path
12n/a
13n/a
14n/a#----------------------------------------------------------------------
15n/a
16n/a
17n/amusicdata = {
18n/a1 : ("Bad English", "The Price Of Love", "Rock"),
19n/a2 : ("DNA featuring Suzanne Vega", "Tom's Diner", "Rock"),
20n/a3 : ("George Michael", "Praying For Time", "Rock"),
21n/a4 : ("Gloria Estefan", "Here We Are", "Rock"),
22n/a5 : ("Linda Ronstadt", "Don't Know Much", "Rock"),
23n/a6 : ("Michael Bolton", "How Am I Supposed To Live Without You", "Blues"),
24n/a7 : ("Paul Young", "Oh Girl", "Rock"),
25n/a8 : ("Paula Abdul", "Opposites Attract", "Rock"),
26n/a9 : ("Richard Marx", "Should've Known Better", "Rock"),
27n/a10: ("Rod Stewart", "Forever Young", "Rock"),
28n/a11: ("Roxette", "Dangerous", "Rock"),
29n/a12: ("Sheena Easton", "The Lover In Me", "Rock"),
30n/a13: ("Sinead O'Connor", "Nothing Compares 2 U", "Rock"),
31n/a14: ("Stevie B.", "Because I Love You", "Rock"),
32n/a15: ("Taylor Dayne", "Love Will Lead You Back", "Rock"),
33n/a16: ("The Bangles", "Eternal Flame", "Rock"),
34n/a17: ("Wilson Phillips", "Release Me", "Rock"),
35n/a18: ("Billy Joel", "Blonde Over Blue", "Rock"),
36n/a19: ("Billy Joel", "Famous Last Words", "Rock"),
37n/a20: ("Billy Joel", "Lullabye (Goodnight, My Angel)", "Rock"),
38n/a21: ("Billy Joel", "The River Of Dreams", "Rock"),
39n/a22: ("Billy Joel", "Two Thousand Years", "Rock"),
40n/a23: ("Janet Jackson", "Alright", "Rock"),
41n/a24: ("Janet Jackson", "Black Cat", "Rock"),
42n/a25: ("Janet Jackson", "Come Back To Me", "Rock"),
43n/a26: ("Janet Jackson", "Escapade", "Rock"),
44n/a27: ("Janet Jackson", "Love Will Never Do (Without You)", "Rock"),
45n/a28: ("Janet Jackson", "Miss You Much", "Rock"),
46n/a29: ("Janet Jackson", "Rhythm Nation", "Rock"),
47n/a30: ("Janet Jackson", "State Of The World", "Rock"),
48n/a31: ("Janet Jackson", "The Knowledge", "Rock"),
49n/a32: ("Spyro Gyra", "End of Romanticism", "Jazz"),
50n/a33: ("Spyro Gyra", "Heliopolis", "Jazz"),
51n/a34: ("Spyro Gyra", "Jubilee", "Jazz"),
52n/a35: ("Spyro Gyra", "Little Linda", "Jazz"),
53n/a36: ("Spyro Gyra", "Morning Dance", "Jazz"),
54n/a37: ("Spyro Gyra", "Song for Lorraine", "Jazz"),
55n/a38: ("Yes", "Owner Of A Lonely Heart", "Rock"),
56n/a39: ("Yes", "Rhythm Of Love", "Rock"),
57n/a40: ("Cusco", "Dream Catcher", "New Age"),
58n/a41: ("Cusco", "Geronimos Laughter", "New Age"),
59n/a42: ("Cusco", "Ghost Dance", "New Age"),
60n/a43: ("Blue Man Group", "Drumbone", "New Age"),
61n/a44: ("Blue Man Group", "Endless Column", "New Age"),
62n/a45: ("Blue Man Group", "Klein Mandelbrot", "New Age"),
63n/a46: ("Kenny G", "Silhouette", "Jazz"),
64n/a47: ("Sade", "Smooth Operator", "Jazz"),
65n/a48: ("David Arkenstone", "Papillon (On The Wings Of The Butterfly)",
66n/a "New Age"),
67n/a49: ("David Arkenstone", "Stepping Stars", "New Age"),
68n/a50: ("David Arkenstone", "Carnation Lily Lily Rose", "New Age"),
69n/a51: ("David Lanz", "Behind The Waterfall", "New Age"),
70n/a52: ("David Lanz", "Cristofori's Dream", "New Age"),
71n/a53: ("David Lanz", "Heartsounds", "New Age"),
72n/a54: ("David Lanz", "Leaves on the Seine", "New Age"),
73n/a99: ("unknown artist", "Unnamed song", "Unknown"),
74n/a}
75n/a
76n/a#----------------------------------------------------------------------
77n/a
78n/aclass AssociateErrorTestCase(unittest.TestCase):
79n/a def setUp(self):
80n/a self.filename = self.__class__.__name__ + '.db'
81n/a self.homeDir = get_new_environment_path()
82n/a self.env = db.DBEnv()
83n/a self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL)
84n/a
85n/a def tearDown(self):
86n/a self.env.close()
87n/a self.env = None
88n/a test_support.rmtree(self.homeDir)
89n/a
90n/a def test00_associateDBError(self):
91n/a if verbose:
92n/a print '\n', '-=' * 30
93n/a print "Running %s.test00_associateDBError..." % \
94n/a self.__class__.__name__
95n/a
96n/a dupDB = db.DB(self.env)
97n/a dupDB.set_flags(db.DB_DUP)
98n/a dupDB.open(self.filename, "primary", db.DB_BTREE, db.DB_CREATE)
99n/a
100n/a secDB = db.DB(self.env)
101n/a secDB.open(self.filename, "secondary", db.DB_BTREE, db.DB_CREATE)
102n/a
103n/a # dupDB has been configured to allow duplicates, it can't
104n/a # associate with a secondary. Berkeley DB will return an error.
105n/a try:
106n/a def f(a,b): return a+b
107n/a dupDB.associate(secDB, f)
108n/a except db.DBError:
109n/a # good
110n/a secDB.close()
111n/a dupDB.close()
112n/a else:
113n/a secDB.close()
114n/a dupDB.close()
115n/a self.fail("DBError exception was expected")
116n/a
117n/a
118n/a
119n/a#----------------------------------------------------------------------
120n/a
121n/a
122n/aclass AssociateTestCase(unittest.TestCase):
123n/a keytype = ''
124n/a envFlags = 0
125n/a dbFlags = 0
126n/a
127n/a def setUp(self):
128n/a self.filename = self.__class__.__name__ + '.db'
129n/a self.homeDir = get_new_environment_path()
130n/a self.env = db.DBEnv()
131n/a self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL |
132n/a db.DB_INIT_LOCK | db.DB_THREAD | self.envFlags)
133n/a
134n/a def tearDown(self):
135n/a self.closeDB()
136n/a self.env.close()
137n/a self.env = None
138n/a test_support.rmtree(self.homeDir)
139n/a
140n/a def addDataToDB(self, d, txn=None):
141n/a for key, value in musicdata.items():
142n/a if type(self.keytype) == type(''):
143n/a key = "%02d" % key
144n/a d.put(key, '|'.join(value), txn=txn)
145n/a
146n/a def createDB(self, txn=None):
147n/a self.cur = None
148n/a self.secDB = None
149n/a self.primary = db.DB(self.env)
150n/a self.primary.set_get_returns_none(2)
151n/a self.primary.open(self.filename, "primary", self.dbtype,
152n/a db.DB_CREATE | db.DB_THREAD | self.dbFlags, txn=txn)
153n/a
154n/a def closeDB(self):
155n/a if self.cur:
156n/a self.cur.close()
157n/a self.cur = None
158n/a if self.secDB:
159n/a self.secDB.close()
160n/a self.secDB = None
161n/a self.primary.close()
162n/a self.primary = None
163n/a
164n/a def getDB(self):
165n/a return self.primary
166n/a
167n/a
168n/a def _associateWithDB(self, getGenre):
169n/a self.createDB()
170n/a
171n/a self.secDB = db.DB(self.env)
172n/a self.secDB.set_flags(db.DB_DUP)
173n/a self.secDB.set_get_returns_none(2)
174n/a self.secDB.open(self.filename, "secondary", db.DB_BTREE,
175n/a db.DB_CREATE | db.DB_THREAD | self.dbFlags)
176n/a self.getDB().associate(self.secDB, getGenre)
177n/a
178n/a self.addDataToDB(self.getDB())
179n/a
180n/a self.finish_test(self.secDB)
181n/a
182n/a def test01_associateWithDB(self):
183n/a if verbose:
184n/a print '\n', '-=' * 30
185n/a print "Running %s.test01_associateWithDB..." % \
186n/a self.__class__.__name__
187n/a
188n/a return self._associateWithDB(self.getGenre)
189n/a
190n/a def _associateAfterDB(self, getGenre) :
191n/a self.createDB()
192n/a self.addDataToDB(self.getDB())
193n/a
194n/a self.secDB = db.DB(self.env)
195n/a self.secDB.set_flags(db.DB_DUP)
196n/a self.secDB.open(self.filename, "secondary", db.DB_BTREE,
197n/a db.DB_CREATE | db.DB_THREAD | self.dbFlags)
198n/a
199n/a # adding the DB_CREATE flag will cause it to index existing records
200n/a self.getDB().associate(self.secDB, getGenre, db.DB_CREATE)
201n/a
202n/a self.finish_test(self.secDB)
203n/a
204n/a def test02_associateAfterDB(self):
205n/a if verbose:
206n/a print '\n', '-=' * 30
207n/a print "Running %s.test02_associateAfterDB..." % \
208n/a self.__class__.__name__
209n/a
210n/a return self._associateAfterDB(self.getGenre)
211n/a
212n/a if db.version() >= (4, 6):
213n/a def test03_associateWithDB(self):
214n/a if verbose:
215n/a print '\n', '-=' * 30
216n/a print "Running %s.test03_associateWithDB..." % \
217n/a self.__class__.__name__
218n/a
219n/a return self._associateWithDB(self.getGenreList)
220n/a
221n/a def test04_associateAfterDB(self):
222n/a if verbose:
223n/a print '\n', '-=' * 30
224n/a print "Running %s.test04_associateAfterDB..." % \
225n/a self.__class__.__name__
226n/a
227n/a return self._associateAfterDB(self.getGenreList)
228n/a
229n/a
230n/a def finish_test(self, secDB, txn=None):
231n/a # 'Blues' should not be in the secondary database
232n/a vals = secDB.pget('Blues', txn=txn)
233n/a self.assertEqual(vals, None, vals)
234n/a
235n/a vals = secDB.pget('Unknown', txn=txn)
236n/a self.assert_(vals[0] == 99 or vals[0] == '99', vals)
237n/a vals[1].index('Unknown')
238n/a vals[1].index('Unnamed')
239n/a vals[1].index('unknown')
240n/a
241n/a if verbose:
242n/a print "Primary key traversal:"
243n/a self.cur = self.getDB().cursor(txn)
244n/a count = 0
245n/a rec = self.cur.first()
246n/a while rec is not None:
247n/a if type(self.keytype) == type(''):
248n/a self.assert_(int(rec[0])) # for primary db, key is a number
249n/a else:
250n/a self.assert_(rec[0] and type(rec[0]) == type(0))
251n/a count = count + 1
252n/a if verbose:
253n/a print rec
254n/a rec = getattr(self.cur, "next")()
255n/a self.assertEqual(count, len(musicdata)) # all items accounted for
256n/a
257n/a
258n/a if verbose:
259n/a print "Secondary key traversal:"
260n/a self.cur = secDB.cursor(txn)
261n/a count = 0
262n/a
263n/a # test cursor pget
264n/a vals = self.cur.pget('Unknown', flags=db.DB_LAST)
265n/a self.assert_(vals[1] == 99 or vals[1] == '99', vals)
266n/a self.assertEqual(vals[0], 'Unknown')
267n/a vals[2].index('Unknown')
268n/a vals[2].index('Unnamed')
269n/a vals[2].index('unknown')
270n/a
271n/a vals = self.cur.pget('Unknown', data='wrong value', flags=db.DB_GET_BOTH)
272n/a self.assertEqual(vals, None, vals)
273n/a
274n/a rec = self.cur.first()
275n/a self.assertEqual(rec[0], "Jazz")
276n/a while rec is not None:
277n/a count = count + 1
278n/a if verbose:
279n/a print rec
280n/a rec = getattr(self.cur, "next")()
281n/a # all items accounted for EXCEPT for 1 with "Blues" genre
282n/a self.assertEqual(count, len(musicdata)-1)
283n/a
284n/a self.cur = None
285n/a
286n/a def getGenre(self, priKey, priData):
287n/a self.assertEqual(type(priData), type(""))
288n/a genre = priData.split('|')[2]
289n/a
290n/a if verbose:
291n/a print 'getGenre key: %r data: %r' % (priKey, priData)
292n/a
293n/a if genre == 'Blues':
294n/a return db.DB_DONOTINDEX
295n/a else:
296n/a return genre
297n/a
298n/a def getGenreList(self, priKey, PriData) :
299n/a v = self.getGenre(priKey, PriData)
300n/a if type(v) == type("") :
301n/a v = [v]
302n/a return v
303n/a
304n/a
305n/a#----------------------------------------------------------------------
306n/a
307n/a
308n/aclass AssociateHashTestCase(AssociateTestCase):
309n/a dbtype = db.DB_HASH
310n/a
311n/aclass AssociateBTreeTestCase(AssociateTestCase):
312n/a dbtype = db.DB_BTREE
313n/a
314n/aclass AssociateRecnoTestCase(AssociateTestCase):
315n/a dbtype = db.DB_RECNO
316n/a keytype = 0
317n/a
318n/a#----------------------------------------------------------------------
319n/a
320n/aclass AssociateBTreeTxnTestCase(AssociateBTreeTestCase):
321n/a envFlags = db.DB_INIT_TXN
322n/a dbFlags = 0
323n/a
324n/a def txn_finish_test(self, sDB, txn):
325n/a try:
326n/a self.finish_test(sDB, txn=txn)
327n/a finally:
328n/a if self.cur:
329n/a self.cur.close()
330n/a self.cur = None
331n/a if txn:
332n/a txn.commit()
333n/a
334n/a def test13_associate_in_transaction(self):
335n/a if verbose:
336n/a print '\n', '-=' * 30
337n/a print "Running %s.test13_associateAutoCommit..." % \
338n/a self.__class__.__name__
339n/a
340n/a txn = self.env.txn_begin()
341n/a try:
342n/a self.createDB(txn=txn)
343n/a
344n/a self.secDB = db.DB(self.env)
345n/a self.secDB.set_flags(db.DB_DUP)
346n/a self.secDB.set_get_returns_none(2)
347n/a self.secDB.open(self.filename, "secondary", db.DB_BTREE,
348n/a db.DB_CREATE | db.DB_THREAD, txn=txn)
349n/a self.getDB().associate(self.secDB, self.getGenre, txn=txn)
350n/a
351n/a self.addDataToDB(self.getDB(), txn=txn)
352n/a except:
353n/a txn.abort()
354n/a raise
355n/a
356n/a self.txn_finish_test(self.secDB, txn=txn)
357n/a
358n/a
359n/a#----------------------------------------------------------------------
360n/a
361n/aclass ShelveAssociateTestCase(AssociateTestCase):
362n/a
363n/a def createDB(self):
364n/a self.primary = dbshelve.open(self.filename,
365n/a dbname="primary",
366n/a dbenv=self.env,
367n/a filetype=self.dbtype)
368n/a
369n/a def addDataToDB(self, d):
370n/a for key, value in musicdata.items():
371n/a if type(self.keytype) == type(''):
372n/a key = "%02d" % key
373n/a d.put(key, value) # save the value as is this time
374n/a
375n/a
376n/a def getGenre(self, priKey, priData):
377n/a self.assertEqual(type(priData), type(()))
378n/a if verbose:
379n/a print 'getGenre key: %r data: %r' % (priKey, priData)
380n/a genre = priData[2]
381n/a if genre == 'Blues':
382n/a return db.DB_DONOTINDEX
383n/a else:
384n/a return genre
385n/a
386n/a
387n/aclass ShelveAssociateHashTestCase(ShelveAssociateTestCase):
388n/a dbtype = db.DB_HASH
389n/a
390n/aclass ShelveAssociateBTreeTestCase(ShelveAssociateTestCase):
391n/a dbtype = db.DB_BTREE
392n/a
393n/aclass ShelveAssociateRecnoTestCase(ShelveAssociateTestCase):
394n/a dbtype = db.DB_RECNO
395n/a keytype = 0
396n/a
397n/a
398n/a#----------------------------------------------------------------------
399n/a
400n/aclass ThreadedAssociateTestCase(AssociateTestCase):
401n/a
402n/a def addDataToDB(self, d):
403n/a t1 = Thread(target = self.writer1,
404n/a args = (d, ))
405n/a t2 = Thread(target = self.writer2,
406n/a args = (d, ))
407n/a
408n/a t1.setDaemon(True)
409n/a t2.setDaemon(True)
410n/a t1.start()
411n/a t2.start()
412n/a t1.join()
413n/a t2.join()
414n/a
415n/a def writer1(self, d):
416n/a for key, value in musicdata.items():
417n/a if type(self.keytype) == type(''):
418n/a key = "%02d" % key
419n/a d.put(key, '|'.join(value))
420n/a
421n/a def writer2(self, d):
422n/a for x in range(100, 600):
423n/a key = 'z%2d' % x
424n/a value = [key] * 4
425n/a d.put(key, '|'.join(value))
426n/a
427n/a
428n/aclass ThreadedAssociateHashTestCase(ShelveAssociateTestCase):
429n/a dbtype = db.DB_HASH
430n/a
431n/aclass ThreadedAssociateBTreeTestCase(ShelveAssociateTestCase):
432n/a dbtype = db.DB_BTREE
433n/a
434n/aclass ThreadedAssociateRecnoTestCase(ShelveAssociateTestCase):
435n/a dbtype = db.DB_RECNO
436n/a keytype = 0
437n/a
438n/a
439n/a#----------------------------------------------------------------------
440n/a
441n/adef test_suite():
442n/a suite = unittest.TestSuite()
443n/a
444n/a suite.addTest(unittest.makeSuite(AssociateErrorTestCase))
445n/a
446n/a suite.addTest(unittest.makeSuite(AssociateHashTestCase))
447n/a suite.addTest(unittest.makeSuite(AssociateBTreeTestCase))
448n/a suite.addTest(unittest.makeSuite(AssociateRecnoTestCase))
449n/a
450n/a suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase))
451n/a
452n/a suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase))
453n/a suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase))
454n/a suite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase))
455n/a
456n/a if have_threads:
457n/a suite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase))
458n/a suite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase))
459n/a suite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase))
460n/a
461n/a return suite
462n/a
463n/a
464n/aif __name__ == '__main__':
465n/a unittest.main(defaultTest='test_suite')