Code

Journal entries for link and multilink properties can now be switched on
[roundup.git] / test / test_db.py
index a20b2488acecedc9127972b3255119c44f947658..9632d365a6dfd036e9df619434ffa0dcfbc4a6cb 100644 (file)
@@ -4,7 +4,7 @@
 # under the same terms as Python, so long as this copyright message and
 # disclaimer are retained in their original form.
 #
-# IN NO EVENT SHALL THE BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: test_db.py,v 1.5 2001-08-07 00:15:51 richard Exp $ 
+# $Id: test_db.py,v 1.15 2002-01-19 13:16:04 rochecompaan Exp $ 
 
 import unittest, os, shutil
 
-from roundup.hyperdb import String, Link, Multilink, Date, Interval, Class, \
-    DatabaseError
+from roundup.hyperdb import String, Password, Link, Multilink, Date, \
+    Interval, Class, DatabaseError
+from roundup.roundupdb import FileClass
+from roundup import date
 
 def setupSchema(db, create):
     status = Class(db, "status", name=String())
@@ -30,37 +32,39 @@ def setupSchema(db, create):
         status.create(name="in-progress")
         status.create(name="testing")
         status.create(name="resolved")
-    Class(db, "user", username=String(), password=String())
+    Class(db, "user", username=String(), password=Password())
     Class(db, "issue", title=String(), status=Link("status"),
-        nosy=Multilink("user"))
-
-#class MyTestResult(unittest._TestResult):
-#    def addError(self, test, err):
-#        print `err`
-#        TestResult.addError(self, test, err)
-#        if self.showAll:
-#            self.stream.writeln("ERROR")
-#        elif self.dots:
-#            self.stream.write('E')
-#        if err[0] is KeyboardInterrupt:
-#            self.shouldStop = 1
+        nosy=Multilink("user"), deadline=Date(), foo=Interval())
+    FileClass(db, "file", name=String(), type=String())
+    db.commit()
 
 class MyTestCase(unittest.TestCase):
-#    def defaultTestResult(self):
-#        return MyTestResult()
     def tearDown(self):
-        if self.db is not None:
-            self.db.close()
+        if os.path.exists('_test_dir'):
             shutil.rmtree('_test_dir')
-    
-class DBTestCase(MyTestCase):
+
+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/'
+    ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
+    FILTER_POSITION = 'bottom'      # one of 'top', 'bottom', 'top and bottom'
+    ANONYMOUS_ACCESS = 'deny'       # either 'deny' or 'allow'
+    ANONYMOUS_REGISTER = 'deny'     # either 'deny' or 'allow'
+    MESSAGES_TO_AUTHOR = 'no'       # either 'yes' or 'no'
+    EMAIL_SIGNATURE_POSITION = 'bottom'
+
+class anydbmDBTestCase(MyTestCase):
     def setUp(self):
         from roundup.backends import anydbm
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        self.db = anydbm.Database('_test_dir', 'test')
+        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)
 
     def testChanges(self):
@@ -73,16 +77,57 @@ class DBTestCase(MyTestCase):
         props = self.db.issue.getprops()
         keys = props.keys()
         keys.sort()
-        self.assertEqual(keys, ['fixer', 'id', 'nosy', 'status', 'title'])
+        self.assertEqual(keys, ['deadline', 'fixer', 'foo', 'id', 'nosy',
+            'status', 'title'])
         self.db.issue.set('5', status='2')
         self.db.issue.get('5', "status")
+
+        a = self.db.issue.get('5', "deadline")
+        self.db.issue.set('5', deadline=date.Date())
+        self.assertNotEqual(a, self.db.issue.get('5', "deadline"))
+
+        a = self.db.issue.get('5', "foo")
+        self.db.issue.set('5', foo=date.Interval('-1d'))
+        self.assertNotEqual(a, self.db.issue.get('5', "foo"))
+
         self.db.status.get('2', "name")
         self.db.issue.get('5', "title")
         self.db.issue.find(status = self.db.status.lookup("in-progress"))
+        self.db.commit()
         self.db.issue.history('5')
         self.db.status.history('1')
         self.db.status.history('2')
 
+    def testTransactions(self):
+        num_issues = len(self.db.issue.list())
+        files_dir = os.path.join('_test_dir', 'files')
+        if os.path.exists(files_dir):
+            num_files = len(os.listdir(files_dir))
+        else:
+            num_files = 0
+        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()
+        self.assertEqual(num_files, len(os.listdir(files_dir)))
+        self.db.file.create(name="test", type="text/plain", content="hi")
+        self.db.commit()
+        self.assertNotEqual(num_files, len(os.listdir(files_dir)))
+        num_files2 = len(os.listdir(files_dir))
+        self.db.file.create(name="test", type="text/plain", content="hi")
+        self.db.rollback()
+        self.assertNotEqual(num_files, len(os.listdir(files_dir)))
+        self.assertEqual(num_files2, len(os.listdir(files_dir)))
+
+
     def testExceptions(self):
         # this tests the exceptions that should be raised
         ar = self.assertRaises
@@ -145,21 +190,69 @@ class DBTestCase(MyTestCase):
         ar(IndexError, self.db.issue.set, '1', title='foo', status='1',
             nosy=['10'])
 
+    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')
+        self.db.commit()
+
+        # journal entry for issue create
+        journal = self.db.getjournal('issue', '1')
+        self.assertEqual(1, len(journal))
+        (nodeid, date_stamp, journaltag, action, params) = journal[0]
+        self.assertEqual(nodeid, '1')
+        self.assertEqual(journaltag, 'test')
+        self.assertEqual(action, 'create')
+        keys = params.keys()
+        keys.sort()
+        self.assertEqual(keys, ['deadline', 'fixer', 'foo', 'nosy', 
+            'status', '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'])
+        self.assertEqual('spam',params['title'])
+
+        # journal entry for link
+        journal = self.db.getjournal('user', '1')
+        self.assertEqual(1, len(journal))
+        self.db.issue.set('1', fixer='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('link', action)
+        self.assertEqual(('issue', '1', 'fixer'), params)
+
+        # journal entry for unlink
+        self.db.issue.set('1', fixer='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('unlink', action)
+        self.assertEqual(('issue', '1', 'fixer'), params)
+
     def testRetire(self):
         pass
 
 
-class ReadOnlyDBTestCase(MyTestCase):
+class anydbmReadOnlyDBTestCase(MyTestCase):
     def setUp(self):
         from roundup.backends import anydbm
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        db = anydbm.Database('_test_dir', 'test')
+        if os.path.exists(config.DATABASE):
+            shutil.rmtree(config.DATABASE)
+        os.makedirs(config.DATABASE + '/files')
+        db = anydbm.Database(config, 'test')
         setupSchema(db, 1)
-        db.close()
-        self.db = anydbm.Database('_test_dir')
+        self.db = anydbm.Database(config)
         setupSchema(self.db, 0)
 
     def testExceptions(self):
@@ -172,57 +265,56 @@ class ReadOnlyDBTestCase(MyTestCase):
         ar(DatabaseError, self.db.status.retire, '1')
 
 
-class bsddbDBTestCase(DBTestCase):
+class bsddbDBTestCase(anydbmDBTestCase):
     def setUp(self):
         from roundup.backends import bsddb
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        self.db = bsddb.Database('_test_dir', 'test')
+        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)
 
-class bsddbReadOnlyDBTestCase(ReadOnlyDBTestCase):
+class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
     def setUp(self):
         from roundup.backends import bsddb
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        db = bsddb.Database('_test_dir', 'test')
+        if os.path.exists(config.DATABASE):
+            shutil.rmtree(config.DATABASE)
+        os.makedirs(config.DATABASE + '/files')
+        db = bsddb.Database(config, 'test')
         setupSchema(db, 1)
-        db.close()
-        self.db = bsddb.Database('_test_dir')
+        self.db = bsddb.Database(config)
         setupSchema(self.db, 0)
 
 
-class bsddb3DBTestCase(DBTestCase):
+class bsddb3DBTestCase(anydbmDBTestCase):
     def setUp(self):
         from roundup.backends import bsddb3
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        self.db = bsddb3.Database('_test_dir', 'test')
+        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)
 
-class bsddb3ReadOnlyDBTestCase(ReadOnlyDBTestCase):
+class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase):
     def setUp(self):
         from roundup.backends import bsddb3
         # remove previous test, ignore errors
-        if os.path.exists('_test_dir'):
-            shutil.rmtree('_test_dir')
-        os.mkdir('_test_dir')
-        db = bsddb3.Database('_test_dir', 'test')
+        if os.path.exists(config.DATABASE):
+            shutil.rmtree(config.DATABASE)
+        os.makedirs(config.DATABASE + '/files')
+        db = bsddb3.Database(config, 'test')
         setupSchema(db, 1)
-        db.close()
-        self.db = bsddb3.Database('_test_dir')
+        self.db = bsddb3.Database(config)
         setupSchema(self.db, 0)
 
 
 def suite():
-    l = [unittest.makeSuite(DBTestCase, 'test'),
-         unittest.makeSuite(ReadOnlyDBTestCase, 'test')]
+    l = [unittest.makeSuite(anydbmDBTestCase, 'test'),
+         unittest.makeSuite(anydbmReadOnlyDBTestCase, 'test')
+    ]
 
     try:
         import bsddb
@@ -231,17 +323,72 @@ def suite():
     except:
         print 'bsddb module not found, skipping bsddb DBTestCase'
 
-    try:
-        import bsddb3
-        l.append(unittest.makeSuite(bsddb3DBTestCase, 'test'))
-        l.append(unittest.makeSuite(bsddb3ReadOnlyDBTestCase, 'test'))
-    except:
-        print 'bsddb3 module not found, skipping bsddb3 DBTestCase'
+#    try:
+#        import bsddb3
+#        l.append(unittest.makeSuite(bsddb3DBTestCase, 'test'))
+#        l.append(unittest.makeSuite(bsddb3ReadOnlyDBTestCase, 'test'))
+#    except:
+#        print 'bsddb3 module not found, skipping bsddb3 DBTestCase'
 
     return unittest.TestSuite(l)
 
 #
 # $Log: not supported by cvs2svn $
+# 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.
 #