summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_gdb/test_misc.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_gdb/test_misc.py')
-rw-r--r--Lib/test/test_gdb/test_misc.py188
1 files changed, 188 insertions, 0 deletions
diff --git a/Lib/test/test_gdb/test_misc.py b/Lib/test/test_gdb/test_misc.py
new file mode 100644
index 0000000..1063e7b
--- /dev/null
+++ b/Lib/test/test_gdb/test_misc.py
@@ -0,0 +1,188 @@
+import re
+import unittest
+from test.support import python_is_optimized
+
+from .util import run_gdb, setup_module, DebuggerTests
+
+
+def setUpModule():
+ setup_module()
+
+
+def gdb_has_frame_select():
+ # Does this build of gdb have gdb.Frame.select ?
+ stdout, stderr = run_gdb("--eval-command=python print(dir(gdb.Frame))")
+ m = re.match(r'.*\[(.*)\].*', stdout)
+ if not m:
+ raise unittest.SkipTest(
+ f"Unable to parse output from gdb.Frame.select test\n"
+ f"stdout={stdout!r}\n"
+ f"stderr={stderr!r}\n")
+ gdb_frame_dir = m.group(1).split(', ')
+ return "'select'" in gdb_frame_dir
+
+HAS_PYUP_PYDOWN = gdb_has_frame_select()
+
+
+@unittest.skipIf(python_is_optimized(),
+ "Python was compiled with optimizations")
+class PyListTests(DebuggerTests):
+ def assertListing(self, expected, actual):
+ self.assertEndsWith(actual, expected)
+
+ def test_basic_command(self):
+ 'Verify that the "py-list" command works'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-list'])
+
+ self.assertListing(' 5 \n'
+ ' 6 def bar(a, b, c):\n'
+ ' 7 baz(a, b, c)\n'
+ ' 8 \n'
+ ' 9 def baz(*args):\n'
+ ' >10 id(42)\n'
+ ' 11 \n'
+ ' 12 foo(1, 2, 3)\n',
+ bt)
+
+ def test_one_abs_arg(self):
+ 'Verify the "py-list" command with one absolute argument'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-list 9'])
+
+ self.assertListing(' 9 def baz(*args):\n'
+ ' >10 id(42)\n'
+ ' 11 \n'
+ ' 12 foo(1, 2, 3)\n',
+ bt)
+
+ def test_two_abs_args(self):
+ 'Verify the "py-list" command with two absolute arguments'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-list 1,3'])
+
+ self.assertListing(' 1 # Sample script for use by test_gdb\n'
+ ' 2 \n'
+ ' 3 def foo(a, b, c):\n',
+ bt)
+
+SAMPLE_WITH_C_CALL = """
+
+from _testcapi import pyobject_vectorcall
+
+def foo(a, b, c):
+ bar(a, b, c)
+
+def bar(a, b, c):
+ pyobject_vectorcall(baz, (a, b, c), None)
+
+def baz(*args):
+ id(42)
+
+foo(1, 2, 3)
+
+"""
+
+
+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")
+ def test_pyup_command(self):
+ 'Verify that the "py-up" command works'
+ bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL,
+ cmds_after_breakpoint=['py-up', 'py-up'])
+ self.assertMultilineMatches(bt,
+ r'''^.*
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
+#[0-9]+ <built-in method pyobject_vectorcall of module object at remote 0x[0-9a-f]+>
+$''')
+
+ @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+ def test_down_at_bottom(self):
+ 'Verify handling of "py-down" at the bottom of the stack'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-down'])
+ self.assertEndsWith(bt,
+ 'Unable to find a newer python frame\n')
+
+ @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+ def test_up_at_top(self):
+ 'Verify handling of "py-up" at the top of the stack'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-up'] * 5)
+ self.assertEndsWith(bt,
+ '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")
+ def test_up_then_down(self):
+ 'Verify "py-up" followed by "py-down"'
+ bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL,
+ cmds_after_breakpoint=['py-up', 'py-up', 'py-down'])
+ self.assertMultilineMatches(bt,
+ r'''^.*
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
+#[0-9]+ <built-in method pyobject_vectorcall of module object at remote 0x[0-9a-f]+>
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
+$''')
+
+class PyPrintTests(DebuggerTests):
+ @unittest.skipIf(python_is_optimized(),
+ "Python was compiled with optimizations")
+ def test_basic_command(self):
+ 'Verify that the "py-print" command works'
+ bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL,
+ 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(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+ def test_print_after_up(self):
+ bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL,
+ 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")
+ 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")
+ 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")
+ 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")
+ 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'])
+ self.assertMultilineMatches(bt,
+ r'''^.*
+Locals for foo
+a = 1
+b = 2
+c = 3
+Locals for <module>
+.*$''')