Skip to content

Commit 64e2c64

Browse files
authored
test_gdb.test_pycfunction: test more calling conventions (GH-13668)
As the code paths for various METH_* conventions are diverging due to optimizations, we should check they continue to be covered by GDB integration.
1 parent cdce057 commit 64e2c64

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

Lib/test/test_gdb.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -867,27 +867,40 @@ def test_gc(self):
867867
# unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
868868
def test_pycfunction(self):
869869
'Verify that "py-bt" displays invocations of PyCFunction instances'
870-
# Tested function must not be defined with METH_NOARGS or METH_O,
871-
# otherwise call_function() doesn't call PyCFunction_Call()
872-
cmd = ('from time import gmtime\n'
873-
'def foo():\n'
874-
' gmtime(1)\n'
875-
'def bar():\n'
876-
' foo()\n'
877-
'bar()\n')
878-
# Verify with "py-bt":
879-
gdb_output = self.get_stack_trace(cmd,
880-
breakpoint='time_gmtime',
881-
cmds_after_breakpoint=['bt', 'py-bt'],
882-
)
883-
self.assertIn('<built-in method gmtime', gdb_output)
884-
885-
# Verify with "py-bt-full":
886-
gdb_output = self.get_stack_trace(cmd,
887-
breakpoint='time_gmtime',
888-
cmds_after_breakpoint=['py-bt-full'],
889-
)
890-
self.assertIn('#1 <built-in method gmtime', gdb_output)
870+
# Various optimizations multiply the code paths by which these are
871+
# called, so test a variety of calling conventions.
872+
for py_name, py_args, c_name, expected_frame_number in (
873+
('gmtime', '', 'time_gmtime', 1), # METH_VARARGS
874+
('len', '[]', 'builtin_len', 2), # METH_O
875+
('locals', '', 'builtin_locals', 2), # METH_NOARGS
876+
('iter', '[]', 'builtin_iter', 2), # METH_FASTCALL
877+
('sorted', '[]', 'builtin_sorted', 2), # METH_FASTCALL|METH_KEYWORDS
878+
):
879+
with self.subTest(c_name):
880+
cmd = ('from time import gmtime\n' # (not always needed)
881+
'def foo():\n'
882+
f' {py_name}({py_args})\n'
883+
'def bar():\n'
884+
' foo()\n'
885+
'bar()\n')
886+
# Verify with "py-bt":
887+
gdb_output = self.get_stack_trace(
888+
cmd,
889+
breakpoint=c_name,
890+
cmds_after_breakpoint=['bt', 'py-bt'],
891+
)
892+
self.assertIn(f'<built-in method {py_name}', gdb_output)
893+
894+
# Verify with "py-bt-full":
895+
gdb_output = self.get_stack_trace(
896+
cmd,
897+
breakpoint=c_name,
898+
cmds_after_breakpoint=['py-bt-full'],
899+
)
900+
self.assertIn(
901+
f'#{expected_frame_number} <built-in method {py_name}',
902+
gdb_output,
903+
)
891904

892905
@unittest.skipIf(python_is_optimized(),
893906
"Python was compiled with optimizations")

0 commit comments

Comments
 (0)