Commit a8c54301 authored by Jérome Perrin's avatar Jérome Perrin

testSelectionTool: open connection in worker thread

In ZODB 5, with commit b6ac40f1 (Uses an unwrapped transaction manager,
2018-10-14) the transaction is bound to the thread opening the
connection.
The previous pattern of opening transaction in the main thread and
passing the already-open connection to the working thread caused the
working thread connection to be managed by the main thread connection
and in ZODB 5 cause the test to block.

Fix this by passing a connection factory method and opening
connection in working thread.
Also simplify closing of connection by using a closing context manager.
parent 7f4768d6
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# #
############################################################################## ##############################################################################
import contextlib
import unittest import unittest
from threading import Thread from threading import Thread
from thread import get_ident from thread import get_ident
...@@ -241,10 +242,10 @@ class TestSelectionPersistence(unittest.TestCase): ...@@ -241,10 +242,10 @@ class TestSelectionPersistence(unittest.TestCase):
def _runWithAnotherConnection(self, thread_func): def _runWithAnotherConnection(self, thread_func):
"""runs `thread_func` with another ZODB connection """runs `thread_func` with another ZODB connection
thread_func must be a callable accepting the connection object as only thread_func must be a callable accepting the connection factory as only
argument. argument.
""" """
t = Thread(target=thread_func, args=(self.db.open(),)) t = Thread(target=thread_func, args=(self.db.open,))
t.start() t.start()
t.join(60) t.join(60)
self.assertFalse(t.isAlive()) self.assertFalse(t.isAlive())
...@@ -253,14 +254,13 @@ class TestSelectionPersistence(unittest.TestCase): ...@@ -253,14 +254,13 @@ class TestSelectionPersistence(unittest.TestCase):
# same user edits the same selection with two different parameters # same user edits the same selection with two different parameters
self.portal_selections.setSelectionParamsFor( self.portal_selections.setSelectionParamsFor(
'test_selection', dict(a="b")) 'test_selection', dict(a="b"))
def thread_func(cnx): def thread_func(cnx_factory):
try: with contextlib.closing(cnx_factory()) as cnx:
portal_selections = cnx.root().portal_selections portal_selections = cnx.root().portal_selections
portal_selections.setSelectionParamsFor( portal_selections.setSelectionParamsFor(
'test_selection', dict(a="c")) 'test_selection', dict(a="c"))
transaction.commit() transaction.commit()
finally:
cnx.close()
self._runWithAnotherConnection(thread_func) self._runWithAnotherConnection(thread_func)
# This would raise a ConflictError without conflict resolution code # This would raise a ConflictError without conflict resolution code
...@@ -272,14 +272,13 @@ class TestSelectionPersistence(unittest.TestCase): ...@@ -272,14 +272,13 @@ class TestSelectionPersistence(unittest.TestCase):
# same user edits two different selections # same user edits two different selections
self.portal_selections.setSelectionParamsFor( self.portal_selections.setSelectionParamsFor(
'test_selection2', dict(a="b")) 'test_selection2', dict(a="b"))
def thread_func(cnx): def thread_func(cnx_factory):
try: with contextlib.closing(cnx_factory()) as cnx:
portal_selections = cnx.root().portal_selections portal_selections = cnx.root().portal_selections
portal_selections.setSelectionParamsFor( portal_selections.setSelectionParamsFor(
'test_selection1', dict(a="b")) 'test_selection1', dict(a="b"))
transaction.commit() transaction.commit()
finally:
cnx.close()
self._runWithAnotherConnection(thread_func) self._runWithAnotherConnection(thread_func)
# This would raise a ConflictError without conflict resolution code # This would raise a ConflictError without conflict resolution code
...@@ -304,14 +303,12 @@ class TestSelectionPersistence(unittest.TestCase): ...@@ -304,14 +303,12 @@ class TestSelectionPersistence(unittest.TestCase):
self.portal_selections.setSelectionParamsFor( self.portal_selections.setSelectionParamsFor(
'test_selection', dict(a="b")) 'test_selection', dict(a="b"))
def thread_func(cnx): def thread_func(cnx_factory):
try: with contextlib.closing(cnx_factory()) as cnx:
portal_selections = cnx.root().portal_selections portal_selections = cnx.root().portal_selections
portal_selections.setSelectionParamsFor( portal_selections.setSelectionParamsFor(
'test_selection', dict(a="b")) 'test_selection', dict(a="b"))
transaction.commit() transaction.commit()
finally:
cnx.close()
self._runWithAnotherConnection(thread_func) self._runWithAnotherConnection(thread_func)
transaction.commit() transaction.commit()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment