Home | History | Annotate | Download | only in Tests
      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