[Checkins] SVN: Products.QueueCatalog/trunk/ - factor out and expand queue conflict tests

Jens Vagelpohl jens at dataflake.org
Mon May 8 10:55:45 EDT 2006


Log message for revision 68024:
  - factor out and expand queue conflict tests
  - update copyrights
  - fix long lines and sone other stylistic improvements
  

Changed:
  U   Products.QueueCatalog/trunk/CHANGES.txt
  U   Products.QueueCatalog/trunk/CatalogEventQueue.py
  U   Products.QueueCatalog/trunk/CatalogEventQueueSet.py
  U   Products.QueueCatalog/trunk/Processor.py
  U   Products.QueueCatalog/trunk/QueueCatalog.py
  U   Products.QueueCatalog/trunk/__init__.py
  A   Products.QueueCatalog/trunk/tests/test_CatalogEventQueue.py
  U   Products.QueueCatalog/trunk/tests/test_CatalogEventQueueSet.py
  U   Products.QueueCatalog/trunk/tests/test_QueueCatalog.py

-=-
Modified: Products.QueueCatalog/trunk/CHANGES.txt
===================================================================
--- Products.QueueCatalog/trunk/CHANGES.txt	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/CHANGES.txt	2006-05-08 14:55:44 UTC (rev 68024)
@@ -6,8 +6,8 @@
 
     - Updated the tests to run on Zope 2.8+
 
-    - Enabled conflict testing after changing it to use a quick and dirty
-      FileStorage, and expanding it a little.
+    - Factored out queue conflict testing after changing it to use a quick 
+      and dirty FileStorage, and expanding it a little.
 
     - Removed the security declaration for a method named refreshCatalog
       which was added in version 1.0 - this is the wrong place to apply

Modified: Products.QueueCatalog/trunk/CatalogEventQueue.py
===================================================================
--- Products.QueueCatalog/trunk/CatalogEventQueue.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/CatalogEventQueue.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
 # All Rights Reserved.
 # 
 # This software is subject to the provisions of the Zope Public License,
@@ -176,7 +176,6 @@
         # transaction previous to the undone transaction.
 
         # Committed is always the currently committed data.
-
         oldstate_data  =  oldstate['_data']
         committed_data = committed['_data']
         newstate_data  =  newstate['_data']
@@ -207,8 +206,6 @@
                 # Check aqainst current value. Either we want a
                 # different event, in which case we give up, or we
                 # do nothing.
-                
-                
                 current = committed_data.get(uid)
                 if current is not None:
                     if current[1] != new[1]:

Modified: Products.QueueCatalog/trunk/CatalogEventQueueSet.py
===================================================================
--- Products.QueueCatalog/trunk/CatalogEventQueueSet.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/CatalogEventQueueSet.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+############################################################################## 
 """ Classes: CatalogEventQueueSet
 
 $Id$

Modified: Products.QueueCatalog/trunk/Processor.py
===================================================================
--- Products.QueueCatalog/trunk/Processor.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/Processor.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
 # All Rights Reserved.
 # 
 # This software is subject to the provisions of the Zope Public License,

Modified: Products.QueueCatalog/trunk/QueueCatalog.py
===================================================================
--- Products.QueueCatalog/trunk/QueueCatalog.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/QueueCatalog.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -327,7 +327,9 @@
         self._update(uid, REMOVED)
 
         if self._immediate_removal:
-            self._process_queue(self._queues[hash(uid) % self._buckets], limit=None)
+            self._process_queue( self._queues[hash(uid) % self._buckets]
+                               , limit=None
+                               )
 
     security.declareProtected(manage_zcatalog_entries, 'process')
     def process(self, max=None):

Modified: Products.QueueCatalog/trunk/__init__.py
===================================================================
--- Products.QueueCatalog/trunk/__init__.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/__init__.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
 # All Rights Reserved.
 # 
 # This software is subject to the provisions of the Zope Public License,

Added: Products.QueueCatalog/trunk/tests/test_CatalogEventQueue.py
===================================================================
--- Products.QueueCatalog/trunk/tests/test_CatalogEventQueue.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/tests/test_CatalogEventQueue.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -0,0 +1,168 @@
+##############################################################################
+#
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
+"""QueueCatalog tests.
+
+$Id$
+"""
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import Testing
+import transaction
+import Zope2
+Zope2.startup()
+
+from Products.ZCatalog.ZCatalog import ZCatalog
+from Products.QueueCatalog.CatalogEventQueue import CatalogEventQueue
+from Products.QueueCatalog.CatalogEventQueue import ADDED
+from Products.QueueCatalog.CatalogEventQueue import CHANGED
+from Products.QueueCatalog.CatalogEventQueue import CHANGED_ADDED
+from Products.QueueCatalog.CatalogEventQueue import REMOVED
+from Products.QueueCatalog.QueueCatalog import QueueCatalog
+from OFS.Application import Application
+from OFS.Folder import Folder
+from Testing.ZopeTestCase.base import TestCase 
+from ZODB.POSException import ConflictError 
+
+
+class QueueConflictTests(unittest.TestCase):
+
+    def _insane_update(self, queue, uid, etype):
+        # Queue update method that allows insane state changes, needed
+        # to provoke pathological queue states
+        data = queue._data
+        current = data.get(uid)
+        if current is not None:
+            generation, current = current
+
+            if ((current is ADDED or current is CHANGED_ADDED)
+                and etype is CHANGED):
+                etype = CHANGED_ADDED
+        else:
+            generation = 0
+
+        data[uid] = generation+1, etype
+
+        queue._p_changed = 1
+
+    def openDB(self):
+        from ZODB.FileStorage import FileStorage
+        from ZODB.DB import DB
+        self.dir = tempfile.mkdtemp()
+        self.storage = FileStorage(os.path.join(self.dir, 'testQCConflicts.fs'))
+        self.db = DB(self.storage)
+
+    def setUp(self):
+        self.openDB()
+        queue = CatalogEventQueue()
+
+        tm1 = transaction.TransactionManager()
+        conn1 = self.db.open(transaction_manager=tm1)
+        r1 = conn1.root()
+        r1["queue"] = queue
+        del queue
+        self.queue = r1["queue"]
+        tm1.commit()
+
+        tm2 = transaction.TransactionManager()
+        conn2 = self.db.open(transaction_manager=tm2)
+        r2 = conn2.root()
+        self.queue2 = r2["queue"]
+        ignored = dir(self.queue2)    # unghostify
+
+    def tearDown(self):
+        transaction.abort()
+        del self.queue
+        del self.queue2
+        if self.storage is not None:
+            self.storage.close()
+            self.storage.cleanup()
+            shutil.rmtree(self.dir)
+
+    def test_rig(self):
+        # Test the test rig
+        self.assertEqual(self.queue._p_serial, self.queue2._p_serial)
+
+    def test_simpleConflict(self):
+        # Using the first connection, index 10 paths
+        for n in range(10):
+            self.queue.update('/f%i' % n, ADDED)
+        self.queue._p_jar.transaction_manager.commit()
+
+        # After this run, the first connection's queuecatalog has 10
+        # entries, the second has none.
+        self.assertEqual(len(self.queue), 10)
+        self.assertEqual(len(self.queue2), 0)
+
+        # Using the second connection, index the other 10 folders
+        for n in range(10):
+            self.queue2.update('/g%i' % n, ADDED)
+
+        # Now both connections' queuecatalogs have 10 entries each, but
+        # for differrent objects
+        self.assertEqual(len(self.queue), 10)
+        self.assertEqual(len(self.queue2), 10)
+
+        # Now we commit. Conflict resolution on the catalog queue should
+        # kick in because both connections have changes. Since none of the
+        # events collide, we should end up with 20 entries in our catalogs.
+        self.queue2._p_jar.transaction_manager.commit()
+        self.queue._p_jar.sync()
+        self.queue2._p_jar.sync()
+        self.assertEqual(len(self.queue), 20)
+        self.assertEqual(len(self.queue2), 20)
+
+    def test_unresolved_add_after_something(self):
+        # If an  event is encountered for an object and we are trying to
+        # commit an ADDED event, a conflict is encountered
+        self._insane_update(self.queue, '/f0', CHANGED)
+        self.queue._p_jar.transaction_manager.commit()
+
+        self._insane_update(self.queue2, '/f0', CHANGED)
+        self.queue2._p_jar.transaction_manager.commit()
+
+        self._insane_update(self.queue, '/f0', CHANGED)
+        self.queue._p_jar.transaction_manager.commit()
+
+        # This commit should now raise a conflict
+        self._insane_update(self.queue2, '/f0', ADDED)
+        self.assertRaises( ConflictError
+                         , self.queue2._p_jar.transaction_manager.commit
+                         )
+
+    def test_unresolved_new_old_current_all_different(self):
+        # If the events we get from the current, new and old states are
+        # all different, we throw in the towel in the form of a conflict.
+        # This test relies on the fact that no OLD state is de-facto treated
+        # as a state.
+        self._insane_update(self.queue, '/f0', CHANGED)
+        self.queue._p_jar.transaction_manager.commit()
+
+        # This commit should now raise a conflict
+        self._insane_update(self.queue2, '/f0', REMOVED)
+        self.assertRaises( ConflictError
+                         , self.queue2._p_jar.transaction_manager.commit
+                         )
+
+def test_suite():
+    return unittest.TestSuite((
+            unittest.makeSuite(QueueConflictTests),
+                    ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+


Property changes on: Products.QueueCatalog/trunk/tests/test_CatalogEventQueue.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: Products.QueueCatalog/trunk/tests/test_CatalogEventQueueSet.py
===================================================================
--- Products.QueueCatalog/trunk/tests/test_CatalogEventQueueSet.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/tests/test_CatalogEventQueueSet.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+############################################################################## 
 from __future__ import generators
 
 import unittest

Modified: Products.QueueCatalog/trunk/tests/test_QueueCatalog.py
===================================================================
--- Products.QueueCatalog/trunk/tests/test_QueueCatalog.py	2006-05-08 14:01:29 UTC (rev 68023)
+++ Products.QueueCatalog/trunk/tests/test_QueueCatalog.py	2006-05-08 14:55:44 UTC (rev 68024)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002-2006 Zope Corporation and Contributors.
 # All Rights Reserved.
 # 
 # This software is subject to the provisions of the Zope Public License,
@@ -16,22 +16,16 @@
 $Id$
 """
 
-import os
-import shutil
-import tempfile
 import unittest
 
 import Testing
-import transaction
 import Zope2
 Zope2.startup()
 
 from Products.ZCatalog.ZCatalog import ZCatalog
 from Products.QueueCatalog.QueueCatalog import QueueCatalog
-from OFS.Application import Application
 from OFS.Folder import Folder
 from Testing.ZopeTestCase.base import TestCase 
-from ZODB.POSException import ConflictError 
 
 class QueueCatalogTests(TestCase):
 
@@ -236,7 +230,7 @@
 
     def testImmediateDeletion(self):
         app = self.app
-        app.test_cat = QueueCatalog(1000)  # 1000 buckets. I don't want collisions here.
+        app.test_cat = QueueCatalog(1000)  # 1000 buckets to prevent collisions
         app.test_cat.id = 'test_cat'
         app.test_cat.manage_edit(location='/real_cat',
                                   immediate_indexes=['id'], immediate_removal=1)
@@ -247,131 +241,16 @@
             f = getattr(app, f.id)
             app.test_cat.catalog_object(f)
         self.assertEqual(app.test_cat.manage_size(), 20)
-        # "Delete" one. This should be processed immediately (including the add-event)
+        # "Delete" one. This should be processed immediately (including 
+        # the add-event)
         app.test_cat.uncatalog_object(getattr(app, 'f1').getPhysicalPath())
         self.assertEqual(app.test_cat.manage_size(), 19)
         del app.test_cat
 
 
-class QueueConflictTests(unittest.TestCase):
-
-    def openDB(self):
-        from ZODB.FileStorage import FileStorage
-        from ZODB.DB import DB
-        self.dir = tempfile.mkdtemp()
-        self.storage = FileStorage(os.path.join(self.dir, 'testQCConflicts.fs'))
-        self.db = DB(self.storage)
-
-    def setUp(self):
-        self.openDB()
-        app = Application()
-
-        tm1 = transaction.TransactionManager()
-        conn1 = self.db.open(transaction_manager=tm1)
-        r1 = conn1.root()
-        r1["Application"] = app
-        del app
-        self.app = r1["Application"]
-        tm1.commit()
-
-        self.app.real_cat = ZCatalog('real_cat')
-        self.app.real_cat.addIndex('id', 'FieldIndex')
-        self.app.real_cat.addIndex('title', 'FieldIndex')
-        self.app.real_cat.addIndex('meta_type', 'FieldIndex')
-        self.app.queue_cat = QueueCatalog(3) # 3 buckets
-        self.app.queue_cat.id = 'queue_cat'
-        self.app.queue_cat.manage_edit(location='/real_cat',
-                                  immediate_indexes=[])
-
-        # Create stuff to catalog
-        for n in range(10):
-            f = Folder()
-            f.id = 'f%d' % n
-            self.app._setOb(f.id, f)
-            g = Folder()
-            g.id = 'g%d' % n
-            self.app._setOb(g.id, g)
-
-        # Make sure everything is committed so the second connection sees it
-        tm1.commit()
-
-        tm2 = transaction.TransactionManager()
-        conn2 = self.db.open(transaction_manager=tm2)
-        r2 = conn2.root()
-        self.app2 = r2["Application"]
-        ignored = dir(self.app2)    # unghostify
-
-    def tearDown(self):
-        transaction.abort()
-        del self.app
-        if self.storage is not None:
-            self.storage.close()
-            self.storage.cleanup()
-            shutil.rmtree(self.dir)
-
-    def test_rig(self):
-        # Test the test rig
-        self.assertEqual(self.app._p_serial, self.app2._p_serial)
-
-    def test_simpleConflict(self):
-        # Using the first connection, index 10 folders
-        for n in range(10):
-            f = getattr(self.app, 'f%d' % n) 
-            self.app.queue_cat.catalog_object(f)
-        self.app._p_jar.transaction_manager.commit()
-
-        # After this run, the first connection's queuecatalog has 10
-        # entries, the second has none.
-        self.assertEqual(self.app.queue_cat.manage_size(), 10)
-        self.assertEqual(self.app2.queue_cat.manage_size(), 0)
-
-        # Using the second connection, index the other 10 folders
-        for n in range(10):
-            g = getattr(self.app2, 'g%d' % n) 
-            self.app2.queue_cat.catalog_object(g)
-
-        # Now both connections' queuecatalogs have 10 entries each, but
-        # for differrent objects
-        self.assertEqual(self.app.queue_cat.manage_size(), 10)
-        self.assertEqual(self.app2.queue_cat.manage_size(), 10)
-
-        # Now we commit. Conflict resolution on the catalog queue should
-        # kick in because both connections have changes. Since none of the
-        # events collide, we should end up with 20 entries in our catalogs.
-        self.app2._p_jar.transaction_manager.commit()
-        self.app._p_jar.sync()
-        self.app2._p_jar.sync()
-        self.assertEqual(self.app.queue_cat.manage_size(), 20)
-        self.assertEqual(self.app2.queue_cat.manage_size(), 20)
-
-    def test_unresolved_add_after_delete(self):
-        # If a DELETE event is encountered for an object and other events
-        # happen afterwards, we have entered the twilight zone and give up.
-
-        # Taking one item and cataloging it in the first connection, then
-        # uncataloging it. There should be 1 event in the queue left
-        # afterwards, for uncataloging the content item (DELETE)
-        f0 = getattr(self.app, 'f0')
-        self.app.queue_cat.catalog_object(f0)
-        self.app._p_jar.transaction_manager.commit()
-        self.app.queue_cat.uncatalog_object('/f0')
-        self.app._p_jar.transaction_manager.commit()
-        self.assertEqual(self.app.queue_cat.manage_size(), 1)
-
-        # In the second connection, I will newly catalog the same folder again
-        # in order to provoke insane state (ADD after DELETE)
-        self.app2.queue_cat.catalog_object(f0)
-
-        # This commit should now raise a conflict
-        self.assertRaises( ConflictError
-                         , self.app2._p_jar.transaction_manager.commit
-                         )
-
-
 def test_suite():
     return unittest.TestSuite((
             unittest.makeSuite(QueueCatalogTests),
-            unittest.makeSuite(QueueConflictTests),
                     ))
 
 if __name__ == '__main__':



More information about the Checkins mailing list