From 3e66f0d14d4541f85ee5daf00dbd3150a02fa4aa Mon Sep 17 00:00:00 2001 From: R David Murray Date: Sat, 27 Oct 2012 13:47:49 -0400 Subject: [PATCH] #15043: Improve test_gdb support of gdb >= 7.4. Instead of requiring the tester to manually add the path to the python-gdb.py file in the checkout to their .gdbinit file, add it automatically when invoking gdb in the test. --- Lib/test/test_gdb.py | 77 ++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 3bf718aa6d6..9d8ff8ed8a1 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -19,27 +19,47 @@ except OSError: # This is what "no gdb" looks like. There may, however, be other # errors that manifest this way too. raise unittest.SkipTest("Couldn't find gdb on the path") -gdb_version_number = re.search(r"^GNU gdb [^\d]*(\d+)\.", gdb_version) -if int(gdb_version_number.group(1)) < 7: +gdb_version_number = re.search("^GNU gdb [^\d]*(\d+)\.(\d)", gdb_version) +gdb_major_version = int(gdb_version_number.group(1)) +gdb_minor_version = int(gdb_version_number.group(2)) +if gdb_major_version < 7: raise unittest.SkipTest("gdb versions before 7.0 didn't support python embedding" " Saw:\n" + gdb_version) +# Location of custom hooks file in a repository checkout. +checkout_hook_path = os.path.join(os.path.dirname(sys.executable), + 'python-gdb.py') + +def run_gdb(*args, **env_vars): + """Runs gdb in --batch mode with the additional arguments given by *args. + + Returns its (stdout, stderr) + """ + if env_vars: + env = os.environ.copy() + env.update(env_vars) + else: + env = None + base_cmd = ('gdb', '--batch') + if (gdb_major_version, gdb_minor_version) >= (7, 4): + base_cmd += ('-iex', 'add-auto-load-safe-path ' + checkout_hook_path) + out, err = subprocess.Popen(base_cmd + args, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, + ).communicate() + return out, err + # Verify that "gdb" was built with the embedded python support enabled: -cmd = "--eval-command=python import sys; print sys.version_info" -p = subprocess.Popen(["gdb", "--batch", cmd], - stdout=subprocess.PIPE) -gdbpy_version, _ = p.communicate() -if gdbpy_version == '': +gdbpy_version, _ = run_gdb("--eval-command=python import sys; print sys.version_info") +if not gdbpy_version: raise unittest.SkipTest("gdb not built with embedded python support") -# Verify that "gdb" can load our custom hooks -p = subprocess.Popen(["gdb", "--batch", cmd, - "--args", sys.executable], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) -__, gdbpy_errors = p.communicate() -if b"auto-loading has been declined" in gdbpy_errors: - msg = "gdb security settings prevent use of custom hooks: %s" - raise unittest.SkipTest(msg % gdbpy_errors) +# Verify that "gdb" can load our custom hooks. In theory this should never +# fail, but we don't handle the case of the hooks file not existing if the +# tests are run from an installed Python (we'll produce failures in that case). +cmd = ['--args', sys.executable] +_, gdbpy_errors = run_gdb('--args', sys.executable) +if "auto-loading has been declined" in gdbpy_errors: + msg = "gdb security settings prevent use of custom hooks: " def python_is_optimized(): cflags = sysconfig.get_config_vars()['PY_CFLAGS'] @@ -51,10 +71,7 @@ def python_is_optimized(): def gdb_has_frame_select(): # Does this build of gdb have gdb.Frame.select ? - cmd = "--eval-command=python print(dir(gdb.Frame))" - p = subprocess.Popen(["gdb", "--batch", cmd], - stdout=subprocess.PIPE) - stdout, _ = p.communicate() + stdout, _ = run_gdb("--eval-command=python print(dir(gdb.Frame))") m = re.match(r'.*\[(.*)\].*', stdout) if not m: raise unittest.SkipTest("Unable to parse output from gdb.Frame.select test") @@ -67,21 +84,6 @@ class DebuggerTests(unittest.TestCase): """Test that the debugger can debug Python.""" - def run_gdb(self, *args, **env_vars): - """Runs gdb with the command line given by *args. - - Returns its stdout, stderr - """ - if env_vars: - env = os.environ.copy() - env.update(env_vars) - else: - env = None - out, err = subprocess.Popen( - args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env - ).communicate() - return out, err - def get_stack_trace(self, source=None, script=None, breakpoint='PyObject_Print', cmds_after_breakpoint=None, @@ -138,7 +140,7 @@ class DebuggerTests(unittest.TestCase): # print ' '.join(args) # Use "args" to invoke gdb, capturing stdout, stderr: - out, err = self.run_gdb(*args, PYTHONHASHSEED='0') + out, err = run_gdb(*args, PYTHONHASHSEED='0') # Ignore some noise on stderr due to the pending breakpoint: err = err.replace('Function "%s" not defined.\n' % breakpoint, '') @@ -155,6 +157,11 @@ class DebuggerTests(unittest.TestCase): 'Do you need "set solib-search-path" or ' '"set sysroot"?\n', '') + err = err.replace('warning: Could not load shared library symbols for ' + 'linux-gate.so.1.\n' + 'Do you need "set solib-search-path" or ' + '"set sysroot"?\n', + '') # Ensure no unexpected error messages: self.assertEqual(err, '')