Code

08b918adebc927eff22b37d4f5f6b738fbf7dd50
[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.11 2001-12-10 23:17:20 richard Exp $ 
20 import unittest, os, shutil
22 from roundup.hyperdb import String, Password, Link, Multilink, Date, \
23     Interval, Class, DatabaseError
25 def setupSchema(db, create):
26     status = Class(db, "status", name=String())
27     status.setkey("name")
28     if create:
29         status.create(name="unread")
30         status.create(name="in-progress")
31         status.create(name="testing")
32         status.create(name="resolved")
33     Class(db, "user", username=String(), password=Password())
34     Class(db, "issue", title=String(), status=Link("status"),
35         nosy=Multilink("user"))
36     db.commit()
38 class MyTestCase(unittest.TestCase):
39     def tearDown(self):
40         if os.path.exists('_test_dir'):
41             shutil.rmtree('_test_dir')
42     
43 class anydbmDBTestCase(MyTestCase):
44     def setUp(self):
45         from roundup.backends import anydbm
46         # remove previous test, ignore errors
47         if os.path.exists('_test_dir'):
48             shutil.rmtree('_test_dir')
49         os.mkdir('_test_dir')
50         self.db = anydbm.Database('_test_dir', 'test')
51         setupSchema(self.db, 1)
53     def testChanges(self):
54         self.db.issue.create(title="spam", status='1')
55         self.db.issue.create(title="eggs", status='2')
56         self.db.issue.create(title="ham", status='4')
57         self.db.issue.create(title="arguments", status='2')
58         self.db.issue.create(title="abuse", status='1')
59         self.db.issue.addprop(fixer=Link("user"))
60         props = self.db.issue.getprops()
61         keys = props.keys()
62         keys.sort()
63         self.assertEqual(keys, ['fixer', 'id', 'nosy', 'status', 'title'])
64         self.db.issue.set('5', status='2')
65         self.db.issue.get('5', "status")
66         self.db.status.get('2', "name")
67         self.db.issue.get('5', "title")
68         self.db.issue.find(status = self.db.status.lookup("in-progress"))
69         self.db.commit()
70         self.db.issue.history('5')
71         self.db.status.history('1')
72         self.db.status.history('2')
74     def testTransactions(self):
75         num_issues = len(self.db.issue.list())
76         self.db.issue.create(title="don't commit me!", status='1')
77         self.assertNotEqual(num_issues, len(self.db.issue.list()))
78         self.db.rollback()
79         self.assertEqual(num_issues, len(self.db.issue.list()))
80         self.db.issue.create(title="please commit me!", status='1')
81         self.assertNotEqual(num_issues, len(self.db.issue.list()))
82         self.db.commit()
83         self.assertNotEqual(num_issues, len(self.db.issue.list()))
84         self.db.rollback()
85         self.assertNotEqual(num_issues, len(self.db.issue.list()))
87     def testExceptions(self):
88         # this tests the exceptions that should be raised
89         ar = self.assertRaises
91         #
92         # class create
93         #
94         # string property
95         ar(TypeError, self.db.status.create, name=1)
96         # invalid property name
97         ar(KeyError, self.db.status.create, foo='foo')
98         # key name clash
99         ar(ValueError, self.db.status.create, name='unread')
100         # invalid link index
101         ar(IndexError, self.db.issue.create, title='foo', status='bar')
102         # invalid link value
103         ar(ValueError, self.db.issue.create, title='foo', status=1)
104         # invalid multilink type
105         ar(TypeError, self.db.issue.create, title='foo', status='1',
106             nosy='hello')
107         # invalid multilink index type
108         ar(ValueError, self.db.issue.create, title='foo', status='1',
109             nosy=[1])
110         # invalid multilink index
111         ar(IndexError, self.db.issue.create, title='foo', status='1',
112             nosy=['10'])
114         #
115         # class get
116         #
117         # invalid node id
118         ar(IndexError, self.db.status.get, '10', 'name')
119         # invalid property name
120         ar(KeyError, self.db.status.get, '2', 'foo')
122         #
123         # class set
124         #
125         # invalid node id
126         ar(IndexError, self.db.issue.set, '1', name='foo')
127         # invalid property name
128         ar(KeyError, self.db.status.set, '1', foo='foo')
129         # string property
130         ar(TypeError, self.db.status.set, '1', name=1)
131         # key name clash
132         ar(ValueError, self.db.status.set, '2', name='unread')
133         # set up a valid issue for me to work on
134         self.db.issue.create(title="spam", status='1')
135         # invalid link index
136         ar(IndexError, self.db.issue.set, '1', title='foo', status='bar')
137         # invalid link value
138         ar(ValueError, self.db.issue.set, '1', title='foo', status=1)
139         # invalid multilink type
140         ar(TypeError, self.db.issue.set, '1', title='foo', status='1',
141             nosy='hello')
142         # invalid multilink index type
143         ar(ValueError, self.db.issue.set, '1', title='foo', status='1',
144             nosy=[1])
145         # invalid multilink index
146         ar(IndexError, self.db.issue.set, '1', title='foo', status='1',
147             nosy=['10'])
149     def testRetire(self):
150         pass
153 class anydbmReadOnlyDBTestCase(MyTestCase):
154     def setUp(self):
155         from roundup.backends import anydbm
156         # remove previous test, ignore errors
157         if os.path.exists('_test_dir'):
158             shutil.rmtree('_test_dir')
159         os.mkdir('_test_dir')
160         db = anydbm.Database('_test_dir', 'test')
161         setupSchema(db, 1)
162         self.db = anydbm.Database('_test_dir')
163         setupSchema(self.db, 0)
165     def testExceptions(self):
166         # this tests the exceptions that should be raised
167         ar = self.assertRaises
169         # this tests the exceptions that should be raised
170         ar(DatabaseError, self.db.status.create, name="foo")
171         ar(DatabaseError, self.db.status.set, '1', name="foo")
172         ar(DatabaseError, self.db.status.retire, '1')
175 class bsddbDBTestCase(anydbmDBTestCase):
176     def setUp(self):
177         from roundup.backends import bsddb
178         # remove previous test, ignore errors
179         if os.path.exists('_test_dir'):
180             shutil.rmtree('_test_dir')
181         os.mkdir('_test_dir')
182         self.db = bsddb.Database('_test_dir', 'test')
183         setupSchema(self.db, 1)
185 class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
186     def setUp(self):
187         from roundup.backends import bsddb
188         # remove previous test, ignore errors
189         if os.path.exists('_test_dir'):
190             shutil.rmtree('_test_dir')
191         os.mkdir('_test_dir')
192         db = bsddb.Database('_test_dir', 'test')
193         setupSchema(db, 1)
194         self.db = bsddb.Database('_test_dir')
195         setupSchema(self.db, 0)
198 class bsddb3DBTestCase(anydbmDBTestCase):
199     def setUp(self):
200         from roundup.backends import bsddb3
201         # remove previous test, ignore errors
202         if os.path.exists('_test_dir'):
203             shutil.rmtree('_test_dir')
204         os.mkdir('_test_dir')
205         self.db = bsddb3.Database('_test_dir', 'test')
206         setupSchema(self.db, 1)
208 class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
209     def setUp(self):
210         from roundup.backends import bsddb3
211         # remove previous test, ignore errors
212         if os.path.exists('_test_dir'):
213             shutil.rmtree('_test_dir')
214         os.mkdir('_test_dir')
215         db = bsddb3.Database('_test_dir', 'test')
216         setupSchema(db, 1)
217         self.db = bsddb3.Database('_test_dir')
218         setupSchema(self.db, 0)
221 def suite():
222     l = [unittest.makeSuite(anydbmDBTestCase, 'test'),
223          unittest.makeSuite(anydbmReadOnlyDBTestCase, 'test')
224     ]
226     try:
227         import bsddb
228         l.append(unittest.makeSuite(bsddbDBTestCase, 'test'))
229         l.append(unittest.makeSuite(bsddbReadOnlyDBTestCase, 'test'))
230     except:
231         print 'bsddb module not found, skipping bsddb DBTestCase'
233 #    try:
234 #        import bsddb3
235 #        l.append(unittest.makeSuite(bsddb3DBTestCase, 'test'))
236 #        l.append(unittest.makeSuite(bsddb3ReadOnlyDBTestCase, 'test'))
237 #    except:
238 #        print 'bsddb3 module not found, skipping bsddb3 DBTestCase'
240     return unittest.TestSuite(l)
243 # $Log: not supported by cvs2svn $
244 # Revision 1.10  2001/12/03 21:33:39  richard
245 # Fixes so the tests use commit and not close
247 # Revision 1.9  2001/12/02 05:06:16  richard
248 # . We now use weakrefs in the Classes to keep the database reference, so
249 #   the close() method on the database is no longer needed.
250 #   I bumped the minimum python requirement up to 2.1 accordingly.
251 # . #487480 ] roundup-server
252 # . #487476 ] INSTALL.txt
254 # I also cleaned up the change message / post-edit stuff in the cgi client.
255 # There's now a clearly marked "TODO: append the change note" where I believe
256 # the change note should be added there. The "changes" list will obviously
257 # have to be modified to be a dict of the changes, or somesuch.
259 # More testing needed.
261 # Revision 1.8  2001/10/09 07:25:59  richard
262 # Added the Password property type. See "pydoc roundup.password" for
263 # implementation details. Have updated some of the documentation too.
265 # Revision 1.7  2001/08/29 06:23:59  richard
266 # Disabled the bsddb3 module entirely in the unit testing. See CHANGES for
267 # details.
269 # Revision 1.6  2001/08/07 00:24:43  richard
270 # stupid typo
272 # Revision 1.5  2001/08/07 00:15:51  richard
273 # Added the copyright/license notice to (nearly) all files at request of
274 # Bizar Software.
276 # Revision 1.4  2001/07/30 03:45:56  richard
277 # Added more DB to test_db. Can skip tests where imports fail.
279 # Revision 1.3  2001/07/29 07:01:39  richard
280 # Added vim command to all source so that we don't get no steenkin' tabs :)
282 # Revision 1.2  2001/07/29 04:09:20  richard
283 # Added the fabricated property "id" to all hyperdb classes.
285 # Revision 1.1  2001/07/27 06:55:07  richard
286 # moving tests -> test
288 # Revision 1.7  2001/07/27 06:26:43  richard
289 # oops - wasn't deleting the test dir after the read-only tests
291 # Revision 1.6  2001/07/27 06:23:59  richard
292 # consistency
294 # Revision 1.5  2001/07/27 06:23:09  richard
295 # Added some new hyperdb tests to make sure we raise the right exceptions.
297 # Revision 1.4  2001/07/25 04:34:31  richard
298 # Added id and log to tests files...
301 # vim: set filetype=python ts=4 sw=4 et si