Code

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