From 9af36fbb64f19842c0cc797c0b586b3a686805e8 Mon Sep 17 00:00:00 2001 From: Hugo Lima Date: Mon, 21 Sep 2009 14:51:26 -0300 Subject: Added all original pyside unit tests to the shiboken version. --- tests/CMakeLists.txt | 16 + tests/phonon/basic_playing_test.py | 60 ++++ tests/phonon/capabilities_test.py | 48 +++ tests/phonon/tone.ogg | Bin 0 -> 4300 bytes tests/qtcore/blocking_signals_test.py | 107 +++++++ tests/qtcore/child_event_test.py | 55 ++++ tests/qtcore/duck_punching_test.py | 56 ++++ tests/qtcore/missing_symbols_test.py | 16 + tests/qtcore/qbitarray_test.py | 100 ++++++ tests/qtcore/qbytearray_buffer_protocol_test.py | 25 ++ .../qbytearray_concatenation_operator_test.py | 52 +++ tests/qtcore/qbytearray_operator_test.py | 61 ++++ tests/qtcore/qbytearray_test.py | 43 +++ tests/qtcore/qcoreapplication_instance_test.py | 20 ++ tests/qtcore/qdatastream_test.py | 20 ++ tests/qtcore/qenum_test.py | 43 +++ tests/qtcore/qevent_test.py | 24 ++ tests/qtcore/qflags_test.py | 23 ++ tests/qtcore/qlocale_test.py | 26 ++ tests/qtcore/qmetaobject_test.py | 31 ++ tests/qtcore/qmodelindex_internalpointer_test.py | 50 +++ tests/qtcore/qobject_children_segfault_test.py | 29 ++ tests/qtcore/qobject_connect_notify_test.py | 70 +++++ tests/qtcore/qobject_event_filter_test.py | 80 +++++ tests/qtcore/qobject_inherits_test.py | 43 +++ tests/qtcore/qobject_parent_test.py | 234 ++++++++++++++ tests/qtcore/qobject_property_test.py | 54 ++++ tests/qtcore/qobject_protected_methods_test.py | 38 +++ tests/qtcore/qobject_test.py | 49 +++ tests/qtcore/qobject_timer_event_test.py | 44 +++ tests/qtcore/qobject_tr_as_instance_test.py | 55 ++++ tests/qtcore/qrect_test.py | 102 ++++++ tests/qtcore/qresource_test.py | 35 +++ tests/qtcore/qsize_test.py | 26 ++ tests/qtcore/qslot_object_test.py | 47 +++ tests/qtcore/qsrand_test.py | 16 + tests/qtcore/qstring_buffer_protocol_test.py | 25 ++ tests/qtcore/qstring_operator_test.py | 104 ++++++ tests/qtcore/qstring_qkeysequence_test.py | 18 ++ tests/qtcore/qstring_test.py | 106 +++++++ tests/qtcore/qstringlist_test.py | 165 ++++++++++ tests/qtcore/qtext_codec_test.py | 20 ++ tests/qtcore/qthread_prod_cons_test.py | 107 +++++++ tests/qtcore/qthread_signal_test.py | 64 ++++ tests/qtcore/qthread_test.py | 76 +++++ tests/qtcore/qtimer_singleshot_test.py | 49 +++ tests/qtcore/qtimer_timeout_test.py | 57 ++++ tests/qtcore/qtnamespace_test.py | 19 ++ tests/qtcore/quoteEnUS.txt | 1 + tests/qtcore/qurl_test.py | 91 ++++++ tests/qtcore/qvariant_test.py | 115 +++++++ tests/qtcore/resources.qrc | 6 + tests/qtcore/resources_mc.py | 39 +++ tests/qtcore/resources_mc.pyc | Bin 0 -> 896 bytes tests/qtcore/static_method_test.py | 18 ++ tests/qtcore/static_protected_methods_test.py | 30 ++ tests/qtcore/thread_signals.py | 39 +++ tests/qtcore/translation_test.py | 48 +++ tests/qtcore/translations/trans_latin.ts | 11 + tests/qtcore/translations/trans_russian.ts | 11 + tests/qtcore/unaryoperator_test.py | 38 +++ tests/qtcore/unicode_test.py | 33 ++ .../qtgui/float_to_int_implicit_conversion_test.py | 32 ++ tests/qtgui/grandparent_method_test.py | 23 ++ tests/qtgui/missing_symbols_test.py | 29 ++ tests/qtgui/paint_event_test.py | 71 +++++ tests/qtgui/parent_method_test.py | 25 ++ tests/qtgui/parent_policy_test.py | 37 +++ tests/qtgui/python_properties_test.py | 19 ++ tests/qtgui/qapp_test.py | 17 + tests/qtgui/qapplication_exit_segfault_test.py | 17 + tests/qtgui/qapplication_singleton_test.py | 12 + tests/qtgui/qbrush_test.py | 24 ++ tests/qtgui/qdatastream_gui_operators_test.py | 19 ++ tests/qtgui/qgraphicsitem_test.py | 35 +++ tests/qtgui/qgraphicsscene_test.py | 152 +++++++++ tests/qtgui/qlabel_pixmap_refcount.py | 46 +++ tests/qtgui/qlayout_ref_test.py | 96 ++++++ tests/qtgui/qlayout_test.py | 52 +++ tests/qtgui/qlcdnumber_test.py | 16 + tests/qtgui/qlistwidgetitem_test.py | 25 ++ tests/qtgui/qmainwindow_test.py | 32 ++ tests/qtgui/qmenu_test.py | 58 ++++ tests/qtgui/qpainter_test.py | 31 ++ tests/qtgui/qpixmap_test.py | 16 + tests/qtgui/qpushbutton_test.py | 30 ++ tests/qtgui/qregion_test.py | 21 ++ tests/qtgui/qshortcut_test.py | 41 +++ tests/qtgui/qstandarditemmodel_test.py | 26 ++ tests/qtgui/qstyle_test.py | 14 + tests/qtgui/qtabwidget_test.py | 21 ++ tests/qtgui/qtoolbar_test.py | 35 +++ tests/qtgui/qtoolbox_test.py | 31 ++ tests/qtgui/qvariant_test.py | 39 +++ tests/qtgui/qwidget_setlayout_test.py | 33 ++ tests/qtgui/qwidget_test.py | 18 ++ tests/qtgui/reference_count_test.py | 71 +++++ tests/qtgui/timed_app_test.py | 14 + tests/qtgui/virtual_protected_inheritance_test.py | 70 +++++ tests/qtgui/virtual_pure_override.py | 48 +++ tests/qtgui/x11_symbols.py | 17 + tests/qthelp/test_help.py | 14 + tests/qtnetwork/http_test.py | 48 +++ tests/qtnetwork/tcpserver_test.py | 25 ++ tests/qtnetwork/udpsocket_test.py | 54 ++++ tests/qtscript/test_base.py | 4 + tests/qtsql/qsqldatabaseandqueries_test.py | 56 ++++ tests/qtuitools/test_ui.py | 14 + tests/qtwebkit/fox.html | 6 + tests/qtwebkit/webpage_test.py | 54 ++++ tests/qtwebkit/webview_test.py | 48 +++ tests/run_test.sh | 13 + tests/signals/args_dont_match.py | 21 ++ tests/signals/invalid_callback_test.py | 29 ++ tests/signals/lambda_test.py | 53 ++++ tests/signals/multiple_connections_test.py | 65 ++++ tests/signals/pysignal_test.py | 105 +++++++ tests/signals/qobject_destroyed_test.py | 23 ++ tests/signals/qobject_receivers_test.py | 48 +++ tests/signals/qobject_sender_test.py | 91 ++++++ tests/signals/segfault_proxyparent_test.py | 73 +++++ tests/signals/short_circuit_test.py | 66 ++++ tests/signals/signal2signal_connect_test.py | 107 +++++++ tests/signals/signal_connectiontype_support.py | 28 ++ tests/signals/signal_emission_test.py | 123 ++++++++ tests/signals/signal_func_test.py | 21 ++ tests/signals/signal_manager_refcount_test.py | 23 ++ tests/signals/signal_with_primitive_type_test.py | 29 ++ tests/signals/slot_reference_count_test.py | 54 ++++ tests/signals/upstream_segfault_test.py | 64 ++++ tests/util/color.py | 12 + tests/util/helper.py | 120 +++++++ tests/util/helper.pyc | Bin 0 -> 5131 bytes tests/util/module_wrapper/PySide/QtAssistant.py | 2 + tests/util/module_wrapper/PySide/QtCore.py | 2 + tests/util/module_wrapper/PySide/QtDesigner.py | 2 + tests/util/module_wrapper/PySide/QtGui.py | 2 + tests/util/module_wrapper/PySide/QtHelp.py | 2 + tests/util/module_wrapper/PySide/QtNetwork.py | 2 + tests/util/module_wrapper/PySide/QtScript.py | 2 + tests/util/module_wrapper/PySide/QtSql.py | 2 + tests/util/module_wrapper/PySide/QtSvg.py | 2 + tests/util/module_wrapper/PySide/QtTest.py | 2 + tests/util/module_wrapper/PySide/QtWebKit.py | 2 + tests/util/module_wrapper/PySide/QtXml.py | 2 + tests/util/module_wrapper/PySide/QtXmlPatterns.py | 2 + tests/util/module_wrapper/PySide/__init__.py | 0 tests/util/module_wrapper/PySide/phonon.py | 2 + tests/util/processtimer.py | 49 +++ tests/util/pyqt_diff.py | 35 +++ tests/util/pyqtcheck.py | 46 +++ tests/util/rename_imports.sh | 13 + tests/util/test_processtimer.py | 66 ++++ tests/util/use_pyqt4.sh | 3 + tests/util/use_pyside.sh | 3 + tests/util/valgrind-python.supp | 349 +++++++++++++++++++++ 156 files changed, 6584 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/phonon/basic_playing_test.py create mode 100644 tests/phonon/capabilities_test.py create mode 100644 tests/phonon/tone.ogg create mode 100644 tests/qtcore/blocking_signals_test.py create mode 100644 tests/qtcore/child_event_test.py create mode 100644 tests/qtcore/duck_punching_test.py create mode 100644 tests/qtcore/missing_symbols_test.py create mode 100755 tests/qtcore/qbitarray_test.py create mode 100755 tests/qtcore/qbytearray_buffer_protocol_test.py create mode 100755 tests/qtcore/qbytearray_concatenation_operator_test.py create mode 100644 tests/qtcore/qbytearray_operator_test.py create mode 100644 tests/qtcore/qbytearray_test.py create mode 100755 tests/qtcore/qcoreapplication_instance_test.py create mode 100644 tests/qtcore/qdatastream_test.py create mode 100644 tests/qtcore/qenum_test.py create mode 100644 tests/qtcore/qevent_test.py create mode 100644 tests/qtcore/qflags_test.py create mode 100644 tests/qtcore/qlocale_test.py create mode 100644 tests/qtcore/qmetaobject_test.py create mode 100644 tests/qtcore/qmodelindex_internalpointer_test.py create mode 100644 tests/qtcore/qobject_children_segfault_test.py create mode 100644 tests/qtcore/qobject_connect_notify_test.py create mode 100644 tests/qtcore/qobject_event_filter_test.py create mode 100644 tests/qtcore/qobject_inherits_test.py create mode 100644 tests/qtcore/qobject_parent_test.py create mode 100644 tests/qtcore/qobject_property_test.py create mode 100644 tests/qtcore/qobject_protected_methods_test.py create mode 100644 tests/qtcore/qobject_test.py create mode 100644 tests/qtcore/qobject_timer_event_test.py create mode 100644 tests/qtcore/qobject_tr_as_instance_test.py create mode 100644 tests/qtcore/qrect_test.py create mode 100644 tests/qtcore/qresource_test.py create mode 100644 tests/qtcore/qsize_test.py create mode 100644 tests/qtcore/qslot_object_test.py create mode 100644 tests/qtcore/qsrand_test.py create mode 100755 tests/qtcore/qstring_buffer_protocol_test.py create mode 100644 tests/qtcore/qstring_operator_test.py create mode 100644 tests/qtcore/qstring_qkeysequence_test.py create mode 100644 tests/qtcore/qstring_test.py create mode 100644 tests/qtcore/qstringlist_test.py create mode 100644 tests/qtcore/qtext_codec_test.py create mode 100644 tests/qtcore/qthread_prod_cons_test.py create mode 100755 tests/qtcore/qthread_signal_test.py create mode 100644 tests/qtcore/qthread_test.py create mode 100644 tests/qtcore/qtimer_singleshot_test.py create mode 100644 tests/qtcore/qtimer_timeout_test.py create mode 100644 tests/qtcore/qtnamespace_test.py create mode 100644 tests/qtcore/quoteEnUS.txt create mode 100644 tests/qtcore/qurl_test.py create mode 100644 tests/qtcore/qvariant_test.py create mode 100644 tests/qtcore/resources.qrc create mode 100644 tests/qtcore/resources_mc.py create mode 100644 tests/qtcore/resources_mc.pyc create mode 100755 tests/qtcore/static_method_test.py create mode 100644 tests/qtcore/static_protected_methods_test.py create mode 100644 tests/qtcore/thread_signals.py create mode 100644 tests/qtcore/translation_test.py create mode 100644 tests/qtcore/translations/trans_latin.ts create mode 100644 tests/qtcore/translations/trans_russian.ts create mode 100755 tests/qtcore/unaryoperator_test.py create mode 100644 tests/qtcore/unicode_test.py create mode 100644 tests/qtgui/float_to_int_implicit_conversion_test.py create mode 100644 tests/qtgui/grandparent_method_test.py create mode 100644 tests/qtgui/missing_symbols_test.py create mode 100644 tests/qtgui/paint_event_test.py create mode 100644 tests/qtgui/parent_method_test.py create mode 100755 tests/qtgui/parent_policy_test.py create mode 100644 tests/qtgui/python_properties_test.py create mode 100644 tests/qtgui/qapp_test.py create mode 100644 tests/qtgui/qapplication_exit_segfault_test.py create mode 100644 tests/qtgui/qapplication_singleton_test.py create mode 100644 tests/qtgui/qbrush_test.py create mode 100644 tests/qtgui/qdatastream_gui_operators_test.py create mode 100644 tests/qtgui/qgraphicsitem_test.py create mode 100644 tests/qtgui/qgraphicsscene_test.py create mode 100644 tests/qtgui/qlabel_pixmap_refcount.py create mode 100644 tests/qtgui/qlayout_ref_test.py create mode 100644 tests/qtgui/qlayout_test.py create mode 100644 tests/qtgui/qlcdnumber_test.py create mode 100644 tests/qtgui/qlistwidgetitem_test.py create mode 100644 tests/qtgui/qmainwindow_test.py create mode 100644 tests/qtgui/qmenu_test.py create mode 100644 tests/qtgui/qpainter_test.py create mode 100644 tests/qtgui/qpixmap_test.py create mode 100644 tests/qtgui/qpushbutton_test.py create mode 100644 tests/qtgui/qregion_test.py create mode 100644 tests/qtgui/qshortcut_test.py create mode 100644 tests/qtgui/qstandarditemmodel_test.py create mode 100644 tests/qtgui/qstyle_test.py create mode 100644 tests/qtgui/qtabwidget_test.py create mode 100644 tests/qtgui/qtoolbar_test.py create mode 100644 tests/qtgui/qtoolbox_test.py create mode 100644 tests/qtgui/qvariant_test.py create mode 100644 tests/qtgui/qwidget_setlayout_test.py create mode 100644 tests/qtgui/qwidget_test.py create mode 100644 tests/qtgui/reference_count_test.py create mode 100644 tests/qtgui/timed_app_test.py create mode 100644 tests/qtgui/virtual_protected_inheritance_test.py create mode 100644 tests/qtgui/virtual_pure_override.py create mode 100644 tests/qtgui/x11_symbols.py create mode 100644 tests/qthelp/test_help.py create mode 100644 tests/qtnetwork/http_test.py create mode 100644 tests/qtnetwork/tcpserver_test.py create mode 100644 tests/qtnetwork/udpsocket_test.py create mode 100644 tests/qtscript/test_base.py create mode 100755 tests/qtsql/qsqldatabaseandqueries_test.py create mode 100644 tests/qtuitools/test_ui.py create mode 100644 tests/qtwebkit/fox.html create mode 100644 tests/qtwebkit/webpage_test.py create mode 100644 tests/qtwebkit/webview_test.py create mode 100755 tests/run_test.sh create mode 100644 tests/signals/args_dont_match.py create mode 100644 tests/signals/invalid_callback_test.py create mode 100644 tests/signals/lambda_test.py create mode 100644 tests/signals/multiple_connections_test.py create mode 100644 tests/signals/pysignal_test.py create mode 100644 tests/signals/qobject_destroyed_test.py create mode 100644 tests/signals/qobject_receivers_test.py create mode 100755 tests/signals/qobject_sender_test.py create mode 100644 tests/signals/segfault_proxyparent_test.py create mode 100644 tests/signals/short_circuit_test.py create mode 100644 tests/signals/signal2signal_connect_test.py create mode 100644 tests/signals/signal_connectiontype_support.py create mode 100644 tests/signals/signal_emission_test.py create mode 100644 tests/signals/signal_func_test.py create mode 100644 tests/signals/signal_manager_refcount_test.py create mode 100644 tests/signals/signal_with_primitive_type_test.py create mode 100644 tests/signals/slot_reference_count_test.py create mode 100644 tests/signals/upstream_segfault_test.py create mode 100644 tests/util/color.py create mode 100644 tests/util/helper.py create mode 100644 tests/util/helper.pyc create mode 100644 tests/util/module_wrapper/PySide/QtAssistant.py create mode 100644 tests/util/module_wrapper/PySide/QtCore.py create mode 100644 tests/util/module_wrapper/PySide/QtDesigner.py create mode 100644 tests/util/module_wrapper/PySide/QtGui.py create mode 100644 tests/util/module_wrapper/PySide/QtHelp.py create mode 100644 tests/util/module_wrapper/PySide/QtNetwork.py create mode 100644 tests/util/module_wrapper/PySide/QtScript.py create mode 100644 tests/util/module_wrapper/PySide/QtSql.py create mode 100644 tests/util/module_wrapper/PySide/QtSvg.py create mode 100644 tests/util/module_wrapper/PySide/QtTest.py create mode 100644 tests/util/module_wrapper/PySide/QtWebKit.py create mode 100644 tests/util/module_wrapper/PySide/QtXml.py create mode 100644 tests/util/module_wrapper/PySide/QtXmlPatterns.py create mode 100644 tests/util/module_wrapper/PySide/__init__.py create mode 100644 tests/util/module_wrapper/PySide/phonon.py create mode 100755 tests/util/processtimer.py create mode 100644 tests/util/pyqt_diff.py create mode 100755 tests/util/pyqtcheck.py create mode 100755 tests/util/rename_imports.sh create mode 100644 tests/util/test_processtimer.py create mode 100644 tests/util/use_pyqt4.sh create mode 100644 tests/util/use_pyside.sh create mode 100644 tests/util/valgrind-python.supp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..915c1664d --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,16 @@ + +file(GLOB TEST_FILES */*_test.py) + +foreach(test_file ${TEST_FILES}) + string(REGEX MATCH "/([^/]+)//?([^/]+)_test.py" test_name ${test_file} ) + add_test(${CMAKE_MATCH_1}_${CMAKE_MATCH_2} sh + ${CMAKE_CURRENT_SOURCE_DIR}/run_test.sh + "${pysidebase_BINARY_DIR}" + "${CMAKE_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}/util" + ${PYTHON_EXECUTABLE} + ${test_file}) + set_tests_properties(${CMAKE_MATCH_1}_${CMAKE_MATCH_2} PROPERTIES TIMEOUT 5) +# Should set python path here +# Looks like it's fixed in 2.8: +# http://www.vtk.org/Bug/print_bug_page.php?bug_id=7885 +endforeach(test_file ${TEST_FILES}) diff --git a/tests/phonon/basic_playing_test.py b/tests/phonon/basic_playing_test.py new file mode 100644 index 000000000..100a036c0 --- /dev/null +++ b/tests/phonon/basic_playing_test.py @@ -0,0 +1,60 @@ + +import os +import unittest + +from PySide import QtCore +from PySide import phonon + +from helper import UsesQCoreApplication + +# XXX Hack to get the correct filename +example_file = os.path.join(os.path.dirname(__file__),'tone.ogg') + +class TestSimplePlaying(UsesQCoreApplication): + def setUp(self): + super(TestSimplePlaying, self).setUp() + self.app.setApplicationName('Dummy') + self.source = phonon.Phonon.MediaSource(example_file) + self.media = phonon.Phonon.MediaObject() + self.media.setCurrentSource(self.source) + + QtCore.QObject.connect(self.media, + QtCore.SIGNAL('finished()'), + self.app, + QtCore.SLOT('quit()')) + + self.called = False + + def tearDown(self): + super(TestSimplePlaying, self).tearDown() + + def testFinishedSignal(self): + # Should pass if finished() is called + self.media.play() + self.app.exec_() + + def testMediaSource(self): + self.assertEqual(self.media.currentSource(), self.source) + + def testPathCreation(self): + output = phonon.Phonon.AudioOutput() + path = phonon.Phonon.createPath(self.media, output) + + # FIXME Both functions below are not exported by PyQt4 + self.assertEqual(path.sink(), output) + self.assertEqual(path.source(), self.media) + + def state_cb(self, newState, OldState): + self.called = True + + def testStateChanged(self): + QtCore.QObject.connect(self.media, + QtCore.SIGNAL('stateChanged(Phonon::State, Phonon::State)'), + self.state_cb) + + self.media.play() + self.app.exec_() + self.assert_(self.called) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/phonon/capabilities_test.py b/tests/phonon/capabilities_test.py new file mode 100644 index 000000000..5f4b7da83 --- /dev/null +++ b/tests/phonon/capabilities_test.py @@ -0,0 +1,48 @@ + +import unittest + +from PySide.QtCore import QString +from PySide import phonon + +from helper import UsesQCoreApplication + +class CapabilitiesTest(UsesQCoreApplication): + def setUp(self): + super(CapabilitiesTest, self).setUp() + self.app.setApplicationName("Dummy") + + def tearDown(self): + super(CapabilitiesTest, self).tearDown() + + + def testExists(self): + self.assert_(phonon.Phonon.BackendCapabilities) + + def testNotifierIdentity(self): + # Notifier is a singleton + self.assertEqual(phonon.Phonon.BackendCapabilities.notifier(), + phonon.Phonon.BackendCapabilities.notifier()) + + self.assert_(phonon.Phonon.BackendCapabilities.notifier() is + phonon.Phonon.BackendCapabilities.notifier()) + + def testDevices(self): + # TODO Improve this test + devices = phonon.Phonon.BackendCapabilities.availableAudioOutputDevices() + for device in devices: + self.assert_(isinstance(device, phonon.Phonon.AudioOutputDevice)) + + def testMimeTypes(self): + # TODO Improve this test + mimeTypes = phonon.Phonon.BackendCapabilities.availableMimeTypes() + for mime in mimeTypes: + self.assert_(isinstance(mime, QString)) + + def testAudioEffects(self): + # TODO Improve this test + effects = phonon.Phonon.BackendCapabilities.availableAudioEffects() + for effect in effects: + self.assert_(isinstance(effect, phonon.Phonon.EffectDescription)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/phonon/tone.ogg b/tests/phonon/tone.ogg new file mode 100644 index 000000000..dc1a455d3 Binary files /dev/null and b/tests/phonon/tone.ogg differ diff --git a/tests/qtcore/blocking_signals_test.py b/tests/qtcore/blocking_signals_test.py new file mode 100644 index 000000000..96582f6cc --- /dev/null +++ b/tests/qtcore/blocking_signals_test.py @@ -0,0 +1,107 @@ + +''' Test case for QObject.signalsBlocked() and blockSignal()''' + +import unittest +import os +from tempfile import mkstemp + +from PySide.QtCore import QObject, SIGNAL, QFile + +class TestSignalsBlockedBasic(unittest.TestCase): + '''Basic test case for signalsBlocked''' + + def testBasic(self): + '''QObject.signalsBlocked() and blockSignals() + The signals aren't blocked by default. + blockSignals returns the previous value''' + obj = QObject() + self.assert_(not obj.signalsBlocked()) + self.assert_(not obj.blockSignals(True)) + self.assert_(obj.signalsBlocked()) + self.assert_(obj.blockSignals(False)) + +class TestSignalsBlocked(unittest.TestCase): + '''Test case to check if the signals are really blocked''' + + def setUp(self): + #Set up the basic resources needed + self.obj = QObject() + self.args = tuple() + self.called = False + + def tearDown(self): + #Delete used resources + del self.obj + del self.args + + def callback(self, *args): + #Default callback + if args == self.args: + self.called = True + else: + raise TypeError("Invalid arguments") + + def testShortCircuitSignals(self): + #Blocking of Python short-circuit signals + QObject.connect(self.obj, SIGNAL('mysignal'), self.callback) + + self.obj.emit(SIGNAL('mysignal')) + self.assert_(self.called) + + self.called = False + self.obj.blockSignals(True) + self.obj.emit(SIGNAL('mysignal')) + self.assert_(not self.called) + + def testPythonSignals(self): + #Blocking of Python typed signals + QObject.connect(self.obj, SIGNAL('mysignal(int,int)'), self.callback) + self.args = (1, 3) + + self.obj.emit(SIGNAL('mysignal(int,int)'), *self.args) + self.assert_(self.called) + + self.called = False + self.obj.blockSignals(True) + self.obj.emit(SIGNAL('mysignal(int,int)'), *self.args) + self.assert_(not self.called) + +class TestQFileSignalBlocking(unittest.TestCase): + '''Test case for blocking the signal QIODevice.aboutToClose()''' + + def setUp(self): + #Set up the needed resources - A temp file and a QFile + self.called = False + handle, self.filename = mkstemp() + os.close(handle) + + self.qfile = QFile(self.filename) + + def tearDown(self): + #Release acquired resources + os.remove(self.filename) + del self.qfile + + def callback(self): + #Default callback + self.called = True + + def testAboutToCloseBlocking(self): + #QIODevice.aboutToClose() blocking + + QObject.connect(self.qfile, SIGNAL('aboutToClose()'), self.callback) + + self.assert_(self.qfile.open(QFile.ReadOnly)) + self.qfile.close() + self.assert_(self.called) + + self.called = False + self.qfile.blockSignals(True) + + self.assert_(self.qfile.open(QFile.ReadOnly)) + self.qfile.close() + self.assert_(not self.called) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/child_event_test.py b/tests/qtcore/child_event_test.py new file mode 100644 index 000000000..ccc27c848 --- /dev/null +++ b/tests/qtcore/child_event_test.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +'''Test case for QObject.childEvent and QTimer.childEvent overloading''' + +import unittest +from time import sleep +from PySide.QtCore import QObject, QTimer, QCoreApplication + +from helper import UsesQCoreApplication + +class ExtQObject(QObject): + def __init__(self): + QObject.__init__(self) + self.child_event_received = False + + def childEvent(self, event): + QObject.childEvent(self, event) + self.child_event_received = True + +class ExtQTimer(QTimer): + def __init__(self): + QTimer.__init__(self) + self.child_event_received = False + + def childEvent(self, event): + QTimer.childEvent(self, event) + self.child_event_received = True + + +class TestChildEvent(UsesQCoreApplication): + '''Test case for QObject::childEvent and QTimer::childEvent''' + + def setUp(self): + UsesQCoreApplication.setUp(self) + + def tearDown(self): + UsesQCoreApplication.tearDown(self) + + def testQObject(self): + parent = ExtQObject() + child = QObject() + child.setParent(parent) + print "parent seted" + #self.assert_(parent.child_event_received) + + """ + def testQTimer(self): + parent = ExtQTimer() + child = QObject() + child.setParent(parent) + self.assert_(parent.child_event_received) + """ + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/duck_punching_test.py b/tests/qtcore/duck_punching_test.py new file mode 100644 index 000000000..ddcf91d7b --- /dev/null +++ b/tests/qtcore/duck_punching_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +'''Test case for duck puching new implementations of C++ virtual methods into object instances.''' + +import unittest +import new +from PySide.QtCore import QObject +from helper import UsesQCoreApplication + +class Duck(QObject): + def __init__(self): + QObject.__init__(self) + def childEvent(self, event): + QObject.childEvent(self, event) + +class TestDuckPunchingOnQObjectInstance(UsesQCoreApplication): + '''Test case for duck puching new implementations of C++ virtual methods into object instances.''' + + def setUp(self): + #Acquire resources + self.duck_childEvent_called = False + UsesQCoreApplication.setUp(self) + + def tearDown(self): + #Release resources + del self.duck_childEvent_called + UsesQCoreApplication.tearDown(self) + + + def testChildEventMonkeyPatch(self): + #Test if the new childEvent injected on QObject instance is called from C++ + parent = QObject() + def childEvent(obj, event): + self.duck_childEvent_called = True + QObject.childEvent(obj, event) + parent.event = new.instancemethod(childEvent, parent, QObject) + child = QObject() + child.setParent(parent) + self.assert_(self.duck_childEvent_called) + + def testChildEventMonkeyPatchWithInheritance(self): + #Test if the new childEvent injected on a QObject's extension class instance is called from C++ + parent = Duck() + def childEvent(obj, event): + QObject.childEvent(obj, event) + self.duck_childEvent_called = True + child = QObject() + child.setParent(parent) + parent.event = new.instancemethod(childEvent, parent, QObject) + child = QObject() + child.setParent(parent) + self.assert_(self.duck_childEvent_called) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/missing_symbols_test.py b/tests/qtcore/missing_symbols_test.py new file mode 100644 index 000000000..f535c53d3 --- /dev/null +++ b/tests/qtcore/missing_symbols_test.py @@ -0,0 +1,16 @@ + +'''(Very) Simple test case for missing names from QtCore''' + +import unittest +from PySide import QtCore + +class MissingClasses(unittest.TestCase): + + def testQSettings(self): # Bug 232 + getattr(QtCore, 'QSettings') + + def testQtTrNoop(self): # Bug 220 + getattr(QtCore, 'QT_TR_NOOP') + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qbitarray_test.py b/tests/qtcore/qbitarray_test.py new file mode 100755 index 000000000..d68b4756d --- /dev/null +++ b/tests/qtcore/qbitarray_test.py @@ -0,0 +1,100 @@ +#!/usr/bin/python +'''Tests if QBitArray class is iterable and also '~' (__invert__) and bitwise operators''' + +import unittest + +from PySide.QtCore import QBitArray + +def bool_list_from_qbitarray(qbitarray): + '''This function is used instead of a list comprehension because + the QBitArray is being tested also to check if it is providing + the iterable protocol. + ''' + qbitarray_values = [] + for i in range(qbitarray.size()): + qbitarray_values.append(qbitarray.at(i)) + return qbitarray_values + +class QBitArrayIsIterableTest(unittest.TestCase): + '''Tests if QBitArray class is iterable and also '~' (__invert__) and bitwise operators''' + + def setUp(self): + #Acquire resources + self.qbitarray = QBitArray(3) + self.qbitarray_values = [True, False, False] + # WARNING: do not pythonify the following loop + for i in range(len(self.qbitarray_values)): + self.qbitarray.setBit(i, self.qbitarray_values[i]) + + self.inverted_qbitarray_values = [not bit for bit in self.qbitarray_values] + + self.other_qbitarray = QBitArray(3) + self.other_qbitarray_values = [True, True, False] + # WARNING: do not pythonify the following loop + for i in range(len(self.other_qbitarray_values)): + self.other_qbitarray.setBit(i, self.other_qbitarray_values[i]) + + def tearDown(self): + #Release resources + del self.qbitarray + del self.other_qbitarray + del self.qbitarray_values + del self.other_qbitarray_values + del self.inverted_qbitarray_values + + def testQBitArrayIsIterable(self): + #Tests if QBitArray class is iterable + qbitarray_is_iterable = True + try: + bitarray = [bit for bit in self.qbitarray] + except: + qbitarray_is_iterable = False + self.assertTrue(qbitarray_is_iterable) + + def testQBitArrayInvertOperator(self): + #Tests QBitArray '~' (__invert__) operator + inverted_qbitarray = ~self.qbitarray + # WARNING: do not pythonify the following loop, the + # iterability of QBitArray class is tested in another place + inverted_qbitarray_values = bool_list_from_qbitarray(inverted_qbitarray) + self.assertEqual(self.inverted_qbitarray_values, inverted_qbitarray_values) + + def testQBitArrayOrBitwiseOperator(self): + #Tests QBitArray '|' (or) operator + has_or_bitwise_operator = True + ored_qbitarray, ored_bool_list = None, None + try: + ored_qbitarray = self.qbitarray | self.other_qbitarray + ored_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)] + except: + has_or_bitwise_operator = False + self.assertTrue(has_or_bitwise_operator) + self.assertEqual(bool_list_from_qbitarray(ored_qbitarray), ored_bool_list) + + def testQBitArrayAndBitwiseOperator(self): + #Tests QBitArray '&' (and) operator + has_and_bitwise_operator = True + anded_qbitarray, anded_bool_list = None, None + try: + anded_qbitarray = self.qbitarray | self.other_qbitarray + anded_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)] + except: + has_and_bitwise_operator = False + self.assertTrue(has_and_bitwise_operator) + self.assertEqual(bool_list_from_qbitarray(anded_qbitarray), anded_bool_list) + + def testQBitArrayXorBitwiseOperator(self): + #Tests QBitArray '^' (xor) operator + has_xor_bitwise_operator = True + xored_qbitarray, xored_bool_list = None, None + try: + xored_qbitarray = self.qbitarray | self.other_qbitarray + xored_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)] + except: + has_xor_bitwise_operator = False + self.assertTrue(has_xor_bitwise_operator) + self.assertEqual(bool_list_from_qbitarray(xored_qbitarray), xored_bool_list) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qbytearray_buffer_protocol_test.py b/tests/qtcore/qbytearray_buffer_protocol_test.py new file mode 100755 index 000000000..6e81f1e03 --- /dev/null +++ b/tests/qtcore/qbytearray_buffer_protocol_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Tests QByteArray implementation of Python buffer protocol''' + +import unittest + +from os.path import isdir +from PySide.QtCore import QByteArray + +class QByteArrayBufferProtocolTest(unittest.TestCase): + '''Tests QByteArray implementation of Python buffer protocol''' + + def testQByteArrayBufferProtocol(self): + #Tests QByteArray implementation of Python buffer protocol using the os.path.isdir + #function which an unicode object or other object implementing the Python buffer protocol + os_path_isdir_function_correctly_called_with_a_qbytearray = True + try: + isdir(QByteArray('/tmp')) + except: + os_path_isdir_function_correctly_called_with_a_qbytearray = False + self.assertTrue(os_path_isdir_function_correctly_called_with_a_qbytearray) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qbytearray_concatenation_operator_test.py b/tests/qtcore/qbytearray_concatenation_operator_test.py new file mode 100755 index 000000000..201c8173c --- /dev/null +++ b/tests/qtcore/qbytearray_concatenation_operator_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QByteArray concatenation with '+' operator''' + +import unittest + +from PySide.QtCore import QByteArray + +class QByteArrayConcatenationOperatorTest(unittest.TestCase): + '''Test cases for QByteArray concatenation with '+' operator''' + + def testConcatQByteArrayAndPythonString(self): + #Test concatenation of a QByteArray with a Python string, in this order + concat_qbytearray_add_python_string_worked = True + qba = QByteArray('foo') + result = None + try: + result = qba + 'bar' + except: + concat_qbytearray_add_python_string_worked = False + self.assertTrue(concat_qbytearray_add_python_string_worked) + # NOTICE: the standard behavior of PyQt is to return a QString object + # for this case. As this is a minor issue the assertion will be left commented. + #self.assertEqual(result.__class__.__name__, 'QString') + + def testConcatPythonStringAndQByteArray(self): + #Test concatenation of a Python string with a QByteArray, in this order + concat_python_string_add_qbytearray_worked = True + qba = QByteArray('foo') + result = None + try: + result = 'bar' + qba + except: + concat_python_string_add_qbytearray_worked = False + self.assertTrue(concat_python_string_add_qbytearray_worked) + self.assertEqual(result.__class__.__name__, 'QByteArray') + + def testConcatPythonUnicodeAndQByteArray(self): + #Test concatenation of a Python unicode object with a QByteArray, in this order + concat_python_unicode_add_qbytearray_worked = True + qba = QByteArray('foo') + result = None + try: + result = u'ümlaut' + qba + except: + concat_python_unicode_add_qbytearray_worked = False + self.assertTrue(concat_python_unicode_add_qbytearray_worked) + self.assertEqual(result.__class__.__name__, 'unicode') + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qbytearray_operator_test.py b/tests/qtcore/qbytearray_operator_test.py new file mode 100644 index 000000000..3485026c1 --- /dev/null +++ b/tests/qtcore/qbytearray_operator_test.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QByteArray operators''' + +import unittest + +from PySide.QtCore import QByteArray, QString + +class QByteArrayOperatorEqual(unittest.TestCase): + '''TestCase for operator QByteArray == QByteArray''' + + def testDefault(self): + #QByteArray() == QByteArray() + obj1 = QByteArray() + obj2 = QByteArray() + self.assertEqual(obj1, obj2) + + def testSimple(self): + #QByteArray(some_string) == QByteArray(some_string) + string = 'egg snakes' + self.assertEqual(QByteArray(string), QByteArray(string)) + + def testPyString(self): + #QByteArray(string) == string + string = 'my test string' + self.assertEqual(QByteArray(string), string) + + def testQString(self): + #QByteArray(string) == QString(string) + string = 'another test string' + self.assertEqual(QByteArray(string), QString(string)) + +class QByteArrayOperatorAt(unittest.TestCase): + '''TestCase for operator QByteArray[]''' + + def testInRange(self): + #QByteArray[x] where x is a valid index + string = 'abcdefgh' + obj = QByteArray(string) + + for i in range(len(string)): + self.assertEqual(obj[i], string[i]) + + def testInRangeReverse(self): + #QByteArray[x] where x is a valid index (reverse order) + string = 'abcdefgh' + obj = QByteArray(string) + + for i in range(len(string)-1, 0, -1): + self.assertEqual(obj[i], string[i]) + + + def testOutOfRange(self): + #QByteArray[x] where x is out of index + string = '1234567' + obj = QByteArray(string) + self.assertRaises(IndexError, lambda :obj[len(string)]) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qbytearray_test.py b/tests/qtcore/qbytearray_test.py new file mode 100644 index 000000000..67f99f3d4 --- /dev/null +++ b/tests/qtcore/qbytearray_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +'''Unit tests for QByteArray''' + +import unittest +import ctypes +import sys + +from PySide.QtCore import QByteArray + +class QByteArrayTestToNumber(unittest.TestCase): + def testToNumberInt(self): + obj = QByteArray('37') + self.assertEqual(37, obj.toInt()[0]) + + def testToNumberFloat(self): + obj = QByteArray('37.109') + self.assertEqual(ctypes.c_float(37.109).value, + obj.toFloat()[0]) + + def testToNumberDouble(self): + obj = QByteArray('37.109') + self.assertEqual(ctypes.c_double(37.109).value, + obj.toDouble()[0]) + +class QByteArraySplit(unittest.TestCase): + '''Test case for QByteArray.split''' + + def testPathSeparator(self): + #QByteArray.split('/') + obj = QByteArray(unittest.__file__) + self.assertEqual(obj.split('/'), unittest.__file__.split('/')) + +class QByteArrayData(unittest.TestCase): + + '''Test case for QByteArray.data''' + + def testData(self): + url = QByteArray("http://web.openbossa.org/") + self.assertEqual(url.data(), "http://web.openbossa.org/") + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qcoreapplication_instance_test.py b/tests/qtcore/qcoreapplication_instance_test.py new file mode 100755 index 000000000..365148d34 --- /dev/null +++ b/tests/qtcore/qcoreapplication_instance_test.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QCoreApplication.instance static method''' + +import unittest + +from PySide.QtCore import QCoreApplication + +class QCoreApplicationInstanceTest(unittest.TestCase): + '''Test cases for QCoreApplication.instance static method''' + + def testQCoreApplicationInstance(self): + #Tests QCoreApplication.instance() + self.assertEqual(QCoreApplication.instance(), None) + app = QCoreApplication([]) + self.assertEqual(QCoreApplication.instance(), app) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qdatastream_test.py b/tests/qtcore/qdatastream_test.py new file mode 100644 index 000000000..d2fcb6d81 --- /dev/null +++ b/tests/qtcore/qdatastream_test.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +'''Unit tests for QDataStream''' + +import unittest + +from PySide.QtCore import QDataStream, QBuffer + +class QDataStreamTest(unittest.TestCase): + '''Test case for QByteArray.split''' + + def testWriteFunction(self): + b = QBuffer() + b.open(QBuffer.ReadWrite) + ds = QDataStream(b) + ds.writeUInt8(chr(True)) + self.assertEqual(b.buffer().at(0), chr(True)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qenum_test.py b/tests/qtcore/qenum_test.py new file mode 100644 index 000000000..99ede66b2 --- /dev/null +++ b/tests/qtcore/qenum_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +'''Test cases for QEnum and QFlags''' + +import unittest + +from PySide.QtCore import QIODevice, QString, Qt, QVariant + +class TestEnum(unittest.TestCase): + + def testToInt(self): + self.assertEqual(QIODevice.NotOpen, 0) + self.assertEqual(QIODevice.ReadOnly, 1) + self.assertEqual(QIODevice.WriteOnly, 2) + self.assertEqual(QIODevice.ReadWrite, 1 | 2) + self.assertEqual(QIODevice.Append, 4) + self.assertEqual(QIODevice.Truncate, 8) + self.assertEqual(QIODevice.Text, 16) + self.assertEqual(QIODevice.Unbuffered, 32) + + def testToIntInFunction(self): + self.assertEqual(QString.number(QIODevice.WriteOnly), "2") + +class TestQFlags(unittest.TestCase): + def testToItn(self): + om = QIODevice.OpenMode(QIODevice.NotOpen) + + self.assertEqual(om, QIODevice.NotOpen) + self.assertTrue(om == 0) + + self.assertTrue(om != QIODevice.ReadOnly) + self.assertTrue(om != 1) + + def testToIntInFunction(self): + om = QIODevice.OpenMode(QIODevice.WriteOnly) + self.assertEqual(QString.number(int(om)), "2") + +class TestDuplicatedValues(unittest.TestCase): + def testQVariant(self): + self.assertEqual(QVariant.LastCoreType, QVariant.Hash) + self.assertEqual(QVariant.LastGuiType, QVariant.Transform) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qevent_test.py b/tests/qtcore/qevent_test.py new file mode 100644 index 000000000..07f23f098 --- /dev/null +++ b/tests/qtcore/qevent_test.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +'''Test cases for QtCore.QEvent''' + +import unittest + +from PySide.QtCore import QEvent + +class QEventTypeFlag(unittest.TestCase): + '''Test case for usage of QEvent.Type flags''' + + def testFlagAccess(self): + #QEvent.Type flags usage + + event = QEvent(QEvent.Timer) + self.assertEqual(event.type(), QEvent.Timer) + + event = QEvent(QEvent.Close) + self.assertEqual(event.type(), QEvent.Close) + + event = QEvent(QEvent.IconTextChange) + self.assertEqual(event.type(), QEvent.IconTextChange) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qflags_test.py b/tests/qtcore/qflags_test.py new file mode 100644 index 000000000..6290926d7 --- /dev/null +++ b/tests/qtcore/qflags_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/python +'''Test cases for QFlags''' + +import unittest +from PySide.QtCore import * + +class QFLagTest(unittest.TestCase): + '''Test case for usage of flags''' + + def testCallFunction(self): + f = QFile("/tmp/t0"); + self.assertEqual(f.open(QIODevice.Truncate | QIODevice.Text | QIODevice.ReadWrite), True) + om = f.openMode() + self.assertEqual(om & QIODevice.Truncate, QIODevice.Truncate) + self.assertEqual(om & QIODevice.Text, QIODevice.Text) + self.assertEqual(om & QIODevice.ReadWrite, QIODevice.ReadWrite) + self.assert_(om == QIODevice.Truncate | QIODevice.Text | QIODevice.ReadWrite) + print (om != QIODevice.ReadOnly) + f.close() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qlocale_test.py b/tests/qtcore/qlocale_test.py new file mode 100644 index 000000000..e2fd49d19 --- /dev/null +++ b/tests/qtcore/qlocale_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +'''Unit tests for QLocale''' + +import unittest +import ctypes +import sys + +from PySide.QtCore import QLocale + +class QLocaleTestToNumber(unittest.TestCase): + def testToNumberInt(self): + obj = QLocale(QLocale.C) + self.assertEqual(37, obj.toInt('37')[0]) + + def testToNumberFloat(self): + obj = QLocale(QLocale.C) + self.assertEqual(ctypes.c_float(37.109).value, + obj.toFloat('37.109')[0]) + + def testToNumberDouble(self): + obj = QLocale(QLocale.C) + self.assertEqual(ctypes.c_double(37.109).value, + obj.toDouble('37.109')[0]) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qmetaobject_test.py b/tests/qtcore/qmetaobject_test.py new file mode 100644 index 000000000..457db087c --- /dev/null +++ b/tests/qtcore/qmetaobject_test.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Tests for static methos conflicts with class methods''' + +import unittest + +from PySide.QtCore import * + +class Foo(QFile): + pass + +class qmetaobject_test(unittest.TestCase): + def test_QMetaObject(self): + qobj = QObject() + qobj_metaobj = qobj.metaObject() + self.assertEqual(qobj_metaobj.className(), "QObject") + + obj = QFile() + m = obj.metaObject() + self.assertEqual(m.className(), "QFile") + self.assertNotEqual(m.methodCount(), qobj_metaobj.methodCount()) + + obj = Foo() + m = obj.metaObject() + self.assertEqual(m.className(), "Foo") + self.assertEqual(m.methodCount(), QFile().metaObject().methodCount()) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qmodelindex_internalpointer_test.py b/tests/qtcore/qmodelindex_internalpointer_test.py new file mode 100644 index 000000000..015d1c926 --- /dev/null +++ b/tests/qtcore/qmodelindex_internalpointer_test.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +''' Test case for QAbstractListModel.createIndex and QModelIndex.internalPointer''' + +import sys +import unittest +from PySide.QtCore import * + +class MyModel (QAbstractListModel): + pass + +class TestQModelIndexInternalPointer(unittest.TestCase): + ''' Test case for QAbstractListModel.createIndex and QModelIndex.internalPointer''' + + def setUp(self): + #Acquire resources + self.model = MyModel() + + def tearDown(self): + #Release resources + del self.model + + def testInternalPointer(self): + #Test QAbstractListModel.createIndex and + #QModelIndex.internalPointer with regular + #Python objects + idx = self.model.createIndex(0, 0, "Hello") + self.assertEqual("Hello", idx.internalPointer()) + a = [1, 2, 3] + idx = self.model.createIndex(0, 0, a) + self.assertEqual(a, idx.internalPointer()) + + def testReferenceCounting(self): + #Test reference counting when retrieving data with + #QModelIndex.internalPointer + a = [1, 2, 3] + a_refcnt = sys.getrefcount(a) + idx = self.model.createIndex(0, 0, a) + ptr = idx.internalPointer() + self.assertEqual(sys.getrefcount(a), a_refcnt + 1) + + def testIndexForDefaultDataArg(self): + #Test QAbstractListModel.createIndex with a default + #value for data argument + idx = self.model.createIndex(0, 0) + self.assertEqual(None, idx.internalPointer()) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qobject_children_segfault_test.py b/tests/qtcore/qobject_children_segfault_test.py new file mode 100644 index 000000000..930a082cf --- /dev/null +++ b/tests/qtcore/qobject_children_segfault_test.py @@ -0,0 +1,29 @@ + +'''Test cases for parent-child relationship''' + +import unittest + +from PySide.QtCore import QObject, QCoreApplication + +class ChildrenCoreApplication(unittest.TestCase): + '''Test case for calling QObject.children after creating a QCoreApp''' + + def testQCoreAppChildren(self): + #QObject.children() after creating a QCoreApplication + # Minimal test: + # 1- Create QCoreApp + # 2- Create parent and childrens + # 3- While keeping the children alive, call parent.children() + # 4- Delete parent + app = QCoreApplication([]) + parent = QObject() + children = [QObject(parent) for x in range(25)] + # Uncomment the lines below to make the test pass + # del children + # del child2 + del parent # XXX Segfaults here + self.assert_(True) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_connect_notify_test.py b/tests/qtcore/qobject_connect_notify_test.py new file mode 100644 index 000000000..441037585 --- /dev/null +++ b/tests/qtcore/qobject_connect_notify_test.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +''' Test case for QObject::connectNotify()''' + +import unittest +from PySide.QtCore import * +from helper import UsesQCoreApplication + +def cute_slot(): + pass + +class Obj(QObject): + def __init__(self): + QObject.__init__(self) + self.con_notified = False + self.dis_notified = False + + def connectNotify(self, signal): + self.con_notified = True + + def disconnectNotify(self, signal): + self.dis_notified = True + + def reset(self): + self.con_notified = False + self.dis_notified = False + +class TestQObjectConnectNotify(UsesQCoreApplication): + '''Test case for QObject::connectNotify''' + def setUp(self): + UsesQCoreApplication.setUp(self) + self.called = False + + def tearDown(self): + UsesQCoreApplication.tearDown(self) + + def testBasic(self): + sender = Obj() + receiver = QObject() + sender.connect(SIGNAL("destroyed()"), receiver, SLOT("deleteLater()")) + self.assert_(sender.con_notified) + sender.disconnect(SIGNAL("destroyed()"), receiver, SLOT("deleteLater()")) + self.assert_(sender.dis_notified) + + def testPySignal(self): + sender = Obj() + receiver = QObject() + sender.connect(SIGNAL("foo()"), receiver, SLOT("deleteLater()")) + self.assert_(sender.con_notified) + sender.disconnect(SIGNAL("foo()"), receiver, SLOT("deleteLater()")) + self.assert_(sender.dis_notified) + + def testPySlots(self): + sender = Obj() + receiver = QObject() + sender.connect(SIGNAL("destroyed()"), cute_slot) + self.assert_(sender.con_notified) + sender.disconnect(SIGNAL("destroyed()"), cute_slot) + self.assert_(sender.dis_notified) + + def testpyAll(self): + sender = Obj() + receiver = QObject() + sender.connect(SIGNAL("foo()"), cute_slot) + self.assert_(sender.con_notified) + sender.disconnect(SIGNAL("foo()"), cute_slot) + self.assert_(sender.dis_notified) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_event_filter_test.py b/tests/qtcore/qobject_event_filter_test.py new file mode 100644 index 000000000..8018fcda0 --- /dev/null +++ b/tests/qtcore/qobject_event_filter_test.py @@ -0,0 +1,80 @@ + +'''Test cases for QObject.eventFilter''' + +import unittest + +from PySide.QtCore import QObject, QTimerEvent + +from helper import UsesQCoreApplication + +class FilterObject(QObject): + '''Filter object for the basic test''' + def __init__(self, obj=None, event_type=None, *args): + #Creates a new filter object + QObject.__init__(self, *args) + self.obj = obj + self.event_type = event_type + self.events_handled = 0 + self.events_bypassed = 0 + + def setTargetObject(self, obj): + #Sets the object that will be filtered + self.obj = obj + + def eventFilter(self, obj, event): + '''Just checks if is the correct object and event type + incrementing counter until reaching the limit. After that it + stops filtering the events for the object.''' + if (self.obj == obj): + if isinstance(event, self.event_type) and self.events_handled < 5: + self.events_handled += 1 + return True + else: + self.events_bypassed += 1 + return False + else: + return QObject.eventFilter(self, obj, event) + +class FilteredObject(QObject): + '''Class that will be filtered. Quits the app after 5 timer events''' + def __init__(self, app, *args): + QObject.__init__(self, *args) + self.app = app + self.times_called = 0 + + def timerEvent(self, evt): + #Overriden method + self.times_called += 1 + + if self.times_called == 5: + self.app.quit() + +class TestQObjectEventFilterPython(UsesQCoreApplication): + '''QObject.eventFilter - Reimplemented in python + Filters 5 TimerEvents and then bypasses the other events to the + timerEvent method. After 5 runs, the timerEvent method will ask + the core application to exit''' + def setUp(self): + #Acquire resources + UsesQCoreApplication.setUp(self) + self.obj_filter = FilterObject(event_type=QTimerEvent) + def tearDown(self): + #Release resources + del self.obj_filter + UsesQCoreApplication.tearDown(self) + + def testEventFilter(self): + #QObject.eventFilter reimplemented in python + filtered = FilteredObject(self.app) + filtered.installEventFilter(self.obj_filter) + self.obj_filter.setTargetObject(filtered) + + filtered.startTimer(0) + + self.app.exec_() + + self.assertEqual(filtered.times_called, 5) + self.assertEqual(self.obj_filter.events_handled, 5) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_inherits_test.py b/tests/qtcore/qobject_inherits_test.py new file mode 100644 index 000000000..9e02b0a46 --- /dev/null +++ b/tests/qtcore/qobject_inherits_test.py @@ -0,0 +1,43 @@ +'''Test cases for QObject methods''' + +import unittest + +from PySide.QtCore import QObject + +class InheritsCase(unittest.TestCase): + '''Test case for QObject.inherits''' + + def testCppInheritance(self): + #QObject.inherits() for c++ classes + #An class inherits itself + self.assert_(QObject().inherits('QObject')) + + def testPythonInheritance(self): + #QObject.inherits() for python classes + + class Dummy(QObject): + #Dummy class + pass + + self.assert_(Dummy().inherits('QObject')) + self.assert_(Dummy().inherits('Dummy')) + self.assert_(not Dummy().inherits('FooBar')) + + def testPythonMultiInheritance(self): + #QObject.inherits() for multiple inheritance + # QObject.inherits(classname) should fail if classname isn't a + # QObject subclass + + class Parent(object): + #Dummy parent + pass + class Dummy(QObject, Parent): + #Dummy class + pass + + self.assert_(Dummy().inherits('QObject')) + self.assert_(not Dummy().inherits('Parent')) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_parent_test.py b/tests/qtcore/qobject_parent_test.py new file mode 100644 index 000000000..4699fc60c --- /dev/null +++ b/tests/qtcore/qobject_parent_test.py @@ -0,0 +1,234 @@ + +'''Test cases for parent-child relationship''' + +import unittest +from sys import getrefcount + +from PySide.QtCore import QObject, QTimer + +class ParentRefCountCase(unittest.TestCase): + '''Test case for the refcount changes of setParent''' + + def setUp(self): + #Acquire resources + self.parent = QObject() + self.child = QObject() + + def tearDown(self): + #Release resources + del self.child + del self.parent + + def testSetParent(self): + #QObject.setParent() refcount changes + self.assertEqual(getrefcount(self.child), 2) + self.child.setParent(self.parent) + self.assertEqual(getrefcount(self.child), 3) + + def testConstructor(self): + #QObject(QObject) refcount changes + child = QObject(self.parent) + self.assertEqual(getrefcount(child), 3) + +class ParentCase(unittest.TestCase): + '''Small collection of tests related to parent-child relationship''' + + def testSetParent(self): + #QObject.setParent() + parent = QObject() + child = QObject() + child.setParent(parent) + + self.assertEqual(parent, child.parent()) + + def testParentConstructor(self): + #QObject(parent) + parent = QObject() + child = QObject(parent) + + self.assertEqual(parent, child.parent()) + + orig_repr = repr(child) + del child + self.assertEqual(orig_repr, repr(parent.children()[0])) + + def testChildren(self): + #QObject.children() + parent = QObject() + children = [QObject(parent) for x in range(25)] + + self.assertEqual(parent.children(), children) + + def testFindChild(self): + #QObject.findChild() with all QObject + parent = QObject() + name = 'object%d' + children = [QObject(parent) for i in range(20)] + + for i, child in enumerate(children): + child.setObjectName(name % i) + + for i, child in enumerate(children): + self.assertEqual(child, parent.findChild(QObject, name % i)) + + def testFindChildren(self): + #QObject.findChildren() with all QObject + parent = QObject() + target_name = 'foo' + children = [QTimer(parent) for i in range(20)] + children.extend([QObject(parent) for i in range(20)]) + + for i, child in enumerate(children): + if i % 5 == 0: + child.setObjectName(target_name) + else: + child.setObjectName(str(i)) + + # Emulates findChildren with the intended outcome + target_children = [x for x in children if x.objectName() == target_name] + test_children = parent.findChildren(QObject, target_name) + + self.assertEqual(sorted(target_children), sorted(test_children)) + + def testParentEquality(self): + #QObject.parent() == parent + parent = QObject() + child = QObject(parent) + self.assertEqual(parent, child.parent()) + + +class TestParentOwnership(unittest.TestCase): + '''Test case for Parent/Child object ownership''' + + def testParentDestructor(self): + parent = QObject() + self.assertEqual(getrefcount(parent), 2) + + child = QObject(parent) + self.assertEqual(getrefcount(child), 3) + self.assertEqual(getrefcount(parent), 2) + + del parent + self.assertEqual(getrefcount(child), 2) + + # this will fail because parent deleted child cpp object + self.assertRaises(RuntimeError, lambda :child.objectName()) + + # test parent with multiples children + def testMultipleChildren(self): + o = QObject() + self.assertEqual(getrefcount(o), 2) + + c = QObject(o) + self.assertEqual(getrefcount(c), 3) + self.assertEqual(getrefcount(o), 2) + + c2 = QObject(o) + self.assertEqual(getrefcount(o), 2) + self.assertEqual(getrefcount(c), 3) + self.assertEqual(getrefcount(c2), 3) + + del o + self.assertEqual(getrefcount(c), 2) + self.assertEqual(getrefcount(c2), 2) + + # this will fail because parent deleted child cpp object + self.assertRaises(RuntimeError, lambda :c.objectName()) + self.assertRaises(RuntimeError, lambda :c2.objectName()) + + # test recursive parent + def testRecursiveParent(self): + o = QObject() + self.assertEqual(getrefcount(o), 2) + + c = QObject(o) + self.assertEqual(getrefcount(c), 3) + self.assertEqual(getrefcount(o), 2) + + c2 = QObject(c) + self.assertEqual(getrefcount(o), 2) + self.assertEqual(getrefcount(c), 3) + self.assertEqual(getrefcount(c2), 3) + + del o + self.assertEqual(getrefcount(c), 2) + self.assertEqual(getrefcount(c2), 2) + + # this will fail because parent deleted child cpp object + self.assertRaises(RuntimeError, lambda :c.objectName()) + self.assertRaises(RuntimeError, lambda :c2.objectName()) + + # test parent transfer + def testParentTransfer(self): + o = QObject() + self.assertEqual(getrefcount(o), 2) + + c = QObject() + self.assertEqual(getrefcount(c), 2) + + c.setParent(o) + self.assertEqual(getrefcount(c), 3) + + c.setParent(None) + self.assertEqual(getrefcount(c), 2) + + del c + del o + + +class ExtQObject(QObject): + def __init__(self): + QObject.__init__(self) + +class ReparentingTest(unittest.TestCase): + '''Test cases for reparenting''' + + def testParentedQObjectIdentity(self): + object_list = [] + parent = QObject() + for i in range(3): + obj = QObject() + object_list.append(obj) + obj.setParent(parent) + for child in parent.children(): + self.assert_(child in object_list) + + def testParentedExtQObjectType(self): + object_list = [] + parent = QObject() + for i in range(3): + obj = ExtQObject() + object_list.append(obj) + obj.setParent(parent) + for orig, child in zip(object_list, parent.children()): + self.assertEqual(type(orig), type(child)) + + def testReparentedQObjectIdentity(self): + object_list = [] + old_parent = QObject() + new_parent = QObject() + for i in range(3): + obj = QObject() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for child in new_parent.children(): + self.assert_(child in object_list) + + def testReparentedExtQObjectType(self): + object_list = [] + old_parent = QObject() + new_parent = QObject() + for i in range(3): + obj = ExtQObject() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for orig, child in zip(object_list, new_parent.children()): + self.assertEqual(type(orig), type(child)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_property_test.py b/tests/qtcore/qobject_property_test.py new file mode 100644 index 000000000..ecf101906 --- /dev/null +++ b/tests/qtcore/qobject_property_test.py @@ -0,0 +1,54 @@ + +'''Test cases for QObject property and setProperty''' + +import unittest + +from PySide.QtCore import QObject, QVariant + +class PropertyCase(unittest.TestCase): + '''Test case for QObject properties''' + + def testObjectNameProperty(self): + #QObject.setProperty() for existing C++ property + obj = QObject() + self.assert_(obj.setProperty('objectName', QVariant('dummy'))) + self.assertEqual(obj.objectName(), 'dummy') + + self.assert_(obj.setProperty('objectName', QVariant('foobar'))) + self.assertEqual(obj.objectName(), 'foobar') + + def testDynamicProperty(self): + #QObject.setProperty() for dynamic properties + obj = QObject() + + # Should return false when creating a new dynamic property + self.assert_(not obj.setProperty('dummy', QVariant('mydata'))) + prop = obj.property('dummy') + self.assert_(isinstance(prop, QVariant)) + self.assert_(prop.isValid()) + self.assertEqual(obj.property('dummy').toString(), 'mydata') + + self.assert_(not obj.setProperty('dummy', QVariant('zigzag'))) + prop = obj.property('dummy') + self.assert_(isinstance(prop, QVariant)) + self.assert_(prop.isValid()) + self.assertEqual(obj.property('dummy').toString(), 'zigzag') + + self.assert_(not obj.setProperty('dummy', QVariant(42))) + prop = obj.property('dummy') + self.assert_(isinstance(prop, QVariant)) + self.assert_(prop.isValid()) + # QVariant.toInt has a bool* arg in C++, so returns a tuple + self.assertEqual(obj.property('dummy').toInt(), (42, True)) + + + def testInvalidProperty(self): + #QObject.property() for invalid properties + obj = QObject() + + prop = obj.property('dummy') + self.assert_(not prop.isValid()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_protected_methods_test.py b/tests/qtcore/qobject_protected_methods_test.py new file mode 100644 index 000000000..37bda37bc --- /dev/null +++ b/tests/qtcore/qobject_protected_methods_test.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +'''Test cases for QObject protected methods''' + +import unittest + +from PySide.QtCore import QObject, QThread, SIGNAL + +class Dummy(QObject): + '''Dummy class''' + pass + +class QObjectReceivers(unittest.TestCase): + '''Test case for QObject.receivers()''' + + def cb(self, *args): + #Dummy callback + pass + + def testQObjectReceiversExtern(self): + #QObject.receivers() - Protected method external access + + obj = Dummy() + self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 0) + + QObject.connect(obj, SIGNAL("destroyed()"), self.cb) + self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 1) + + def testQThreadReceiversExtern(self): + #QThread.receivers() - Inherited protected method + + obj = QThread() + self.assertEqual(obj.receivers(SIGNAL('destroyed()')), 0) + QObject.connect(obj, SIGNAL("destroyed()"), self.cb) + self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 1) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_test.py b/tests/qtcore/qobject_test.py new file mode 100644 index 000000000..848cce361 --- /dev/null +++ b/tests/qtcore/qobject_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QObject methods''' + +import unittest + +from PySide.QtCore import QObject + +class ObjectNameCase(unittest.TestCase): + '''Tests related to QObject object name''' + + def testSimple(self): + #QObject.objectName(string) + name = 'object1' + obj = QObject() + obj.setObjectName(name) + + self.assertEqual(name, obj.objectName()) + + def testEmpty(self): + #QObject.objectName('') + name = '' + obj = QObject() + obj.setObjectName(name) + + self.assertEqual(name, obj.objectName()) + + def testNone(self): + #QObject.objectName(None) + obj = QObject() + + self.assertRaises(TypeError, obj.setObjectName, None) + + def testDefault(self): + #QObject.objectName() default + obj = QObject() + self.assertEqual('', obj.objectName()) + + def testUnicode(self): + #QObject.setObjectName(unicode) + name = u'diseño' + #FIXME Strange error on upstream when using equal(name, obj) + obj = QObject() + obj.setObjectName(name) + self.assertEqual(obj.objectName(), name) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_timer_event_test.py b/tests/qtcore/qobject_timer_event_test.py new file mode 100644 index 000000000..b46207d88 --- /dev/null +++ b/tests/qtcore/qobject_timer_event_test.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +'''Test case for QObject.timerEvent overloading''' + +import unittest +from time import sleep +from PySide.QtCore import QObject, QCoreApplication + +from helper import UsesQCoreApplication + +class Dummy(QObject): + + def __init__(self, app): + super(Dummy, self).__init__() + self.times_called = 0 + self.app = app + + def timerEvent(self, event): + QObject.timerEvent(self, event) + event.accept() + self.times_called += 1 + + if self.times_called == 5: + self.app.exit(0) + +class QObjectTimerEvent(UsesQCoreApplication): + + def setUp(self): + #Acquire resources + super(QObjectTimerEvent, self).setUp() + + def tearDown(self): + #Release resources + super(QObjectTimerEvent, self).tearDown() + + def testTimerEvent(self): + #QObject.timerEvent overloading + obj = Dummy(self.app) + timer_id = obj.startTimer(200) + self.app.exec_() + obj.killTimer(timer_id) + self.assertEqual(obj.times_called, 5) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qobject_tr_as_instance_test.py b/tests/qtcore/qobject_tr_as_instance_test.py new file mode 100644 index 000000000..5aa70530b --- /dev/null +++ b/tests/qtcore/qobject_tr_as_instance_test.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +'''Unit tests for QObject's tr and trUtf8 static methods.''' + +import os +import unittest +from PySide.QtCore import QObject + +#from helper import UsesQCoreApplication + +class QObjectTrTest(unittest.TestCase): + '''Test case to check if QObject tr and trUtf8 static methods could be treated as instance methods.''' + + def setUp(self): + self.obj = QObject() + + def tearDown(self): + del self.obj + + def testTrCommonCase(self): + #Test common case for QObject.tr + invar1 = 'test1' + outvar1 = self.obj.tr(invar1) + invar2 = 'test2' + outvar2 = self.obj.tr(invar2, 'test comment') + self.assertEqual((invar1, invar2), (outvar1, outvar2)) + + def testTrAsInstanceMethod(self): + #Test QObject.tr as instance + invar1 = 'test1' + outvar1 = QObject.tr(self.obj, invar1) + invar2 = 'test2' + outvar2 = QObject.tr(self.obj, invar2, 'test comment') + self.assertEqual((invar1, invar2), (outvar1, outvar2)) + + def testTrUtf8CommonCase(self): + #Test common case for QObject.trUtf8 + invar1 = 'test1' + outvar1 = self.obj.trUtf8(invar1) + invar2 = 'test2' + outvar2 = self.obj.trUtf8(invar2, 'test comment') + self.assertEqual((invar1, invar2), (outvar1, outvar2)) + + def testTrUtf8AsInstanceMethod(self): + #Test QObject.trUtf8 as instance + invar1 = 'test1' + outvar1 = QObject.trUtf8(self.obj, invar1) + invar2 = 'test2' + outvar2 = QObject.trUtf8(self.obj, invar2, 'test comment') + self.assertEqual((invar1, invar2), (outvar1, outvar2)) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qrect_test.py b/tests/qtcore/qrect_test.py new file mode 100644 index 000000000..3c5f5be05 --- /dev/null +++ b/tests/qtcore/qrect_test.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +'''Test cases for QRect''' + +import unittest + +from PySide.QtCore import QPoint, QRect + +class RectConstructor(unittest.TestCase): + + def testDefault(self): + #QRect() + obj = QRect() + + self.assert_(obj.isNull()) + + def testConstructorQPoint(self): + topLeft = QPoint(3, 0) + bottomRight = QPoint(0, 3) + + rect1 = QRect(topLeft, bottomRight) + rect2 = QRect(topLeft, bottomRight) + + self.assertEqual(rect1, rect2) + +class RectOperator(unittest.TestCase): + '''Test case for QRect operators''' + + def testEqual(self): + '''QRect == QRect + Note: operator == must be working as it's the main check + for correctness''' + rect1 = QRect() + rect2 = QRect() + self.assertEqual(rect1, rect2) + + rect1 = QRect(0, 4, 100, 300) + rect2 = QRect(0, 4, 100, 300) + self.assertEqual(rect1, rect2) + + def testNullRectIntersection(self): + #QRect & QRect for null rects + rect1 = QRect() + rect2 = QRect() + rect3 = rect1 & rect2 + self.assertEqual(rect3, rect1) + self.assertEqual(rect3, rect2) + + def testNoIntersect(self): + '''QRect & QRect for non-intersecting QRects + Non-intersecting QRects return a 'null' QRect for operator &''' + rect1 = QRect(10, 10, 5, 5) + rect2 = QRect(20, 20, 5, 5) + rect3 = rect1 & rect2 + self.assertEqual(rect3, QRect()) + + def testIntersectPartial(self): + #QRect & QRect for partial intersections + rect1 = QRect(10, 10, 10, 10) + rect2 = QRect(15, 15, 10, 10) + rect3 = rect1 & rect2 + self.assertEqual(rect3, QRect(15, 15, 5, 5)) + + def testIntersetEnclosed(self): + #QRect & QRect for a qrect inside another + rect1 = QRect(10, 10, 20, 20) + rect2 = QRect(15, 15, 5, 5) + rect3 = rect1 & rect2 + self.assertEqual(rect3, rect2) + + def testNullRectIntersectBounding(self): + #QRect | QRect for null rects + rect1 = QRect() + rect2 = QRect() + rect3 = rect1 & rect2 + self.assertEqual(rect3, rect1) + self.assertEqual(rect3, rect2) + + def testNoIntersectBounding(self): + '''QRect | QRect for non-intersecting QRects + Non-intersecting QRects return a greater QRect for operator |''' + rect1 = QRect(10, 10, 5, 5) + rect2 = QRect(20, 20, 5, 5) + rect3 = rect1 | rect2 + self.assertEqual(rect3, QRect(10, 10, 15, 15)) + + def testBoundingPartialIntersection(self): + #QRect | QRect for partial intersections + rect1 = QRect(10, 10, 10, 10) + rect2 = QRect(15, 15, 10, 10) + rect3 = rect1 | rect2 + self.assertEqual(rect3, QRect(10, 10, 15, 15)) + + def testBoundingEnclosed(self): + #QRect | QRect for a qrect inside another + rect1 = QRect(10, 10, 20, 20) + rect2 = QRect(15, 15, 5, 5) + rect3 = rect1 | rect2 + self.assertEqual(rect3, rect1) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qresource_test.py b/tests/qtcore/qresource_test.py new file mode 100644 index 000000000..7fef29e01 --- /dev/null +++ b/tests/qtcore/qresource_test.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +'''Test cases for QResource usage''' + +import unittest +import os +from PySide.QtCore import QFile, QIODevice +import resources_mc + +class ResourcesUsage(unittest.TestCase): + '''Test case for resources usage''' + + def setUp(self): + try: + f = open('quoteEnUS.txt') + except IOError: + f = open(os.path.join('qtcore', 'quoteEnUS.txt')) + + self.text = f.read() + f.close() + + def tearDown(self): + self.text = None + + def testPhrase(self): + #Test loading of quote.txt resource + f = QFile(':/quote.txt') + f.open(QIODevice.ReadOnly|QIODevice.Text) + content = f.readAll() + f.close() + self.assertEqual(self.text, content) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qsize_test.py b/tests/qtcore/qsize_test.py new file mode 100644 index 000000000..4fb060b74 --- /dev/null +++ b/tests/qtcore/qsize_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +'''Unit tests for QSize''' + +import unittest + +from PySide.QtCore import QSize + +class QSizeOperator(unittest.TestCase): + def testOperatorMultiply(self): + #QSize operator * float + # bug 131 + a = QSize(1, 1) + x = a * 3.4 + self.assertEqual(QSize(3, 3), x) + + def testOperatorRevertedMultiply(self): + #QSize operator * float, reverted + # bug 132 + a = QSize(1, 1) + x = 3.4 * a + self.assertEqual(QSize(3, 3), x) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qslot_object_test.py b/tests/qtcore/qslot_object_test.py new file mode 100644 index 000000000..862541b0b --- /dev/null +++ b/tests/qtcore/qslot_object_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +import unittest +from PySide import QtCore + +global qApp + +class objTest(QtCore.QObject): + + def __init__(self, parent=None): + QtCore.QObject.__init__(self, parent) + + self.ok = False + + def slot(self): + global qApp + + self.ok = True + qApp.quit() + + + +class slotTest(unittest.TestCase): + def quit_app(self): + global qApp + + qApp.quit() + + def testBasic(self): + global qApp + timer = QtCore.QTimer() + timer.setInterval(100) + + my_obj = objTest() + my_slot = QtCore.SLOT("slot()") + timer.connect(QtCore.SIGNAL("timeout()"), my_obj, my_slot) + timer.start(100) + + QtCore.QTimer.singleShot(1000, self.quit_app) + qApp.exec_() + + self.assert_(my_obj.ok) + + +if __name__ == '__main__': + global qApp + qApp = QtCore.QCoreApplication([]) + unittest.main() diff --git a/tests/qtcore/qsrand_test.py b/tests/qtcore/qsrand_test.py new file mode 100644 index 000000000..97d0a3b0b --- /dev/null +++ b/tests/qtcore/qsrand_test.py @@ -0,0 +1,16 @@ +import gc +import unittest + +from PySide.QtCore import qsrand + +class OverflowExceptionCollect(unittest.TestCase): + '''Test case for OverflowError exception during garbage collection. See bug #147''' + + def testOverflow(self): + # NOTE: PyQt4 raises TypeError, but boost.python raises OverflowError + self.assertRaises(OverflowError, qsrand, 42415335332353253) + # should not abort if bug #147 is fixed + gc.collect() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qstring_buffer_protocol_test.py b/tests/qtcore/qstring_buffer_protocol_test.py new file mode 100755 index 000000000..6ce6167dc --- /dev/null +++ b/tests/qtcore/qstring_buffer_protocol_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Tests QString implementation of Python buffer protocol''' + +import unittest + +from os.path import isdir +from PySide.QtCore import QString + +class QStringBufferProtocolTest(unittest.TestCase): + '''Tests QString implementation of Python buffer protocol''' + + def testQStringBufferProtocol(self): + #Tests QString implementation of Python buffer protocol using the os.path.isdir + #function which an unicode object or other object implementing the Python buffer protocol + os_path_isdir_function_correctly_called_with_a_qstring = True + try: + isdir(QString('/tmp')) + except: + os_path_isdir_function_correctly_called_with_a_qstring = False + self.assertTrue(os_path_isdir_function_correctly_called_with_a_qstring) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qstring_operator_test.py b/tests/qtcore/qstring_operator_test.py new file mode 100644 index 000000000..0174fdbce --- /dev/null +++ b/tests/qtcore/qstring_operator_test.py @@ -0,0 +1,104 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QString operators''' + +import unittest + +from PySide.QtCore import QString, QByteArray + +class QStringOperatorEqual(unittest.TestCase): + '''TestCase for operator QString == QString''' + + def testDefault(self): + #QString() == QString() + obj1 = QString() + obj2 = QString() + self.assertEqual(obj1, obj2) + + def testSimple(self): + #QString(some_string) == QString(some_string) + string = 'egg snakes' + self.assertEqual(QString(string), QString(string)) + + def testUnicode(self): + #QString(unicode) == QString(unicode) + string = u'àâãá' + self.assertEqual(QString(string), QString(string)) + + def testPyString(self): + #QString(string) == string + string = 'my test string' + self.assertEqual(QString(string), string) + self.assertEqual(string, QString(string)) + + def testPyUnicodeString(self): + #QString(unicode) == unicode + string = u'àâãá' + self.assertEqual(QString(string), string) + self.assertEqual(string, unicode(QString(string))) + + def testQByteArray(self): + #QString(string) == QByteArray(string) + string = 'another test string' + self.assertEqual(QString(string), QByteArray(string)) + +class QStringOperatorAt(unittest.TestCase): + '''TestCase for operator QString[]''' + + def testInRange(self): + #QString[x] where x is a valid index + string = 'abcdefgh' + obj = QString(string) + + for i in range(len(string)): + self.assertEqual(obj[i], string[i]) + + def testInRangeReverse(self): + #QString[x] where x is a valid index (reverse order) + string = 'abcdefgh' + obj = QString(string) + + for i in range(len(string)-1, 0, -1): + self.assertEqual(obj[i], string[i]) + + + def testInRangeUnicode(self): + #QString[x] where x is a valid index (unicode) + string = u'àâãá' + obj = QString(string) + + for i in range(len(string)): + self.assertEqual(obj[i], string[i]) + + def testInRangeUnicodeReverse(self): + #QString[x] where x is a valid index (unicode) (reverse order) + string = u'àâãá' + obj = QString(string) + + for i in range(len(string)-1, 0, -1): + self.assertEqual(obj[i], string[i]) + + def testOutOfRange(self): + #QString[x] where x is out of index + string = '1234567' + obj = QString(string) + self.assertRaises(IndexError, lambda :obj[len(string)]) + + def testReturnQString(self): + #QString[x] must return a QString + string = QString('123456') + data = string[0] + self.assert_(isinstance(data, QString)) + +class QStringOperatorAdd(unittest.TestCase): + '''TestCase for operator QString[]''' + + def testOperatorAdd(self): + str1 = '123' + str2 = QString('456') + self.assertEquals('123456', str1 + str2) + self.assertEquals('456123', str2 + str1) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qstring_qkeysequence_test.py b/tests/qtcore/qstring_qkeysequence_test.py new file mode 100644 index 000000000..d39459cef --- /dev/null +++ b/tests/qtcore/qstring_qkeysequence_test.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Tests QString using QKeySequence parameter''' + +import unittest + +from PySide.QtCore import QString +from PySide.QtGui import QKeySequence + +class QStringQKeySequenceTest(unittest.TestCase): + '''Tests QString using QKeySequence parameter''' + + def testQStringQKeySequence(self): + a = QString(QKeySequence("Ctrl+A")) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qstring_test.py b/tests/qtcore/qstring_test.py new file mode 100644 index 000000000..35863a16b --- /dev/null +++ b/tests/qtcore/qstring_test.py @@ -0,0 +1,106 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QString''' + +import unittest +import ctypes +import sys + +from PySide.QtCore import QString, QByteArray + +class QStringToNumber(unittest.TestCase): + def testToNumberInt(self): + obj = QString('37') + self.assertEqual(37, obj.toInt()[0]) + + def testToNumberFloat(self): + obj = QString('37.109') + self.assertEqual(ctypes.c_float(37.109).value, + obj.toFloat()[0]) + + def testToNumberDouble(self): + obj = QString('37.109') + self.assertEqual(ctypes.c_double(37.109).value, + obj.toDouble()[0]) + + def testToULongLong(self): + obj = QString('37109') + self.assertEqual(ctypes.c_ulong(37109).value, + obj.toULongLong()[0]) + +class QStringConstructor(unittest.TestCase): + '''Test case for QString constructors''' + + def testQStringDefault(self): + #QString() + obj1 = QString() + obj2 = QString() + + self.assertEqual(obj1, obj2) + + def testQStringFromPy(self): + #QString(const char*) + sample = 'a new string' + obj1 = QString(sample) + obj2 = QString(sample) + self.assertEqual(obj1, obj2) + + def testQStringFromUnicode(self): + sample = u'áâãà' + obj1 = QString(sample) + obj2 = QString(sample) + self.assertEqual(obj1, obj2) + self.assertEqual(obj1, sample) + self.assertEqual(obj2, sample) + + def testQStringFromByteArray(self): + # QByteArray(const char *) must be working + sample = QByteArray('foo') + obj1 = QString(sample) + obj2 = QString(sample) + self.assertEqual(obj1, obj2) + + def testQStringArg(self): + a = QString("%1 %2 %3").arg(1).arg("two").arg(3.14) + self.assertEquals("1 two 3.14", str(a)) + + def testQStringArgNegative(self): + a = QString("%1").arg(-20) + self.assertEquals("-20", str(a)) + + +class QStringComparison(unittest.TestCase): + '''Test case for comparison to python strings''' + + def testComparePyString(self): + #Compare QStrings and Python strings. + py = '' + qstr = QString() + self.assertEqual(py, qstr) + + py = 'The quick brown fox jumps over the lazy dog' + qstr = QString(py) + self.assertEqual(py, qstr) + +class QStringRange(unittest.TestCase): + '''Test case for ranges in python strings''' + + def testSimpleRange(self): + #Test open start and open end intervals + py = 'The quick brown fox jumps over the lazy dog' + qstr = QString(py) + self.assertEqual(py[5:], qstr[5:]) + self.assertEqual(py[:7], qstr[:7]) + +class QStringIndexOf(unittest.TestCase): + def testEmpty(self): + string = QString() + self.assertEqual(string.indexOf(QString("aaa")), -1) + self.assertEqual(string.indexOf(QString()), 0) + + def testString(self): + string = QString("the quick brown fox") + self.assertEqual(string.indexOf("quick", 0), 4) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qstringlist_test.py b/tests/qtcore/qstringlist_test.py new file mode 100644 index 000000000..e2a238eb2 --- /dev/null +++ b/tests/qtcore/qstringlist_test.py @@ -0,0 +1,165 @@ + +# -*- coding: utf-8 -*- + +'''Test cases for QStringList''' + +import unittest +from random import shuffle + +from PySide.QtCore import QStringList, QString + +from helper import random_string + +class UsesManyStrings(unittest.TestCase): + '''Helper class to setup a list of strings and QStrings''' + def setUp(self): + #Creates a list of strings and python strings + self.size = 10 + # List of Python strings + self.samples = [random_string() for x in range(self.size)] + # List of QStrings + self.strings = map(QString, self.samples) + + self.obj = QStringList(self.strings) + + +class TestConstructorBasic(unittest.TestCase): + '''Basic constructor test''' + + def testEmpty(self): + #QStringList() - default constructor + obj = QStringList() + self.assert_(isinstance(obj, QStringList)) + + def testQString(self): + #QStringList(QString) + qstr = QString('aaaa') + obj = QStringList(qstr) + self.assert_(isinstance(obj, QStringList)) + + def testPyString(self): + #QStringList(python_string) constructor + string = 'forty two' + obj = QStringList(string) + self.assert_(isinstance(obj, QStringList)) + + def testPyStringUnicode(self): + #QStringList(unicode python_string) constructor + string = 'Nação Zumbi' + obj = QStringList(string) + self.assert_(isinstance(obj, QStringList)) + + +class TestConstructorList(UsesManyStrings): + '''Test case for QStringList(List) constructor''' + + def testListQString(self): + #QStringList([QString]) constructor + obj = QStringList(self.strings) + self.assert_(isinstance(obj, QStringList)) + + def testListPyString(self): + #QStringList([python_string]) constructor + obj = QStringList(self.samples) + self.assert_(isinstance(obj, QStringList)) + + def testListMixed(self): + #QStringList([python_string and QString]) mixed constructor + mixed = self.samples + self.strings + shuffle(mixed) + obj = QStringList(mixed) + self.assert_(isinstance(obj, QStringList)) + + def testCopyList(self): + #QStringList(QStringList(list)) - copy constructor + obj = QStringList(self.strings) + obj2 = QStringList(obj) + self.assert_(isinstance(obj2, QStringList)) + self.assertEqual(obj, obj2) + + +class TestComparison(unittest.TestCase): + '''Test case for comparison of QStringLists''' + + def testEqual(self): + #QStringList == QStringList + string = QString('aaaabvbbcccedde') + obj1 = QStringList(string) + obj2 = QStringList(string) + self.assertEqual(obj1, obj2) + + +class TestIndexing(unittest.TestCase): + '''Test case for indexing through []''' + def testInvalidIndexEmpty(self): + #QStringList[x] for empty list + obj = QStringList() + self.assertRaises(IndexError, lambda:obj[0]) + + def testInvalidIndexQString(self): + #QStringList[1] raising IndexError for QStringList(QString) + obj = QStringList(QString('aaaaa')) + self.assertRaises(IndexError, lambda:obj[1]) + + def testValidIndexQString(self): + #QStringList[0] not raising IndexError for QStringList(QString) + string = QString('abcdefg') + obj = QStringList(string) + self.assertEqual(obj[0], string) + + def testNegativeIndexing(self): + #QStringList[-1] not raising IndexError for QStringList(QString) + string = QString('abcdefg') + obj = QStringList(string) + self.assertEqual(obj[-1], string) + + +class TestListIndexing(UsesManyStrings): + '''Test case for indexing QStringList longer than 1 string''' + + def testValid(self): + #QStringList[] for valid indexes + for i in range(self.size): + self.assertEqual(self.strings[i], self.obj[i]) + + def testNegativeValid(self): + #QStringList[] for valid indexes + for i in range(-1, -self.size, -1): + self.assertEqual(self.strings[i], self.obj[i]) + + def testInvalid(self): + #QStringList[] for invalid negative indexes + self.assertRaises(IndexError, lambda : self.obj[self.size]) + self.assertRaises(IndexError, lambda : self.obj[-(self.size+1)]) + + +class TestSlicing(UsesManyStrings): + '''Test case for slicing a QStringList''' + + def testSlicing(self): + #QStringList slicing + for i in range(self.size): + self.assertEqual(self.obj[i:], self.strings[i:]) + self.assertEqual(self.obj[:i], self.strings[:i]) + for j in range(i): + self.assertEqual(self.obj[j:i], self.strings[j:i]) + + for i in range(-1, -self.size, -1): + self.assertEqual(self.obj[:i], self.strings[:i]) + + +class TestShiftOperator(UsesManyStrings): + '''Test case for QStringList lshift operator''' + + def testShiftOperator(self): + #QStringList lshift + a = QStringList() + a << "a" << "b" << "c"; + self.assertEquals(3, a.count()) + b = ["1", "2", "3"] + c = ["4", "5", "6"] + a << b << c + self.assertEquals(9, a.count()) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qtext_codec_test.py b/tests/qtcore/qtext_codec_test.py new file mode 100644 index 000000000..2bd7f8139 --- /dev/null +++ b/tests/qtcore/qtext_codec_test.py @@ -0,0 +1,20 @@ +import gc +import unittest + +from PySide.QtCore import QTextCodec + +class TestCodecGetters(unittest.TestCase): + + def testCodecsNames(self): + for codec_name in QTextCodec.availableCodecs(): + codec = QTextCodec.codecForName(codec_name) + self.assert_(type(codec), QTextCodec) + + def testCodecsMibs(self): + for codec_num in QTextCodec.availableMibs(): + codec = QTextCodec.codecForMib(codec_num) + self.assert_(type(codec), QTextCodec) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qthread_prod_cons_test.py b/tests/qtcore/qthread_prod_cons_test.py new file mode 100644 index 000000000..fc634dd88 --- /dev/null +++ b/tests/qtcore/qthread_prod_cons_test.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +'''Producer-Consumer test/example with QThread''' + +import unittest +from random import random +import logging + +logging.basicConfig(level=logging.WARNING) + +from PySide.QtCore import QThread, QCoreApplication, QObject, SIGNAL + +class Bucket(QObject): + '''Dummy class to hold the produced values''' + def __init__(self, max_size=10, *args): + #Constructor which receives the max number of produced items + super(Bucket, self).__init__(*args) + self.data = [] + self.max_size = 10 + + def pop(self): + #Retrieves an item + return self.data.pop(0) + + def push(self, data): + #Pushes an item + self.data.append(data) + +class Producer(QThread): + '''Producer thread''' + + def __init__(self, bucket, *args): + #Constructor. Receives the bucket + super(Producer, self).__init__(*args) + self.runs = 0 + self.bucket = bucket + self.production_list = [] + + def run(self): + #Produces at most bucket.max_size items + while self.runs < self.bucket.max_size: + value = int(random()*10) % 10 + self.bucket.push(value) + self.production_list.append(value) + logging.debug('PRODUCER - pushed %d' % value) + self.runs += 1 + self.msleep(5) + + + +class Consumer(QThread): + '''Consumer thread''' + def __init__(self, bucket, *args): + #Constructor. Receives the bucket + super(Consumer, self).__init__(*args) + self.runs = 0 + self.bucket = bucket + self.consumption_list = [] + + def run(self): + #Consumes at most bucket.max_size items + while self.runs < self.bucket.max_size: + try: + value = self.bucket.pop() + self.consumption_list.append(value) + logging.debug('CONSUMER - got %d' % value) + self.runs += 1 + except IndexError: + logging.debug('CONSUMER - empty bucket') + self.msleep(5) + +class ProducerConsumer(unittest.TestCase): + '''Basic test case for producer-consumer QThread''' + + def setUp(self): + #Create fixtures + self.app = QCoreApplication([]) + + def tearDown(self): + #Destroy fixtures + del self.app + + def finishCb(self): + #Quits the application + self.app.exit(0) + + def testProdCon(self): + #QThread producer-consumer example + bucket = Bucket() + prod = Producer(bucket) + cons = Consumer(bucket) + + prod.start() + cons.start() + + QObject.connect(prod, SIGNAL('finished()'), self.finishCb) + QObject.connect(cons, SIGNAL('finished()'), self.finishCb) + + self.app.exec_() + + prod.wait() + cons.wait() + + self.assertEqual(prod.production_list, cons.consumption_list) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qthread_signal_test.py b/tests/qtcore/qthread_signal_test.py new file mode 100755 index 000000000..edd7d77f4 --- /dev/null +++ b/tests/qtcore/qthread_signal_test.py @@ -0,0 +1,64 @@ + +'''Test cases for connecting signals between threads''' + +import unittest + +from PySide.QtCore import QThread, QObject, SIGNAL, QCoreApplication + +thread_run = False + +class Source(QObject): + def __init__(self, *args): + QObject.__init__(self, *args) + + def emit_sig(self): + self.emit(SIGNAL('source()')) + +class Target(QObject): + def __init__(self, *args): + QObject.__init__(self, *args) + self.called = False + + def myslot(self): + self.called = True + +class ThreadJustConnects(QThread): + def __init__(self, source, *args): + QThread.__init__(self, *args) + self.source = source + self.target = Target() + + def run(self): + global thread_run + thread_run = True + QObject.connect(self.source, SIGNAL('source()'), self.target.myslot) + + while not self.target.called: + pass + + + +class BasicConnection(unittest.TestCase): + + def testEmitOutsideThread(self): + global thread_run + + app = QCoreApplication([]) + source = Source() + thread = ThreadJustConnects(source) + + QObject.connect(thread, SIGNAL('finished()'), lambda: app.exit(0)) + thread.start() + + while not thread_run: + pass + + source.emit_sig() + + app.exec_() + thread.wait() + + self.assert_(thread.target.called) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qthread_test.py b/tests/qtcore/qthread_test.py new file mode 100644 index 000000000..410afb908 --- /dev/null +++ b/tests/qtcore/qthread_test.py @@ -0,0 +1,76 @@ +#!/usr/bin/python +'''Test cases for QThread''' + +import unittest +from PySide.QtCore import QThread, QCoreApplication, QObject, SIGNAL, QMutex, QTimer +from PySide.QtCore import QEventLoop + +from helper import UsesQCoreApplication + +mutex = QMutex() + +class Dummy(QThread): + '''Dummy thread''' + def __init__(self, *args): + super(Dummy, self).__init__(*args) + self.called = False + + def run(self): + #Start-quit sequence + mutex.lock() + self.called = True + mutex.unlock() + +class QThreadSimpleCase(UsesQCoreApplication): + + def setUp(self): + UsesQCoreApplication.setUp(self) + self.called = False + + def tearDown(self): + UsesQCoreApplication.tearDown(self) + + def testThread(self): + #Basic QThread test + obj = Dummy() + obj.start() + obj.wait() + + self.assert_(obj.called) + + def cb(self, *args): + self.called = True + #self.exit_app_cb() + + def abort_application(self): + self._thread.terminate() + self.app.quit() + + def testSignalFinished(self): + #QThread.finished() (signal) + obj = Dummy() + QObject.connect(obj, SIGNAL('finished()'), self.cb) + mutex.lock() + obj.start() + mutex.unlock() + + self._thread = obj + QTimer.singleShot(1000, self.abort_application) + self.app.exec_() + + self.assert_(self.called) + + def testSignalStarted(self): + #QThread.started() (signal) + obj = Dummy() + QObject.connect(obj, SIGNAL('started()'), self.cb) + obj.start() + + self._thread = obj + QTimer.singleShot(1000, self.abort_application) + self.app.exec_() + + self.assert_(self.called) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qtimer_singleshot_test.py b/tests/qtcore/qtimer_singleshot_test.py new file mode 100644 index 000000000..96107ecce --- /dev/null +++ b/tests/qtcore/qtimer_singleshot_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +'''Test cases for QTimer.singleShot''' + +import unittest + +from PySide.QtCore import QObject, QTimer, QCoreApplication, SIGNAL +from helper import UsesQCoreApplication + +class WatchDog(QObject): + '''Exits the QCoreApplication main loop after sometime.''' + + def __init__(self, watched): + QObject.__init__(self) + self.times_called = 0 + self.watched = watched + + def timerEvent(self, evt): + self.times_called += 1 + if self.times_called == 20: + self.watched.exit_app_cb() + +class TestSingleShot(UsesQCoreApplication): + '''Test case for QTimer.singleShot''' + + def setUp(self): + #Acquire resources + UsesQCoreApplication.setUp(self) + self.watchdog = WatchDog(self) + self.called = False + + def tearDown(self): + #Release resources + del self.watchdog + del self.called + UsesQCoreApplication.tearDown(self) + + def callback(self): + self.called = True + self.app.quit() + + def testSingleShot(self): + timer = QTimer.singleShot(100, self.callback) + self.app.exec_() + self.assert_(self.called) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qtimer_timeout_test.py b/tests/qtcore/qtimer_timeout_test.py new file mode 100644 index 000000000..8dfe39529 --- /dev/null +++ b/tests/qtcore/qtimer_timeout_test.py @@ -0,0 +1,57 @@ + +'''Test case for timeout() signals from QTimer object.''' + +import unittest +import os +from tempfile import mkstemp +from PySide.QtCore import QObject, QTimer, SIGNAL +from helper import UsesQCoreApplication + +class WatchDog(QObject): + '''Exits the QCoreApplication main loop after sometime.''' + + def __init__(self, watched): + QObject.__init__(self) + self.times_called = 0 + self.watched = watched + + def timerEvent(self, evt): + self.times_called += 1 + if self.times_called == 20: + self.watched.exit_app_cb() + + +class TestTimeoutSignal(UsesQCoreApplication): + '''Test case to check if the signals are really being caught''' + + def setUp(self): + #Acquire resources + UsesQCoreApplication.setUp(self) + self.watchdog = WatchDog(self) + self.timer = QTimer() + self.called = False + + def tearDown(self): + #Release resources + del self.watchdog + del self.timer + del self.called + UsesQCoreApplication.tearDown(self) + + def callback(self, *args): + #Default callback + self.called = True + + def testTimeoutSignal(self): + #Test the QTimer timeout() signal + QObject.connect(self.timer, SIGNAL('timeout()'), self.callback) + self.timer.start(4) + self.watchdog.startTimer(10) + + self.app.exec_() + + self.assert_(self.called) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/qtnamespace_test.py b/tests/qtcore/qtnamespace_test.py new file mode 100644 index 000000000..3343a276b --- /dev/null +++ b/tests/qtcore/qtnamespace_test.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +'''Test suite for QtCore.Qt namespace''' + +import unittest + +from PySide.QtCore import Qt + +class QtNamespace(unittest.TestCase): + '''Test case for accessing attributes from Qt namespace''' + + def testBasic(self): + #Access to Qt namespace + getattr(Qt, 'Horizontal') + getattr(Qt, 'WindowMaximizeButtonHint') + self.assert_(True) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/quoteEnUS.txt b/tests/qtcore/quoteEnUS.txt new file mode 100644 index 000000000..909b4fa17 --- /dev/null +++ b/tests/qtcore/quoteEnUS.txt @@ -0,0 +1 @@ +Fine! Dishonor! Dishonor on you, dishonor on ya cow! diff --git a/tests/qtcore/qurl_test.py b/tests/qtcore/qurl_test.py new file mode 100644 index 000000000..14243a11a --- /dev/null +++ b/tests/qtcore/qurl_test.py @@ -0,0 +1,91 @@ +#!/usr/bin/python +'''Test suite for QtCore.QUrl''' + +import unittest + +from PySide.QtCore import QUrl + +class QUrlBasicConstructor(unittest.TestCase): + '''Tests the basic constructors''' + + def testBasic(self): + #Default constructor for QUrl + url = QUrl() + self.assertEqual(url.toString(), "") + + def testSetAttributes(self): + #Construct QUrl by set* methods + url = QUrl() + + url.setScheme('ftp') + self.assertEqual(url.toString(), 'ftp:') + + url.setHost('www.google.com') + self.assertEqual(url.toString(), 'ftp://www.google.com') + + url.setPort(8080) + self.assertEqual(url.toString(), 'ftp://www.google.com:8080') + + url.setPath('mail/view') + self.assertEqual(url.toString(), + 'ftp://www.google.com:8080/mail/view') + + url.setUserName('john') + self.assertEqual(url.toString(), + 'ftp://john@www.google.com:8080/mail/view') + + url.setPassword('abc123') + self.assertEqual(url.toString(), + 'ftp://john:abc123@www.google.com:8080/mail/view') + +class QueryItemsTest(unittest.TestCase): + '''Test query item management''' + + def testQueryItems(self): + #QUrl.queryItems + url = QUrl('http://www.google.com/search?q=python&hl=en') + valid_data = [(('q'), ('python')), (('hl'), ('en'))] + + self.assertEqual(sorted(url.queryItems()), sorted(valid_data)) + + def testEncodedQueryItems(self): + #QUrl.encodedQueryItems + url = QUrl('http://www.google.com/search?q=python&hl=en') + valid_data = [(('q'), ('python')), (('hl'), ('en'))] + + self.assertEqual(sorted(url.encodedQueryItems()), sorted(valid_data)) + + def testSetQueryItems(self): + #QUrl.setQueryItems + urla = QUrl('http://www.google.com/search?q=python&hl=en') + urlb = QUrl('http://www.google.com/search') + + urlb.setQueryItems(urla.queryItems()) + + self.assertEqual(urla, urlb) + + def testAddQueryItem(self): + #QUrl.addQueryItem + url = QUrl() + valid_data = [('hl', 'en'), ('user', 'konqui')] + + url.addQueryItem(*valid_data[0]) + self.assertEqual(url.queryItems()[0], valid_data[0]) + + url.addQueryItem(*valid_data[1]) + self.assertEqual(sorted(url.queryItems()), sorted(valid_data)) + + def testAllEncodedQueryItemsValues(self): + #QUrl.allEncodedQueryItemValues + url = QUrl() + key = 'key' + valid_data = ['data', 'valid', 'test'] + + for i, data in enumerate(valid_data): + url.addQueryItem(key, data) + self.assertEqual(url.allEncodedQueryItemValues(key), + list(valid_data[:i+1])) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/qvariant_test.py b/tests/qtcore/qvariant_test.py new file mode 100644 index 000000000..b3f80c895 --- /dev/null +++ b/tests/qtcore/qvariant_test.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QVariant''' + +import unittest +import sys + +from PySide.QtCore import QSize, QVariant, QByteArray, QStringList + +class Dummy(object): + pass + +class MySize(QSize): + pass + +class QVariantToNumber(unittest.TestCase): + def testToNumberInt(self): + obj = QVariant('37') + self.assertEqual(37, obj.toInt()[0]) + + def testToNumberFloat(self): + obj = QVariant('37.109') + self.assertEqual(37.109, obj.toDouble()[0]) + +class QVariantTypeName(unittest.TestCase): + def testTypeNameQString(self): + #QVariant.typeName() + obj = QVariant('aaaa') + self.assertEqual('QString', obj.typeName()) + + def testTypeNameInt(self): + obj = QVariant(34) + self.assertEqual('int', obj.typeName()) + + def testTypeNameDouble(self): + obj = QVariant(3.14) + self.assertEqual('double', obj.typeName()) + + def testTypeNameBool(self): + obj = QVariant(True) + self.assertEqual('bool', obj.typeName()) + + def testTypeNameQByteArray(self): + obj = QVariant(QByteArray('aaaa')) + self.assertEqual('QByteArray', obj.typeName()) + + def testTypeNameNone(self): + obj = QVariant() + self.assertEqual(None, obj.typeName()) + + def testTypeNameQVariantList(self): + obj = QVariant([1,Dummy(),3,4]) + self.assertEqual('QVariantList', obj.typeName()) + + def testTypeNameQStringList(self): + obj = QVariant(QStringList()) + self.assertEqual('QStringList', obj.typeName()) + + def testTypeNamePythonClasses(self): + ## QVariant of python classes + d = Dummy() + obj = QVariant(d) + self.assertEqual('PyQt_PyObject', obj.typeName()) + + # This works only on PyQt4 4.5.x, not on PyQt4 4.4.x or PySide + def testSubClassConvertion(self): + mysize = MySize(0, 0) + variant = QVariant(mysize) + + assert(variant.type() != QVariant.Size) + assert(variant.toPyObject() is mysize) + +class QVariantConstructor(unittest.TestCase): + def testCopyConstructor(self): + obj = QVariant(1) + cpy = QVariant(obj) + + self.assertEqual(obj.type(), cpy.type()) + + def testQStringConstructor(self): + obj = QVariant("PySide") + self.assertEqual(obj.type(), QVariant.String) + +class QVariantToPyObject(unittest.TestCase): + def testQVariantPyList(self): + obj = QVariant([1, 'two', 3]) + self.assertEqual(obj.toPyObject(), [1, 'two', 3]) + + def testPyObject(self): + d = Dummy() + obj = QVariant(d) + self.assertEqual(d, obj.toPyObject()) + + def atestNoneToPyObject(self): + # XXX Do not run by default because segfaults with PyQt4 + obj = QVariant() + self.assertEqual(None, obj.toPyObject()) + + def testQStringToPyObject(self): + d = 'abc' + obj = QVariant('abc') + self.assertEqual(d, obj.toPyObject()) + +class QVartiantTypeTest(unittest.TestCase): + def testQSize(self): + class MySize(QSize): + pass + + mysize = MySize(5, 5) + variant = QVariant(mysize) + self.assert_(variant.type() != QVariant.Size) + self.assert_(variant.toPyObject() is mysize) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/resources.qrc b/tests/qtcore/resources.qrc new file mode 100644 index 000000000..cea17b440 --- /dev/null +++ b/tests/qtcore/resources.qrc @@ -0,0 +1,6 @@ + + + quoteEnUS.txt + + + diff --git a/tests/qtcore/resources_mc.py b/tests/qtcore/resources_mc.py new file mode 100644 index 000000000..132c8db12 --- /dev/null +++ b/tests/qtcore/resources_mc.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created: Thu Mar 26 11:08:45 2009 +# by: The Resource Compiler for PyQt (Qt v4.5.0) +# +# WARNING! All changes made in this file will be lost! + +from PySide import QtCore + +qt_resource_data = "\ +\x00\x00\x00\x35\ +\x46\ +\x69\x6e\x65\x21\x20\x44\x69\x73\x68\x6f\x6e\x6f\x72\x21\x20\x44\ +\x69\x73\x68\x6f\x6e\x6f\x72\x20\x6f\x6e\x20\x79\x6f\x75\x2c\x20\ +\x64\x69\x73\x68\x6f\x6e\x6f\x72\x20\x6f\x6e\x20\x79\x61\x20\x63\ +\x6f\x77\x21\x0a\ +" + +qt_resource_name = "\ +\x00\x09\ +\x06\xa8\xaa\x74\ +\x00\x71\ +\x00\x75\x00\x6f\x00\x74\x00\x65\x00\x2e\x00\x74\x00\x78\x00\x74\ +" + +qt_resource_struct = "\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/tests/qtcore/resources_mc.pyc b/tests/qtcore/resources_mc.pyc new file mode 100644 index 000000000..a8140b1d1 Binary files /dev/null and b/tests/qtcore/resources_mc.pyc differ diff --git a/tests/qtcore/static_method_test.py b/tests/qtcore/static_method_test.py new file mode 100755 index 000000000..26955d925 --- /dev/null +++ b/tests/qtcore/static_method_test.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +'''Tests for static methos conflicts with class methods''' + +import unittest + +from PySide import QtCore + +class static_function_test(unittest.TestCase): + def testMemberQFileExists(self): + f = QtCore.QFile("/tmp/foo.txt") + self.assertEqual(f.exists(), False) + + def testStatocQFileExists(self): + self.assertEqual(QtCore.QFile.fileExists("/tmp/foo.txt"), False) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/static_protected_methods_test.py b/tests/qtcore/static_protected_methods_test.py new file mode 100644 index 000000000..9d920a438 --- /dev/null +++ b/tests/qtcore/static_protected_methods_test.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +'''Unit tests for static protected methods''' + +import unittest, time + +from PySide.QtCore import QThread + +class Test (QThread): + def run(self): + start = time.time() + self.sleep(1) + self.time_elapsed = time.time() - start + +class QStaticProtectedCall(unittest.TestCase): + '''Test case for static protected method call''' + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPathSeparator(self): + thread = Test() + thread.start() + thread.wait() + self.assertTrue(thread.time_elapsed <= 1.1) # tolarance of 100ms + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/thread_signals.py b/tests/qtcore/thread_signals.py new file mode 100644 index 000000000..e2b66730b --- /dev/null +++ b/tests/qtcore/thread_signals.py @@ -0,0 +1,39 @@ + +''' Test case for QObject.signalsBlocked() and blockSignal()''' + +import unittest +import os +from tempfile import mkstemp + +from PySide.QtCore import QObject, SIGNAL, QFile, QThread, QTimer +from helper import UsesQCoreApplication + +class MyThread(QThread): + + def run(self): + self.emit(SIGNAL("test(const QString&)"), + "INdT - PySide"); + +class TestThreadSignal(UsesQCoreApplication): + + __called__ = True + def _callback(self, msg): + self.assertEqual(msg, "INdT - PySide") + self.__called__ = True + self._quit() + + def _quit(self): + self.app.quit() + + def testThread(self): + t = MyThread() + QObject.connect(t, SIGNAL("test(const QString&)"), + self._callback); + + t.start() + QTimer.singleShot(100, self._quit) + self.app.exec_() + self.assert_(self.__called__); + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtcore/translation_test.py b/tests/qtcore/translation_test.py new file mode 100644 index 000000000..31bb20e74 --- /dev/null +++ b/tests/qtcore/translation_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +'''Unit tests to test QTranslator and translation in general.''' + +import os +import unittest +from PySide.QtCore import QObject, QTranslator, QCoreApplication + +from helper import UsesQCoreApplication + +class TranslationTest(UsesQCoreApplication): + '''Test case for Qt translation facilities.''' + + def setUp(self): + super(TranslationTest, self).setUp() + self.trdir = os.path.join(os.path.dirname(__file__), 'translations') + # os.system is probably not the best way to do it + os.system('lrelease %s/*.ts > /dev/null' % self.trdir) + + def tearDown(self): + os.system('rm %s/*.qm > /dev/null' % self.trdir) + super(TranslationTest, self).tearDown() + + def testLatin(self): + #Set string value to Latin + translator = QTranslator() + translator.load(os.path.join(self.trdir, 'trans_latin.qm')) + self.app.installTranslator(translator) + + obj = QObject() + obj.setObjectName(obj.tr('Hello World!')) + self.assertEqual(obj.objectName(), u'Orbis, te saluto!') + + def testRussian(self): + #Set string value to Russian + translator = QTranslator() + translator.load(os.path.join(self.trdir, 'trans_russian.qm')) + self.app.installTranslator(translator) + + obj = QObject() + obj.setObjectName(obj.tr('Hello World!')) + self.assertEqual(obj.objectName(), u'привет мир!') + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/translations/trans_latin.ts b/tests/qtcore/translations/trans_latin.ts new file mode 100644 index 000000000..b9fcf41be --- /dev/null +++ b/tests/qtcore/translations/trans_latin.ts @@ -0,0 +1,11 @@ + + + + + QObject + + Hello World! + Orbis, te saluto! + + + diff --git a/tests/qtcore/translations/trans_russian.ts b/tests/qtcore/translations/trans_russian.ts new file mode 100644 index 000000000..d1ba49bd2 --- /dev/null +++ b/tests/qtcore/translations/trans_russian.ts @@ -0,0 +1,11 @@ + + + + + QObject + + Hello World! + привет мир! + + + diff --git a/tests/qtcore/unaryoperator_test.py b/tests/qtcore/unaryoperator_test.py new file mode 100755 index 000000000..94db1feec --- /dev/null +++ b/tests/qtcore/unaryoperator_test.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +'''Tests the presence of unary operator __neg__ on the QPoint class''' + +import unittest + +from PySide.QtCore import QPoint + +class NegUnaryOperatorTest(unittest.TestCase): + '''Tests the presence of unary operator __neg__ on the QPoint class''' + + def setUp(self): + #Acquire resources + self.x, self.y = 10, 20 + self.neg_x, self.neg_y = -self.x, -self.y + self.qpoint = QPoint(self.x, self.y) + + def tearDown(self): + #Release resources + del self.qpoint + del self.x + del self.y + del self.neg_x + del self.neg_y + + def testNegUnaryOperator(self): + #Test __neg__ unary operator on QPoint class + __neg__method_exists = True + try: + neg_qpoint = -self.qpoint + except: + __neg__method_exists = False + + self.assertTrue(__neg__method_exists) + self.assertEqual(self.qpoint, -neg_qpoint) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtcore/unicode_test.py b/tests/qtcore/unicode_test.py new file mode 100644 index 000000000..f0bb883ed --- /dev/null +++ b/tests/qtcore/unicode_test.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +'''Unit tests for QString conversion to/from Python Unicode''' + +import unittest + +from PySide.QtCore import QObject + +class UnicodeConversion(unittest.TestCase): + '''Test case for QString to/from Python Unicode conversion''' + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSetRegularStringRetrieveUnicode(self): + #Set regular Python string retrieve unicode + obj = QObject() + obj.setObjectName('test') + self.assertEqual(obj.objectName(), u'test') + + def testSetUnicodeRetrieveUnicode(self): + #Set Python unicode string and retrieve unicode + obj = QObject() + obj.setObjectName(u'ümlaut') + self.assertEqual(obj.objectName(), u'ümlaut') + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/float_to_int_implicit_conversion_test.py b/tests/qtgui/float_to_int_implicit_conversion_test.py new file mode 100644 index 000000000..cc7d18fd9 --- /dev/null +++ b/tests/qtgui/float_to_int_implicit_conversion_test.py @@ -0,0 +1,32 @@ + +'''Test cases for QImage''' + +import unittest + +from PySide.QtGui import QImage, qRgb + +from helper import UsesQApplication + +class SetPixelFloat(UsesQApplication): + '''Test case for calling setPixel with float as argument''' + + def setUp(self): + #Acquire resources + super(SetPixelFloat, self).setUp() + self.color = qRgb(255, 0, 0) + self.image = QImage(200, 200, QImage.Format_RGB32) + + def tearDown(self): + #Release resources + del self.color + del self.image + super(SetPixelFloat, self).tearDown() + + def testFloat(self): + #QImage.setPixel(float, float, color) - Implicit conversion + self.image.setPixel(3.14, 4.2, self.color) + self.assertEqual(self.image.pixel(3.14, 4.2), self.color) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/grandparent_method_test.py b/tests/qtgui/grandparent_method_test.py new file mode 100644 index 000000000..3c1829377 --- /dev/null +++ b/tests/qtgui/grandparent_method_test.py @@ -0,0 +1,23 @@ + +'''Tests for calling methods further than the direct parent''' + +import unittest + +from PySide.QtGui import QPushButton, QWidget + +from helper import UsesQApplication + +class Dummy(QPushButton): + + def show(self): + QWidget.show(self) + self.called = True + +class GrandParentMethod(UsesQApplication): + def testMethod(self): + obj = Dummy() + obj.show() + self.assert_(obj.called) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/missing_symbols_test.py b/tests/qtgui/missing_symbols_test.py new file mode 100644 index 000000000..de23c569e --- /dev/null +++ b/tests/qtgui/missing_symbols_test.py @@ -0,0 +1,29 @@ + +'''(Very) Simple test case for missing names from QtGui''' + +import unittest +from PySide import QtGui + +class MissingClasses(unittest.TestCase): + def testQDrag(self): # Bug 222 + getattr(QtGui, 'QDrag') + + def testQDropEvent(self): # Bug 255 + getattr(QtGui, 'QDropEvent') + +class MissingMembers(unittest.TestCase): + + def testQFontMetricsSize(self): # Bug 223 + QtGui.QFontMetrics.size + + def testQLayoutSetSpacing(self): # Bug 231 + QtGui.QLayout.setSpacing + + def testQImageLoad(self): # Bug 257 + QtGui.QImage.load + + def testQStandardItemModelinsertRow(self): # Bug 227 + QtGui.QStandardItemModel.insertRow + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/paint_event_test.py b/tests/qtgui/paint_event_test.py new file mode 100644 index 000000000..02253908e --- /dev/null +++ b/tests/qtgui/paint_event_test.py @@ -0,0 +1,71 @@ + +'''Test paint event override in python''' + +import unittest + +from PySide.QtCore import QTimerEvent +from PySide.QtGui import QApplication, QWidget + +from helper import UsesQApplication + +class MyWidget(QWidget): + '''Sample widget''' + + def __init__(self, app=None): + #Creates a new widget + if app is None: + app = QApplication([]) + + super(MyWidget, self).__init__() + self.app = app + self.runs = 0 + self.max_runs = 5 + self.paint_event_called = False + + def timerEvent(self, event): + #Timer event method + self.runs += 1 + + if self.runs == self.max_runs: + self.app.quit() + + if not isinstance(event, QTimerEvent): + raise TypeError('Invalid event type. Must be QTimerEvent') + + def paintEvent(self, event): + #Empty paint event method + # XXX: should be using super here, but somehow PyQt4 + # complains about paintEvent not present in super + QWidget.paintEvent(self, event) + self.paint_event_called = True + + +class PaintEventOverride(UsesQApplication): + '''Test case for overriding QWidget.paintEvent''' + + qapplication = True + + def setUp(self): + #Acquire resources + super(PaintEventOverride, self).setUp() + self.widget = MyWidget(self.app) + + def tearDown(self): + #Release resources + del self.widget + super(PaintEventOverride, self).tearDown() + + def testPaintEvent(self): + #Test QWidget.paintEvent override + timer_id = self.widget.startTimer(100) + self.widget.show() + self.app.exec_() + + self.widget.killTimer(timer_id) + + self.assert_(self.widget.paint_event_called) + self.assertEqual(self.widget.runs, 5) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/parent_method_test.py b/tests/qtgui/parent_method_test.py new file mode 100644 index 000000000..8d0ba9601 --- /dev/null +++ b/tests/qtgui/parent_method_test.py @@ -0,0 +1,25 @@ + +import unittest + +from PySide.QtCore import QObject, QTimer, QThread +from PySide.QtGui import * + +class Foo(QTableView): + def __init__(self, parent=None): + QTableView.__init__(self, parent) + +from helper import UsesQApplication + +class TestParentType(UsesQApplication): + + def testParentType(self): + # Test the problem with calling QObject.parent from a QWidget + # when the parent is a python class derived from a QWidget-derived + # class. The method was returning the last C++ class in the hierarchy + parent = Foo() + w2 = QWidget(parent) + self.assert_(isinstance(w2.parentWidget(), Foo)) + self.assert_(isinstance(w2.parent(), Foo)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/parent_policy_test.py b/tests/qtgui/parent_policy_test.py new file mode 100755 index 000000000..e90da5a49 --- /dev/null +++ b/tests/qtgui/parent_policy_test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import unittest + +from helper import UsesQApplication +from PySide.QtCore import QAbstractTableModel, QVariant +from PySide.QtGui import QTableView + +class TestModel(QAbstractTableModel): + def __init__(self, parent=None): + QAbstractTableModel.__init__(self, parent) + def rowCount(self, parent): + return 0 + def columnCount(self, parent): + return 0 + def data(self, index, role): + return QVariant() + +class ParentPolicyTest(UsesQApplication): + + def testModelWithoutParent(self): + view = QTableView() + model = TestModel() + view.setModel(model) + samemodel = view.model() + self.assertEqual(model, samemodel) + + def testModelWithParent(self): + view = QTableView() + model = TestModel(self.app) + view.setModel(model) + samemodel = view.model() + self.assertEqual(model, samemodel) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/python_properties_test.py b/tests/qtgui/python_properties_test.py new file mode 100644 index 000000000..ce50431a1 --- /dev/null +++ b/tests/qtgui/python_properties_test.py @@ -0,0 +1,19 @@ +import unittest +from PySide import QtGui, QtCore + +class Properties(unittest.TestCase): + + def testStaticProperty(self): + self.assertEqual(QtGui.QGraphicsItem.UserType, 65536) + + def testMemberProperty(self): + i = QtGui.QGraphicsItem() + self.assertEqual(i.UserType, 65536) + + def testInstanceProperty(self): + p = QtGui.QStyleOptionViewItemV3() + self.assert_(isinstance(p.locale, QtCore.QLocale)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qapp_test.py b/tests/qtgui/qapp_test.py new file mode 100644 index 000000000..c371492e6 --- /dev/null +++ b/tests/qtgui/qapp_test.py @@ -0,0 +1,17 @@ + +''' Test the presence of qApp Macro''' + +import unittest + +from PySide import QtGui + +class QAppPresence(unittest.TestCase): + + def testQApp(self): + #QtGui.qApp variable is instance of QApplication + self.assert_(isinstance(QtGui.qApp, QtGui.QApplication)) + + +if __name__ == '__main__': + app = QtGui.QApplication([]) + unittest.main() diff --git a/tests/qtgui/qapplication_exit_segfault_test.py b/tests/qtgui/qapplication_exit_segfault_test.py new file mode 100644 index 000000000..72b810a98 --- /dev/null +++ b/tests/qtgui/qapplication_exit_segfault_test.py @@ -0,0 +1,17 @@ + +import unittest +import sys + +from PySide.QtGui import QApplication, QPushButton, QWidget, QSpinBox + +class QApplicationDelete(unittest.TestCase): + '''Test for segfault when deleting a QApplication before a QWidget''' + + def testQPushButton(self): + #QApplication deleted before QPushButton + a = QApplication([]) + b = QPushButton('aaaa') + del a + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qapplication_singleton_test.py b/tests/qtgui/qapplication_singleton_test.py new file mode 100644 index 000000000..9c959f9d4 --- /dev/null +++ b/tests/qtgui/qapplication_singleton_test.py @@ -0,0 +1,12 @@ + +import unittest + +from PySide.QtGui import QApplication + +class TestSingleton(unittest.TestCase): + def testBasic(self): + a = QApplication([]) + self.assertRaises(RuntimeError, QApplication, []) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qbrush_test.py b/tests/qtgui/qbrush_test.py new file mode 100644 index 000000000..cf11652a5 --- /dev/null +++ b/tests/qtgui/qbrush_test.py @@ -0,0 +1,24 @@ + +'''Test cases for QBrush''' + +import unittest + +from PySide.QtCore import Qt +from PySide.QtGui import QApplication, QColor, QBrush + +from helper import UsesQApplication + +class Constructor(UsesQApplication): + '''Test case for constructor of QBrush''' + + def testQColor(self): + #QBrush(QColor) constructor + color = QColor('black') + obj = QBrush(color) + self.assertEqual(obj.color(), color) + + obj = QBrush(Qt.blue) + self.assertEqual(obj.color(), Qt.blue) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qdatastream_gui_operators_test.py b/tests/qtgui/qdatastream_gui_operators_test.py new file mode 100644 index 000000000..7d46984ff --- /dev/null +++ b/tests/qtgui/qdatastream_gui_operators_test.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +import unittest +import sys + +from PySide import QtGui, QtCore + + +class QAppPresence(unittest.TestCase): + + def testQPixmap(self): + ds = QtCore.QDataStream() + p = QtGui.QPixmap() + ds << p + ds >> p + +if __name__ == '__main__': + app = QtGui.QApplication([]) + unittest.main() diff --git a/tests/qtgui/qgraphicsitem_test.py b/tests/qtgui/qgraphicsitem_test.py new file mode 100644 index 000000000..43545a431 --- /dev/null +++ b/tests/qtgui/qgraphicsitem_test.py @@ -0,0 +1,35 @@ + +''' Test cases related to QGraphicsItem and subclasses''' + +import unittest + +from PySide.QtGui import QGraphicsScene, QPolygonF, QColor, QBrush + +from helper import UsesQApplication + +class QColorOnSetBrush(UsesQApplication): + '''Test case for passing a QColor directly to setBrush''' + + def setUp(self): + #Acquire resources + super(QColorOnSetBrush, self).setUp() + + self.scene = QGraphicsScene() + poly = QPolygonF() + self.item = self.scene.addPolygon(poly) + self.color = QColor('black') + + def tearDown(self): + #Release resources + del self.color + del self.item + del self.scene + super(QColorOnSetBrush, self).tearDown() + + def testQColor(self): + #QGraphicsAbstractShapeItem.setBrush(QColor) + self.item.setBrush(self.color) + self.assertEqual(QBrush(self.color), self.item.brush()) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qgraphicsscene_test.py b/tests/qtgui/qgraphicsscene_test.py new file mode 100644 index 000000000..abfd5839c --- /dev/null +++ b/tests/qtgui/qgraphicsscene_test.py @@ -0,0 +1,152 @@ + +'''Basic test cases for QGraphicsScene''' + +import unittest +import gc + +from PySide.QtCore import QPointF +from PySide.QtGui import QApplication, QPushButton, QPolygonF, QPixmap +from PySide.QtGui import QGraphicsScene, QPainterPath +from PySide.QtGui import QGraphicsEllipseItem, QGraphicsLineItem +from PySide.QtGui import QGraphicsPathItem, QGraphicsPixmapItem +from PySide.QtGui import QGraphicsPolygonItem, QGraphicsRectItem +from PySide.QtGui import QGraphicsSimpleTextItem, QGraphicsTextItem +from PySide.QtGui import QGraphicsProxyWidget + +from helper import UsesQApplication + +class Constructor(unittest.TestCase): + '''QGraphicsScene constructor''' + + def testConstructor(self): + #QGraphicsScene constructor + obj = QGraphicsScene() + self.assert_(isinstance(obj, QGraphicsScene)) + + +class ConstructorWithRect(unittest.TestCase): + '''QGraphicsScene qrect constructor and related sizes''' + + def setUp(self): + #Acquire resources + # PyQt4 doesn't accept a QRect as argument to constructor + self.scene = QGraphicsScene(0, 200, 150, 175) + + def tearDown(self): + #Release resources + del self.scene + + def testHeight(self): + #QGraphicsScene.height() + self.assertEqual(self.scene.height(), 175) + + def testWidth(self): + #QGraphicsScene.width() + self.assertEqual(self.scene.width(), 150) + + +class AddItem(UsesQApplication): + '''Tests for QGraphicsScene.add*''' + + qapplication = True + + def setUp(self): + #Acquire resources + super(AddItem, self).setUp() + self.scene = QGraphicsScene() + # While the scene does not inherits from QWidget, requires + # an application to make the internals work. + + def tearDown(self): + #Release resources + del self.scene + super(AddItem, self).tearDown() + + def testEllipse(self): + #QGraphicsScene.addEllipse + item = self.scene.addEllipse(100, 100, 100, 100) + self.assert_(isinstance(item, QGraphicsEllipseItem)) + + def testLine(self): + #QGraphicsScene.addLine + item = self.scene.addLine(100, 100, 200, 200) + self.assert_(isinstance(item, QGraphicsLineItem)) + + def testPath(self): + #QGraphicsScene.addPath + item = self.scene.addPath(QPainterPath()) + self.assert_(isinstance(item, QGraphicsPathItem)) + + def testPixmap(self): + #QGraphicsScene.addPixmap + item = self.scene.addPixmap(QPixmap()) + self.assert_(isinstance(item, QGraphicsPixmapItem)) + + def testPolygon(self): + #QGraphicsScene.addPolygon + points = [QPointF(0, 0), QPointF(100, 100), QPointF(0, 100)] + item = self.scene.addPolygon(QPolygonF(points)) + self.assert_(isinstance(item, QGraphicsPolygonItem)) + + def testRect(self): + #QGraphicsScene.addRect + item = self.scene.addRect(100, 100, 100, 100) + self.assert_(isinstance(item, QGraphicsRectItem)) + + def testSimpleText(self): + #QGraphicsScene.addSimpleText + item = self.scene.addSimpleText('Monty Python 42') + self.assert_(isinstance(item, QGraphicsSimpleTextItem)) + + def testText(self): + #QGraphicsScene.addText + item = self.scene.addText('Monty Python 42') + self.assert_(isinstance(item, QGraphicsTextItem)) + + def testWidget(self): + #QGraphicsScene.addWidget + # XXX: printing some X11 error when using under PyQt4 + item = self.scene.addWidget(QPushButton()) + self.assert_(isinstance(item, QGraphicsProxyWidget)) + + +class ItemRetrieve(UsesQApplication): + '''Tests for QGraphicsScene item retrieval methods''' + + qapplication = True + + def setUp(self): + #Acquire resources + super(ItemRetrieve, self).setUp() + self.scene = QGraphicsScene() + + self.topleft = QGraphicsRectItem(0, 0, 100, 100) + self.topright = QGraphicsRectItem(100, 0, 100, 100) + self.bottomleft = QGraphicsRectItem(0, 100, 100, 100) + self.bottomright = QGraphicsRectItem(100, 100, 100, 100) + + self.items = [self.topleft, self.topright, self.bottomleft, + self.bottomright] + + for item in self.items: + self.scene.addItem(item) + + def tearDown(self): + #Release resources + del self.scene + super(ItemRetrieve, self).tearDown() + + def testItems(self): + #QGraphicsScene.items() + items = self.scene.items() + self.assertEqual(items, self.items) + + def testItemAt(self): + #QGraphicsScene.itemAt() + self.assertEqual(self.scene.itemAt(50, 50), self.topleft) + self.assertEqual(self.scene.itemAt(150, 50), self.topright) + self.assertEqual(self.scene.itemAt(50, 150), self.bottomleft) + self.assertEqual(self.scene.itemAt(150, 150), self.bottomright) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qlabel_pixmap_refcount.py b/tests/qtgui/qlabel_pixmap_refcount.py new file mode 100644 index 000000000..db8783e98 --- /dev/null +++ b/tests/qtgui/qlabel_pixmap_refcount.py @@ -0,0 +1,46 @@ + +'''Test cases for QLabel->pixmap refcount control''' + +import unittest +import sys + + +from helper import UsesQApplication +from PySide.QtGui import QApplication, QLabel, QPixmap + +class QLabelTest(UsesQApplication): + '''Test case for constructor of QBrush''' + + def testDestroyOwner(self): + p = QPixmap() + l = QLabel() + l.setPixmap(p) + + del p + + p1 = l.pixmap() + self.assertEqual(sys.getrefcount(p1), 2) + self.assertEqual(sys.getrefcount(l), 2) + + del l + self.assertEqual(sys.getrefcount(p1), 2) + + + def testRefCount(self): + p = QPixmap() + l = QLabel() + l.setPixmap(p) + + del p + + p1 = l.pixmap() + self.assertEqual(sys.getrefcount(p1), 2) + + p2 = l.pixmap() + self.assertEqual(sys.getrefcount(p2), 3) + + p3 = l.pixmap() + self.assertEqual(sys.getrefcount(p3), 4) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qlayout_ref_test.py b/tests/qtgui/qlayout_ref_test.py new file mode 100644 index 000000000..a8e924f14 --- /dev/null +++ b/tests/qtgui/qlayout_ref_test.py @@ -0,0 +1,96 @@ + +'''Test cases for QLayout handling of child widgets references''' + +import unittest +from sys import getrefcount + +from PySide.QtGui import QHBoxLayout, QVBoxLayout, QGridLayout +from PySide.QtGui import QStackedLayout, QFormLayout +from PySide.QtGui import QApplication, QPushButton, QLabel + +from helper import UsesQApplication + +class SaveReference(UsesQApplication): + '''Test case to check if QLayout-derived classes increment the refcount + of widgets passed to addWidget()''' + + # Adding here as nose can't see the qapplication attrib we inherit + qapplication = True + + def setUp(self): + #Acquire resources + super(SaveReference, self).setUp() + self.widget1 = QPushButton('click me') + self.widget2 = QLabel('aaa') + + def tearDown(self): + #Release resources + del self.widget2 + del self.widget1 + super(SaveReference, self).tearDown() + + def checkLayoutReference(self, layout): + #Checks the reference cound handling of layout.addWidget + self.assertEqual(getrefcount(self.widget1), 2) + layout.addWidget(self.widget1) + self.assertEqual(getrefcount(self.widget1), 3) + + self.assertEqual(getrefcount(self.widget2), 2) + layout.addWidget(self.widget2) + self.assertEqual(getrefcount(self.widget2), 3) + + # Check if doesn't mess around with previous widget refcount + self.assertEqual(getrefcount(self.widget1), 3) + + def testHBoxReference(self): + #QHBoxLayout.addWidget reference count + self.checkLayoutReference(QHBoxLayout()) + + def testVBoxReference(self): + #QVBoxLayout.addWidget reference count + self.checkLayoutReference(QVBoxLayout()) + + def testGridReference(self): + #QGridLayout.addWidget reference count + self.checkLayoutReference(QGridLayout()) + + def testFormReference(self): + #QFormLayout.addWidget reference count + self.checkLayoutReference(QFormLayout()) + + def testStackedReference(self): + #QStackedLayout.addWidget reference count + self.checkLayoutReference(QStackedLayout()) + + +class MultipleAdd(UsesQApplication): + '''Test case to check if refcount is incremented only once when multiple + calls to addWidget are made with the same widget''' + + qapplication = True + + def setUp(self): + #Acquire resources + super(MultipleAdd, self).setUp() + self.widget = QPushButton('click me') + self.layout = QHBoxLayout() + + def tearDown(self): + #Release resources + del self.widget + del self.layout + super(MultipleAdd, self).tearDown() + + def testRefCount(self): + #Multiple QLayout.addWidget calls on the same widget + self.assertEqual(getrefcount(self.widget), 2) + self.layout.addWidget(self.widget) + self.assertEqual(getrefcount(self.widget), 3) + self.layout.addWidget(self.widget) + self.assertEqual(getrefcount(self.widget), 3) + self.layout.addWidget(self.widget) + self.assertEqual(getrefcount(self.widget), 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qlayout_test.py b/tests/qtgui/qlayout_test.py new file mode 100644 index 000000000..ae773bb0a --- /dev/null +++ b/tests/qtgui/qlayout_test.py @@ -0,0 +1,52 @@ +import unittest +import sys + +from helper import UsesQApplication +from PySide.QtGui import QLayout, QWidget, QPushButton, QWidgetItem + +class MyLayout(QLayout): + def __init__(self, parent=None): + QLayout.__init__(self, parent) + self._list = [] + + def addItem(self, item): + self.add(item) + + def addWidget(self, widget): + self.add(QWidgetItem(widget)) + + def itemAt(self, index): + if index < len(self._list): + return self._list[index] + + return None + + def count(self): + return len(self._list) + + def add(self, item): + self._list.append(item) + + + +#Test if a layout implemented in python, the QWidget.setLayout works +#fine because this implement som layout functions used in glue code of +#QWidget, then in c++ when call a virtual function this need call the QLayout +#function implemented in python + +class QLayoutTest(UsesQApplication): + + def testOwnershipTransfer(self): + b = QPushButton("teste") + l = MyLayout() + l.addWidget(b) + + self.assertEqual(sys.getrefcount(b), 2) + + w = QWidget() + w.setLayout(l) + + self.assertEqual(sys.getrefcount(b), 3) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qlcdnumber_test.py b/tests/qtgui/qlcdnumber_test.py new file mode 100644 index 000000000..eb6a4f396 --- /dev/null +++ b/tests/qtgui/qlcdnumber_test.py @@ -0,0 +1,16 @@ +import unittest + +from PySide.QtGui import QApplication, QLCDNumber + +class QLCDNumberOverflow(unittest.TestCase): + '''Test case for unhandled overflow on QLCDNumber() numDigits argument (see bug #215).''' + + def setUp(self): + self.app = QApplication([]) + + def testnumDigitsOverflow(self): + # NOTE: PyQt4 raises TypeError, but boost.python raises OverflowError + self.assertRaises(OverflowError, QLCDNumber, 840835495615213080) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qlistwidgetitem_test.py b/tests/qtgui/qlistwidgetitem_test.py new file mode 100644 index 000000000..8f96c518f --- /dev/null +++ b/tests/qtgui/qlistwidgetitem_test.py @@ -0,0 +1,25 @@ + +import unittest + +from PySide import QtGui + +from helper import UsesQApplication + +class QListWidgetItemConstructor(UsesQApplication): + + def setUp(self): + super(QListWidgetItemConstructor, self).setUp() + self.widgetList = QtGui.QListWidget() + + def tearDown(self): + del self.widgetList + super(QListWidgetItemConstructor, self).tearDown() + + def testConstructorWithParent(self): + # Bug 235 - QListWidgetItem constructor not saving ownership + QtGui.QListWidgetItem(self.widgetList) + item = self.widgetList.item(0) + self.assertEqual(item.listWidget(), self.widgetList) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qmainwindow_test.py b/tests/qtgui/qmainwindow_test.py new file mode 100644 index 000000000..fce145d53 --- /dev/null +++ b/tests/qtgui/qmainwindow_test.py @@ -0,0 +1,32 @@ +import unittest +import sys + +from PySide import QtGui +from PySide import QtCore + +from helper import UsesQApplication + +class MainWindow(QtGui.QMainWindow): + def __init__(self): + QtGui.QMainWindow.__init__(self) + + self.createToolbar() + + def createToolbar(self): + pointerButton = QtGui.QToolButton() + pointerToolbar = self.addToolBar("Pointer type") + pointerToolbar.addWidget(pointerButton) + + +class TestMainWindow(UsesQApplication): + + def testCreateToolbar(self): + w = MainWindow() + w.show() + QtCore.QTimer.singleShot(1000, self.app.quit) + self.app.exec_() + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qmenu_test.py b/tests/qtgui/qmenu_test.py new file mode 100644 index 000000000..37faf1613 --- /dev/null +++ b/tests/qtgui/qmenu_test.py @@ -0,0 +1,58 @@ + +import unittest + +from PySide.QtGui import QMenu, QKeySequence, QIcon +from PySide.QtCore import SLOT + +from helper import UsesQApplication + +class QMenuAddAction(UsesQApplication): + + def setUp(self): + super(QMenuAddAction, self).setUp() + self.menu = QMenu() + + def tearDown(self): + del self.menu + super(QMenuAddAction, self).tearDown() + + def testAddActionWithoutKeySequenceCallable(self): + # bug #280 + action = self.menu.addAction(self.app.tr('aaa'), lambda : 1) + + def testAddActionKeySequenceCallable(self): + # bug #228 + action = self.menu.addAction(self.app.tr('aaa'), lambda : 1, + QKeySequence(self.app.tr('Ctrl+O'))) + + def testAddActionKeySequenceSlot(self): + action = self.menu.addAction('Quit', self.app, SLOT('quit()'), + QKeySequence('Ctrl+O')) + +class QMenuAddActionWithIcon(UsesQApplication): + + def setUp(self): + super(QMenuAddActionWithIcon, self).setUp() + self.menu = QMenu() + self.icon = QIcon() + + def tearDown(self): + del self.menu + del self.icon + super(QMenuAddActionWithIcon, self).tearDown() + + def testAddActionWithoutKeySequenceCallable(self): + # bug #280 + action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda : 1) + + def testAddActionKeySequenceCallable(self): + # bug #228 + action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda : 1, + QKeySequence(self.app.tr('Ctrl+O'))) + + def testAddActionKeySequenceSlot(self): + action = self.menu.addAction(self.icon, 'Quit', self.app, SLOT('quit()'), + QKeySequence('Ctrl+O')) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qpainter_test.py b/tests/qtgui/qpainter_test.py new file mode 100644 index 000000000..a51d87d64 --- /dev/null +++ b/tests/qtgui/qpainter_test.py @@ -0,0 +1,31 @@ +import unittest + +from PySide.QtGui import QPainter +from PySide.QtCore import QRect, Qt + +class QPainterDrawText(unittest.TestCase): + + def setUp(self): + self.painter = QPainter() + self.text = 'teste!' + + def tearDown(self): + del self.text + del self.painter + + def testDrawText(self): + # bug #254 + rect = self.painter.drawText(100, 100, 100, 100, + Qt.AlignCenter | Qt.TextWordWrap, + self.text) + self.assertNotEqual(rect, None) + + def testDrawTextWithRect(self): + # bug #225 + rect = QRect(100, 100, 100, 100) + self.painter.drawText(rect, Qt.AlignCenter | Qt.TextWordWrap, + self.text) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qpixmap_test.py b/tests/qtgui/qpixmap_test.py new file mode 100644 index 000000000..1bff9fff3 --- /dev/null +++ b/tests/qtgui/qpixmap_test.py @@ -0,0 +1,16 @@ +import unittest + +from helper import UsesQApplication +from PySide.QtGui import QPixmap +from PySide.QtCore import QVariant + +#Only test if is possible create a QPixmap from a QVariant +class QPixmapTest(UsesQApplication): + def testQVariantConstructor(self): + pixmap = QPixmap() + v = QVariant(pixmap) + pixmap_copy = QPixmap(v) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qpushbutton_test.py b/tests/qtgui/qpushbutton_test.py new file mode 100644 index 000000000..984960879 --- /dev/null +++ b/tests/qtgui/qpushbutton_test.py @@ -0,0 +1,30 @@ +import unittest + +from helper import UsesQApplication +from PySide.QtGui import QPushButton, QMenu, QWidget +from PySide.QtCore import QTimer + +class MyWidget(QWidget): + def __init__(self): + QWidget.__init__(self) + + m = QMenu(self) + b = QPushButton("Hello", self) + b.setMenu(m) + + +class QPushButtonTest(UsesQApplication): + def createMenu(self, button): + m = QMenu() + button.setMenu(m) + + def testSetMenu(self): + w = MyWidget() + w.show() + + timer = QTimer.singleShot(100, self.app.quit) + self.app.exec_() + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qregion_test.py b/tests/qtgui/qregion_test.py new file mode 100644 index 000000000..2274d5e92 --- /dev/null +++ b/tests/qtgui/qregion_test.py @@ -0,0 +1,21 @@ +import unittest +import sys + +from PySide.QtGui import QRegion +from PySide.QtCore import QPoint +from helper import UsesQApplication + +class QRegionTest(UsesQApplication): + + def testFunctionUnit(self): + r = QRegion(0, 0, 10, 10) + r2 = QRegion(5, 5, 10, 10) + + ru = r.united(r2) + self.assert_(ru.contains(QPoint(0,0))) + self.assert_(ru.contains(QPoint(5,5))) + self.assert_(ru.contains(QPoint(10,10))) + self.assert_(ru.contains(QPoint(14,14))) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qshortcut_test.py b/tests/qtgui/qshortcut_test.py new file mode 100644 index 000000000..c08cf217c --- /dev/null +++ b/tests/qtgui/qshortcut_test.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +''' Test the QShortcut constructor''' + +import unittest +import sys + +from PySide import QtGui, QtCore + +class Foo(QtGui.QWidget): + def __init__(self): + QtGui.QWidget.__init__(self) + self.ok = False + + def slot_of_foo(self): + self.ok = True + +class MyShortcut(QtGui.QShortcut): + def __init__(self, keys, wdg, slot): + QtGui.QShortcut.__init__(self, keys, wdg, slot) + + def emit_signal(self): + self.emit(QtCore.SIGNAL("activated()")) + +class QAppPresence(unittest.TestCase): + + def testQShortcut(self): + self.qapp = QtGui.QApplication([]) + f = Foo() + + self.sc = MyShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), f, f.slot_of_foo) + QtCore.QTimer.singleShot(0, self.init); + self.qapp.exec_() + self.assertEquals(f.ok, True) + + def init(self): + self.sc.emit_signal(); + self.qapp.quit() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qstandarditemmodel_test.py b/tests/qtgui/qstandarditemmodel_test.py new file mode 100644 index 000000000..d83d856da --- /dev/null +++ b/tests/qtgui/qstandarditemmodel_test.py @@ -0,0 +1,26 @@ +import unittest + +from PySide.QtGui import * +from PySide.QtCore import * + +from helper import UsesQApplication + +class QStandardItemModelTest(UsesQApplication): + + def setUp(self): + super(QStandardItemModelTest, self).setUp() + self.window = QWidget() + self.model = QStandardItemModel(0, 3, self.window) + + def tearDown(self): + del self.window + del self.model + super(QStandardItemModelTest, self).tearDown() + + def testInsertRow(self): + # bug #227 + self.model.insertRow(0) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qstyle_test.py b/tests/qtgui/qstyle_test.py new file mode 100644 index 000000000..c4a55d67d --- /dev/null +++ b/tests/qtgui/qstyle_test.py @@ -0,0 +1,14 @@ + +import unittest + +from PySide.QtGui import QPixmap, QStyle + +from helper import UsesQApplication + +class StandardPixmap(UsesQApplication): + def testDefaultOptions(self): # Bug 253 + pixmap = self.app.style().standardPixmap(QStyle.SP_DirClosedIcon) + self.assert_(isinstance(pixmap, QPixmap)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qtabwidget_test.py b/tests/qtgui/qtabwidget_test.py new file mode 100644 index 000000000..143f99cab --- /dev/null +++ b/tests/qtgui/qtabwidget_test.py @@ -0,0 +1,21 @@ + +import unittest + +from PySide.QtGui import QTabWidget +from helper import TimedQApplication + +class RemoveTabMethod(TimedQApplication): + def setUp(self): + TimedQApplication.setUp(self) + self.tab = QTabWidget() + + def tearDown(self): + del self.tab + TimedQApplication.tearDown(self) + + + def testRemoveTabPresence(self): + self.assert_(getattr(self.tab, 'removeTab')) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qtoolbar_test.py b/tests/qtgui/qtoolbar_test.py new file mode 100644 index 000000000..1bcf566db --- /dev/null +++ b/tests/qtgui/qtoolbar_test.py @@ -0,0 +1,35 @@ + +'''Test cases for QToolbar''' + +import unittest + +from PySide.QtGui import QToolBar, QMainWindow, QAction + +from helper import UsesQApplication + +class AddActionText(UsesQApplication): + '''Test case for calling QToolbar.addAction passing a text''' + + def setUp(self): + #Acquire resources + super(AddActionText, self).setUp() + self.window = QMainWindow() + self.toolbar = QToolBar() + self.window.addToolBar(self.toolbar) + + def tearDown(self): + #Release resources + super(AddActionText, self).tearDown() + del self.toolbar + del self.window + + def testText(self): + #QToolBar.addAction(text) - add a QToolButton + self.toolbar.addAction('aaaa') + self.assertEqual(len(self.toolbar.actions()), 1) + action = self.toolbar.actions()[0] + self.assert_(isinstance(action, QAction)) + self.assertEqual(action.text(), 'aaaa') + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qtoolbox_test.py b/tests/qtgui/qtoolbox_test.py new file mode 100644 index 000000000..dd0d2c6a5 --- /dev/null +++ b/tests/qtgui/qtoolbox_test.py @@ -0,0 +1,31 @@ + +import unittest + +from PySide.QtGui import QToolBox, QWidget, QIcon + +from helper import UsesQApplication + +class OwnershipControl(UsesQApplication): + + def setUp(self): + super(OwnershipControl, self).setUp() + self.toolbox = QToolBox() + + def tearDown(self): + del self.toolbox + super(OwnershipControl, self).tearDown() + + def testAddItem(self): + # Was losing ownership of the widget. + index = self.toolbox.addItem(QWidget(), 'item') + item = self.toolbox.widget(index) + self.assert_(isinstance(item, QWidget)) + + def testAddItemWithIcon(self): + index = self.toolbox.addItem(QWidget(), QIcon(), 'item') + item = self.toolbox.widget(index) + self.assert_(isinstance(item, QWidget)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qvariant_test.py b/tests/qtgui/qvariant_test.py new file mode 100644 index 000000000..052e67d71 --- /dev/null +++ b/tests/qtgui/qvariant_test.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +'''Test cases for QVariant with QtGui types''' + +import unittest + +from PySide.QtCore import * +from PySide.QtGui import * + +class Dummy(object): + pass + +class QVariantTypeName(unittest.TestCase): + def testQPen(self): + obj = QVariant(QPen(Qt.red)) + self.assertEqual('QPen', obj.typeName()) + + def testQColor(self): + obj = QVariant(QColor(Qt.red)) + self.assertEqual('QColor', obj.typeName()) + + def testGlobalColor(self): + obj = QVariant(Qt.red) + # XXX: PyQt4 returns int instead of QColor like the C++ version + self.assertEqual('QColor', obj.typeName()) + + def testEnums(self): + obj = QVariant(Qt.SolidLine) + self.assertEqual('int', obj.typeName()) + +class QVariantQColorImplicitlyConvertion(unittest.TestCase): + def testConversions(self): + c1 = QColor(0, 0, 0) + v = QVariant(c1) + c2 = QColor(v) + self.assertEqual(c1, c2) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/qwidget_setlayout_test.py b/tests/qtgui/qwidget_setlayout_test.py new file mode 100644 index 000000000..c715396ed --- /dev/null +++ b/tests/qtgui/qwidget_setlayout_test.py @@ -0,0 +1,33 @@ +#!/usr/bin/python + +import unittest + +from PySide.QtGui import QWidget, QVBoxLayout, QPushButton, QApplication, QHBoxLayout +from helper import UsesQApplication + +class QWidgetTest(UsesQApplication): + + def test_setLayout(self): + layout = QVBoxLayout() + btn1 = QPushButton("button_v1") + layout.addWidget(btn1) + + btn2 = QPushButton("button_v2") + layout.addWidget(btn2) + + layout2 = QHBoxLayout() + + btn1 = QPushButton("button_h1") + layout2.addWidget(btn1) + + btn2 = QPushButton("button_h2") + layout2.addWidget(btn2) + + layout.addLayout(layout2) + + widget = QWidget() + widget.setLayout(layout) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/qwidget_test.py b/tests/qtgui/qwidget_test.py new file mode 100644 index 000000000..288db372a --- /dev/null +++ b/tests/qtgui/qwidget_test.py @@ -0,0 +1,18 @@ + +import unittest + +from PySide.QtGui import QWidget +from helper import UsesQApplication + +class QWidgetVisible(UsesQApplication): + + def testBasic(self): + # Also related to bug #244, on existence of setVisible''' + widget = QWidget() + self.assert_(not widget.isVisible()) + widget.setVisible(True) + self.assert_(widget.isVisible()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/reference_count_test.py b/tests/qtgui/reference_count_test.py new file mode 100644 index 000000000..b54986821 --- /dev/null +++ b/tests/qtgui/reference_count_test.py @@ -0,0 +1,71 @@ + +'''Test cases for Reference count when the object is created in c++ side''' + +import unittest + +import sys +import weakref +import gc + + +from PySide.QtCore import Qt, QPointF +from PySide.QtGui import QApplication, QGraphicsScene, QGraphicsRectItem, QPolygonF, QGraphicsPolygonItem, QGraphicsRectItem + +from helper import UsesQApplication + +destroyedRect = False +destroyedPol = False + +def rect_del(o): + global destroyedRect + destroyedRect = True + +def pol_del(o): + global destroyedPol + destroyedPol = True + +class ReferenceCount(UsesQApplication): + + def setUp(self): + super(ReferenceCount, self).setUp() + self.scene = QGraphicsScene() + + def tearDown(self): + super(ReferenceCount, self).tearDown() + + def beforeTest(self): + points = [QPointF(0, 0), QPointF(100, 100), QPointF(0, 100)] + pol = self.scene.addPolygon(QPolygonF(points)) + self.assert_(isinstance(pol, QGraphicsPolygonItem)) + self.wrp = weakref.ref(pol, pol_del) + + #refcount need be 3 because one ref for QGraphicsScene, and one to rect obj + self.assertEqual(sys.getrefcount(pol), 3) + + def testReferenceCount(self): + global destroyedRect + global destroyedPol + + self.beforeTest() + + rect = self.scene.addRect(10.0, 10.0, 10.0, 10.0) + self.assert_(isinstance(rect, QGraphicsRectItem)) + + self.wrr = weakref.ref(rect, rect_del) + + #refcount need be 3 because one ref for QGraphicsScene, and one to rect obj + self.assertEqual(sys.getrefcount(rect), 3) + + del rect + #not destroyed because one ref continue in QGraphicsScene + self.assertEqual(destroyedRect, False) + self.assertEqual(destroyedPol, False) + + del self.scene + + #QGraphicsScene was destroyed and this destroy internal ref to rect + self.assertEqual(destroyedRect, True) + self.assertEqual(destroyedPol, True) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/timed_app_test.py b/tests/qtgui/timed_app_test.py new file mode 100644 index 000000000..4af9a0130 --- /dev/null +++ b/tests/qtgui/timed_app_test.py @@ -0,0 +1,14 @@ + +import unittest + +from helper import TimedQApplication + +class TestTimedApp(TimedQApplication): + '''Simple test case for TimedQApplication''' + + def testFoo(self): + #Simple test of TimedQApplication + self.app.exec_() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtgui/virtual_protected_inheritance_test.py b/tests/qtgui/virtual_protected_inheritance_test.py new file mode 100644 index 000000000..15de37dfb --- /dev/null +++ b/tests/qtgui/virtual_protected_inheritance_test.py @@ -0,0 +1,70 @@ + +'''Test cases for overriding inherited protected virtual methods''' + +import unittest + +from PySide.QtCore import QTimerEvent +from PySide.QtGui import QApplication, QSpinBox + +from helper import UsesQApplication + +class MySpinButton(QSpinBox): + '''Simple example class of overriding QObject.timerEvent''' + + def __init__(self, max_runs=5, app=None): + #Creates a new spinbox that will run and quit + super(MySpinButton, self).__init__() + + if app is None: + app = QApplication([]) + + self.app = app + self.max_runs = max_runs + self.runs = 0 + + def timerEvent(self, event): + #Timer event method + self.runs += 1 + + self.setValue(self.runs) + + if self.runs == self.max_runs: + self.app.quit() + + if not isinstance(event, QTimerEvent): + raise TypeError('Invalid event type. Must be TimerEvent') + +class TimerEventTest(UsesQApplication): + '''Test case for running QObject.timerEvent from inherited class''' + + qapplication = True + + def setUp(self): + #Acquire resources + super(TimerEventTest, self).setUp() + self.widget = MySpinButton(app=self.app) + + def tearDown(self): + #Release resources + del self.widget + super(TimerEventTest, self).tearDown() + + def testMethod(self): + #QWidget.timerEvent overrinding (protected inherited) + timer_id = self.widget.startTimer(0) + + self.app.exec_() + + self.widget.killTimer(timer_id) + + self.assertEqual(self.widget.runs, 5) + + +if __name__ == '__main__': + unittest.main() + #app = QApplication([]) + #widget = MySpinButton(app=app) + #widget.startTimer(500) + #widget.show() + #app.exec_() + diff --git a/tests/qtgui/virtual_pure_override.py b/tests/qtgui/virtual_pure_override.py new file mode 100644 index 000000000..c496e4907 --- /dev/null +++ b/tests/qtgui/virtual_pure_override.py @@ -0,0 +1,48 @@ +#!/usr/bin/python + +import unittest + +from PySide.QtGui import QGraphicsScene, QGraphicsRectItem, QGraphicsView, QApplication, QBrush, QColor +from PySide.QtCore import QTimer +from helper import UsesQApplication + +qgraphics_item_painted = False + +class RoundRectItem(QGraphicsRectItem): + + def __init__(self, x, y, w, h): + QGraphicsRectItem.__init__(self, x, y, w, h) + + def paint(self, painter, qstyleoptiongraphicsitem, qwidget): + global qgraphics_item_painted + qgraphics_item_painted = True + + +class QGraphicsItemTest(UsesQApplication): + + def createRoundRect(self, scene): + item = RoundRectItem(10, 10, 100, 100) + item.setBrush(QBrush(QColor(255, 0, 0))) + scene.addItem(item) + return item + + def quit_app(self): + self.app.quit() + + def test_setParentItem(self): + global qgraphics_item_painted + + scene = QGraphicsScene() + scene.addText("test") + view = QGraphicsView(scene) + + rect = self.createRoundRect(scene) + view.show() + QTimer.singleShot(1000, self.quit_app) + self.app.exec_() + self.assert_(qgraphics_item_painted) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtgui/x11_symbols.py b/tests/qtgui/x11_symbols.py new file mode 100644 index 000000000..29cce150e --- /dev/null +++ b/tests/qtgui/x11_symbols.py @@ -0,0 +1,17 @@ + +''' Test the presence of X11 symbols in QtGui''' + +import unittest + +from PySide.QtGui import QPixmap + +class X11Test(unittest.TestCase): + + def test(self): + self.assert_('handle' in dir(QPixmap)) + self.assert_('x11Info' in dir(QPixmap)) + self.assert_('x11PictureHandle' in dir(QPixmap)) + self.assert_('x11SetDefaultScreen' in dir(QPixmap)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qthelp/test_help.py b/tests/qthelp/test_help.py new file mode 100644 index 000000000..e2ff532a6 --- /dev/null +++ b/tests/qthelp/test_help.py @@ -0,0 +1,14 @@ + +import unittest + +from PySide.QtHelp import QHelpEngine + +from helper import UsesQApplication + +class QHelpEngineCreation(UsesQApplication): + + def testConstructor(self): + helpEngine = QHelpEngine('mycollection.qch') + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtnetwork/http_test.py b/tests/qtnetwork/http_test.py new file mode 100644 index 000000000..28564f5a0 --- /dev/null +++ b/tests/qtnetwork/http_test.py @@ -0,0 +1,48 @@ + +'''Test cases for QHttp''' + +import unittest + +from PySide.QtCore import * +from PySide.QtNetwork import * + +from helper import UsesQApplication + +class HttpSignalsCase(UsesQApplication): + '''Test case for launching QHttp signals''' + + def setUp(self): + super(HttpSignalsCase, self).setUp() + + self.http = QHttp() + self.url = QUrl('http://www.google.com') + self.timer = QTimer.singleShot(250, self.app.quit) + + def tearDown(self): + del self.http + super(HttpSignalsCase, self).tearDown() + + def callback(self, ident): + self.called = True + + def testDefaultArgs(self): + #QHttp signal requestStarted signal + # @bug 114 + QObject.connect(self.http, SIGNAL('requestStarted(int)'), self.callback) + self.http.get(self.url.path()) + + self.app.exec_() + self.assert_(self.called) + +class testHttp(UsesQApplication): + def testRead(self): + header = QHttpRequestHeader("GET", QString(QUrl.toPercentEncoding("/index.html"))) + header.setValue("Host", "qtsoftware.com"); + http = QHttp() + http.setHost("qtsoftware.com") + http.request(header) + data = http.read(100) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtnetwork/tcpserver_test.py b/tests/qtnetwork/tcpserver_test.py new file mode 100644 index 000000000..77f830e36 --- /dev/null +++ b/tests/qtnetwork/tcpserver_test.py @@ -0,0 +1,25 @@ + +'''Test cases for QTCPServer''' + +import unittest + +from PySide.QtNetwork import QTcpServer + +class ListenDefaultArgsCase(unittest.TestCase): + '''Test case for TcpServer.listen with default args''' + + def setUp(self): + #Acquire resources + self.server = QTcpServer() + + def tearDown(self): + #Release resources + del self.server + + def testDefaultArgs(self): + # @bug 108 + #Default arguments for QTcpServer.listen + self.server.listen() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtnetwork/udpsocket_test.py b/tests/qtnetwork/udpsocket_test.py new file mode 100644 index 000000000..26cff7f65 --- /dev/null +++ b/tests/qtnetwork/udpsocket_test.py @@ -0,0 +1,54 @@ + +'''Test cases for QUdpSocket''' + +import unittest + +from PySide.QtCore import QUrl, QObject, SIGNAL, QCoreApplication, QTimer +from PySide.QtNetwork import QUdpSocket, QHostAddress + +class HttpSignalsCase(unittest.TestCase): + '''Test case for bug #124 - readDatagram signature + + QUdpSocket.readDatagram must return a tuple with the datagram, host and + port, while receiving only the max payload size.''' + + def setUp(self): + #Acquire resources + self.app = QCoreApplication([]) + self.socket = QUdpSocket() + self.socket.bind(45454) + self.server = QUdpSocket() + self.timer = QTimer.singleShot(1000, self.app.quit) + self.a = QTimer.singleShot(100, self.broadcast) + #self.a = QTimer() + #self.a.setInterval(100) + #QObject.connect(self.a, SIGNAL('timeout()'), self.broadcast) + #self.a.start() + + def tearDown(self): + #Release resources + del self.socket + del self.server + del self.app + + def broadcast(self): + addr = QHostAddress(QHostAddress.Broadcast) + self.server.writeDatagram('datagram', addr, 45454) + + def callback(self): + while self.socket.hasPendingDatagrams(): + datagram, host, port = self.socket.readDatagram( + self.socket.pendingDatagramSize()) + self.called = True + self.app.quit() + + def testDefaultArgs(self): + #QUdpSocket.readDatagram pythonic return + # @bug 124 + QObject.connect(self.socket, SIGNAL('readyRead()'), self.callback) + self.app.exec_() + + self.assert_(self.called) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtscript/test_base.py b/tests/qtscript/test_base.py new file mode 100644 index 000000000..6ad27e007 --- /dev/null +++ b/tests/qtscript/test_base.py @@ -0,0 +1,4 @@ +from PySide import QtScript + + +#only test if the module import works fine bug #278 diff --git a/tests/qtsql/qsqldatabaseandqueries_test.py b/tests/qtsql/qsqldatabaseandqueries_test.py new file mode 100755 index 000000000..49f220937 --- /dev/null +++ b/tests/qtsql/qsqldatabaseandqueries_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +'''Test cases for QtSql database creation, destruction and queries''' + +import sys +import unittest + +from PySide import QtSql +from PySide.QtCore import QVariant, QString + +class SqlDatabaseCreationDestructionAndQueries(unittest.TestCase): + '''Test cases for QtSql database creation, destruction and queries''' + + def setUp(self): + #Acquire resources + self.assertFalse(QtSql.QSqlDatabase.drivers().isEmpty(), "installed Qt has no DB drivers") + self.assertTrue("QSQLITE" in QtSql.QSqlDatabase.drivers(), "\"QSQLITE\" driver not available in this Qt version") + self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE") + self.db.setDatabaseName(":memory:") + self.assertTrue(self.db.open()) + + def tearDown(self): + #Release resources + self.db.close() + QtSql.QSqlDatabase.removeDatabase(":memory:") + del self.db + + def testTableCreationAndDestruction(self): + #Test table creation and destruction + query = QtSql.QSqlQuery() + query.exec_("CREATE TABLE dummy(id int primary key, dummyfield varchar(20))") + query.exec_("DROP TABLE dummy") + query.clear() + + def testTableInsertionAndRetrieval(self): + #Test table creation, insertion and retrieval + query = QtSql.QSqlQuery() + query.exec_("CREATE TABLE person(id int primary key, " + "firstname varchar(20), lastname varchar(20))") + query.exec_("INSERT INTO person VALUES(101, 'George', 'Harrison')") + query.prepare("INSERT INTO person (id, firstname, lastname) " + "VALUES (:id, :firstname, :lastname)") + query.bindValue(":id", QVariant(102)) + query.bindValue(":firstname", QVariant("John")) + query.bindValue(":lastname", QVariant("Lennon")) + query.exec_() + + lastname = '' + query.exec_("SELECT lastname FROM person where id=101") + self.assertTrue(query.isActive()) + query.next() + lastname = query.value(0).toString() + self.assertEqual(lastname, 'Harrison') + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/qtuitools/test_ui.py b/tests/qtuitools/test_ui.py new file mode 100644 index 000000000..6f599cefb --- /dev/null +++ b/tests/qtuitools/test_ui.py @@ -0,0 +1,14 @@ + +import unittest + +from PySide.QtUiTools import QUiLoader + +from helper import UsesQApplication + +class QUiLoaderCreation(UsesQApplication): + + def testConstructor(self): + loader = QUiLoader() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtwebkit/fox.html b/tests/qtwebkit/fox.html new file mode 100644 index 000000000..e7691eb66 --- /dev/null +++ b/tests/qtwebkit/fox.html @@ -0,0 +1,6 @@ + +Title + +

The quick brown fox jumps over the lazy dog.

+ + diff --git a/tests/qtwebkit/webpage_test.py b/tests/qtwebkit/webpage_test.py new file mode 100644 index 000000000..ed98c9f8d --- /dev/null +++ b/tests/qtwebkit/webpage_test.py @@ -0,0 +1,54 @@ + +'''Test cases for QWebPage''' + +import unittest + +from PySide.QtCore import QObject, SIGNAL, QUrl +from PySide.QtWebKit import QWebPage +from PySide.QtNetwork import QNetworkAccessManager + +from helper import adjust_filename, TimedQApplication + +class TestFindText(TimedQApplication): + '''Test cases for finding text''' + + def setUp(self): + TimedQApplication.setUp(self, timeout=250) + self.page = QWebPage() + QObject.connect(self.page, SIGNAL('loadFinished(bool)'), + self.load_finished) + self.called = False + + def tearDown(self): + #Release resources + del self.page + self.called = False + TimedQApplication.tearDown(self) + + def testFindSelectText(self): + url = QUrl.fromLocalFile(adjust_filename('fox.html', __file__)) + self.page.currentFrame().setUrl(url) + self.app.exec_() + self.assert_(self.called) + + def load_finished(self, ok): + #Callback to check if load was successful + self.assert_(self.page.findText('fox')) + self.assertEqual(self.page.selectedText(), 'fox') + self.app.quit() + if ok: + self.called = True + +class SetNetworkAccessManaterCase(TimedQApplication): + + def testSetNetworkAccessManager(self): + page = QWebPage() + manager = QNetworkAccessManager() + page.setNetworkAccessManager(manager) + + def testNetWorkAccessManager(self): + page = QWebPage() + a = page.networkAccessManager() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/qtwebkit/webview_test.py b/tests/qtwebkit/webview_test.py new file mode 100644 index 000000000..176d4873e --- /dev/null +++ b/tests/qtwebkit/webview_test.py @@ -0,0 +1,48 @@ + +'''Test cases for QWebView''' + +import unittest + +from PySide.QtCore import QObject, SIGNAL, QUrl +from PySide.QtWebKit import QWebView + +from helper import adjust_filename, TimedQApplication + + +class TestLoadFinished(TimedQApplication): + '''Test case for signal QWebView.loadFinished(bool)''' + + def setUp(self): + #Acquire resources + TimedQApplication.setUp(self, timeout=250) + self.view = QWebView() + QObject.connect(self.view, SIGNAL('loadFinished(bool)'), + self.load_finished) + self.called = False + + def tearDown(self): + #Release resources + del self.view + self.called = False + TimedQApplication.tearDown(self) + + def testLoadFinishedFromFile(self): + url = QUrl.fromLocalFile(adjust_filename('fox.html', __file__)) + self.view.setUrl(url) + self.app.exec_() + + self.assert_(self.called) + + def testLoadFinishedFromUrl(self): + url = QUrl('http://www.python.org') + self.view.setUrl(url) + self.app.exec_() + + def load_finished(self, ok): + #Callback to check if load was successful + self.app.quit() + if ok: + self.called = True + +if __name__ == '__main__': + unittest.main() diff --git a/tests/run_test.sh b/tests/run_test.sh new file mode 100755 index 000000000..85058c185 --- /dev/null +++ b/tests/run_test.sh @@ -0,0 +1,13 @@ +#!/usr/bin/python + +# This is a nasty workaround of a CTest limitation +# of setting the environment variables for the test. + +# $1: LD_LIBRARY_PATH +# $2: $PYTHON_PATH +# $3: python executable +# $4: test file + +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$1 +export PYTHONPATH=$PYTHON_PATH:$2 +$3 $4 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() + diff --git a/tests/util/color.py b/tests/util/color.py new file mode 100644 index 000000000..4ddd31cab --- /dev/null +++ b/tests/util/color.py @@ -0,0 +1,12 @@ + +'''Function to print a colored line to terminal''' + +RED='\033[0;31m%s\033[m' + +def print_colored(message, color=RED): + print color % message + +if __name__ == '__main__': + print '42 - the answer' + print_colored("But what's the question?") + print 'Hum?' diff --git a/tests/util/helper.py b/tests/util/helper.py new file mode 100644 index 000000000..e27ee1ed9 --- /dev/null +++ b/tests/util/helper.py @@ -0,0 +1,120 @@ + +'''Helper classes and functions''' + +import os +import unittest + +from random import randint + +from PySide.QtCore import QCoreApplication, QTimer + +try: + from PySide.QtGui import QApplication +except ImportError: + has_gui = False +else: + has_gui = True + +def adjust_filename(filename, orig_mod_filename): + dirpath = os.path.dirname(os.path.abspath(orig_mod_filename)) + return os.path.join(dirpath, filename) + +class BasicPySlotCase(object): + '''Base class that tests python slots and signal emissions. + + Python slots are defined as any callable passed to QObject.connect(). + ''' + def setUp(self): + self.called = False + + def tearDown(self): + try: + del self.args + except: + pass + + def cb(self, *args): + '''Simple callback with arbitrary arguments. + + The test function must setup the 'args' attribute with a sequence + containing the arguments expected to be received by this slot. + Currently only a single connection is supported. + ''' + if tuple(self.args) == args: + self.called = True + else: + raise ValueError('Invalid arguments for callback') + + +_instance = None +_timed_instance = None + +if has_gui: + class UsesQApplication(unittest.TestCase): + '''Helper class to provide QApplication instances''' + + qapplication = True + + def setUp(self): + '''Creates the QApplication instance''' + + # Simple way of making instance a singleton + super(UsesQApplication, self).setUp() + global _instance + if _instance is None: + _instance = QApplication([]) + + self.app = _instance + + def tearDown(self): + '''Deletes the reference owned by self''' + del self.app + super(UsesQApplication, self).tearDown() + + class TimedQApplication(unittest.TestCase): + '''Helper class with timed QApplication exec loop''' + + def setUp(self, timeout=100): + '''Setups this Application. + + timeout - timeout in milisseconds''' + global _timed_instance + if _timed_instance is None: + _timed_instance = QApplication([]) + + self.app = _timed_instance + QTimer.singleShot(timeout, self.app.quit) + + def tearDown(self): + '''Delete resources''' + del self.app + +_core_instance = None + +class UsesQCoreApplication(unittest.TestCase): + '''Helper class for test cases that require an QCoreApplication + Just connect or call self.exit_app_cb. When called, will ask + self.app to exit. + ''' + + def setUp(self): + '''Set up resources''' + + global _core_instance + if _core_instance is None: + _core_instance = QCoreApplication([]) + + self.app = _core_instance + + def tearDown(self): + '''Release resources''' + del self.app + + def exit_app_cb(self): + '''Quits the application''' + self.app.exit(0) + + +def random_string(size=5): + '''Generate random string with the given size''' + return ''.join(map(chr, [randint(33, 126) for x in range(size)])) diff --git a/tests/util/helper.pyc b/tests/util/helper.pyc new file mode 100644 index 000000000..e6c45fa60 Binary files /dev/null and b/tests/util/helper.pyc differ diff --git a/tests/util/module_wrapper/PySide/QtAssistant.py b/tests/util/module_wrapper/PySide/QtAssistant.py new file mode 100644 index 000000000..d0975d51e --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtAssistant.py @@ -0,0 +1,2 @@ + +from PyQt4.QtAssistant import * diff --git a/tests/util/module_wrapper/PySide/QtCore.py b/tests/util/module_wrapper/PySide/QtCore.py new file mode 100644 index 000000000..a6a225649 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtCore.py @@ -0,0 +1,2 @@ + +from PyQt4.QtCore import * diff --git a/tests/util/module_wrapper/PySide/QtDesigner.py b/tests/util/module_wrapper/PySide/QtDesigner.py new file mode 100644 index 000000000..5cf9d5f6d --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtDesigner.py @@ -0,0 +1,2 @@ + +from PyQt4.QtDesigner import * diff --git a/tests/util/module_wrapper/PySide/QtGui.py b/tests/util/module_wrapper/PySide/QtGui.py new file mode 100644 index 000000000..0b8b4e957 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtGui.py @@ -0,0 +1,2 @@ + +from PyQt4.QtGui import * diff --git a/tests/util/module_wrapper/PySide/QtHelp.py b/tests/util/module_wrapper/PySide/QtHelp.py new file mode 100644 index 000000000..dd3fd6cd8 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtHelp.py @@ -0,0 +1,2 @@ + +from PyQt4.QtHelp import * diff --git a/tests/util/module_wrapper/PySide/QtNetwork.py b/tests/util/module_wrapper/PySide/QtNetwork.py new file mode 100644 index 000000000..1a669a421 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtNetwork.py @@ -0,0 +1,2 @@ + +from PyQt4.QtNetwork import * diff --git a/tests/util/module_wrapper/PySide/QtScript.py b/tests/util/module_wrapper/PySide/QtScript.py new file mode 100644 index 000000000..4f6b30e8e --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtScript.py @@ -0,0 +1,2 @@ + +from PyQt4.QtScript import * diff --git a/tests/util/module_wrapper/PySide/QtSql.py b/tests/util/module_wrapper/PySide/QtSql.py new file mode 100644 index 000000000..35dd0a106 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtSql.py @@ -0,0 +1,2 @@ + +from PyQt4.QtSql import * diff --git a/tests/util/module_wrapper/PySide/QtSvg.py b/tests/util/module_wrapper/PySide/QtSvg.py new file mode 100644 index 000000000..f308222b9 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtSvg.py @@ -0,0 +1,2 @@ + +from PyQt4.QtSvg import * diff --git a/tests/util/module_wrapper/PySide/QtTest.py b/tests/util/module_wrapper/PySide/QtTest.py new file mode 100644 index 000000000..95f64006b --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtTest.py @@ -0,0 +1,2 @@ + +from PyQt4.QtTest import * diff --git a/tests/util/module_wrapper/PySide/QtWebKit.py b/tests/util/module_wrapper/PySide/QtWebKit.py new file mode 100644 index 000000000..bffc79968 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtWebKit.py @@ -0,0 +1,2 @@ + +from PyQt4.QtWebKit import * diff --git a/tests/util/module_wrapper/PySide/QtXml.py b/tests/util/module_wrapper/PySide/QtXml.py new file mode 100644 index 000000000..2888a4e49 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtXml.py @@ -0,0 +1,2 @@ + +from PyQt4.QtXml import * diff --git a/tests/util/module_wrapper/PySide/QtXmlPatterns.py b/tests/util/module_wrapper/PySide/QtXmlPatterns.py new file mode 100644 index 000000000..6de76d830 --- /dev/null +++ b/tests/util/module_wrapper/PySide/QtXmlPatterns.py @@ -0,0 +1,2 @@ + +from PyQt4.QtXmlPatterns import * diff --git a/tests/util/module_wrapper/PySide/__init__.py b/tests/util/module_wrapper/PySide/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/util/module_wrapper/PySide/phonon.py b/tests/util/module_wrapper/PySide/phonon.py new file mode 100644 index 000000000..2e4bd72a3 --- /dev/null +++ b/tests/util/module_wrapper/PySide/phonon.py @@ -0,0 +1,2 @@ + +from PyQt4.phonon import * diff --git a/tests/util/processtimer.py b/tests/util/processtimer.py new file mode 100755 index 000000000..1991746ac --- /dev/null +++ b/tests/util/processtimer.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import time,os + +class TimeoutException(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + +class ProcessTimer(object): + '''Timeout function for controlling a subprocess.Popen instance. + + Naive implementation using busy loop, see later other means + of doing this. + ''' + + def __init__(self, proc, timeout): + self.proc = proc + self.timeout = timeout + + def waitfor(self): + time_passed = 0 + while(self.proc.poll() is None and time_passed < self.timeout): + time_passed = time_passed + 1 + time.sleep(1) + + if time_passed >= self.timeout: + raise TimeoutException("Timeout expired, possible deadlock") + +if __name__ == "__main__": + #simple example + + from subprocess import Popen + + proc = Popen(['sleep','10']) + t = ProcessTimer(proc,5) + try: + t.waitfor() + except TimeoutException: + print "timeout - PID: %d" % (t.proc.pid) + #TODO: detect SO and kill accordingly + #Linux + os.kill(t.proc.pid, 9) + #Windows (not tested) + #subprocess.Popen("taskkill /F /T /PID %i"%handle.pid , shell=True) + print "exit code: %d" % (t.proc.poll()) + diff --git a/tests/util/pyqt_diff.py b/tests/util/pyqt_diff.py new file mode 100644 index 000000000..b270750ed --- /dev/null +++ b/tests/util/pyqt_diff.py @@ -0,0 +1,35 @@ + +'''Script to show the difference between PyQt4 and ours''' + +import sys + +from color import print_colored + +def check_module_diff(module_name): + '''Difference between PySide and PyQt4 versions of qt bindings. + Returns a tuple with the members present only on PySide and only on PyQt4''' + boost_module = getattr(__import__('PySide.' + module_name), module_name) + orig_module = getattr(__import__('PyQt4.' + module_name), module_name) + + boost_set = set(dir(boost_module)) + orig_set = set(dir(orig_module)) + + return sorted(boost_set - orig_set), sorted(orig_set - boost_set) + + +def main(argv=None): + if argv is None: + argv = sys.argv + + module_name = argv[1] if len(argv) >= 2 else 'QtCore' + + only_boost, only_orig = check_module_diff(module_name) + + print_colored('Only on Boost version') + print only_boost + + print_colored('Only on SIP version') + print only_orig + +if __name__ == '__main__': + main() diff --git a/tests/util/pyqtcheck.py b/tests/util/pyqtcheck.py new file mode 100755 index 000000000..a75744a11 --- /dev/null +++ b/tests/util/pyqtcheck.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +import sys +from optparse import OptionParser + +import PyQt4 +from PyQt4 import QtCore, QtGui, QtNetwork + +modules = [QtCore, QtGui, QtNetwork] + +def search(klass, method=None): + for module in modules: + try: + klass_obj = getattr(module, klass) + print "%s *found* on module %s" % (klass, module.__name__) + except AttributeError: + print "%s not found on module %s" % (klass, module.__name__) + continue + + if method is None: + continue + + try: + meth_obj = getattr(klass_obj, method) + + meth_name = ".".join([klass, method]) + klass_name = ".".join([module.__name__, klass]) + print "\"%s\" *found* on class %s" % (meth_name, klass_name) + except AttributeError: + print "\"%s\" not found on class %s" % (method, klass) + + +def main(argv=None): + if argv is None: + argv = sys.argv[1:] + + try: + klass, method = argv[0].split(".") + except: + klass = argv[0] + method = None + + search(klass, method) + +if __name__ == '__main__': + main() diff --git a/tests/util/rename_imports.sh b/tests/util/rename_imports.sh new file mode 100755 index 000000000..fd3ba1c62 --- /dev/null +++ b/tests/util/rename_imports.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Rename import statements from .py script to use a specific module name +set -e + +if [ $# -lt 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +old_name=$1; shift +new_name=$1; shift + +find "$@" -name "*.py" -exec sed -ri "s/(import|from) $old_name/\1 $new_name/" '{}' \; diff --git a/tests/util/test_processtimer.py b/tests/util/test_processtimer.py new file mode 100644 index 000000000..816ce5165 --- /dev/null +++ b/tests/util/test_processtimer.py @@ -0,0 +1,66 @@ + +'Tests for processtimer.py' + +import unittest +import os + +from subprocess import Popen, PIPE +from processtimer import TimeoutException, ProcessTimer + +class TimeoutTest(unittest.TestCase): + + def tearDown(self): + try: + os.kill(self.proc.pid, 9) + except OSError: + pass + + def testRaise(self): + self.proc = Popen(['python2.5', '-c', 'while True: pass' ], stdout=PIPE, stderr=PIPE) + timer = ProcessTimer(self.proc, 1) + self.assertRaises(TimeoutException, timer.waitfor) + +class SimpleTest(unittest.TestCase): + + def tearDown(self): + try: + os.kill(self.proc.pid, 9) + except OSError: + pass + def testSimple(self): + self.proc = Popen(['python2.5', '-c', '"print"'], stdout=PIPE, stderr=PIPE) + timer = ProcessTimer(self.proc, 10) + timer.waitfor() + +class TestEchoOutput(unittest.TestCase): + + def tearDown(self): + try: + os.kill(self.proc.pid, 9) + except OSError: + pass + + def testOutput(self): + self.proc = Popen(['python2.5', '-c', 'print 1',], stdout=PIPE, stderr=PIPE) + timer = ProcessTimer(self.proc, 1) + timer.waitfor() + self.assertEqual(self.proc.stdout.read().strip(), '1') + +class TestRetCode(unittest.TestCase): + + def tearDown(self): + try: + os.kill(self.proc.pid, 9) + except OSError: + pass + + def testSimple(self): + self.proc = Popen(['python2.5', '-c', 'print 1'], stdout=PIPE, stderr=PIPE) + timer = ProcessTimer(self.proc, 10) + timer.waitfor() + + self.assertEqual(self.proc.poll(), 0) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/util/use_pyqt4.sh b/tests/util/use_pyqt4.sh new file mode 100644 index 000000000..5b88fa5c7 --- /dev/null +++ b/tests/util/use_pyqt4.sh @@ -0,0 +1,3 @@ + +OLD_PYTHONPATH=$PYTHONPATH +PYTHONPATH=`pwd`/util/module_wrapper:$PYTHONPATH diff --git a/tests/util/use_pyside.sh b/tests/util/use_pyside.sh new file mode 100644 index 000000000..516207473 --- /dev/null +++ b/tests/util/use_pyside.sh @@ -0,0 +1,3 @@ + +PYTHONPATH=$OLD_PYTHONPATH +unset OLD_PYTHONPATH diff --git a/tests/util/valgrind-python.supp b/tests/util/valgrind-python.supp new file mode 100644 index 000000000..a54b451b3 --- /dev/null +++ b/tests/util/valgrind-python.supp @@ -0,0 +1,349 @@ +# +# This is a valgrind suppression file that should be used when using valgrind. +# +# Here's an example of running valgrind: +# +# cd python/dist/src +# valgrind --tool=memcheck --suppressions=Misc/valgrind-python.supp \ +# ./python -E -tt ./Lib/test/regrtest.py -u bsddb,network +# +# You must edit Objects/obmalloc.c and uncomment Py_USING_MEMORY_DEBUGGER +# to use the preferred suppressions with Py_ADDRESS_IN_RANGE. +# +# If you do not want to recompile Python, you can uncomment +# suppressions for PyObject_Free and PyObject_Realloc. +# +# See Misc/README.valgrind for more information. + +# all tool names: Addrcheck,Memcheck,cachegrind,helgrind,massif +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64) + Memcheck:Value8 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:Py_ADDRESS_IN_RANGE +} + +# +# Leaks (including possible leaks) +# Hmmm, I wonder if this masks some real leaks. I think it does. +# Will need to fix that. +# + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:realloc + fun:_PyObject_GC_Resize + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_New + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_NewVar + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +# +# Non-python specific leaks +# + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:memalign + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:PyObject_Realloc +} + +### +### All the suppressions below are for errors that occur within libraries +### that Python uses. The problems to not appear to be related to Python's +### use of the libraries. +### + +{ + Generic gentoo ld problems + Memcheck:Cond + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so +} + +{ + DBM problems, see test_dbm + Memcheck:Param + write(buf) + fun:write + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_close +} + +{ + DBM problems, see test_dbm + Memcheck:Value8 + fun:memmove + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + DBM problems, see test_dbm + Memcheck:Cond + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + DBM problems, see test_dbm + Memcheck:Cond + fun:memmove + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + GDBM problems, see test_gdbm + Memcheck:Param + write(buf) + fun:write + fun:gdbm_open + +} + +{ + ZLIB problems, see test_gzip + Memcheck:Cond + obj:/lib/libz.so.1.2.3 + obj:/lib/libz.so.1.2.3 + fun:deflate +} + +{ + Avoid problems w/readline doing a putenv and leaking on exit + Memcheck:Leak + fun:malloc + fun:xmalloc + fun:sh_set_lines_and_columns + fun:_rl_get_screen_size + fun:_rl_init_terminal_io + obj:/lib/libreadline.so.4.3 + fun:rl_initialize +} + +### +### These occur from somewhere within the SSL, when running +### test_socket_sll. They are too general to leave on by default. +### +###{ +### somewhere in SSL stuff +### Memcheck:Cond +### fun:memset +###} +###{ +### somewhere in SSL stuff +### Memcheck:Value4 +### fun:memset +###} +### +###{ +### somewhere in SSL stuff +### Memcheck:Cond +### fun:MD5_Update +###} +### +###{ +### somewhere in SSL stuff +### Memcheck:Value4 +### fun:MD5_Update +###} + +# +# All of these problems come from using test_socket_ssl +# +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_bin2bn +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_num_bits_word +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:BN_num_bits_word +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_mod_exp_mont_word +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_mod_exp_mont +} + +{ + from test_socket_ssl + Memcheck:Param + write(buf) + fun:write + obj:/usr/lib/libcrypto.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:RSA_verify +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:RSA_verify +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:DES_set_key_unchecked +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:DES_encrypt2 +} + +{ + from test_socket_ssl + Memcheck:Cond + obj:/usr/lib/libssl.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Value4 + obj:/usr/lib/libssl.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BUF_MEM_grow_clean +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:memcpy + fun:ssl3_read_bytes +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:SHA1_Update +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:SHA1_Update +} + + -- cgit v1.2.3