aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/tests
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-16 08:11:29 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-16 11:04:51 +0200
commit3c551005dcb8de4bb083aa934a8fdff1298f14f9 (patch)
treea38307a6bee159e979d22c09651066625cf3956b /sources/pyside2/tests
parent92a6f4b71770e0a6e63c8210992ba81448657373 (diff)
Fix slots being invoked from the wrong thread
In case the signal connections are routed via some GlobalReceiverV2 instance, it needs to be moved to the receiver's thread. Fixes: PYSIDE-1354 Change-Id: I85926efeab157e47ec42a830fda024d299807786 Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/pyside2/tests')
-rw-r--r--sources/pyside2/tests/signals/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/signals/signal_across_threads.py106
2 files changed, 107 insertions, 0 deletions
diff --git a/sources/pyside2/tests/signals/CMakeLists.txt b/sources/pyside2/tests/signals/CMakeLists.txt
index 740319f39..14936869f 100644
--- a/sources/pyside2/tests/signals/CMakeLists.txt
+++ b/sources/pyside2/tests/signals/CMakeLists.txt
@@ -26,6 +26,7 @@ PYSIDE_TEST(segfault_proxyparent_test.py)
PYSIDE_TEST(self_connect_test.py)
PYSIDE_TEST(short_circuit_test.py)
PYSIDE_TEST(signal2signal_connect_test.py)
+PYSIDE_TEST(signal_across_threads.py)
PYSIDE_TEST(signal_autoconnect_test.py)
PYSIDE_TEST(signal_connectiontype_support_test.py)
PYSIDE_TEST(signal_enum_test.py)
diff --git a/sources/pyside2/tests/signals/signal_across_threads.py b/sources/pyside2/tests/signals/signal_across_threads.py
new file mode 100644
index 000000000..907f059a1
--- /dev/null
+++ b/sources/pyside2/tests/signals/signal_across_threads.py
@@ -0,0 +1,106 @@
+#############################################################################
+##
+## Copyright (C) 2020 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+'''Test case for PYSIDE-1354: Ensure that slots are invoked from the receiver's
+thread context when using derived classes (and thus, a global receiver).'''
+
+import os
+import sys
+import unittest
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from PySide2.QtCore import QObject, QThread, QTimer, Slot
+from helper.usesqcoreapplication import UsesQCoreApplication
+
+
+class ReceiverBase(QObject):
+ def __init__(self, parent=None):
+ super(ReceiverBase, self).__init__(parent)
+ self.senderThread = None
+
+ @Slot()
+ def slot_function(self):
+ self.senderThread = QThread.currentThread()
+
+
+class Receiver(ReceiverBase):
+ pass
+
+
+class TestThread(QThread):
+ def __init__(self, parent=None):
+ super(TestThread, self).__init__(parent)
+
+ def run(self):
+ pass
+
+
+class SignalAcrossThreads(UsesQCoreApplication):
+ def setUp(self):
+ UsesQCoreApplication.setUp(self)
+ self._timer_tick = 0
+ self._timer = QTimer()
+ self._timer.setInterval(20)
+ self._timer.timeout.connect(self._control_test)
+ self._worker_thread = TestThread()
+
+ def tearDown(self):
+ UsesQCoreApplication.tearDown(self)
+
+ @Slot()
+ def _control_test(self):
+ if self._timer_tick == 0:
+ self._worker_thread.start()
+ elif self._timer_tick == 1:
+ self._worker_thread.wait()
+ else:
+ self._timer.stop()
+ self.app.quit()
+ self._timer_tick += 1
+
+ def test(self):
+ worker_thread_receiver = Receiver()
+ worker_thread_receiver.moveToThread(self._worker_thread)
+ self._worker_thread.started.connect(worker_thread_receiver.slot_function)
+
+ main_thread = QThread.currentThread()
+ main_thread_receiver = Receiver()
+ self._worker_thread.started.connect(main_thread_receiver.slot_function)
+
+ self._timer.start()
+ self.app.exec_()
+
+ self.assertEqual(worker_thread_receiver.senderThread, self._worker_thread)
+ self.assertEqual(main_thread_receiver.senderThread, main_thread)
+
+
+if __name__ == '__main__':
+ unittest.main()