Skip to content

bpo-37382: check for debug info before testing GDB #14331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/library/test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ The :mod:`test.support` module defines the following functions:
Return ``True`` if Python was not built with ``-O0`` or ``-Og``.


.. function:: python_has_debug_info()

Return ``True`` if Python was built with ``-g``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add ".. versionadded:: 3.9".



.. function:: with_pymalloc()

Return :data:`_testcapi.WITH_PYMALLOC`.
Expand Down
1 change: 1 addition & 0 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ def collect_test_support(info_add):

call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available')
call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized')
call_func(info_add, 'test_support.python_has_debug_info', support, 'python_has_debug_info')


def collect_cc(info_add):
Expand Down
10 changes: 10 additions & 0 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,16 @@ def disable_gc():
gc.enable()


def python_has_debug_info():
"""Find if Python was built with debug information."""
cflags = sysconfig.get_config_var('PY_CFLAGS') or ''
final_opt = ""
for opt in cflags.split():
if opt.startswith('-g'):
final_opt = opt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just returning True here? (and "return False" outside the loop)

return final_opt == '-g'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you reject "-ggdb"? I heard that it's even better than "-g".



def python_is_optimized():
"""Find if Python was built with optimizations."""
cflags = sysconfig.get_config_var('PY_CFLAGS') or ''
Expand Down
58 changes: 29 additions & 29 deletions Lib/test/test_gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import unittest

from test import support
from test.support import run_unittest, findfile, python_is_optimized
from test.support import run_unittest, findfile, python_has_debug_info

def get_gdb_version():
try:
Expand Down Expand Up @@ -657,8 +657,8 @@ def foo(a, b, c):
re.DOTALL),
'Unexpected gdb representation: %r\n%s' % (gdb_output, gdb_output))

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
class PyListTests(DebuggerTests):
def assertListing(self, expected, actual):
self.assertEndsWith(actual, expected)
Expand Down Expand Up @@ -701,8 +701,8 @@ def test_two_abs_args(self):

class StackNavigationTests(DebuggerTests):
@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_pyup_command(self):
'Verify that the "py-up" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
Expand Down Expand Up @@ -730,8 +730,8 @@ def test_up_at_top(self):
'Unable to find an older python frame\n')

@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_up_then_down(self):
'Verify "py-up" followed by "py-down"'
bt = self.get_stack_trace(script=self.get_sample_script(),
Expand All @@ -745,8 +745,8 @@ def test_up_then_down(self):
$''')

class PyBtTests(DebuggerTests):
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_bt(self):
'Verify that the "py-bt" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
Expand All @@ -765,8 +765,8 @@ def test_bt(self):
foo\(1, 2, 3\)
''')

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_bt_full(self):
'Verify that the "py-bt-full" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
Expand Down Expand Up @@ -813,8 +813,8 @@ def run(self):
cmds_after_breakpoint=['thread apply all py-bt-full'])
self.assertIn('Waiting for the GIL', gdb_output)

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
# 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
Expand All @@ -839,8 +839,8 @@ def test_gc(self):
)
self.assertIn('Garbage-collecting', gdb_output)

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
# 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
Expand Down Expand Up @@ -881,8 +881,8 @@ def test_pycfunction(self):
gdb_output,
)

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_wrapper_call(self):
cmd = textwrap.dedent('''
class MyList(list):
Expand All @@ -908,52 +908,52 @@ def __init__(self):


class PyPrintTests(DebuggerTests):
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_basic_command(self):
'Verify that the "py-print" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-print args'])
self.assertMultilineMatches(bt,
r".*\nlocal 'args' = \(1, 2, 3\)\n.*")

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
def test_print_after_up(self):
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-up', 'py-print c', 'py-print b', 'py-print a'])
self.assertMultilineMatches(bt,
r".*\nlocal 'c' = 3\nlocal 'b' = 2\nlocal 'a' = 1\n.*")

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_printing_global(self):
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-print __name__'])
self.assertMultilineMatches(bt,
r".*\nglobal '__name__' = '__main__'\n.*")

@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_printing_builtin(self):
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-print len'])
self.assertMultilineMatches(bt,
r".*\nbuiltin 'len' = <built-in method len of module object at remote 0x-?[0-9a-f]+>\n.*")

class PyLocalsTests(DebuggerTests):
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_basic_command(self):
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-locals'])
self.assertMultilineMatches(bt,
r".*\nargs = \(1, 2, 3\)\n.*")

@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
@unittest.skipIf(python_is_optimized(),
"Python was compiled with optimizations")
@unittest.skipUnless(python_has_debug_info(),
"Python was compiled without debug info")
def test_locals_after_up(self):
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-up', 'py-up', 'py-locals'])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GDB tests are now run whenever Python is compiled with debug info,
regardless of optimization flags. A new function
``test.support.python_has_debug_info`` is added for this.