Code

4edb232cee1c76d481d67d9616d83170b358dc73
[roundup.git] / test / test_db.py
1 #
2 # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
3 # This module is free software, and you may redistribute it and/or modify
4 # under the same terms as Python, so long as this copyright message and
5 # disclaimer are retained in their original form.
6 #
7 # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
8 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
9 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
10 # POSSIBILITY OF SUCH DAMAGE.
11 #
12 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
17
18 # $Id: test_db.py,v 1.44 2002-09-10 03:01:20 richard Exp $ 
20 import unittest, os, shutil, time
22 from roundup.hyperdb import String, Password, Link, Multilink, Date, \
23     Interval, DatabaseError, Boolean, Number
24 from roundup import date, password
25 from roundup.indexer import Indexer
27 def setupSchema(db, create, module):
28     status = module.Class(db, "status", name=String())
29     status.setkey("name")
30     user = module.Class(db, "user", username=String(), password=Password(),
31         assignable=Boolean(), age=Number(), roles=String())
32     user.setkey("username")
33     file = module.FileClass(db, "file", name=String(), type=String(),
34         comment=String(indexme="yes"))
35     issue = module.IssueClass(db, "issue", title=String(indexme="yes"),
36         status=Link("status"), nosy=Multilink("user"), deadline=Date(),
37         foo=Interval(), files=Multilink("file"), assignedto=Link('user'))
38     session = module.Class(db, 'session', title=String())
39     session.disableJournalling()
40     db.post_init()
41     if create:
42         status.create(name="unread")
43         status.create(name="in-progress")
44         status.create(name="testing")
45         status.create(name="resolved")
46     db.commit()
48 class MyTestCase(unittest.TestCase):
49     def tearDown(self):
50         if os.path.exists('_test_dir'):
51             shutil.rmtree('_test_dir')
53 class config:
54     DATABASE='_test_dir'
55     MAILHOST = 'localhost'
56     MAIL_DOMAIN = 'fill.me.in.'
57     TRACKER_NAME = 'Roundup issue tracker'
58     TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN
59     TRACKER_WEB = 'http://some.useful.url/'
60     ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
61     FILTER_POSITION = 'bottom'      # one of 'top', 'bottom', 'top and bottom'
62     ANONYMOUS_ACCESS = 'deny'       # either 'deny' or 'allow'
63     ANONYMOUS_REGISTER = 'deny'     # either 'deny' or 'allow'
64     MESSAGES_TO_AUTHOR = 'no'       # either 'yes' or 'no'
65     EMAIL_SIGNATURE_POSITION = 'bottom'
67 class anydbmDBTestCase(MyTestCase):
68     def setUp(self):
69         from roundup.backends import anydbm
70         # remove previous test, ignore errors
71         if os.path.exists(config.DATABASE):
72             shutil.rmtree(config.DATABASE)
73         os.makedirs(config.DATABASE + '/files')
74         self.db = anydbm.Database(config, 'test')
75         setupSchema(self.db, 1, anydbm)
76         self.db2 = anydbm.Database(config, 'test')
77         setupSchema(self.db2, 0, anydbm)
79     def testStringChange(self):
80         self.db.issue.create(title="spam", status='1')
81         self.assertEqual(self.db.issue.get('1', 'title'), 'spam')
82         self.db.issue.set('1', title='eggs')
83         self.assertEqual(self.db.issue.get('1', 'title'), 'eggs')
84         self.db.commit()
85         self.assertEqual(self.db.issue.get('1', 'title'), 'eggs')
86         self.db.issue.create(title="spam", status='1')
87         self.db.commit()
88         self.assertEqual(self.db.issue.get('2', 'title'), 'spam')
89         self.db.issue.set('2', title='ham')
90         self.assertEqual(self.db.issue.get('2', 'title'), 'ham')
91         self.db.commit()
92         self.assertEqual(self.db.issue.get('2', 'title'), 'ham')
93         self.db.issue.set('1', title=None)
94         self.assertEqual(self.db.issue.get('1', "title"), None)
96     def testLinkChange(self):
97         self.db.issue.create(title="spam", status='1')
98         self.assertEqual(self.db.issue.get('1', "status"), '1')
99         self.db.issue.set('1', status='2')
100         self.assertEqual(self.db.issue.get('1', "status"), '2')
101         self.db.issue.set('1', status=None)
102         self.assertEqual(self.db.issue.get('1', "status"), None)
104     def testMultilinkChange(self):
105         u1 = self.db.user.create(username='foo')
106         u2 = self.db.user.create(username='bar')
107         self.db.issue.create(title="spam", nosy=[u1])
108         self.assertEqual(self.db.issue.get('1', "nosy"), [u1])
109         self.db.issue.set('1', nosy=[])
110         self.assertEqual(self.db.issue.get('1', "nosy"), [])
111         self.db.issue.set('1', nosy=[u1,u2])
112         self.assertEqual(self.db.issue.get('1', "nosy"), [u1,u2])
114     def testDateChange(self):
115         self.db.issue.create(title="spam", status='1')
116         a = self.db.issue.get('1', "deadline")
117         self.db.issue.set('1', deadline=date.Date())
118         b = self.db.issue.get('1', "deadline")
119         self.db.commit()
120         self.assertNotEqual(a, b)
121         self.assertNotEqual(b, date.Date('1970-1-1 00:00:00'))
122         self.db.issue.set('1', deadline=date.Date())
123         self.db.issue.set('1', deadline=None)
124         self.assertEqual(self.db.issue.get('1', "deadline"), None)
126     def testIntervalChange(self):
127         self.db.issue.create(title="spam", status='1')
128         a = self.db.issue.get('1', "foo")
129         self.db.issue.set('1', foo=date.Interval('-1d'))
130         self.assertNotEqual(self.db.issue.get('1', "foo"), a)
131         self.db.issue.set('1', foo=None)
132         self.assertEqual(self.db.issue.get('1', "foo"), None)
134     def testBooleanChange(self):
135         userid = self.db.user.create(username='foo', assignable=1)
136         self.db.user.create(username='foo2', assignable=0)
137         a = self.db.user.get(userid, 'assignable')
138         self.db.user.set(userid, assignable=0)
139         self.assertNotEqual(self.db.user.get(userid, 'assignable'), a)
140         self.db.user.set(userid, assignable=0)
141         self.db.user.set(userid, assignable=1)
142         self.db.user.set('1', assignable=None)
143         self.assertEqual(self.db.user.get('1', "assignable"), None)
145     def testNumberChange(self):
146         self.db.user.create(username='foo', age='1')
147         a = self.db.user.get('1', 'age')
148         self.db.user.set('1', age='3')
149         self.assertNotEqual(self.db.user.get('1', 'age'), a)
150         self.db.user.set('1', age='1.0')
151         self.db.user.set('1', age=None)
152         self.assertEqual(self.db.user.get('1', "age"), None)
154     def testNewProperty(self):
155         self.db.issue.create(title="spam", status='1')
156         self.db.issue.addprop(fixer=Link("user"))
157         # force any post-init stuff to happen
158         self.db.post_init()
159         props = self.db.issue.getprops()
160         keys = props.keys()
161         keys.sort()
162         self.assertEqual(keys, ['activity', 'assignedto', 'creation',
163             'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages',
164             'nosy', 'status', 'superseder', 'title'])
165         self.assertEqual(self.db.issue.get('1', "fixer"), None)
167     def testRetire(self):
168         self.db.issue.create(title="spam", status='1')
169         b = self.db.status.get('1', 'name')
170         a = self.db.status.list()
171         self.db.status.retire('1')
172         # make sure the list is different 
173         self.assertNotEqual(a, self.db.status.list())
174         # can still access the node if necessary
175         self.assertEqual(self.db.status.get('1', 'name'), b)
176         self.db.commit()
177         self.assertEqual(self.db.status.get('1', 'name'), b)
178         self.assertNotEqual(a, self.db.status.list())
180     def testSerialisation(self):
181         self.db.issue.create(title="spam", status='1',
182             deadline=date.Date(), foo=date.Interval('-1d'))
183         self.db.commit()
184         assert isinstance(self.db.issue.get('1', 'deadline'), date.Date)
185         assert isinstance(self.db.issue.get('1', 'foo'), date.Interval)
186         self.db.user.create(username="fozzy",
187             password=password.Password('t. bear'))
188         self.db.commit()
189         assert isinstance(self.db.user.get('1', 'password'), password.Password)
191     def testTransactions(self):
192         # remember the number of items we started
193         num_issues = len(self.db.issue.list())
194         num_files = self.db.numfiles()
195         self.db.issue.create(title="don't commit me!", status='1')
196         self.assertNotEqual(num_issues, len(self.db.issue.list()))
197         self.db.rollback()
198         self.assertEqual(num_issues, len(self.db.issue.list()))
199         self.db.issue.create(title="please commit me!", status='1')
200         self.assertNotEqual(num_issues, len(self.db.issue.list()))
201         self.db.commit()
202         self.assertNotEqual(num_issues, len(self.db.issue.list()))
203         self.db.rollback()
204         self.assertNotEqual(num_issues, len(self.db.issue.list()))
205         self.db.file.create(name="test", type="text/plain", content="hi")
206         self.db.rollback()
207         self.assertEqual(num_files, self.db.numfiles())
208         for i in range(10):
209             self.db.file.create(name="test", type="text/plain", 
210                     content="hi %d"%(i))
211             self.db.commit()
212         num_files2 = self.db.numfiles()
213         self.assertNotEqual(num_files, num_files2)
214         self.db.file.create(name="test", type="text/plain", content="hi")
215         self.db.rollback()
216         self.assertNotEqual(num_files, self.db.numfiles())
217         self.assertEqual(num_files2, self.db.numfiles())
219     def testDestroyNoJournalling(self):
220         self.innerTestDestroy(klass=self.db.session)
222     def testDestroyJournalling(self):
223         self.innerTestDestroy(klass=self.db.issue)
225     def innerTestDestroy(self, klass):
226         newid = klass.create(title='Mr Friendly')
227         n = len(klass.list())
228         self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
229         klass.destroy(newid)
230         self.assertRaises(IndexError, klass.get, newid, 'title')
231         self.assertNotEqual(len(klass.list()), n)
232         if klass.do_journal:
233             self.assertRaises(IndexError, klass.history, newid)
235         # now with a commit
236         newid = klass.create(title='Mr Friendly')
237         n = len(klass.list())
238         self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
239         self.db.commit()
240         klass.destroy(newid)
241         self.assertRaises(IndexError, klass.get, newid, 'title')
242         self.db.commit()
243         self.assertRaises(IndexError, klass.get, newid, 'title')
244         self.assertNotEqual(len(klass.list()), n)
245         if klass.do_journal:
246             self.assertRaises(IndexError, klass.history, newid)
248         # now with a rollback
249         newid = klass.create(title='Mr Friendly')
250         n = len(klass.list())
251         self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
252         self.db.commit()
253         klass.destroy(newid)
254         self.assertNotEqual(len(klass.list()), n)
255         self.assertRaises(IndexError, klass.get, newid, 'title')
256         self.db.rollback()
257         self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
258         self.assertEqual(len(klass.list()), n)
259         if klass.do_journal:
260             self.assertNotEqual(klass.history(newid), [])
262     def testExceptions(self):
263         # this tests the exceptions that should be raised
264         ar = self.assertRaises
266         #
267         # class create
268         #
269         # string property
270         ar(TypeError, self.db.status.create, name=1)
271         # invalid property name
272         ar(KeyError, self.db.status.create, foo='foo')
273         # key name clash
274         ar(ValueError, self.db.status.create, name='unread')
275         # invalid link index
276         ar(IndexError, self.db.issue.create, title='foo', status='bar')
277         # invalid link value
278         ar(ValueError, self.db.issue.create, title='foo', status=1)
279         # invalid multilink type
280         ar(TypeError, self.db.issue.create, title='foo', status='1',
281             nosy='hello')
282         # invalid multilink index type
283         ar(ValueError, self.db.issue.create, title='foo', status='1',
284             nosy=[1])
285         # invalid multilink index
286         ar(IndexError, self.db.issue.create, title='foo', status='1',
287             nosy=['10'])
289         #
290         # key property
291         # 
292         # key must be a String
293         ar(TypeError, self.db.user.setkey, 'password')
294         # key must exist
295         ar(KeyError, self.db.user.setkey, 'fubar')
297         #
298         # class get
299         #
300         # invalid node id
301         ar(IndexError, self.db.issue.get, '1', 'title')
302         # invalid property name
303         ar(KeyError, self.db.status.get, '2', 'foo')
305         #
306         # class set
307         #
308         # invalid node id
309         ar(IndexError, self.db.issue.set, '1', title='foo')
310         # invalid property name
311         ar(KeyError, self.db.status.set, '1', foo='foo')
312         # string property
313         ar(TypeError, self.db.status.set, '1', name=1)
314         # key name clash
315         ar(ValueError, self.db.status.set, '2', name='unread')
316         # set up a valid issue for me to work on
317         self.db.issue.create(title="spam", status='1')
318         # invalid link index
319         ar(IndexError, self.db.issue.set, '6', title='foo', status='bar')
320         # invalid link value
321         ar(ValueError, self.db.issue.set, '6', title='foo', status=1)
322         # invalid multilink type
323         ar(TypeError, self.db.issue.set, '6', title='foo', status='1',
324             nosy='hello')
325         # invalid multilink index type
326         ar(ValueError, self.db.issue.set, '6', title='foo', status='1',
327             nosy=[1])
328         # invalid multilink index
329         ar(IndexError, self.db.issue.set, '6', title='foo', status='1',
330             nosy=['10'])
331         # invalid number value
332         ar(TypeError, self.db.user.create, username='foo', age='a')
333         # invalid boolean value
334         ar(TypeError, self.db.user.create, username='foo', assignable='true')
335         self.db.user.create(username='foo')
336         # invalid number value
337         ar(TypeError, self.db.user.set, '3', username='foo', age='a')
338         # invalid boolean value
339         ar(TypeError, self.db.user.set, '3', username='foo', assignable='true')
341     def testJournals(self):
342         self.db.user.create(username="mary")
343         self.db.user.create(username="pete")
344         self.db.issue.create(title="spam", status='1')
345         self.db.commit()
347         # journal entry for issue create
348         journal = self.db.getjournal('issue', '1')
349         self.assertEqual(1, len(journal))
350         (nodeid, date_stamp, journaltag, action, params) = journal[0]
351         self.assertEqual(nodeid, '1')
352         self.assertEqual(journaltag, 'test')
353         self.assertEqual(action, 'create')
354         keys = params.keys()
355         keys.sort()
356         self.assertEqual(keys, ['assignedto', 'deadline', 'files',
357             'foo', 'messages', 'nosy', 'status', 'superseder', 'title'])
358         self.assertEqual(None,params['deadline'])
359         self.assertEqual(None,params['foo'])
360         self.assertEqual([],params['nosy'])
361         self.assertEqual('1',params['status'])
362         self.assertEqual('spam',params['title'])
364         # journal entry for link
365         journal = self.db.getjournal('user', '1')
366         self.assertEqual(1, len(journal))
367         self.db.issue.set('1', assignedto='1')
368         self.db.commit()
369         journal = self.db.getjournal('user', '1')
370         self.assertEqual(2, len(journal))
371         (nodeid, date_stamp, journaltag, action, params) = journal[1]
372         self.assertEqual('1', nodeid)
373         self.assertEqual('test', journaltag)
374         self.assertEqual('link', action)
375         self.assertEqual(('issue', '1', 'assignedto'), params)
377         # journal entry for unlink
378         self.db.issue.set('1', assignedto='2')
379         self.db.commit()
380         journal = self.db.getjournal('user', '1')
381         self.assertEqual(3, len(journal))
382         (nodeid, date_stamp, journaltag, action, params) = journal[2]
383         self.assertEqual('1', nodeid)
384         self.assertEqual('test', journaltag)
385         self.assertEqual('unlink', action)
386         self.assertEqual(('issue', '1', 'assignedto'), params)
388         # test disabling journalling
389         # ... get the last entry
390         time.sleep(1)
391         entry = self.db.getjournal('issue', '1')[-1]
392         (x, date_stamp, x, x, x) = entry
393         self.db.issue.disableJournalling()
394         self.db.issue.set('1', title='hello world')
395         self.db.commit()
396         entry = self.db.getjournal('issue', '1')[-1]
397         (x, date_stamp2, x, x, x) = entry
398         # see if the change was journalled when it shouldn't have been
399         self.assertEqual(date_stamp, date_stamp2)
400         self.db.issue.enableJournalling()
401         self.db.issue.set('1', title='hello world 2')
402         self.db.commit()
403         entry = self.db.getjournal('issue', '1')[-1]
404         (x, date_stamp2, x, x, x) = entry
405         # see if the change was journalled
406         self.assertNotEqual(date_stamp, date_stamp2)
408     def testPack(self):
409         self.db.issue.create(title="spam", status='1')
410         self.db.commit()
411         self.db.issue.set('1', status='2')
412         self.db.commit()
414         # sleep for at least a second, then get a date to pack at
415         time.sleep(1)
416         pack_before = date.Date('.')
418         # one more entry
419         self.db.issue.set('1', status='3')
420         self.db.commit()
422         # pack
423         self.db.pack(pack_before)
424         journal = self.db.getjournal('issue', '1')
426         # we should have the create and last set entries now
427         self.assertEqual(2, len(journal))
429     def testIDGeneration(self):
430         id1 = self.db.issue.create(title="spam", status='1')
431         id2 = self.db2.issue.create(title="eggs", status='2')
432         self.assertNotEqual(id1, id2)
434     def testSearching(self):
435         self.db.file.create(content='hello', type="text/plain")
436         self.db.file.create(content='world', type="text/frozz",
437             comment='blah blah')
438         self.db.issue.create(files=['1', '2'], title="flebble plop")
439         self.db.issue.create(title="flebble frooz")
440         self.db.commit()
441         self.assertEquals(self.db.indexer.search(['hello'], self.db.issue),
442             {'1': {'files': ['1']}})
443         self.assertEquals(self.db.indexer.search(['world'], self.db.issue), {})
444         self.assertEquals(self.db.indexer.search(['frooz'], self.db.issue),
445             {'2': {}})
446         self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue),
447             {'2': {}, '1': {}})
449     def testReindexing(self):
450         self.db.issue.create(title="frooz")
451         self.db.commit()
452         self.assertEquals(self.db.indexer.search(['frooz'], self.db.issue),
453             {'1': {}})
454         self.db.issue.set('1', title="dooble")
455         self.db.commit()
456         self.assertEquals(self.db.indexer.search(['dooble'], self.db.issue),
457             {'1': {}})
458         self.assertEquals(self.db.indexer.search(['frooz'], self.db.issue), {})
460     def testForcedReindexing(self):
461         self.db.issue.create(title="flebble frooz")
462         self.db.commit()
463         self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue),
464             {'1': {}})
465         self.db.indexer.quiet = 1
466         self.db.indexer.force_reindex()
467         self.db.post_init()
468         self.db.indexer.quiet = 9
469         self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue),
470             {'1': {}})
472 class anydbmReadOnlyDBTestCase(MyTestCase):
473     def setUp(self):
474         from roundup.backends import anydbm
475         # remove previous test, ignore errors
476         if os.path.exists(config.DATABASE):
477             shutil.rmtree(config.DATABASE)
478         os.makedirs(config.DATABASE + '/files')
479         db = anydbm.Database(config, 'test')
480         setupSchema(db, 1, anydbm)
481         self.db = anydbm.Database(config)
482         setupSchema(self.db, 0, anydbm)
483         self.db2 = anydbm.Database(config, 'test')
484         setupSchema(self.db2, 0, anydbm)
486     def testExceptions(self):
487         # this tests the exceptions that should be raised
488         ar = self.assertRaises
490         # this tests the exceptions that should be raised
491         ar(DatabaseError, self.db.status.create, name="foo")
492         ar(DatabaseError, self.db.status.set, '1', name="foo")
493         ar(DatabaseError, self.db.status.retire, '1')
496 class bsddbDBTestCase(anydbmDBTestCase):
497     def setUp(self):
498         from roundup.backends import bsddb
499         # remove previous test, ignore errors
500         if os.path.exists(config.DATABASE):
501             shutil.rmtree(config.DATABASE)
502         os.makedirs(config.DATABASE + '/files')
503         self.db = bsddb.Database(config, 'test')
504         setupSchema(self.db, 1, bsddb)
505         self.db2 = bsddb.Database(config, 'test')
506         setupSchema(self.db2, 0, bsddb)
508 class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
509     def setUp(self):
510         from roundup.backends import bsddb
511         # remove previous test, ignore errors
512         if os.path.exists(config.DATABASE):
513             shutil.rmtree(config.DATABASE)
514         os.makedirs(config.DATABASE + '/files')
515         db = bsddb.Database(config, 'test')
516         setupSchema(db, 1, bsddb)
517         self.db = bsddb.Database(config)
518         setupSchema(self.db, 0, bsddb)
519         self.db2 = bsddb.Database(config, 'test')
520         setupSchema(self.db2, 0, bsddb)
523 class bsddb3DBTestCase(anydbmDBTestCase):
524     def setUp(self):
525         from roundup.backends import bsddb3
526         # remove previous test, ignore errors
527         if os.path.exists(config.DATABASE):
528             shutil.rmtree(config.DATABASE)
529         os.makedirs(config.DATABASE + '/files')
530         self.db = bsddb3.Database(config, 'test')
531         setupSchema(self.db, 1, bsddb3)
532         self.db2 = bsddb3.Database(config, 'test')
533         setupSchema(self.db2, 0, bsddb3)
535 class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
536     def setUp(self):
537         from roundup.backends import bsddb3
538         # remove previous test, ignore errors
539         if os.path.exists(config.DATABASE):
540             shutil.rmtree(config.DATABASE)
541         os.makedirs(config.DATABASE + '/files')
542         db = bsddb3.Database(config, 'test')
543         setupSchema(db, 1, bsddb3)
544         self.db = bsddb3.Database(config)
545         setupSchema(self.db, 0, bsddb3)
546         self.db2 = bsddb3.Database(config, 'test')
547         setupSchema(self.db2, 0, bsddb3)
550 class gadflyDBTestCase(anydbmDBTestCase):
551     ''' Gadfly doesn't support multiple connections to the one local
552         database
553     '''
554     def setUp(self):
555         from roundup.backends import gadfly
556         # remove previous test, ignore errors
557         if os.path.exists(config.DATABASE):
558             shutil.rmtree(config.DATABASE)
559         config.GADFLY_DATABASE = ('test', config.DATABASE)
560         os.makedirs(config.DATABASE + '/files')
561         self.db = gadfly.Database(config, 'test')
562         setupSchema(self.db, 1, gadfly)
564     def testIDGeneration(self):
565         id1 = self.db.issue.create(title="spam", status='1')
566         id2 = self.db.issue.create(title="eggs", status='2')
567         self.assertNotEqual(id1, id2)
569     def testNewProperty(self):
570         # gadfly doesn't have an ALTER TABLE command :(
571         pass
573 class gadflyReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
574     def setUp(self):
575         from roundup.backends import gadfly
576         # remove previous test, ignore errors
577         if os.path.exists(config.DATABASE):
578             shutil.rmtree(config.DATABASE)
579         config.GADFLY_DATABASE = ('test', config.DATABASE)
580         os.makedirs(config.DATABASE + '/files')
581         db = gadfly.Database(config, 'test')
582         setupSchema(db, 1, gadfly)
583         self.db = gadfly.Database(config)
584         setupSchema(self.db, 0, gadfly)
587 class metakitDBTestCase(anydbmDBTestCase):
588     def setUp(self):
589         from roundup.backends import metakit
590         import weakref
591         metakit._instances = weakref.WeakValueDictionary()
592         # remove previous test, ignore errors
593         if os.path.exists(config.DATABASE):
594             shutil.rmtree(config.DATABASE)
595         os.makedirs(config.DATABASE + '/files')
596         self.db = metakit.Database(config, 'test')
597         setupSchema(self.db, 1, metakit)
598         self.db2 = metakit.Database(config, 'test')
599         setupSchema(self.db2, 0, metakit)
601     def testTransactions(self):
602         # remember the number of items we started
603         num_issues = len(self.db.issue.list())
604         self.db.issue.create(title="don't commit me!", status='1')
605         self.assertNotEqual(num_issues, len(self.db.issue.list()))
606         self.db.rollback()
607         self.assertEqual(num_issues, len(self.db.issue.list()))
608         self.db.issue.create(title="please commit me!", status='1')
609         self.assertNotEqual(num_issues, len(self.db.issue.list()))
610         self.db.commit()
611         self.assertNotEqual(num_issues, len(self.db.issue.list()))
612         self.db.rollback()
613         self.assertNotEqual(num_issues, len(self.db.issue.list()))
614         self.db.file.create(name="test", type="text/plain", content="hi")
615         self.db.rollback()
616         for i in range(10):
617             self.db.file.create(name="test", type="text/plain", 
618                     content="hi %d"%(i))
619             self.db.commit()
620         # TODO: would be good to be able to ensure the file is not on disk after
621         # a rollback...
622         self.assertNotEqual(num_files, num_files2)
623         self.db.file.create(name="test", type="text/plain", content="hi")
624         self.db.rollback()
626 class metakitReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
627     def setUp(self):
628         from roundup.backends import metakit
629         import weakref
630         metakit._instances = weakref.WeakValueDictionary()
631         # remove previous test, ignore errors
632         if os.path.exists(config.DATABASE):
633             shutil.rmtree(config.DATABASE)
634         os.makedirs(config.DATABASE + '/files')
635         db = metakit.Database(config, 'test')
636         setupSchema(db, 1, metakit)
637         self.db = metakit.Database(config)
638         setupSchema(self.db, 0, metakit)
639         self.db2 = metakit.Database(config, 'test')
640         setupSchema(self.db2, 0, metakit)
642 def suite():
643     l = [
644          unittest.makeSuite(anydbmDBTestCase, 'test'),
645          unittest.makeSuite(anydbmReadOnlyDBTestCase, 'test')
646     ]
647     #return unittest.TestSuite(l)
649     try:
650         import bsddb
651         l.append(unittest.makeSuite(bsddbDBTestCase, 'test'))
652         l.append(unittest.makeSuite(bsddbReadOnlyDBTestCase, 'test'))
653     except:
654         print 'bsddb module not found, skipping bsddb DBTestCase'
656     try:
657         import bsddb3
658         l.append(unittest.makeSuite(bsddb3DBTestCase, 'test'))
659         l.append(unittest.makeSuite(bsddb3ReadOnlyDBTestCase, 'test'))
660     except:
661         print 'bsddb3 module not found, skipping bsddb3 DBTestCase'
663     try:
664         import gadfly
665         l.append(unittest.makeSuite(gadflyDBTestCase, 'test'))
666         l.append(unittest.makeSuite(gadflyReadOnlyDBTestCase, 'test'))
667     except:
668         print 'gadfly module not found, skipping gadfly DBTestCase'
670     try:
671         import metakit
672         l.append(unittest.makeSuite(metakitDBTestCase, 'test'))
673         l.append(unittest.makeSuite(metakitReadOnlyDBTestCase, 'test'))
674     except:
675         print 'metakit module not found, skipping metakit DBTestCase'
677     return unittest.TestSuite(l)
679 # vim: set filetype=python ts=4 sw=4 et si