diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-21 14:51:26 -0300 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-21 14:52:09 -0300 |
commit | 9af36fbb64f19842c0cc797c0b586b3a686805e8 (patch) | |
tree | 6bbc050ded0f85517ea75f5dc6dc1ed172168248 /tests/util | |
parent | aa12538d63685ef8f75adaa79411b751929b727d (diff) |
Added all original pyside unit tests to the shiboken version.
Diffstat (limited to 'tests/util')
26 files changed, 724 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 000000000..e6c45fa60 --- /dev/null +++ b/tests/util/helper.pyc 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 --- /dev/null +++ b/tests/util/module_wrapper/PySide/__init__.py 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 <old_name> <new_name> <directories...>" + 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 +} + + |