diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-21 14:51:26 -0300 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-21 14:52:09 -0300 |
commit | 9af36fbb64f19842c0cc797c0b586b3a686805e8 (patch) | |
tree | 6bbc050ded0f85517ea75f5dc6dc1ed172168248 /tests/signals | |
parent | aa12538d63685ef8f75adaa79411b751929b727d (diff) |
Added all original pyside unit tests to the shiboken version.
Diffstat (limited to 'tests/signals')
-rw-r--r-- | tests/signals/args_dont_match.py | 21 | ||||
-rw-r--r-- | tests/signals/invalid_callback_test.py | 29 | ||||
-rw-r--r-- | tests/signals/lambda_test.py | 53 | ||||
-rw-r--r-- | tests/signals/multiple_connections_test.py | 65 | ||||
-rw-r--r-- | tests/signals/pysignal_test.py | 105 | ||||
-rw-r--r-- | tests/signals/qobject_destroyed_test.py | 23 | ||||
-rw-r--r-- | tests/signals/qobject_receivers_test.py | 48 | ||||
-rwxr-xr-x | tests/signals/qobject_sender_test.py | 91 | ||||
-rw-r--r-- | tests/signals/segfault_proxyparent_test.py | 73 | ||||
-rw-r--r-- | tests/signals/short_circuit_test.py | 66 | ||||
-rw-r--r-- | tests/signals/signal2signal_connect_test.py | 107 | ||||
-rw-r--r-- | tests/signals/signal_connectiontype_support.py | 28 | ||||
-rw-r--r-- | tests/signals/signal_emission_test.py | 123 | ||||
-rw-r--r-- | tests/signals/signal_func_test.py | 21 | ||||
-rw-r--r-- | tests/signals/signal_manager_refcount_test.py | 23 | ||||
-rw-r--r-- | tests/signals/signal_with_primitive_type_test.py | 29 | ||||
-rw-r--r-- | tests/signals/slot_reference_count_test.py | 54 | ||||
-rw-r--r-- | tests/signals/upstream_segfault_test.py | 64 |
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() + |