(root)/
Python-3.11.7/
Lib/
test/
test_gdb/
test_cfunction.py
       1  import textwrap
       2  import unittest
       3  from test import support
       4  
       5  from .util import setup_module, DebuggerTests
       6  
       7  
       8  def setUpModule():
       9      setup_module()
      10  
      11  
      12  @unittest.skipIf(support.python_is_optimized(),
      13                   "Python was compiled with optimizations")
      14  @support.requires_resource('cpu')
      15  class ESC[4;38;5;81mCFunctionTests(ESC[4;38;5;149mDebuggerTests):
      16      def check(self, func_name, cmd):
      17          # Verify with "py-bt":
      18          gdb_output = self.get_stack_trace(
      19              cmd,
      20              breakpoint=func_name,
      21              cmds_after_breakpoint=['bt', 'py-bt'],
      22              # bpo-45207: Ignore 'Function "meth_varargs" not
      23              # defined.' message in stderr.
      24              ignore_stderr=True,
      25          )
      26          self.assertIn(f'<built-in method {func_name}', gdb_output)
      27  
      28      # Some older versions of gdb will fail with
      29      #  "Cannot find new threads: generic error"
      30      # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
      31      #
      32      # gdb will also generate many erroneous errors such as:
      33      #     Function "meth_varargs" not defined.
      34      # This is because we are calling functions from an "external" module
      35      # (_testcapimodule) rather than compiled-in functions. It seems difficult
      36      # to suppress these. See also the comment in DebuggerTests.get_stack_trace
      37      def check_pycfunction(self, func_name, args):
      38          'Verify that "py-bt" displays invocations of PyCFunction instances'
      39  
      40          if support.verbose:
      41              print()
      42  
      43          # Various optimizations multiply the code paths by which these are
      44          # called, so test a variety of calling conventions.
      45          for obj in (
      46              '_testcapi',
      47              '_testcapi.MethClass',
      48              '_testcapi.MethClass()',
      49              '_testcapi.MethStatic()',
      50  
      51              # XXX: bound methods don't yet give nice tracebacks
      52              # '_testcapi.MethInstance()',
      53          ):
      54              with self.subTest(f'{obj}.{func_name}'):
      55                  call = f'{obj}.{func_name}({args})'
      56                  cmd = textwrap.dedent(f'''
      57                      import _testcapi
      58                      def foo():
      59                          {call}
      60                      def bar():
      61                          foo()
      62                      bar()
      63                  ''')
      64                  if support.verbose:
      65                      print(f'  test call: {call}', flush=True)
      66  
      67                  self.check(func_name, cmd)
      68  
      69      def test_pycfunction_noargs(self):
      70          self.check_pycfunction('meth_noargs', '')
      71  
      72      def test_pycfunction_o(self):
      73          self.check_pycfunction('meth_o', '[]')
      74  
      75      def test_pycfunction_varargs(self):
      76          self.check_pycfunction('meth_varargs', '')
      77  
      78      def test_pycfunction_varargs_keywords(self):
      79          self.check_pycfunction('meth_varargs_keywords', '')
      80  
      81      def test_pycfunction_fastcall(self):
      82          self.check_pycfunction('meth_fastcall', '')
      83  
      84      def test_pycfunction_fastcall_keywords(self):
      85          self.check_pycfunction('meth_fastcall_keywords', '')