]> granicus.if.org Git - python/commitdiff
#15043: Improve test_gdb support of gdb >= 7.4.
authorR David Murray <rdmurray@bitdance.com>
Sat, 27 Oct 2012 17:22:41 +0000 (13:22 -0400)
committerR David Murray <rdmurray@bitdance.com>
Sat, 27 Oct 2012 17:22:41 +0000 (13:22 -0400)
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

index fb8261beff0e6b69d14e83dd19902b1ab6178f41..6d96550a9bc892ebae77df77b4e320b0d8683592 100644 (file)
@@ -19,39 +19,57 @@ 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(b"^GNU gdb [^\d]*(\d+)\.", gdb_version)
-if int(gdb_version_number.group(1)) < 7:
+gdb_version_number = re.search(b"^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.decode('ascii', 'replace'))
 
+# 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) decoded from utf-8 using the replace handler.
+    """
+    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.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
+
 # 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 == b'':
+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: "
+    raise unittest.SkipTest(msg + gdbpy_errors.rstrip())
 
 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()
-    m = re.match(br'.*\[(.*)\].*', stdout)
+    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")
-    gdb_frame_dir = m.group(1).split(b', ')
-    return b"'select'" in gdb_frame_dir
+    gdb_frame_dir = m.group(1).split(', ')
+    return "'select'" in gdb_frame_dir
 
 HAS_PYUP_PYDOWN = gdb_has_frame_select()
 
@@ -61,21 +79,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.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
-
     def get_stack_trace(self, source=None, script=None,
                         breakpoint=BREAKPOINT_FN,
                         cmds_after_breakpoint=None,
@@ -132,7 +135,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, '')
@@ -149,6 +152,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, '')