2023-09-28 08:24:15 -03:00
|
|
|
import textwrap
|
|
|
|
import unittest
|
|
|
|
from test import support
|
|
|
|
|
|
|
|
from .util import setup_module, DebuggerTests
|
|
|
|
|
|
|
|
|
|
|
|
def setUpModule():
|
|
|
|
setup_module()
|
|
|
|
|
|
|
|
|
2023-09-28 14:04:01 -03:00
|
|
|
@unittest.skipIf(support.python_is_optimized(),
|
2023-09-28 08:24:15 -03:00
|
|
|
"Python was compiled with optimizations")
|
|
|
|
@support.requires_resource('cpu')
|
|
|
|
class CFunctionTests(DebuggerTests):
|
2023-09-28 14:04:01 -03:00
|
|
|
def check(self, func_name, cmd):
|
|
|
|
# Verify with "py-bt":
|
|
|
|
gdb_output = self.get_stack_trace(
|
|
|
|
cmd,
|
|
|
|
breakpoint=func_name,
|
|
|
|
cmds_after_breakpoint=['bt', 'py-bt'],
|
|
|
|
# bpo-45207: Ignore 'Function "meth_varargs" not
|
|
|
|
# defined.' message in stderr.
|
|
|
|
ignore_stderr=True,
|
|
|
|
)
|
|
|
|
self.assertIn(f'<built-in method {func_name}', gdb_output)
|
|
|
|
|
2023-09-28 08:24:15 -03:00
|
|
|
# Some older versions of gdb will fail with
|
|
|
|
# "Cannot find new threads: generic error"
|
|
|
|
# unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
|
|
|
|
#
|
|
|
|
# gdb will also generate many erroneous errors such as:
|
|
|
|
# Function "meth_varargs" not defined.
|
|
|
|
# This is because we are calling functions from an "external" module
|
|
|
|
# (_testcapimodule) rather than compiled-in functions. It seems difficult
|
|
|
|
# to suppress these. See also the comment in DebuggerTests.get_stack_trace
|
2023-09-28 14:04:01 -03:00
|
|
|
def check_pycfunction(self, func_name, args):
|
2023-09-28 08:24:15 -03:00
|
|
|
'Verify that "py-bt" displays invocations of PyCFunction instances'
|
2023-09-28 14:04:01 -03:00
|
|
|
|
|
|
|
if support.verbose:
|
|
|
|
print()
|
|
|
|
|
2023-09-28 08:24:15 -03:00
|
|
|
# Various optimizations multiply the code paths by which these are
|
|
|
|
# called, so test a variety of calling conventions.
|
2023-09-28 14:04:01 -03:00
|
|
|
for obj in (
|
|
|
|
'_testcapi',
|
|
|
|
'_testcapi.MethClass',
|
|
|
|
'_testcapi.MethClass()',
|
|
|
|
'_testcapi.MethStatic()',
|
|
|
|
|
|
|
|
# XXX: bound methods don't yet give nice tracebacks
|
|
|
|
# '_testcapi.MethInstance()',
|
2023-09-28 08:24:15 -03:00
|
|
|
):
|
2023-09-28 14:04:01 -03:00
|
|
|
with self.subTest(f'{obj}.{func_name}'):
|
|
|
|
call = f'{obj}.{func_name}({args})'
|
|
|
|
cmd = textwrap.dedent(f'''
|
|
|
|
import _testcapi
|
|
|
|
def foo():
|
|
|
|
{call}
|
|
|
|
def bar():
|
|
|
|
foo()
|
|
|
|
bar()
|
|
|
|
''')
|
|
|
|
if support.verbose:
|
|
|
|
print(f' test call: {call}', flush=True)
|
|
|
|
|
|
|
|
self.check(func_name, cmd)
|
|
|
|
|
|
|
|
def test_pycfunction_noargs(self):
|
|
|
|
self.check_pycfunction('meth_noargs', '')
|
|
|
|
|
|
|
|
def test_pycfunction_o(self):
|
|
|
|
self.check_pycfunction('meth_o', '[]')
|
|
|
|
|
|
|
|
def test_pycfunction_varargs(self):
|
|
|
|
self.check_pycfunction('meth_varargs', '')
|
|
|
|
|
|
|
|
def test_pycfunction_varargs_keywords(self):
|
|
|
|
self.check_pycfunction('meth_varargs_keywords', '')
|
|
|
|
|
|
|
|
def test_pycfunction_fastcall(self):
|
|
|
|
self.check_pycfunction('meth_fastcall', '')
|
|
|
|
|
|
|
|
def test_pycfunction_fastcall_keywords(self):
|
|
|
|
self.check_pycfunction('meth_fastcall_keywords', '')
|