Mercurial > pub > dyncall > bindings
diff python/pydc/test/types.py @ 29:6cc2b7fc7ea2
bigger pydc update:
- cleanups and refactoring
- python 2 fixes in var conversions (especially w/ respect to int vs long)
- fix to pydc.free() which didn't work at all
- fix to return python bool as actual bool
- test lib covering all conversions (manual verification, though :-/)
author | Tassilo Philipp |
---|---|
date | Wed, 08 Apr 2020 22:17:43 +0200 |
parents | |
children | 2682a627168c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/pydc/test/types.py Wed Apr 08 22:17:43 2020 +0200 @@ -0,0 +1,182 @@ +import pydc +import sys +import platform + + + + +def theader(title): + print(title) + print('%8s %20s %16s %-20s %12s %-12s -> %16s %-16s # %s' % ('DC_SIG', 'C_RET_T', 'C_FSYM', 'C_PARAMLIST', 'PYTHON_ARG_T', 'IN_ARGS', 'RET_VAL', 'PYTHON_RET_T', 'NOTES')) + + +def t(lib, dcsig, c_rtype, c_fsym, c_paramlist, extra_msg, *args): + try: + fp = pydc.find(lib, c_fsym) + r = pydc.call(fp, dcsig, *args) + rt = type(r).__name__ + except: + r = '[EXCEPTION]' + rt = '!' + extra_msg += ' "'+str(sys.exc_info()[1])+'"' + + inarg_types = '('+','.join(map(lambda x: type(x).__name__, args))+')' + inargs = ','.join(map(str, args)) + print('%8s %20s %16s %-20s %12s %-12s -> %16.16s %-16s # %s' % (dcsig, c_rtype, c_fsym, c_paramlist, inarg_types, inargs, str(r), '('+rt+')', extra_msg)) + + + +# some libc tests ------------------ + +try: + if sys.platform == "win32": + libc = pydc.load("msvcrt") + elif sys.platform == "darwin": + libc = pydc.load("/usr/lib/libc.dylib") + elif "bsd" in sys.platform: + libc = pydc.load("/usr/lib/libc.so") + #libc = pydc.load("/lib/libc.so.7") + elif platform.architecture()[0] == "64bit": + libc = pydc.load("/lib64/libc.so.6") + else: + libc = pydc.load("/lib/libc.so.6") + + theader('CLIB TESTS:') + + # void() + t(libc, ")v", "void", "sranddev", "(void)", '') + + # int() + t(libc, ")i", "int", "rand", "(void)", '') + + # void(unsigned int) + t(libc, "I)v", "void", "srand", "(int)", '', 123) + + # int() (and one different helper call for test) + t(libc, ")i", "int", "rand", "(void)", 'with seed <------,') + t(libc, "I)v", "void", "srand", "(int)", 'set same seed |', 123) + t(libc, ")i", "int", "rand", "(void)", 'should be same result...') + t(libc, ")i", "int", "rand", "(void)", '...and now different result') + + # int(int) + t(libc, "i)i", "int", "abs", "(int)", ' 10 => 10', 10) + t(libc, "i)i", "int", "abs", "(int)", ' 0 => 0', 0) + t(libc, "i)i", "int", "abs", "(int)", ' -9209 => 9209', -9209) + + # long(long) + t(libc, "j)j", "long", "labs", "(long)", ' 48 => 48', 48) + t(libc, "j)j", "long", "labs", "(long)", ' 0 => 0', 0) + t(libc, "j)j", "long", "labs", "(long)", '-4271477497 => 4271477497', -4271477497) + + # long long(long long) + t(libc, "l)l", "long long", "labs", "(long long)", ' 6334810198 => 6334810198', 6334810198) + t(libc, "l)l", "long long", "labs", "(long long)", ' 1 => 1', 1) + t(libc, "l)l", "long long", "labs", "(long long)", ' 0 => 0', 0) + t(libc, "l)l", "long long", "labs", "(long long)", ' -1 => 1', -1) + t(libc, "l)l", "long long", "labs", "(long long)", '-7358758407 => 7358758407', -7358758407) + + pydc.free(libc) +except: + print("skipping clib tests because: "+str(sys.exc_info()[1])) + + +# tests with own .so for testing all conversions ------------------ + +l = pydc.load(sys.path[0]+"/test.so") + +# test all possible arg types and their conversions to and from python, with +# specific focus/tests in areas where python 2 and 3 differ +theader('ARG & RET TYPE CONVERSION TESTS:') +t(l, "B)B", "int", "i_plus_one", "(int)", ' False => True (using int func in C)', False) +t(l, "c)c", "char", "c_plus_one", "(char)", ' "a" (97) => 98', 'a') +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' "a" (97) => 98', 'a') +t(l, "c)c", "char", "c_plus_one", "(char)", ' -2 => -1', -2) +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' 10 => 11', 10) +t(l, "s)s", "short", "s_plus_one", "(short)", ' 10 => 11', 10) +t(l, "S)S", "unsigned short", "us_plus_one", "(unsigned short)", ' 10 => 11', 10) +t(l, "i)i", "int", "i_plus_one", "(int)", ' 10 => 11', 10) +t(l, "I)I", "unsigned int", "ui_plus_one", "(unsigned int)", ' 10 => 11', 10) +t(l, "j)j", "long", "l_plus_one", "(long)", ' 10 => 11', 10) +t(l, "J)J", "unsigned long", "ul_plus_one", "(unsigned long)", ' 10 => 11', 10) +t(l, "l)l", "long long", "ll_plus_one", "(long long)", ' 10 => 11', 10) +t(l, "L)L", "unsigned long long", "ull_plus_one", "(unsigned long long)", ' 10 => 11', 10) +t(l, "f)f", "float", "f_plus_one", "(float)", ' -1.23 => -0.23', -1.23) +t(l, "d)d", "double", "d_plus_one", "(double)", ' 5.67 => 6.67', 5.67) +t(l, "Z)Z", "const char*", "cc_plus_one", "(const char*)", '"lose char" => "ose char"', 'lose char') +t(l, "p)Z", "const char*", "cc_plus_one", "(const char*)", '"w/pointer" => "/pointer"', 'w/pointer') +t(l, "p)p", "const char*", "cc_plus_one", "(const char*)", ' "x" => p+1 (retval is prob odd addr)', 'x') +t(l, "p)p", "const char*", "cc_plus_one", "(const char*)", ' 0xdeadc0de => 0xdeadc0de+1=3735929055',0xdeadc0de) + +# tested checked value conversions +theader('ARG & RET TYPE CONVERSION TESTS FOR RANGE CHECKED TYPES:') +t(l, "c)c", "char", "c_plus_one", "(char)", ' "~" => 127', '~') +t(l, "c)c", "char", "c_plus_one", "(char)", ' "~" => 127', '~') +t(l, "c)c", "char", "c_plus_one", "(char)", ' "" => input exc:', '') +t(l, "c)c", "char", "c_plus_one", "(char)", ' "" => input exc:', '') +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' "ab" => input exc:', 'ab') +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' "ab" => input exc:', 'ab') + +t(l, "c)c", "char", "c_plus_one", "(char)", ' -128 => -127', -128) +t(l, "c)c", "char", "c_plus_one", "(char)", ' 127 => -128 (wrapped)', 127) +t(l, "c)c", "char", "c_plus_one", "(char)", ' -129 => input exc:', -129) +t(l, "c)c", "char", "c_plus_one", "(char)", ' 128 => input exc:', 128) + +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' 0 => 1', 0) +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' 255 => 0 (wrapped)', 255) +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' -1 => input exc:', -1) +t(l, "C)C", "unsigned char", "uc_plus_one", "(unsigned char)", ' 256 => input exc:', 256) + +t(l, "s)s", "short", "s_plus_one", "(short)", ' -32768 => -32767', -32768) +t(l, "s)s", "short", "s_plus_one", "(short)", ' 32767 => -32768 (wrapped)', 32767) +t(l, "s)s", "short", "s_plus_one", "(short)", ' -32769 => input exc:', -32769) +t(l, "s)s", "short", "s_plus_one", "(short)", ' 32768 => input exc:', 32768) + +t(l, "S)S", "unsigned short", "us_plus_one", "(unsigned short)", ' 0 => 1', 0) +t(l, "S)S", "unsigned short", "us_plus_one", "(unsigned short)", ' 65535 => 0 (wrapped)', 65535) +t(l, "S)S", "unsigned short", "us_plus_one", "(unsigned short)", ' -1 => input exc:', -1) +t(l, "S)S", "unsigned short", "us_plus_one", "(unsigned short)", ' 65536 => input exc:', 65536) + + +# int +# rand(void); +#rand() +#define DC_SIGCHAR_VOID 'v' ra +#define DC_SIGCHAR_BOOL 'B' +#define DC_SIGCHAR_CHAR 'c' 2 versions +#define DC_SIGCHAR_UCHAR 'C' +#define DC_SIGCHAR_SHORT 's' +#define DC_SIGCHAR_USHORT 'S' +#define DC_SIGCHAR_INT 'i' r +#define DC_SIGCHAR_UINT 'I' a +#define DC_SIGCHAR_LONG 'j' ra +#define DC_SIGCHAR_ULONG 'J' +#define DC_SIGCHAR_LONGLONG 'l' ra +#define DC_SIGCHAR_ULONGLONG 'L' +#define DC_SIGCHAR_FLOAT 'f' +#define DC_SIGCHAR_DOUBLE 'd' +#define DC_SIGCHAR_POINTER 'p' +#define DC_SIGCHAR_STRING 'Z' +#define DC_SIGCHAR_STRUCT 'T' +#define DC_SIGCHAR_ENDARG ')' /* also works for end struct */ + + + +# SIG | FROM PYTHON 2 | FROM PYTHON 3 @@@ | C/C++ | TO PYTHON 2 | TO PYTHON 3 @@@ +# ----+------------------------------------+------------------------------------+---------------------------------+------------------------------------+----------------------------------- +# 'v' | | | void | ?NoneType (returned for "xxx)v") | NoneType (returned for "xxx)v") +# 'B' | ?PyBool | ?PyBool | bool | ?PyBool | ?PyBool +# 'c' | ?PyInt (range checked) | ?PyLong (range checked) | char | ?PyInt | ?PyLong +# 'C' | ?PyInt (range checked) | ?PyLong (range checked) | unsigned char | ?PyInt | ?PyLong +# 's' | ?PyInt (range checked) | ?PyLong (range checked) | short | ?PyInt | ?PyLong +# 'S' | ?PyInt (range checked) | ?PyLong (range checked) | unsigned short | ?PyInt | ?PyLong +# 'i' | ?PyInt | ?PyLong | int | ?PyInt | ?PyLong +# 'I' | ?PyInt | ?PyLong | unsigned int | ?PyInt | ?PyLong +# 'j' | ?PyLong | ?PyLong | long | ?PyLong | ?PyLong +# 'J' | ?PyLong | ?PyLong | unsigned long | ?PyLong | ?PyLong +# 'l' | ?PyLongLong | ?PyLongLong | long long | ?PyLongLong | ?PyLongLong +# 'L' | ?PyLongLong | ?PyLongLong | unsigned long long | ?PyLongLong | ?PyLongLong +# 'f' | ?PyFloat (cast to single precision) | ?PyFloat (cast to single precision) | float | ?PyFloat (cast to double precision) | ?PyFloat (cast to double precision) +# 'd' | ?PyFloat | ?PyFloat | double | ?PyFloat | ?PyFloat +# 'p' | ?PyUnicode/PyString/PyLong | ?PyUnicode/PyBytes/PyLong | void* | ?Py_ssize_t | ?Py_ssize_t +# 'Z' | ?PyUnicode/PyString | ?PyUnicode/PyBytes | const char* (UTF-8 for unicode) | ?PyString | ?PyUnicode +