import textwrap import unittest from test import support from .util import setup_module, DebuggerTests def setUpModule(): setup_module() @unittest.skipIf(support.python_is_optimized(), "Python was compiled with optimizations") @support.requires_resource('cpu') class CFunctionTests(DebuggerTests): 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) # 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 def check_pycfunction(self, func_name, args): 'Verify that "py-bt" displays invocations of PyCFunction instances' if support.verbose: print() # Various optimizations multiply the code paths by which these are # called, so test a variety of calling conventions. for obj in ( '_testcapi', '_testcapi.MethClass', '_testcapi.MethClass()', '_testcapi.MethStatic()', # XXX: bound methods don't yet give nice tracebacks # '_testcapi.MethInstance()', ): 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', '')