changeset 6365:7f00fc5958ca

Make memorydb persistent across re-open This allows memorydb to be used for more tests, in particular re-opening with another user for checking permissions.
author Ralf Schlatterbeck <rsc@runtux.com>
date Wed, 31 Mar 2021 12:49:28 +0200
parents e8361bce72de
children f2c31f5ec50b
files roundup/backends/__init__.py roundup/test/memorydb.py test/db_test_base.py test/test_mailgw.py test/test_memorydb.py
diffstat 5 files changed, 48 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/backends/__init__.py	Tue Mar 30 21:04:53 2021 -0400
+++ b/roundup/backends/__init__.py	Wed Mar 31 12:49:28 2021 +0200
@@ -54,6 +54,9 @@
         else:
             modname = e.args[0][16:] if e.args[0].startswith('No module named ') else None
 
+        # It's always ok if memorydb is not found
+        if modname.endswith('back_memorydb'):
+            return 0
         if modname and (modname in _modules.get(name, (name,))):
             return 0
         raise
@@ -65,9 +68,15 @@
     This function has side-effect of registering backward-compatible
     globals for all available backends.
 
+    Note: Since memorydb does not live in the backends directory, it will
+    never be found in the default setup. It *can* be enabled by preloading
+    test/memorydb and injecting into roundup.backends. So the normal user
+    can never configure memorydb but it makes using the tests easier
+    because we do not need to monkey-patch list_backends.
+
     '''
     l = []
-    for name in 'anydbm', 'mysql', 'sqlite', 'postgresql':
+    for name in 'anydbm', 'mysql', 'sqlite', 'postgresql', 'memorydb':
         if have_backend(name):
             l.append(name)
     return l
--- a/roundup/test/memorydb.py	Tue Mar 30 21:04:53 2021 -0400
+++ b/roundup/test/memorydb.py	Wed Mar 31 12:49:28 2021 +0200
@@ -38,6 +38,9 @@
     return config
 
 def create(journaltag, create=True, debug=False, prefix=default_prefix):
+    # "Nuke" in-memory db
+    db_nuke('')
+
     db = Database(new_config(debug), journaltag)
 
     # load standard schema
@@ -214,12 +217,12 @@
 
     dbtype = "memorydb"
 
+    # Make it a little more persistent across re-open
+    memdb = {}
+
     def __init__(self, config, journaltag=None):
         self.config, self.journaltag = config, journaltag
         self.classes = {}
-        self.items = {}
-        self.ids = {}
-        self.journals = {}
         self.files = {}
         self.tx_files = {}
         self.security = security.Security(self)
@@ -236,6 +239,10 @@
         self.destroyednodes = {}# keep track of the destroyed nodes by class
         self.transactions = []
         self.tx_Source = None
+        # persistence across re-open
+        self.items = self.__class__.memdb.get('items', {})
+        self.ids = self.__class__.memdb.get('ids', {})
+        self.journals = self.__class__.memdb.get('journals', {})
 
     def filename(self, classname, nodeid, property=None, create=0):
         shutil.copyfile(__file__, __file__+'.dummy')
@@ -290,6 +297,10 @@
         # kill the schema too
         self.classes = {}
         # just keep the .items
+        # persistence across re-open
+        self.__class__.memdb['items'] = self.items
+        self.__class__.memdb['ids'] = self.ids
+        self.__class__.memdb['journals'] = self.journals
 
     #
     # Classes
@@ -472,4 +483,13 @@
             properties['superseder'] = hyperdb.Multilink(classname)
         Class.__init__(self, db, classname, **properties)
 
+# Methods to check for existence and nuke the db
+# We don't support multiple named databases
+
+def db_exists(name):
+    return bool(Database.memdb)
+
+def db_nuke(name):
+    Database.memdb = {}
+
 # vim: set et sts=4 sw=4 :
--- a/test/db_test_base.py	Tue Mar 30 21:04:53 2021 -0400
+++ b/test/db_test_base.py	Wed Mar 31 12:49:28 2021 +0200
@@ -1379,15 +1379,13 @@
             self.assertEqual(result [4][4], jp3)
         self.db.close()
         # Verify that normal user doesn't see obsolete props/classes
-        # Backend memorydb cannot re-open db for different user
-        if self.db.dbtype != 'memorydb':
-            self.open_database('mary')
-            setupSchema(self.db, 0, self.module)
-            # allow mary to see issue fields like title
-            self.db.security.addPermissionToRole('User', 'View', 'issue')
-            result=self.db.issue.history(id)
-            self.assertEqual(len(result), 2)
-            self.assertEqual(result [1][4], jp0)
+        self.open_database('mary')
+        setupSchema(self.db, 0, self.module)
+        # allow mary to see issue fields like title
+        self.db.security.addPermissionToRole('User', 'View', 'issue')
+        result=self.db.issue.history(id)
+        self.assertEqual(len(result), 2)
+        self.assertEqual(result [1][4], jp0)
 
     def testJournalPreCommit(self):
         id = self.db.user.create(username="mary")
--- a/test/test_mailgw.py	Tue Mar 30 21:04:53 2021 -0400
+++ b/test/test_mailgw.py	Wed Mar 31 12:49:28 2021 +0200
@@ -223,6 +223,7 @@
         if os.path.exists(SENDMAILDEBUG):
             os.remove(SENDMAILDEBUG)
         self.db.close()
+        memorydb.db_nuke('')
 
     def _allowAnonymousSubmit(self):
         p = [
--- a/test/test_memorydb.py	Tue Mar 30 21:04:53 2021 -0400
+++ b/test/test_memorydb.py	Wed Mar 31 12:49:28 2021 +0200
@@ -10,12 +10,14 @@
 
     def nuke_database(self):
         # really kill it
+        memorydb.db_nuke('')
         self.db = None
 
     db = None
-    def open_database(self):
-        if self.db is None:
-            self.db = self.module.Database(config, 'admin')
+    def open_database(self, user='admin'):
+        if self.db:
+            self.db.close()
+        self.db = self.module.Database(config, user)
         return self.db
 
     def setUp(self):
@@ -25,6 +27,8 @@
     def tearDown(self):
         if self.db is not None:
             self.db.close()
+            self.db = None
+        self.nuke_database()
 
     # nuke and re-create db for restore
     def nukeAndCreate(self):

Roundup Issue Tracker: http://roundup-tracker.org/