1 # -*- coding: UTF-8 -*- 2 3 """ 4 Test libpython.py. This is already partly tested by test_libcython_in_gdb and 5 Lib/test/test_gdb.py in the Python source. These tests are run in gdb and 6 called from test_libcython_in_gdb.main() 7 """ 8 9 import os 10 import sys 11 12 import gdb 13 14 from Cython.Debugger import libcython 15 from Cython.Debugger import libpython 16 17 import test_libcython_in_gdb 18 from test_libcython_in_gdb import _debug, inferior_python_version 19 20 21 class TestPrettyPrinters(test_libcython_in_gdb.DebugTestCase): 22 """ 23 Test whether types of Python objects are correctly inferred and that 24 the right libpython.PySomeTypeObjectPtr classes are instantiated. 25 26 Also test whether values are appropriately formatted (don't be too 27 laborious as Lib/test/test_gdb.py already covers this extensively). 28 29 Don't take care of decreffing newly allocated objects as a new 30 interpreter is started for every test anyway. 31 """ 32 33 def setUp(self): 34 super(TestPrettyPrinters, self).setUp() 35 self.break_and_run('b = c = d = 0') 36 37 def get_pyobject(self, code): 38 value = gdb.parse_and_eval(code) 39 assert libpython.pointervalue(value) != 0 40 return value 41 42 def pyobject_fromcode(self, code, gdbvar=None): 43 if gdbvar is not None: 44 d = {'varname':gdbvar, 'code':code} 45 gdb.execute('set $%(varname)s = %(code)s' % d) 46 code = '$' + gdbvar 47 48 return libpython.PyObjectPtr.from_pyobject_ptr(self.get_pyobject(code)) 49 50 def get_repr(self, pyobject): 51 return pyobject.get_truncated_repr(libpython.MAX_OUTPUT_LEN) 52 53 def alloc_bytestring(self, string, gdbvar=None): 54 if inferior_python_version < (3, 0): 55 funcname = 'PyString_FromStringAndSize' 56 else: 57 funcname = 'PyBytes_FromStringAndSize' 58 59 assert '"' not in string 60 61 # ensure double quotes 62 code = '(PyObject *) %s("%s", %d)' % (funcname, string, len(string)) 63 return self.pyobject_fromcode(code, gdbvar=gdbvar) 64 65 def alloc_unicodestring(self, string, gdbvar=None): 66 self.alloc_bytestring(string.encode('UTF-8'), gdbvar='_temp') 67 68 postfix = libpython.get_inferior_unicode_postfix() 69 funcname = 'PyUnicode%s_FromEncodedObject' % (postfix,) 70 71 return self.pyobject_fromcode( 72 '(PyObject *) %s($_temp, "UTF-8", "strict")' % funcname, 73 gdbvar=gdbvar) 74 75 def test_bytestring(self): 76 bytestring = self.alloc_bytestring("spam") 77 78 if inferior_python_version < (3, 0): 79 bytestring_class = libpython.PyStringObjectPtr 80 expected = repr("spam") 81 else: 82 bytestring_class = libpython.PyBytesObjectPtr 83 expected = "b'spam'" 84 85 self.assertEqual(type(bytestring), bytestring_class) 86 self.assertEqual(self.get_repr(bytestring), expected) 87 88 def test_unicode(self): 89 unicode_string = self.alloc_unicodestring(u"spam ") 90 91 expected = "'spam '" 92 if inferior_python_version < (3, 0): 93 expected = 'u' + expected 94 95 self.assertEqual(type(unicode_string), libpython.PyUnicodeObjectPtr) 96 self.assertEqual(self.get_repr(unicode_string), expected) 97 98 def test_int(self): 99 if inferior_python_version < (3, 0): 100 intval = self.pyobject_fromcode('PyInt_FromLong(100)') 101 self.assertEqual(type(intval), libpython.PyIntObjectPtr) 102 self.assertEqual(self.get_repr(intval), '100') 103 104 def test_long(self): 105 longval = self.pyobject_fromcode('PyLong_FromLong(200)', 106 gdbvar='longval') 107 assert gdb.parse_and_eval('$longval->ob_type == &PyLong_Type') 108 109 self.assertEqual(type(longval), libpython.PyLongObjectPtr) 110 self.assertEqual(self.get_repr(longval), '200') 111 112 def test_frame_type(self): 113 frame = self.pyobject_fromcode('PyEval_GetFrame()') 114 115 self.assertEqual(type(frame), libpython.PyFrameObjectPtr) 116