summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_gdb.py
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2019-09-10 11:21:09 (GMT)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-09-10 11:21:09 (GMT)
commitf958377b67c36a98d4df67b94c01eb29e3104f61 (patch)
tree9258fb47193c6d18c3a6a2c3fe4f64d7b1199ce8 /Lib/test/test_gdb.py
parentf1a297acb60b88917712450ebd3cfa707e6efd6b (diff)
downloadcpython-f958377b67c36a98d4df67b94c01eb29e3104f61.zip
cpython-f958377b67c36a98d4df67b94c01eb29e3104f61.tar.gz
cpython-f958377b67c36a98d4df67b94c01eb29e3104f61.tar.bz2
bpo-37499: Test various C calling conventions (GH-15776)
Add functions with various calling conventions to `_testcapi`, expose them as module-level functions, bound methods, class methods, and static methods, and test calling them and introspecting them through GDB. https://bugs.python.org/issue37499 Co-authored-by: Jeroen Demeyer <J.Demeyer@UGent.be> Automerge-Triggered-By: @pganssle
Diffstat (limited to 'Lib/test/test_gdb.py')
-rw-r--r--Lib/test/test_gdb.py81
1 files changed, 50 insertions, 31 deletions
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index a2aa16c..e515d0d 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -838,47 +838,66 @@ id(42)
)
self.assertIn('Garbage-collecting', gdb_output)
+
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
# 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 test_pycfunction(self):
'Verify that "py-bt" displays invocations of PyCFunction instances'
# Various optimizations multiply the code paths by which these are
# called, so test a variety of calling conventions.
- for py_name, py_args, c_name, expected_frame_number in (
- ('gmtime', '', 'time_gmtime', 1), # METH_VARARGS
- ('len', '[]', 'builtin_len', 1), # METH_O
- ('locals', '', 'builtin_locals', 1), # METH_NOARGS
- ('iter', '[]', 'builtin_iter', 1), # METH_FASTCALL
- ('sorted', '[]', 'builtin_sorted', 1), # METH_FASTCALL|METH_KEYWORDS
+ for func_name, args, expected_frame in (
+ ('meth_varargs', '', 1),
+ ('meth_varargs_keywords', '', 1),
+ ('meth_o', '[]', 1),
+ ('meth_noargs', '', 1),
+ ('meth_fastcall', '', 1),
+ ('meth_fastcall_keywords', '', 1),
):
- with self.subTest(c_name):
- cmd = ('from time import gmtime\n' # (not always needed)
- 'def foo():\n'
- f' {py_name}({py_args})\n'
- 'def bar():\n'
- ' foo()\n'
- 'bar()\n')
- # Verify with "py-bt":
- gdb_output = self.get_stack_trace(
- cmd,
- breakpoint=c_name,
- cmds_after_breakpoint=['bt', 'py-bt'],
- )
- self.assertIn(f'<built-in method {py_name}', gdb_output)
-
- # Verify with "py-bt-full":
- gdb_output = self.get_stack_trace(
- cmd,
- breakpoint=c_name,
- cmds_after_breakpoint=['py-bt-full'],
- )
- self.assertIn(
- f'#{expected_frame_number} <built-in method {py_name}',
- gdb_output,
- )
+ 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}'):
+ cmd = textwrap.dedent(f'''
+ import _testcapi
+ def foo():
+ {obj}.{func_name}({args})
+ def bar():
+ foo()
+ bar()
+ ''')
+ # Verify with "py-bt":
+ gdb_output = self.get_stack_trace(
+ cmd,
+ breakpoint=func_name,
+ cmds_after_breakpoint=['bt', 'py-bt'],
+ )
+ self.assertIn(f'<built-in method {func_name}', gdb_output)
+
+ # Verify with "py-bt-full":
+ gdb_output = self.get_stack_trace(
+ cmd,
+ breakpoint=func_name,
+ cmds_after_breakpoint=['py-bt-full'],
+ )
+ self.assertIn(
+ f'#{expected_frame} <built-in method {func_name}',
+ gdb_output,
+ )
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")