From 7bf069b6110278102c8f4719975a5eb5a5af25f9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 20 Mar 2020 08:23:26 +0100 Subject: [PATCH] bpo-40019: Skip test_gdb if Python was optimized (GH-19081) test_gdb now skips tests if it detects that gdb failed to read debug information because the Python binary is optimized. --- Lib/test/test_gdb.py | 9 +++++++++ .../2020-03-20-00-30-36.bpo-40019.zOqHpQ.rst | 2 ++ Tools/gdb/libpython.py | 16 +++++++++------- 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2020-03-20-00-30-36.bpo-40019.zOqHpQ.rst diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index eb94f92961f..fb1480145a7 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -230,6 +230,15 @@ class DebuggerTests(unittest.TestCase): " because the Program Counter is" " not present") + # bpo-40019: Skip the test if gdb failed to read debug information + # because the Python binary is optimized. + for pattern in ( + '(frame information optimized out)', + 'Unable to read information on python frame', + ): + if pattern in out: + raise unittest.SkipTest(f"{pattern!r} found in gdb output") + return out def get_gdb_repr(self, source, diff --git a/Misc/NEWS.d/next/Tests/2020-03-20-00-30-36.bpo-40019.zOqHpQ.rst b/Misc/NEWS.d/next/Tests/2020-03-20-00-30-36.bpo-40019.zOqHpQ.rst new file mode 100644 index 00000000000..a9d0b3970ae --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2020-03-20-00-30-36.bpo-40019.zOqHpQ.rst @@ -0,0 +1,2 @@ +test_gdb now skips tests if it detects that gdb failed to read debug +information because the Python binary is optimized. diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index cd7ae1097d4..33bf5ac821f 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -99,6 +99,8 @@ hexdigits = "0123456789abcdef" ENCODING = locale.getpreferredencoding() +FRAME_INFO_OPTIMIZED_OUT = '(frame information optimized out)' +UNABLE_READ_INFO_PYTHON_FRAME = 'Unable to read information on python frame' EVALFRAME = '_PyEval_EvalFrameDefault' class NullPyObjectPtr(RuntimeError): @@ -918,7 +920,7 @@ class PyFrameObjectPtr(PyObjectPtr): def filename(self): '''Get the path of the current Python source file, as a string''' if self.is_optimized_out(): - return '(frame information optimized out)' + return FRAME_INFO_OPTIMIZED_OUT return self.co_filename.proxyval(set()) def current_line_num(self): @@ -949,7 +951,7 @@ class PyFrameObjectPtr(PyObjectPtr): '''Get the text of the current source line as a string, with a trailing newline character''' if self.is_optimized_out(): - return '(frame information optimized out)' + return FRAME_INFO_OPTIMIZED_OUT lineno = self.current_line_num() if lineno is None: @@ -970,7 +972,7 @@ class PyFrameObjectPtr(PyObjectPtr): def write_repr(self, out, visited): if self.is_optimized_out(): - out.write('(frame information optimized out)') + out.write(FRAME_INFO_OPTIMIZED_OUT) return lineno = self.current_line_num() lineno = str(lineno) if lineno is not None else "?" @@ -993,7 +995,7 @@ class PyFrameObjectPtr(PyObjectPtr): def print_traceback(self): if self.is_optimized_out(): - sys.stdout.write(' (frame information optimized out)\n') + sys.stdout.write(' %s\n' % FRAME_INFO_OPTIMIZED_OUT) return visited = set() lineno = self.current_line_num() @@ -1744,7 +1746,7 @@ class PyList(gdb.Command): pyop = frame.get_pyop() if not pyop or pyop.is_optimized_out(): - print('Unable to read information on python frame') + print(UNABLE_READ_INFO_PYTHON_FRAME) return filename = pyop.filename() @@ -1904,7 +1906,7 @@ class PyPrint(gdb.Command): pyop_frame = frame.get_pyop() if not pyop_frame: - print('Unable to read information on python frame') + print(UNABLE_READ_INFO_PYTHON_FRAME) return pyop_var, scope = pyop_frame.get_var_by_name(name) @@ -1938,7 +1940,7 @@ class PyLocals(gdb.Command): pyop_frame = frame.get_pyop() if not pyop_frame: - print('Unable to read information on python frame') + print(UNABLE_READ_INFO_PYTHON_FRAME) return for pyop_name, pyop_value in pyop_frame.iter_locals():