aboutsummaryrefslogtreecommitdiffstats
path: root/tests/signals
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-09-21 14:51:26 -0300
committerHugo Lima <hugo.lima@openbossa.org>2009-09-21 14:52:09 -0300
commit9af36fbb64f19842c0cc797c0b586b3a686805e8 (patch)
tree6bbc050ded0f85517ea75f5dc6dc1ed172168248 /tests/signals
parentaa12538d63685ef8f75adaa79411b751929b727d (diff)
Added all original pyside unit tests to the shiboken version.
Diffstat (limited to 'tests/signals')
-rw-r--r--tests/signals/args_dont_match.py21
-rw-r--r--tests/signals/invalid_callback_test.py29
-rw-r--r--tests/signals/lambda_test.py53
-rw-r--r--tests/signals/multiple_connections_test.py65
-rw-r--r--tests/signals/pysignal_test.py105
-rw-r--r--tests/signals/qobject_destroyed_test.py23
-rw-r--r--tests/signals/qobject_receivers_test.py48
-rwxr-xr-xtests/signals/qobject_sender_test.py91
-rw-r--r--tests/signals/segfault_proxyparent_test.py73
-rw-r--r--tests/signals/short_circuit_test.py66
-rw-r--r--tests/signals/signal2signal_connect_test.py107
-rw-r--r--tests/signals/signal_connectiontype_support.py28
-rw-r--r--tests/signals/signal_emission_test.py123
-rw-r--r--tests/signals/signal_func_test.py21
-rw-r--r--tests/signals/signal_manager_refcount_test.py23
-rw-r--r--tests/signals/signal_with_primitive_type_test.py29
-rw-r--r--tests/signals/slot_reference_count_test.py54
-rw-r--r--tests/signals/upstream_segfault_test.py64
18 files changed, 1023 insertions, 0 deletions
diff --git a/tests/signals/args_dont_match.py b/tests/signals/args_dont_match.py
new file mode 100644
index 000000000..b81c5682c
--- /dev/null
+++ b/tests/signals/args_dont_match.py
@@ -0,0 +1,21 @@
+
+import unittest
+from PySide.QtCore import *
+
+class ArgsDontMatch(unittest.TestCase):
+
+ def callback(self, arg1):
+ self.ok = True
+
+ def testConnectSignalToSlotWithLessArgs(self):
+ self.ok = False
+ obj1 = QObject()
+ QObject.connect(obj1, SIGNAL('the_signal(int, int, int)'), self.callback)
+ obj1.emit(SIGNAL('the_signal(int, int, int)'), 1, 2, 3)
+
+ self.assert_(self.ok)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/invalid_callback_test.py b/tests/signals/invalid_callback_test.py
new file mode 100644
index 000000000..3328bb5c6
--- /dev/null
+++ b/tests/signals/invalid_callback_test.py
@@ -0,0 +1,29 @@
+
+'''Test cases for passing invalid callbacks to QObject.connect'''
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL
+
+class InvalidCallback(unittest.TestCase):
+ '''Test case for passing an invalid callback to QObject.connect'''
+
+ def setUp(self):
+ #Acquire resources
+ self.obj = QObject()
+
+ def tearDown(self):
+ #Release resources
+ try:
+ del self.obj
+ except AttributeError:
+ pass
+
+ def testIntegerCb(self):
+ #Test passing an int as callback to QObject.connect
+ self.assertRaises(TypeError, QObject.connect, self.obj,
+ SIGNAL('destroyed()'), 42)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/signals/lambda_test.py b/tests/signals/lambda_test.py
new file mode 100644
index 000000000..9a76ced09
--- /dev/null
+++ b/tests/signals/lambda_test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+'''Connecting lambda to signals'''
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL
+from PySide.QtGui import QApplication, QSpinBox, QPushButton
+
+from helper import UsesQApplication
+
+class Dummy(QObject):
+ def __init__(self, *args):
+ super(Dummy, self).__init__(*args)
+
+class BasicCase(unittest.TestCase):
+
+ def testSimplePythonSignalNoArgs(self):
+ #Connecting a lambda to a simple python signal without arguments
+ obj = Dummy()
+ QObject.connect(obj, SIGNAL('foo()'), lambda : setattr(obj, 'called', True))
+ obj.emit(SIGNAL('foo()'))
+ self.assert_(obj.called)
+
+ def testSimplePythonSignal(self):
+ #Connecting a lambda to a simple python signal witharguments
+ obj = Dummy()
+ arg = 42
+ QObject.connect(obj, SIGNAL('foo(int)'), lambda x : setattr(obj, 'arg', 42))
+ obj.emit(SIGNAL('foo(int)'), arg)
+ self.assertEqual(obj.arg, arg)
+
+class QtSigLambda(UsesQApplication):
+
+ qapplication = True
+
+ def testButton(self):
+ #Connecting a lambda to a QPushButton.clicked()
+ obj = QPushButton('label')
+ QObject.connect(obj, SIGNAL('clicked()'), lambda : setattr(obj, 'called', True))
+ obj.click()
+ self.assert_(obj.called)
+
+ def testSpinButton(self):
+ #Connecting a lambda to a QPushButton.clicked()
+ obj = QSpinBox()
+ arg = 444
+ QObject.connect(obj, SIGNAL('valueChanged(int)'), lambda x: setattr(obj, 'arg', 444))
+ obj.setValue(444)
+ self.assertEqual(obj.arg, arg)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/multiple_connections_test.py b/tests/signals/multiple_connections_test.py
new file mode 100644
index 000000000..f8dab32d5
--- /dev/null
+++ b/tests/signals/multiple_connections_test.py
@@ -0,0 +1,65 @@
+
+import unittest
+import random
+
+from PySide.QtCore import QObject, SIGNAL
+from PySide.QtGui import QPushButton, QSpinBox, QApplication
+
+from helper import BasicPySlotCase, UsesQApplication
+
+def random_gen(count=100, largest=99, lowest=0):
+ for i in range(count):
+ yield random.randint(lowest, largest)
+
+class MultipleSignalConnections(UsesQApplication):
+
+ qapplication = True
+
+ def run_many(self, sender, signal, receivers, args=None):
+ """Utility method to connect a list of receivers to a signal.
+ sender - QObject that will emit the signal
+ signal - string with the signal signature
+ receivers - list of BasicPySlotCase instances
+ args - tuple with the arguments to be sent.
+ """
+
+ if args is None:
+ args = tuple()
+
+ for rec in receivers:
+ rec.setUp()
+ QObject.connect(sender, SIGNAL(signal), rec.cb)
+ rec.args = tuple(args)
+
+ sender.emit(SIGNAL(signal), *args)
+
+ for rec in receivers:
+ self.assert_(rec.called)
+
+ def testButtonClick(self):
+ """Multiple connections to QPushButton.clicked()"""
+ sender = QPushButton('button')
+ receivers = [BasicPySlotCase() for x in range(30)]
+ self.run_many(sender, 'clicked()', receivers)
+
+ def testSpinBoxValueChanged(self):
+ """Multiple connections to QSpinBox.valueChanged(int)"""
+ for test in random_gen(30):
+ sender = QSpinBox()
+ #FIXME if number of receivers if higher than 50, segfaults
+ receivers = [BasicPySlotCase() for x in range(10)]
+ self.run_many(sender, 'valueChanged(int)', receivers, (test,))
+
+ def testPythonSignal(self):
+ """Multiple connections to a python signal (short-circuit)"""
+ class Dummy(QObject):
+ pass
+
+ for test in random_gen(30):
+ sender = Dummy()
+ receivers = [BasicPySlotCase() for x in range(10)]
+ self.run_many(sender, 'foobar', receivers, (test, ))
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/signals/pysignal_test.py b/tests/signals/pysignal_test.py
new file mode 100644
index 000000000..923d8b782
--- /dev/null
+++ b/tests/signals/pysignal_test.py
@@ -0,0 +1,105 @@
+
+import unittest
+from PySide.QtCore import QObject, SIGNAL, SLOT
+from PySide.QtGui import QSpinBox, QApplication, QWidget
+
+class Dummy(QObject):
+ """Dummy class used in this test."""
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class PythonSigSlot(unittest.TestCase):
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except:
+ pass
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Python signal and slots without arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo()'), self.callback)
+ self.args = tuple()
+ obj1.emit(SIGNAL('foo()'), *self.args)
+
+ self.assert_(self.called)
+
+ def testWithArgs(self):
+ """Python signal and slots with integer arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo(int)'), self.callback)
+ self.args = (42,)
+ obj1.emit(SIGNAL('foo(int)'), *self.args)
+
+ self.assert_(self.called)
+
+app = QApplication([])
+
+class SpinBoxPySignal(unittest.TestCase):
+ """Tests the connection of python signals to QSpinBox qt slots."""
+
+ qapplication = True
+
+ def setUp(self):
+ self.obj = Dummy()
+ self.spin = QSpinBox()
+ self.spin.setValue(0)
+
+ def tearDown(self):
+ del self.obj
+ del self.spin
+
+ def testValueChanged(self):
+ """Emission of a python signal to QSpinBox setValue(int)"""
+ QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)'))
+ self.assertEqual(self.spin.value(), 0)
+
+ self.obj.emit(SIGNAL('dummy(int)'), 4)
+ self.assertEqual(self.spin.value(), 4)
+
+ def testValueChangedMultiple(self):
+ """Multiple emissions of a python signal to QSpinBox setValue(int)"""
+ QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)'))
+ self.assertEqual(self.spin.value(), 0)
+
+ self.obj.emit(SIGNAL('dummy(int)'), 4)
+ self.assertEqual(self.spin.value(), 4)
+
+ self.obj.emit(SIGNAL('dummy(int)'), 77)
+ self.assertEqual(self.spin.value(), 77)
+
+
+class WidgetPySignal(unittest.TestCase):
+ """Tests the connection of python signals to QWidget qt slots."""
+
+ qapplication = True
+
+ def setUp(self):
+ self.obj = Dummy()
+ self.widget = QWidget()
+
+ def tearDown(self):
+ del self.obj
+ del self.widget
+
+ def testShow(self):
+ """Emission of a python signal to QWidget slot show()"""
+ self.widget.hide()
+
+ QObject.connect(self.obj, SIGNAL('dummy()'), self.widget, SLOT('show()'))
+ self.assert_(not self.widget.isVisible())
+
+ self.obj.emit(SIGNAL('dummy()'))
+ self.assert_(self.widget.isVisible())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/qobject_destroyed_test.py b/tests/signals/qobject_destroyed_test.py
new file mode 100644
index 000000000..01d1b5886
--- /dev/null
+++ b/tests/signals/qobject_destroyed_test.py
@@ -0,0 +1,23 @@
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL
+
+class QObjectDestroyed(unittest.TestCase):
+ """Very simple test case for the destroyed() signal of QObject"""
+
+ def setUp(self):
+ self.called = False
+
+ def destroyed_cb(self):
+ self.called = True
+
+ def testDestroyed(self):
+ """Emission of QObject.destroyed() to a python slot"""
+ obj = QObject()
+ QObject.connect(obj, SIGNAL('destroyed()'), self.destroyed_cb)
+ del obj
+ self.assert_(self.called)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/qobject_receivers_test.py b/tests/signals/qobject_receivers_test.py
new file mode 100644
index 000000000..e1d429ec6
--- /dev/null
+++ b/tests/signals/qobject_receivers_test.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+''' Test case for QObject.receivers()'''
+
+import unittest
+from PySide.QtCore import *
+
+def cute_slot():
+ pass
+
+class TestQObjectReceivers(unittest.TestCase):
+ '''Test case for QObject::receivers'''
+
+ def testBasic(self):
+ sender = QObject()
+ receiver1 = QObject()
+ receiver2 = QObject()
+ self.assertEqual(sender.receivers(SIGNAL("")), 0)
+ sender.connect(sender, SIGNAL("destroyed()"), receiver1, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 1)
+ sender.connect(sender, SIGNAL("destroyed()"), receiver2, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 2)
+ sender.disconnect(sender, SIGNAL("destroyed()"), receiver2, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 1)
+ del receiver2
+ del receiver1
+ del sender
+
+ def testPySlots(self):
+ sender = QObject()
+ receiver = QObject()
+ sender.connect(sender, SIGNAL("destroyed()"), cute_slot)
+ self.assertEqual(sender.receivers(SIGNAL("destroyed( )")), 1)
+ sender.connect(sender, SIGNAL("destroyed()"), receiver, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 2)
+ del sender
+ del receiver
+
+ def testPySignals(self):
+ sender = QObject()
+ receiver = QObject()
+ sender.connect(sender, SIGNAL("some_dynamic_signal()"), cute_slot)
+ self.assertEqual(sender.receivers(SIGNAL("some_dynamic_signal( )")), 1)
+ sender.connect(sender, SIGNAL("some_dynamic_signal()"), receiver, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("some_dynamic_signal( )")), 2)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/qobject_sender_test.py b/tests/signals/qobject_sender_test.py
new file mode 100755
index 000000000..5f11cda04
--- /dev/null
+++ b/tests/signals/qobject_sender_test.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+'''Test cases for QObject.sender()'''
+
+import unittest
+from PySide.QtCore import *
+from helper import UsesQCoreApplication
+
+class ExtQTimer(QTimer):
+ def __init__(self):
+ QTimer.__init__(self)
+
+class Receiver(QObject):
+ def __init__(self):
+ QObject.__init__(self)
+ self.the_sender = None
+
+ def callback(self):
+ self.the_sender = self.sender()
+ if QCoreApplication.instance():
+ QCoreApplication.instance().exit()
+
+class ObjectSenderTest(unittest.TestCase):
+ '''Test case for QObject.sender() method.'''
+
+ def testSenderPythonSignal(self):
+ sender = QObject()
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('foo()'), recv.callback)
+ sender.emit(SIGNAL('foo()'))
+ self.assertEquals(sender, recv.the_sender)
+
+class ObjectSenderCheckOnReceiverTest(unittest.TestCase):
+ '''Test case for QObject.sender() method, this one tests the equality on the Receiver object.'''
+
+ def testSenderPythonSignal(self):
+ sender = QObject()
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('foo()'), recv.callback)
+ sender.emit(SIGNAL('foo()'))
+ self.assertEquals(sender, recv.the_sender)
+
+class ObjectSenderWithQAppTest(UsesQCoreApplication):
+ '''Test case for QObject.sender() method with QApplication.'''
+
+ def testSenderCppSignal(self):
+ sender = QTimer()
+ sender.setObjectName('foo')
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('timeout()'), recv.callback)
+ sender.start(10)
+ self.app.exec_()
+ self.assertEquals(sender, recv.the_sender)
+
+ def testSenderCppSignalSingleShotTimer(self):
+ recv = Receiver()
+ QTimer.singleShot(10, recv.callback)
+ self.app.exec_()
+ self.assertEquals(QObject, type(recv.the_sender))
+
+ def testSenderCppSignalWithPythonExtendedClass(self):
+ sender = ExtQTimer()
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('timeout()'), recv.callback)
+ sender.start(10)
+ self.app.exec_()
+ self.assertEquals(sender, recv.the_sender)
+
+class ObjectSenderWithQAppCheckOnReceiverTest(UsesQCoreApplication):
+ '''Test case for QObject.sender() method with QApplication.'''
+
+ def testSenderCppSignal(self):
+ sender = QTimer()
+ sender.setObjectName('foo')
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('timeout()'), recv.callback)
+ sender.start(10)
+ self.app.exec_()
+ self.assertEquals(sender, recv.the_sender)
+
+ def testSenderCppSignalWithPythonExtendedClass(self):
+ sender = ExtQTimer()
+ recv = Receiver()
+ QObject.connect(sender, SIGNAL('timeout()'), recv.callback)
+ sender.start(10)
+ self.app.exec_()
+ self.assertEquals(sender, recv.the_sender)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/signals/segfault_proxyparent_test.py b/tests/signals/segfault_proxyparent_test.py
new file mode 100644
index 000000000..2b41f67c4
--- /dev/null
+++ b/tests/signals/segfault_proxyparent_test.py
@@ -0,0 +1,73 @@
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL
+
+# Description of the problem
+# After creating an PyObject that inherits from QObject, connecting it,
+# deleting it and later creating another Python QObject-based object, this
+# new object will point to the same memory position as the first one.
+
+# Somehow the underlying QObject also points to the same position.
+
+# In PyQt4, the connection works fine with the same memory behavior,
+# so it looks like specific to SIP.
+
+class Dummy(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class Joe(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class SegfaultCase(unittest.TestCase):
+ """Test case for the segfault happening when parent() is called inside
+ ProxyObject"""
+
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except:
+ pass
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testSegfault(self):
+ """Regression: Segfault for qobjects in the same memory position."""
+ obj = Dummy()
+ QObject.connect(obj, SIGNAL('bar(int)'), self.callback)
+ self.args = (33,)
+ obj.emit(SIGNAL('bar(int)'), self.args[0])
+ self.assert_(self.called)
+ del obj
+
+ obj = Joe()
+ QObject.connect(obj, SIGNAL('bar(int)'), self.callback)
+ self.args = (33,)
+ obj.emit(SIGNAL('bar(int)'), self.args[0])
+ self.assert_(self.called)
+
+
+ def testSameReference(self):
+ """Example of how sip(?) reuses memory positions"""
+ obj = Dummy()
+ s1 = str(obj)
+ del obj
+ obj = Dummy()
+ s2 = str(obj)
+ self.assertEqual(s1, s2)
+
+ obj2 = Dummy()
+ s3 = str(obj2)
+ self.assertNotEqual(s2, s3)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/signals/short_circuit_test.py b/tests/signals/short_circuit_test.py
new file mode 100644
index 000000000..e36420cad
--- /dev/null
+++ b/tests/signals/short_circuit_test.py
@@ -0,0 +1,66 @@
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL, SLOT
+
+class Dummy(QObject):
+ """Dummy class used in this test."""
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class ShortCircuitSignals(unittest.TestCase):
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except:
+ pass
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Short circuit signal without arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo'), self.callback)
+ self.args = tuple()
+ obj1.emit(SIGNAL('foo'), *self.args)
+
+ self.assert_(self.called)
+
+ def testWithArgs(self):
+ """Short circuit signal with integer arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo'), self.callback)
+ self.args = (42,)
+ obj1.emit(SIGNAL('foo'), *self.args)
+
+ self.assert_(self.called)
+
+ def testMultipleArgs(self):
+ """Short circuit signal with multiple arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo'), self.callback)
+ self.args = (42,33,'char')
+ obj1.emit(SIGNAL('foo'), *self.args)
+
+ self.assert_(self.called)
+
+ def testComplexArgs(self):
+ """Short circuit signal with complex arguments"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo'), self.callback)
+ self.args = (42, obj1)
+ obj1.emit(SIGNAL('foo'), *self.args)
+
+ self.assert_(self.called)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/signal2signal_connect_test.py b/tests/signals/signal2signal_connect_test.py
new file mode 100644
index 000000000..bdc2328bf
--- /dev/null
+++ b/tests/signals/signal2signal_connect_test.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+
+''' Test case for signal to signal connections.'''
+
+import unittest
+from PySide.QtCore import *
+
+def cute_slot():
+ pass
+
+class TestSignal2SignalConnect(unittest.TestCase):
+ '''Test case for signal to signal connections'''
+
+ def setUp(self):
+ #Set up the basic resources needed
+ self.sender = QObject()
+ self.forwarder = QObject()
+ self.args = None
+ self.called = False
+
+ def tearDown(self):
+ #Delete used resources
+ try:
+ del self.sender
+ except:
+ pass
+ try:
+ del self.forwarder
+ except:
+ pass
+ del self.args
+
+ def callback_noargs(self):
+ #Default callback without arguments
+ self.called = True
+
+ def callback_args(self, *args):
+ #Default callback with arguments
+ if args == self.args:
+ self.called = True
+ else:
+ raise TypeError("Invalid arguments")
+
+ def callback_qobject(self, *args):
+ #Default callback for QObject as argument
+ if args[0].objectName() == self.args[0]:
+ self.called = True
+ else:
+ raise TypeError("Invalid arguments")
+
+
+ def testSignalWithoutArguments(self):
+ QObject.connect(self.sender, SIGNAL("destroyed()"),
+ self.forwarder, SIGNAL("forward()"))
+ QObject.connect(self.forwarder, SIGNAL("forward()"),
+ self.callback_noargs)
+ del self.sender
+ self.assert_(self.called)
+
+
+ def testSignalWithOnePrimitiveTypeArgument(self):
+ QObject.connect(self.sender, SIGNAL("mysignal(int)"),
+ self.forwarder, SIGNAL("mysignal(int)"))
+ QObject.connect(self.forwarder, SIGNAL("mysignal(int)"),
+ self.callback_args)
+ self.args = (19,)
+ self.sender.emit(SIGNAL('mysignal(int)'), *self.args)
+ self.assert_(self.called)
+
+
+ def testSignalWithMultiplePrimitiveTypeArguments(self):
+ QObject.connect(self.sender, SIGNAL("mysignal(int,int)"),
+ self.forwarder, SIGNAL("mysignal(int,int)"))
+ QObject.connect(self.forwarder, SIGNAL("mysignal(int,int)"),
+ self.callback_args)
+ self.args = (23, 29)
+ self.sender.emit(SIGNAL('mysignal(int,int)'), *self.args)
+ self.assert_(self.called)
+
+
+ def testSignalWithOneStringArgument(self):
+ QObject.connect(self.sender, SIGNAL("mysignal(QString)"),
+ self.forwarder, SIGNAL("mysignal(QString)"))
+ QObject.connect(self.forwarder, SIGNAL("mysignal(QString)"),
+ self.callback_args)
+ self.args = ('myargument',)
+ self.sender.emit(SIGNAL('mysignal(QString)'), *self.args)
+ self.assert_(self.called)
+
+
+ def testSignalWithOneQObjectArgument(self):
+ QObject.connect(self.sender, SIGNAL('destroyed(QObject*)'),
+ self.forwarder, SIGNAL('forward(QObject*)'))
+ QObject.connect(self.forwarder, SIGNAL('forward(QObject*)'),
+ self.callback_qobject)
+
+ obj_name = 'sender'
+ self.sender.setObjectName(obj_name)
+ self.args = (obj_name, )
+ del self.sender
+ self.assert_(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/tests/signals/signal_connectiontype_support.py b/tests/signals/signal_connectiontype_support.py
new file mode 100644
index 000000000..d0c35c53a
--- /dev/null
+++ b/tests/signals/signal_connectiontype_support.py
@@ -0,0 +1,28 @@
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL, Qt
+
+class Dummy(QObject):
+ """Dummy class used in this test."""
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class TestConnectionTypeSupport(unittest.TestCase):
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Connect signal using a Qt.ConnectionType as argument"""
+ obj1 = Dummy()
+
+ QObject.connect(obj1, SIGNAL('foo'), self.callback, Qt.DirectConnection)
+ self.args = tuple()
+ obj1.emit(SIGNAL('foo'), *self.args)
+
+ self.assert_(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/signal_emission_test.py b/tests/signals/signal_emission_test.py
new file mode 100644
index 000000000..8d9af620c
--- /dev/null
+++ b/tests/signals/signal_emission_test.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+"""Tests covering signal emission and receiving to python slots"""
+
+import sys
+import unittest
+
+from PySide.QtCore import QObject, QTimer, QCoreApplication, SIGNAL, SLOT
+from PySide.QtGui import QSpinBox, QPushButton, QApplication
+from helper import BasicPySlotCase, UsesQApplication
+
+class ButtonPySlot(UsesQApplication, BasicPySlotCase):
+ """Tests the connection of python slots to QPushButton signals"""
+
+ qapplication = True
+
+ def setUp(self):
+ super(ButtonPySlot, self).setUp()
+
+ def tearDown(self):
+ super(ButtonPySlot, self).setUp()
+
+ def testButtonClicked(self):
+ """Connection of a python slot to QPushButton.clicked()"""
+ button = QPushButton('Mylabel')
+ QObject.connect(button, SIGNAL('clicked()'), self.cb)
+ self.args = tuple()
+ button.emit(SIGNAL('clicked()'))
+ self.assert_(self.called)
+
+ def testButtonClickedWrongArgs(self):
+ """Python slot connected to QPushButton.clicked() and more args"""
+ button = QPushButton('Mylabel')
+ QObject.connect(button, SIGNAL('clicked()'), self.cb)
+ self.args = tuple()
+ button.emit(SIGNAL('clicked()'), 44)
+ self.assert_(self.called)
+
+ def testButtonClick(self):
+ """Indirect qt signal emission using the QPushButton.click() method """
+ button = QPushButton('label')
+ QObject.connect(button, SIGNAL('clicked()'), self.cb)
+ self.args = tuple()
+ button.click()
+ self.assert_(self.called)
+
+
+class SpinBoxPySlot(UsesQApplication, BasicPySlotCase):
+ """Tests the connection of python slots to QSpinBox signals"""
+
+ qapplication = True
+
+ def setUp(self):
+ super(SpinBoxPySlot, self).setUp()
+ self.spin = QSpinBox()
+
+ def tearDown(self):
+ del self.spin
+ super(SpinBoxPySlot, self).tearDown()
+
+ def testSpinBoxValueChanged(self):
+ """Connection of a python slot to QSpinBox.valueChanged(int)"""
+ QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
+ self.args = [3]
+ self.spin.emit(SIGNAL('valueChanged(int)'), *self.args)
+ self.assert_(self.called)
+
+ def testSpinBoxValueChangedImplicit(self):
+ """Indirect qt signal emission using QSpinBox.setValue(int)"""
+ QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
+ self.args = [42]
+ self.spin.setValue(self.args[0])
+ self.assert_(self.called)
+
+ def atestSpinBoxValueChangedFewArgs(self):
+ """Emission of signals with fewer arguments than needed"""
+ # XXX: PyQt4 crashes on the assertRaises
+ QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
+ self.args = (554,)
+ self.assertRaises(TypeError, self.spin.emit, SIGNAL('valueChanged(int)'))
+
+class QSpinBoxQtSlots(UsesQApplication):
+ """Tests the connection to QSpinBox qt slots"""
+
+ qapplication = True
+
+ def testSetValueIndirect(self):
+ """Indirect signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
+ spinSend = QSpinBox()
+ spinRec = QSpinBox()
+
+ spinRec.setValue(5)
+
+ QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)'))
+ self.assertEqual(spinRec.value(), 5)
+ spinSend.setValue(3)
+ self.assertEqual(spinRec.value(), 3)
+ self.assertEqual(spinSend.value(), 3)
+
+ def testSetValue(self):
+ """Direct signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
+ spinSend = QSpinBox()
+ spinRec = QSpinBox()
+
+ spinRec.setValue(5)
+ spinSend.setValue(42)
+
+ QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)'))
+ self.assertEqual(spinRec.value(), 5)
+ self.assertEqual(spinSend.value(), 42)
+ spinSend.emit(SIGNAL('valueChanged(int)'), 3)
+
+ self.assertEqual(spinRec.value(), 3)
+ #Direct emission shouldn't change the value of the emitter
+ self.assertEqual(spinSend.value(), 42)
+
+ spinSend.emit(SIGNAL('valueChanged(int)'), 66)
+ self.assertEqual(spinRec.value(), 66)
+ self.assertEqual(spinSend.value(), 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/signal_func_test.py b/tests/signals/signal_func_test.py
new file mode 100644
index 000000000..39bd1b293
--- /dev/null
+++ b/tests/signals/signal_func_test.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+
+from PySide.QtCore import SIGNAL, SLOT
+
+class SIGNALSLOTTests(unittest.TestCase):
+ '''Test the output of SIGNAL and SLOT.'''
+
+ def testSIGNAL(self):
+ #SIGNAL function
+ a = "foobar"
+ self.assertEqual(str(SIGNAL(a)), "2foobar")
+
+ def testSLOT(self):
+ #SLOT function
+ a = "foobar"
+ self.assertEqual(str(SLOT(a)), "1foobar")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/signal_manager_refcount_test.py b/tests/signals/signal_manager_refcount_test.py
new file mode 100644
index 000000000..191ce9d63
--- /dev/null
+++ b/tests/signals/signal_manager_refcount_test.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+from sys import getrefcount
+import unittest
+from PySide.QtCore import QObject, SIGNAL
+
+class SignalManagerRefCount(unittest.TestCase):
+ """Simple test case to check if the signal_manager is erroneously incrementing the object refcounter"""
+
+ def testObjectRefcount(self):
+ """Emission of QObject.destroyed() to a python slot"""
+ def callback():
+ pass
+ obj = QObject()
+ refcount = getrefcount(obj)
+ QObject.connect(obj, SIGNAL('destroyed()'), callback)
+ self.assertEqual(refcount, getrefcount(obj))
+ QObject.disconnect(obj, SIGNAL('destroyed()'), callback)
+ self.assertEqual(refcount, getrefcount(obj))
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/signals/signal_with_primitive_type_test.py b/tests/signals/signal_with_primitive_type_test.py
new file mode 100644
index 000000000..96ff353cc
--- /dev/null
+++ b/tests/signals/signal_with_primitive_type_test.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+import unittest
+from PySide.QtCore import *
+
+
+class SignalPrimitiveTypeTest(unittest.TestCase):
+
+ def signalValueChanged(self, v):
+ self.called = True
+ self._app.quit()
+
+ def createTimeLine(self):
+ self.called = False
+ tl = QTimeLine(10000)
+ QObject.connect(tl, SIGNAL("valueChanged(qreal)"), self.signalValueChanged)
+ return tl
+
+ def testTimeLine(self):
+ self._valueChangedCount = 0
+ self._app = QCoreApplication([])
+ tl = self.createTimeLine()
+ tl.start()
+ self._app.exec_()
+ self.assert_(self.called)
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/tests/signals/slot_reference_count_test.py b/tests/signals/slot_reference_count_test.py
new file mode 100644
index 000000000..62037f28c
--- /dev/null
+++ b/tests/signals/slot_reference_count_test.py
@@ -0,0 +1,54 @@
+
+''' Forced disconnection: Delete one end of the signal connection'''
+
+import unittest
+from sys import getrefcount
+
+from PySide.QtCore import QObject, SIGNAL, SLOT
+
+class Dummy(QObject):
+ def dispatch(self):
+ self.emit(SIGNAL('foo()'))
+
+class PythonSignalRefCount(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = Dummy()
+
+ def tearDown(self):
+ self.emitter
+
+ def testRefCount(self):
+ def cb(*args):
+ pass
+
+ self.assertEqual(getrefcount(cb), 2)
+
+ QObject.connect(self.emitter, SIGNAL('foo()'), cb)
+ self.assertEqual(getrefcount(cb), 3)
+
+ QObject.disconnect(self.emitter, SIGNAL('foo()'), cb)
+ self.assertEqual(getrefcount(cb), 2)
+
+class CppSignalRefCount(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = QObject()
+
+ def tearDown(self):
+ self.emitter
+
+ def testRefCount(self):
+ def cb(*args):
+ pass
+
+ self.assertEqual(getrefcount(cb), 2)
+
+ QObject.connect(self.emitter, SIGNAL('destroyed()'), cb)
+ self.assertEqual(getrefcount(cb), 3)
+
+ QObject.disconnect(self.emitter, SIGNAL('destroyed()'), cb)
+ self.assertEqual(getrefcount(cb), 2)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/signals/upstream_segfault_test.py b/tests/signals/upstream_segfault_test.py
new file mode 100644
index 000000000..793b04b1c
--- /dev/null
+++ b/tests/signals/upstream_segfault_test.py
@@ -0,0 +1,64 @@
+
+import unittest
+
+from PySide.QtCore import QObject, SIGNAL, SLOT
+
+# Upstream version of segfault_test
+
+class Dummy(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class Joe(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+class SegfaultCase(unittest.TestCase):
+ """Test case for the segfault happening when parent() is called inside
+ ProxyObject"""
+
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except:
+ pass
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testSegfault(self):
+ obj = Dummy()
+ QObject.connect(obj, SIGNAL('bar(int)'), self.callback)
+ self.args = (33,)
+ obj.emit(SIGNAL('bar(int)'), self.args[0])
+ self.assert_(self.called)
+
+ del obj
+ obj = Joe()
+ QObject.connect(obj, SIGNAL('bar(int)'), self.callback)
+ self.args = (33,)
+ obj.emit(SIGNAL('bar(int)'), self.args[0])
+ self.assert_(self.called)
+
+
+ def testSameReference(self):
+ """Example of how sip reuses an already used PyObject"""
+ obj = Dummy()
+ s1 = str(obj)
+ del obj
+ obj = Dummy()
+ s2 = str(obj)
+ self.assertEqual(s1, s2)
+
+ obj2 = Dummy()
+ s3 = str(obj2)
+ self.assertNotEqual(s2, s3)
+
+
+if __name__ == '__main__':
+ unittest.main()
+