[Erp5-report] r17549 - /erp5/trunk/products/ERP5Form/tests/testSelectionTool.py

nobody at svn.erp5.org nobody at svn.erp5.org
Tue Nov 13 10:46:58 CET 2007


Author: jerome
Date: Tue Nov 13 10:46:58 2007
New Revision: 17549

URL: http://svn.erp5.org?rev=17549&view=rev
Log:
Test that selections are persistent and resist to concurent modifications.

Modified:
    erp5/trunk/products/ERP5Form/tests/testSelectionTool.py

Modified: erp5/trunk/products/ERP5Form/tests/testSelectionTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Form/tests/testSelectionTool.py?rev=17549&r1=17548&r2=17549&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Form/tests/testSelectionTool.py (original)
+++ erp5/trunk/products/ERP5Form/tests/testSelectionTool.py Tue Nov 13 10:46:58 2007
@@ -27,10 +27,15 @@
 ##############################################################################
 
 import unittest
+from threading import Thread
+from thread import get_ident
+
+from Testing import ZODButil
 
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
 from AccessControl.SecurityManagement import newSecurityManager
 from Products.ERP5Form.Selection import Selection
+from Products.ERP5Form.SelectionTool import SelectionTool
 
 
 class TestSelectionTool(ERP5TypeTestCase):
@@ -231,7 +236,128 @@
     self.assertEquals(None,
                       self.portal_selections.getSelectionIndexFor('test_selection'))
 
+
+
+class TestSelectionPersistence(unittest.TestCase):
+  """SelectionTool tests that needs a "real" FileStorage to make sure selection
+  are really persistent and supports conflict resolution.
+  """
+  def setUp(self):
+    # patch selection tool class so that we don't need a portal_membership to
+    # find the current user name
+    SelectionTool._getUserId_saved = SelectionTool._getUserId
+    SelectionTool._getUserId = lambda self: 'user'
+
+    self.db = ZODButil.makeDB()
+    self.cnx = self.db.open()
+    self.portal_selections = \
+      self.cnx.root().portal_selections = SelectionTool()
+    self.portal_selections.setSelectionFor('test_selection', Selection())
+    get_transaction().commit()
+    
+  def tearDown(self):
+    # revert the patch from setUp
+    SelectionTool._getUserId = SelectionTool._getUserId_saved
+    self.cnx.close()
+    ZODButil.cleanDB()
+  
+  def _runWithAnotherConnection(self, thread_func):
+    """runs `thread_func` with another ZODB connection
+
+    thread_func must be a callable accepting the connection object as only
+    argument.
+    """
+    t = Thread(target=thread_func, args=(self.db.open(),))
+    t.start()
+    t.join(60)
+    self.assertFalse(t.isAlive())
+
+  def testSelectionParamConflictResolution(self):
+    # same user edits the same selection with two different parameters
+    self.portal_selections.setSelectionParamsFor(
+                       'test_selection', dict(a="b"))
+    def thread_func(cnx):
+      try:
+        portal_selections = cnx.root().portal_selections
+        portal_selections.setSelectionParamsFor(
+                              'test_selection', dict(a="c"))
+        get_transaction().commit()
+      finally:
+        cnx.close()
+    self._runWithAnotherConnection(thread_func)
+
+    # This would raise a ConflictError without conflict resolution code
+    get_transaction().commit()
+    params = self.portal_selections.getSelectionParamsFor('test_selection')
+    self.assertTrue(params.get('a'))
+
+  def testSelectionNameConflictResolution(self):
+    # same user edits two different selections
+    self.portal_selections.setSelectionParamsFor(
+                       'test_selection2', dict(a="b"))
+    def thread_func(cnx):
+      try:
+        portal_selections = cnx.root().portal_selections
+        portal_selections.setSelectionParamsFor(
+                       'test_selection1', dict(a="b"))
+        get_transaction().commit()
+      finally:
+        cnx.close()
+    self._runWithAnotherConnection(thread_func)
+
+    # This would raise a ConflictError without conflict resolution code
+    get_transaction().commit()
+    params = self.portal_selections.getSelectionParamsFor('test_selection1')
+    self.assertEquals(params.get('a'), 'b')
+    params = self.portal_selections.getSelectionParamsFor('test_selection2')
+    self.assertEquals(params.get('a'), 'b')
+
+  def testDifferentUsernameConflictResolution(self):
+    # different users edits selections
+    SelectionTool._getUserId = lambda self: 'user-%s' % get_ident()
+    # Note that in current implementation, the first time we initialized a
+    # selection for a user the mapping user -> selections is modified, which
+    # will generate a conflict if we have two new users at the same time.
+    # This test just checks that once we have initialized a user it doesn't
+    # generate conflicts when another users also modifies it owns selection.
+    # So we make sure that selection container is initialized for this user
+    self.portal_selections.setSelectionParamsFor(
+                       'test_selection', dict(initialized="1"))
+    get_transaction().commit()
+
+    self.portal_selections.setSelectionParamsFor(
+                       'test_selection', dict(a="b"))
+    def thread_func(cnx):
+      try:
+        portal_selections = cnx.root().portal_selections
+        portal_selections.setSelectionParamsFor(
+                       'test_selection', dict(a="b"))
+        get_transaction().commit()
+      finally:
+        cnx.close()
+    self._runWithAnotherConnection(thread_func)
+
+    get_transaction().commit()
+    # this check is quite low level.
+    # we know that setUp stored one selection, and each of our 2 threads stored
+    # one selection.
+    self.assertEquals(3, len(self.portal_selections.selection_data.keys()))
+
+  def testPersistentSelections(self):
+    # test that selection parameters are persistent
+    self.portal_selections.setSelectionParamsFor(
+                 'test_selection', dict(key="saved_value"))
+    get_transaction().commit()
+    self.cnx.close()
+
+    self.cnx = self.db.open()
+    portal_selections = self.cnx.root().portal_selections
+    self.assertEquals('saved_value',
+        portal_selections.getSelectionParamsFor('test_selection').get('key'))
+
+
 def test_suite():
   suite = unittest.TestSuite()
   suite.addTest(unittest.makeSuite(TestSelectionTool))
+  suite.addTest(unittest.makeSuite(TestSelectionPersistence))
   return suite




More information about the Erp5-report mailing list