mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	* Split test_pycfunction.py: add test_cfunction_full.py. Split the function into the following 6 functions. In verbose mode, these "pycfunction" tests now log each tested call. * test_pycfunction_noargs() * test_pycfunction_o() * test_pycfunction_varargs() * test_pycfunction_varargs_keywords() * test_pycfunction_fastcall() * test_pycfunction_fastcall_keywords() * Move get_gdb_repr() to PrettyPrintTests. * Replace DebuggerTests.get_sample_script() with SAMPLE_SCRIPT. * Rename checkout_hook_path to CHECKOUT_HOOK_PATH. * Rename gdb_version to GDB_VERSION_TEXT. * Replace (gdb_major_version, gdb_minor_version) with GDB_VERSION. * run_gdb() uses "backslashreplace" error handler instead of "replace". * Add check_gdb() function to util.py. * Enhance support.check_cflags_pgo(): check also for sysconfig PGO_PROF_USE_FLAG (if available) in compiler flags. * Move some SkipTest checks to test_gdb/__init__.py. * Elaborate why gdb cannot be tested on Windows: gdb doesn't support PDB debug symbol files.
		
			
				
	
	
		
			188 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import re
 | 
						|
import unittest
 | 
						|
from test.support import python_is_optimized
 | 
						|
 | 
						|
from .util import run_gdb, setup_module, DebuggerTests, SAMPLE_SCRIPT
 | 
						|
 | 
						|
 | 
						|
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=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=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=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=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=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=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=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=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=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>
 | 
						|
.*$''')
 |