X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=test%2Ftest_db.py;h=315ab2fd3e71bd55bc39fe8c24b2c59513f3c6e0;hb=7520e02f86cafa83c87f69a0c671a583aae14368;hp=e8a51b0b93f2a74050465a5b3bdb3899f49071c1;hpb=3ee3a04f9c1a4d3a911e633347c72d61be685019;p=roundup.git diff --git a/test/test_db.py b/test/test_db.py index e8a51b0..315ab2f 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -15,27 +15,31 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_db.py,v 1.25 2002-07-09 04:19:09 richard Exp $ +# $Id: test_db.py,v 1.55 2002-09-24 01:59:44 richard Exp $ -import unittest, os, shutil +import unittest, os, shutil, time from roundup.hyperdb import String, Password, Link, Multilink, Date, \ - Interval, Class, DatabaseError -from roundup.roundupdb import FileClass + Interval, DatabaseError, Boolean, Number from roundup import date, password from roundup.indexer import Indexer -def setupSchema(db, create): - status = Class(db, "status", name=String()) +def setupSchema(db, create, module): + status = module.Class(db, "status", name=String()) status.setkey("name") - user = Class(db, "user", username=String(), password=Password()) - file = FileClass(db, "file", name=String(), type=String(), - comment=String(indexme="yes")) - issue = Class(db, "issue", title=String(indexme="yes"), + user = module.Class(db, "user", username=String(), password=Password(), + assignable=Boolean(), age=Number(), roles=String()) + user.setkey("username") + file = module.FileClass(db, "file", name=String(), type=String(), + comment=String(indexme="yes"), fooz=Password()) + issue = module.IssueClass(db, "issue", title=String(indexme="yes"), status=Link("status"), nosy=Multilink("user"), deadline=Date(), - foo=Interval(), files=Multilink("file")) + foo=Interval(), files=Multilink("file"), assignedto=Link('user')) + session = module.Class(db, 'session', title=String()) + session.disableJournalling() db.post_init() if create: + user.create(username="admin", roles='Admin') status.create(name="unread") status.create(name="in-progress") status.create(name="testing") @@ -44,6 +48,9 @@ def setupSchema(db, create): class MyTestCase(unittest.TestCase): def tearDown(self): + self.db.close() + if hasattr(self, 'db2'): + self.db2.close() if os.path.exists('_test_dir'): shutil.rmtree('_test_dir') @@ -51,9 +58,9 @@ class config: DATABASE='_test_dir' MAILHOST = 'localhost' MAIL_DOMAIN = 'fill.me.in.' - INSTANCE_NAME = 'Roundup issue tracker' - ISSUE_TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN - ISSUE_TRACKER_WEB = 'http://some.useful.url/' + TRACKER_NAME = 'Roundup issue tracker' + TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN + TRACKER_WEB = 'http://some.useful.url/' ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN FILTER_POSITION = 'bottom' # one of 'top', 'bottom', 'top and bottom' ANONYMOUS_ACCESS = 'deny' # either 'deny' or 'allow' @@ -68,16 +75,21 @@ class anydbmDBTestCase(MyTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = anydbm.Database(config, 'test') - setupSchema(self.db, 1) - self.db2 = anydbm.Database(config, 'test') - setupSchema(self.db2, 0) + self.db = anydbm.Database(config, 'admin') + setupSchema(self.db, 1, anydbm) + self.db2 = anydbm.Database(config, 'admin') + setupSchema(self.db2, 0, anydbm) def testStringChange(self): + # test set & retrieve self.db.issue.create(title="spam", status='1') self.assertEqual(self.db.issue.get('1', 'title'), 'spam') + + # change and make sure we retrieve the correct value self.db.issue.set('1', title='eggs') self.assertEqual(self.db.issue.get('1', 'title'), 'eggs') + + # do some commit stuff self.db.commit() self.assertEqual(self.db.issue.get('1', 'title'), 'eggs') self.db.issue.create(title="spam", status='1') @@ -88,11 +100,27 @@ class anydbmDBTestCase(MyTestCase): self.db.commit() self.assertEqual(self.db.issue.get('2', 'title'), 'ham') + # make sure we can unset + self.db.issue.set('1', title=None) + self.assertEqual(self.db.issue.get('1', "title"), None) + def testLinkChange(self): self.db.issue.create(title="spam", status='1') self.assertEqual(self.db.issue.get('1', "status"), '1') self.db.issue.set('1', status='2') self.assertEqual(self.db.issue.get('1', "status"), '2') + self.db.issue.set('1', status=None) + self.assertEqual(self.db.issue.get('1', "status"), None) + + def testMultilinkChange(self): + u1 = self.db.user.create(username='foo') + u2 = self.db.user.create(username='bar') + self.db.issue.create(title="spam", nosy=[u1]) + self.assertEqual(self.db.issue.get('1', "nosy"), [u1]) + self.db.issue.set('1', nosy=[]) + self.assertEqual(self.db.issue.get('1', "nosy"), []) + self.db.issue.set('1', nosy=[u1,u2]) + self.assertEqual(self.db.issue.get('1', "nosy"), [u1,u2]) def testDateChange(self): self.db.issue.create(title="spam", status='1') @@ -103,21 +131,53 @@ class anydbmDBTestCase(MyTestCase): self.assertNotEqual(a, b) self.assertNotEqual(b, date.Date('1970-1-1 00:00:00')) self.db.issue.set('1', deadline=date.Date()) + self.db.issue.set('1', deadline=None) + self.assertEqual(self.db.issue.get('1', "deadline"), None) def testIntervalChange(self): self.db.issue.create(title="spam", status='1') a = self.db.issue.get('1', "foo") self.db.issue.set('1', foo=date.Interval('-1d')) self.assertNotEqual(self.db.issue.get('1', "foo"), a) + self.db.issue.set('1', foo=None) + self.assertEqual(self.db.issue.get('1', "foo"), None) + + def testBooleanChange(self): + userid = self.db.user.create(username='foo', assignable=1) + self.assertEqual(1, self.db.user.get(userid, 'assignable')) + self.db.user.set(userid, assignable=0) + self.assertEqual(self.db.user.get(userid, 'assignable'), 0) + self.db.user.set(userid, assignable=None) + self.assertEqual(self.db.user.get('1', "assignable"), None) + + def testNumberChange(self): + nid = self.db.user.create(username='foo', age=1) + self.assertEqual(1, self.db.user.get(nid, 'age')) + self.db.user.set('1', age=3) + self.assertNotEqual(self.db.user.get('1', 'age'), 1) + self.db.user.set('1', age=1.0) + self.db.user.set('1', age=None) + self.assertEqual(self.db.user.get('1', "age"), None) + + def testKeyValue(self): + newid = self.db.user.create(username="spam") + self.assertEqual(self.db.user.lookup('spam'), newid) + self.db.commit() + self.assertEqual(self.db.user.lookup('spam'), newid) + self.db.user.retire(newid) + self.assertRaises(KeyError, self.db.user.lookup, 'spam') def testNewProperty(self): self.db.issue.create(title="spam", status='1') self.db.issue.addprop(fixer=Link("user")) + # force any post-init stuff to happen + self.db.post_init() props = self.db.issue.getprops() keys = props.keys() keys.sort() - self.assertEqual(keys, ['deadline', 'files', 'fixer', 'foo', 'id', - 'nosy', 'status', 'title']) + self.assertEqual(keys, ['activity', 'assignedto', 'creation', + 'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages', + 'nosy', 'status', 'superseder', 'title']) self.assertEqual(self.db.issue.get('1', "fixer"), None) def testRetire(self): @@ -172,6 +232,49 @@ class anydbmDBTestCase(MyTestCase): self.assertNotEqual(num_files, self.db.numfiles()) self.assertEqual(num_files2, self.db.numfiles()) + def testDestroyNoJournalling(self): + self.innerTestDestroy(klass=self.db.session) + + def testDestroyJournalling(self): + self.innerTestDestroy(klass=self.db.issue) + + def innerTestDestroy(self, klass): + newid = klass.create(title='Mr Friendly') + n = len(klass.list()) + self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly') + klass.destroy(newid) + self.assertRaises(IndexError, klass.get, newid, 'title') + self.assertNotEqual(len(klass.list()), n) + if klass.do_journal: + self.assertRaises(IndexError, klass.history, newid) + + # now with a commit + newid = klass.create(title='Mr Friendly') + n = len(klass.list()) + self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly') + self.db.commit() + klass.destroy(newid) + self.assertRaises(IndexError, klass.get, newid, 'title') + self.db.commit() + self.assertRaises(IndexError, klass.get, newid, 'title') + self.assertNotEqual(len(klass.list()), n) + if klass.do_journal: + self.assertRaises(IndexError, klass.history, newid) + + # now with a rollback + newid = klass.create(title='Mr Friendly') + n = len(klass.list()) + self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly') + self.db.commit() + klass.destroy(newid) + self.assertNotEqual(len(klass.list()), n) + self.assertRaises(IndexError, klass.get, newid, 'title') + self.db.rollback() + self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly') + self.assertEqual(len(klass.list()), n) + if klass.do_journal: + self.assertNotEqual(klass.history(newid), []) + def testExceptions(self): # this tests the exceptions that should be raised ar = self.assertRaises @@ -199,11 +302,19 @@ class anydbmDBTestCase(MyTestCase): ar(IndexError, self.db.issue.create, title='foo', status='1', nosy=['10']) + # + # key property + # + # key must be a String + ar(TypeError, self.db.file.setkey, 'fooz') + # key must exist + ar(KeyError, self.db.file.setkey, 'fubar') + # # class get # # invalid node id - ar(IndexError, self.db.status.get, '10', 'name') + ar(IndexError, self.db.issue.get, '99', 'title') # invalid property name ar(KeyError, self.db.status.get, '2', 'foo') @@ -211,7 +322,7 @@ class anydbmDBTestCase(MyTestCase): # class set # # invalid node id - ar(IndexError, self.db.issue.set, '1', name='foo') + ar(IndexError, self.db.issue.set, '99', title='foo') # invalid property name ar(KeyError, self.db.status.set, '1', foo='foo') # string property @@ -219,23 +330,31 @@ class anydbmDBTestCase(MyTestCase): # key name clash ar(ValueError, self.db.status.set, '2', name='unread') # set up a valid issue for me to work on - self.db.issue.create(title="spam", status='1') + id = self.db.issue.create(title="spam", status='1') # invalid link index - ar(IndexError, self.db.issue.set, '6', title='foo', status='bar') + ar(IndexError, self.db.issue.set, id, title='foo', status='bar') # invalid link value - ar(ValueError, self.db.issue.set, '6', title='foo', status=1) + ar(ValueError, self.db.issue.set, id, title='foo', status=1) # invalid multilink type - ar(TypeError, self.db.issue.set, '6', title='foo', status='1', + ar(TypeError, self.db.issue.set, id, title='foo', status='1', nosy='hello') # invalid multilink index type - ar(ValueError, self.db.issue.set, '6', title='foo', status='1', + ar(ValueError, self.db.issue.set, id, title='foo', status='1', nosy=[1]) # invalid multilink index - ar(IndexError, self.db.issue.set, '6', title='foo', status='1', + ar(IndexError, self.db.issue.set, id, title='foo', status='1', nosy=['10']) + # invalid number value + ar(TypeError, self.db.user.create, username='foo', age='a') + # invalid boolean value + ar(TypeError, self.db.user.create, username='foo', assignable='true') + nid = self.db.user.create(username='foo') + # invalid number value + ar(TypeError, self.db.user.set, nid, username='foo', age='a') + # invalid boolean value + ar(TypeError, self.db.user.set, nid, username='foo', assignable='true') def testJournals(self): - self.db.issue.addprop(fixer=Link("user", do_journal='yes')) self.db.user.create(username="mary") self.db.user.create(username="pete") self.db.issue.create(title="spam", status='1') @@ -246,14 +365,13 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(1, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[0] self.assertEqual(nodeid, '1') - self.assertEqual(journaltag, 'test') + self.assertEqual(journaltag, self.db.user.lookup('admin')) self.assertEqual(action, 'create') keys = params.keys() keys.sort() - self.assertEqual(keys, ['deadline', 'files', 'fixer', 'foo', 'nosy', - 'status', 'title']) + self.assertEqual(keys, ['assignedto', 'deadline', 'files', + 'foo', 'messages', 'nosy', 'status', 'superseder', 'title']) self.assertEqual(None,params['deadline']) - self.assertEqual(None,params['fixer']) self.assertEqual(None,params['foo']) self.assertEqual([],params['nosy']) self.assertEqual('1',params['status']) @@ -262,37 +380,68 @@ class anydbmDBTestCase(MyTestCase): # journal entry for link journal = self.db.getjournal('user', '1') self.assertEqual(1, len(journal)) - self.db.issue.set('1', fixer='1') + self.db.issue.set('1', assignedto='1') self.db.commit() journal = self.db.getjournal('user', '1') self.assertEqual(2, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[1] self.assertEqual('1', nodeid) - self.assertEqual('test', journaltag) + self.assertEqual('1', journaltag) self.assertEqual('link', action) - self.assertEqual(('issue', '1', 'fixer'), params) + self.assertEqual(('issue', '1', 'assignedto'), params) # journal entry for unlink - self.db.issue.set('1', fixer='2') + self.db.issue.set('1', assignedto='2') self.db.commit() journal = self.db.getjournal('user', '1') self.assertEqual(3, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[2] self.assertEqual('1', nodeid) - self.assertEqual('test', journaltag) + self.assertEqual('1', journaltag) self.assertEqual('unlink', action) - self.assertEqual(('issue', '1', 'fixer'), params) + self.assertEqual(('issue', '1', 'assignedto'), params) + + # test disabling journalling + # ... get the last entry + time.sleep(1) + entry = self.db.getjournal('issue', '1')[-1] + (x, date_stamp, x, x, x) = entry + self.db.issue.disableJournalling() + self.db.issue.set('1', title='hello world') + self.db.commit() + entry = self.db.getjournal('issue', '1')[-1] + (x, date_stamp2, x, x, x) = entry + # see if the change was journalled when it shouldn't have been + self.assertEqual(date_stamp, date_stamp2) + time.sleep(1) + self.db.issue.enableJournalling() + self.db.issue.set('1', title='hello world 2') + self.db.commit() + entry = self.db.getjournal('issue', '1')[-1] + (x, date_stamp2, x, x, x) = entry + # see if the change was journalled + self.assertNotEqual(date_stamp, date_stamp2) def testPack(self): - self.db.issue.create(title="spam", status='1') + id = self.db.issue.create(title="spam", status='1') self.db.commit() - self.db.issue.set('1', status='2') + self.db.issue.set(id, status='2') self.db.commit() - self.db.issue.set('1', status='3') + + # sleep for at least a second, then get a date to pack at + time.sleep(2) + pack_before = date.Date('.') + time.sleep(2) + + # one more entry + self.db.issue.set(id, status='3') self.db.commit() - pack_before = date.Date(". + 1d") + + # pack self.db.pack(pack_before) - journal = self.db.getjournal('issue', '1') + journal = self.db.getjournal('issue', id) + + # we should have the create and last set entries now self.assertEqual(2, len(journal)) def testIDGeneration(self): @@ -338,6 +487,51 @@ class anydbmDBTestCase(MyTestCase): self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue), {'1': {}}) + def testStringFind(self): + ids = [] + ids.append(self.db.issue.create(title="spam")) + self.db.issue.create(title="not spam") + ids.append(self.db.issue.create(title="spam")) + ids.sort() + got = self.db.issue.stringFind(title='spam') + got.sort() + self.assertEqual(got, ids) + self.assertEqual(self.db.issue.stringFind(title='fubar'), []) + + def filteringSetup(self): + for user in ( + {'username': 'bleep'}, + {'username': 'blop'}, + {'username': 'blorp'}): + self.db.user.create(**user) + iss = self.db.issue + for issue in ( + {'title': 'issue one', 'status': '2'}, + {'title': 'issue two', 'status': '1'}, + {'title': 'issue three', 'status': '1', 'nosy': ['1','2']}): + self.db.issue.create(**issue) + self.db.commit() + return self.assertEqual, self.db.issue.filter + + def testFilteringString(self): + ae, filt = self.filteringSetup() + ae(filt(None, {'title': 'issue one'}, ('+','id'), (None,None)), ['1']) + ae(filt(None, {'title': 'issue'}, ('+','id'), (None,None)), + ['1','2','3']) + + def testFilteringLink(self): + ae, filt = self.filteringSetup() + ae(filt(None, {'status': '1'}, ('+','id'), (None,None)), ['2','3']) + + def testFilteringMultilink(self): + ae, filt = self.filteringSetup() + ae(filt(None, {'nosy': '2'}, ('+','id'), (None,None)), ['3']) + + def testFilteringMany(self): + ae, filt = self.filteringSetup() + ae(filt(None, {'nosy': '2', 'status': '1'}, ('+','id'), (None,None)), + ['3']) + class anydbmReadOnlyDBTestCase(MyTestCase): def setUp(self): from roundup.backends import anydbm @@ -345,12 +539,12 @@ class anydbmReadOnlyDBTestCase(MyTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = anydbm.Database(config, 'test') - setupSchema(db, 1) + db = anydbm.Database(config, 'admin') + setupSchema(db, 1, anydbm) self.db = anydbm.Database(config) - setupSchema(self.db, 0) - self.db2 = anydbm.Database(config, 'test') - setupSchema(self.db2, 0) + setupSchema(self.db, 0, anydbm) + self.db2 = anydbm.Database(config, 'admin') + setupSchema(self.db2, 0, anydbm) def testExceptions(self): # this tests the exceptions that should be raised @@ -369,10 +563,10 @@ class bsddbDBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = bsddb.Database(config, 'test') - setupSchema(self.db, 1) - self.db2 = bsddb.Database(config, 'test') - setupSchema(self.db2, 0) + self.db = bsddb.Database(config, 'admin') + setupSchema(self.db, 1, bsddb) + self.db2 = bsddb.Database(config, 'admin') + setupSchema(self.db2, 0, bsddb) class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): def setUp(self): @@ -381,12 +575,12 @@ class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = bsddb.Database(config, 'test') - setupSchema(db, 1) + db = bsddb.Database(config, 'admin') + setupSchema(db, 1, bsddb) self.db = bsddb.Database(config) - setupSchema(self.db, 0) - self.db2 = bsddb.Database(config, 'test') - setupSchema(self.db2, 0) + setupSchema(self.db, 0, bsddb) + self.db2 = bsddb.Database(config, 'admin') + setupSchema(self.db2, 0, bsddb) class bsddb3DBTestCase(anydbmDBTestCase): @@ -396,10 +590,10 @@ class bsddb3DBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = bsddb3.Database(config, 'test') - setupSchema(self.db, 1) - self.db2 = bsddb3.Database(config, 'test') - setupSchema(self.db2, 0) + self.db = bsddb3.Database(config, 'admin') + setupSchema(self.db, 1, bsddb3) + self.db2 = bsddb3.Database(config, 'admin') + setupSchema(self.db2, 0, bsddb3) class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): def setUp(self): @@ -408,179 +602,157 @@ class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = bsddb3.Database(config, 'test') - setupSchema(db, 1) + db = bsddb3.Database(config, 'admin') + setupSchema(db, 1, bsddb3) self.db = bsddb3.Database(config) - setupSchema(self.db, 0) - self.db2 = bsddb3.Database(config, 'test') - setupSchema(self.db2, 0) + setupSchema(self.db, 0, bsddb3) + self.db2 = bsddb3.Database(config, 'admin') + setupSchema(self.db2, 0, bsddb3) + + +class gadflyDBTestCase(anydbmDBTestCase): + ''' Gadfly doesn't support multiple connections to the one local + database + ''' + def setUp(self): + from roundup.backends import gadfly + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + config.GADFLY_DATABASE = ('test', config.DATABASE) + os.makedirs(config.DATABASE + '/files') + self.db = gadfly.Database(config, 'admin') + setupSchema(self.db, 1, gadfly) + def testIDGeneration(self): + id1 = self.db.issue.create(title="spam", status='1') + id2 = self.db.issue.create(title="eggs", status='2') + self.assertNotEqual(id1, id2) + +class gadflyReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): + def setUp(self): + from roundup.backends import gadfly + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + config.GADFLY_DATABASE = ('test', config.DATABASE) + os.makedirs(config.DATABASE + '/files') + db = gadfly.Database(config, 'admin') + setupSchema(db, 1, gadfly) + self.db = gadfly.Database(config) + setupSchema(self.db, 0, gadfly) + + +class sqliteDBTestCase(anydbmDBTestCase): + def setUp(self): + from roundup.backends import sqlite + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + os.makedirs(config.DATABASE + '/files') + self.db = sqlite.Database(config, 'admin') + setupSchema(self.db, 1, sqlite) + + def testIDGeneration(self): + pass + +class sqliteReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): + def setUp(self): + from roundup.backends import sqlite + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + os.makedirs(config.DATABASE + '/files') + db = sqlite.Database(config, 'admin') + setupSchema(db, 1, sqlite) + self.db = sqlite.Database(config) + setupSchema(self.db, 0, sqlite) + + +class metakitDBTestCase(anydbmDBTestCase): + def setUp(self): + from roundup.backends import metakit + import weakref + metakit._instances = weakref.WeakValueDictionary() + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + os.makedirs(config.DATABASE + '/files') + self.db = metakit.Database(config, 'admin') + setupSchema(self.db, 1, metakit) + + def testIDGeneration(self): + id1 = self.db.issue.create(title="spam", status='1') + id2 = self.db.issue.create(title="eggs", status='2') + self.assertNotEqual(id1, id2) + + def testTransactions(self): + # remember the number of items we started + num_issues = len(self.db.issue.list()) + self.db.issue.create(title="don't commit me!", status='1') + self.assertNotEqual(num_issues, len(self.db.issue.list())) + self.db.rollback() + self.assertEqual(num_issues, len(self.db.issue.list())) + self.db.issue.create(title="please commit me!", status='1') + self.assertNotEqual(num_issues, len(self.db.issue.list())) + self.db.commit() + self.assertNotEqual(num_issues, len(self.db.issue.list())) + self.db.rollback() + self.assertNotEqual(num_issues, len(self.db.issue.list())) + self.db.file.create(name="test", type="text/plain", content="hi") + self.db.rollback() + for i in range(10): + self.db.file.create(name="test", type="text/plain", + content="hi %d"%(i)) + self.db.commit() + # TODO: would be good to be able to ensure the file is not on disk after + # a rollback... + self.assertNotEqual(num_files, num_files2) + self.db.file.create(name="test", type="text/plain", content="hi") + self.db.rollback() + +class metakitReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): + def setUp(self): + from roundup.backends import metakit + import weakref + metakit._instances = weakref.WeakValueDictionary() + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + os.makedirs(config.DATABASE + '/files') + db = metakit.Database(config, 'admin') + setupSchema(db, 1, metakit) + self.db = metakit.Database(config) + setupSchema(self.db, 0, metakit) def suite(): l = [ unittest.makeSuite(anydbmDBTestCase, 'test'), unittest.makeSuite(anydbmReadOnlyDBTestCase, 'test') ] +# return unittest.TestSuite(l) + + from roundup import backends + if hasattr(backends, 'gadfly'): + l.append(unittest.makeSuite(gadflyDBTestCase, 'test')) + l.append(unittest.makeSuite(gadflyReadOnlyDBTestCase, 'test')) + + if hasattr(backends, 'sqlite'): + l.append(unittest.makeSuite(sqliteDBTestCase, 'test')) + l.append(unittest.makeSuite(sqliteReadOnlyDBTestCase, 'test')) - try: - import bsddb + if hasattr(backends, 'bsddb'): l.append(unittest.makeSuite(bsddbDBTestCase, 'test')) l.append(unittest.makeSuite(bsddbReadOnlyDBTestCase, 'test')) - except: - print 'bsddb module not found, skipping bsddb DBTestCase' - try: - import bsddb3 + if hasattr(backends, 'bsddb3'): l.append(unittest.makeSuite(bsddb3DBTestCase, 'test')) l.append(unittest.makeSuite(bsddb3ReadOnlyDBTestCase, 'test')) - except: - print 'bsddb3 module not found, skipping bsddb3 DBTestCase' + + if hasattr(backends, 'metakit'): + l.append(unittest.makeSuite(metakitDBTestCase, 'test')) + l.append(unittest.makeSuite(metakitReadOnlyDBTestCase, 'test')) return unittest.TestSuite(l) -# -# $Log: not supported by cvs2svn $ -# Revision 1.24 2002/07/09 03:02:53 richard -# More indexer work: -# - all String properties may now be indexed too. Currently there's a bit of -# "issue" specific code in the actual searching which needs to be -# addressed. In a nutshell: -# + pass 'indexme="yes"' as a String() property initialisation arg, eg: -# file = FileClass(db, "file", name=String(), type=String(), -# comment=String(indexme="yes")) -# + the comment will then be indexed and be searchable, with the results -# related back to the issue that the file is linked to -# - as a result of this work, the FileClass has a default MIME type that may -# be overridden in a subclass, or by the use of a "type" property as is -# done in the default templates. -# - the regeneration of the indexes (if necessary) is done once the schema is -# set up in the dbinit. -# -# Revision 1.23 2002/06/20 23:51:48 richard -# Cleaned up the hyperdb tests -# -# Revision 1.22 2002/05/21 05:52:11 richard -# Well whadya know, bsddb3 works again. -# The backend is implemented _exactly_ the same as bsddb - so there's no -# using its transaction or locking support. It'd be nice to use those some -# day I suppose. -# -# Revision 1.21 2002/04/15 23:25:15 richard -# . node ids are now generated from a lockable store - no more race conditions -# -# We're using the portalocker code by Jonathan Feinberg that was contributed -# to the ASPN Python cookbook. This gives us locking across Unix and Windows. -# -# Revision 1.20 2002/04/03 05:54:31 richard -# Fixed serialisation problem by moving the serialisation step out of the -# hyperdb.Class (get, set) into the hyperdb.Database. -# -# Also fixed htmltemplate after the showid changes I made yesterday. -# -# Unit tests for all of the above written. -# -# Revision 1.19 2002/02/25 14:34:31 grubert -# . use blobfiles in back_anydbm which is used in back_bsddb. -# change test_db as dirlist does not work for subdirectories. -# ATTENTION: blobfiles now creates subdirectories for files. -# -# Revision 1.18 2002/01/22 07:21:13 richard -# . fixed back_bsddb so it passed the journal tests -# -# ... it didn't seem happy using the back_anydbm _open method, which is odd. -# Yet another occurrance of whichdb not being able to recognise older bsddb -# databases. Yadda yadda. Made the HYPERDBDEBUG stuff more sane in the -# process. -# -# Revision 1.17 2002/01/22 05:06:09 rochecompaan -# We need to keep the last 'set' entry in the journal to preserve -# information on 'activity' for nodes. -# -# Revision 1.16 2002/01/21 16:33:20 rochecompaan -# You can now use the roundup-admin tool to pack the database -# -# Revision 1.15 2002/01/19 13:16:04 rochecompaan -# Journal entries for link and multilink properties can now be switched on -# or off. -# -# Revision 1.14 2002/01/16 07:02:57 richard -# . lots of date/interval related changes: -# - more relaxed date format for input -# -# Revision 1.13 2002/01/14 02:20:15 richard -# . changed all config accesses so they access either the instance or the -# config attriubute on the db. This means that all config is obtained from -# instance_config instead of the mish-mash of classes. This will make -# switching to a ConfigParser setup easier too, I hope. -# -# At a minimum, this makes migration a _little_ easier (a lot easier in the -# 0.5.0 switch, I hope!) -# -# Revision 1.12 2001/12/17 03:52:48 richard -# Implemented file store rollback. As a bonus, the hyperdb is now capable of -# storing more than one file per node - if a property name is supplied, -# the file is called designator.property. -# I decided not to migrate the existing files stored over to the new naming -# scheme - the FileClass just doesn't specify the property name. -# -# Revision 1.11 2001/12/10 23:17:20 richard -# Added transaction tests to test_db -# -# Revision 1.10 2001/12/03 21:33:39 richard -# Fixes so the tests use commit and not close -# -# Revision 1.9 2001/12/02 05:06:16 richard -# . We now use weakrefs in the Classes to keep the database reference, so -# the close() method on the database is no longer needed. -# I bumped the minimum python requirement up to 2.1 accordingly. -# . #487480 ] roundup-server -# . #487476 ] INSTALL.txt -# -# I also cleaned up the change message / post-edit stuff in the cgi client. -# There's now a clearly marked "TODO: append the change note" where I believe -# the change note should be added there. The "changes" list will obviously -# have to be modified to be a dict of the changes, or somesuch. -# -# More testing needed. -# -# Revision 1.8 2001/10/09 07:25:59 richard -# Added the Password property type. See "pydoc roundup.password" for -# implementation details. Have updated some of the documentation too. -# -# Revision 1.7 2001/08/29 06:23:59 richard -# Disabled the bsddb3 module entirely in the unit testing. See CHANGES for -# details. -# -# Revision 1.6 2001/08/07 00:24:43 richard -# stupid typo -# -# Revision 1.5 2001/08/07 00:15:51 richard -# Added the copyright/license notice to (nearly) all files at request of -# Bizar Software. -# -# Revision 1.4 2001/07/30 03:45:56 richard -# Added more DB to test_db. Can skip tests where imports fail. -# -# Revision 1.3 2001/07/29 07:01:39 richard -# Added vim command to all source so that we don't get no steenkin' tabs :) -# -# Revision 1.2 2001/07/29 04:09:20 richard -# Added the fabricated property "id" to all hyperdb classes. -# -# Revision 1.1 2001/07/27 06:55:07 richard -# moving tests -> test -# -# Revision 1.7 2001/07/27 06:26:43 richard -# oops - wasn't deleting the test dir after the read-only tests -# -# Revision 1.6 2001/07/27 06:23:59 richard -# consistency -# -# Revision 1.5 2001/07/27 06:23:09 richard -# Added some new hyperdb tests to make sure we raise the right exceptions. -# -# Revision 1.4 2001/07/25 04:34:31 richard -# Added id and log to tests files... -# -# # vim: set filetype=python ts=4 sw=4 et si