mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 757cbd4f29
			
		
	
	
		757cbd4f29
		
			
		
	
	
	
	
		
			
			* 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.
		
			
				
	
	
		
			134 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import textwrap
 | |
| import unittest
 | |
| from test import support
 | |
| from test.support import python_is_optimized
 | |
| 
 | |
| from .util import setup_module, DebuggerTests, CET_PROTECTION, SAMPLE_SCRIPT
 | |
| 
 | |
| 
 | |
| def setUpModule():
 | |
|     setup_module()
 | |
| 
 | |
| 
 | |
| class PyBtTests(DebuggerTests):
 | |
|     @unittest.skipIf(python_is_optimized(),
 | |
|                      "Python was compiled with optimizations")
 | |
|     def test_bt(self):
 | |
|         'Verify that the "py-bt" command works'
 | |
|         bt = self.get_stack_trace(script=SAMPLE_SCRIPT,
 | |
|                                   cmds_after_breakpoint=['py-bt'])
 | |
|         self.assertMultilineMatches(bt,
 | |
|                                     r'''^.*
 | |
| Traceback \(most recent call first\):
 | |
|   <built-in method id of module object .*>
 | |
|   File ".*gdb_sample.py", line 10, in baz
 | |
|     id\(42\)
 | |
|   File ".*gdb_sample.py", line 7, in bar
 | |
|     baz\(a, b, c\)
 | |
|   File ".*gdb_sample.py", line 4, in foo
 | |
|     bar\(a=a, b=b, c=c\)
 | |
|   File ".*gdb_sample.py", line 12, in <module>
 | |
|     foo\(1, 2, 3\)
 | |
| ''')
 | |
| 
 | |
|     @unittest.skipIf(python_is_optimized(),
 | |
|                      "Python was compiled with optimizations")
 | |
|     def test_bt_full(self):
 | |
|         'Verify that the "py-bt-full" command works'
 | |
|         bt = self.get_stack_trace(script=SAMPLE_SCRIPT,
 | |
|                                   cmds_after_breakpoint=['py-bt-full'])
 | |
|         self.assertMultilineMatches(bt,
 | |
|                                     r'''^.*
 | |
| #[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
 | |
|     baz\(a, b, c\)
 | |
| #[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\)
 | |
|     bar\(a=a, b=b, c=c\)
 | |
| #[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 12, in <module> \(\)
 | |
|     foo\(1, 2, 3\)
 | |
| ''')
 | |
| 
 | |
|     @unittest.skipIf(python_is_optimized(),
 | |
|                      "Python was compiled with optimizations")
 | |
|     @support.requires_resource('cpu')
 | |
|     def test_threads(self):
 | |
|         'Verify that "py-bt" indicates threads that are waiting for the GIL'
 | |
|         cmd = '''
 | |
| from threading import Thread
 | |
| 
 | |
| class TestThread(Thread):
 | |
|     # These threads would run forever, but we'll interrupt things with the
 | |
|     # debugger
 | |
|     def run(self):
 | |
|         i = 0
 | |
|         while 1:
 | |
|              i += 1
 | |
| 
 | |
| t = {}
 | |
| for i in range(4):
 | |
|    t[i] = TestThread()
 | |
|    t[i].start()
 | |
| 
 | |
| # Trigger a breakpoint on the main thread
 | |
| id(42)
 | |
| 
 | |
| '''
 | |
|         # Verify with "py-bt":
 | |
|         gdb_output = self.get_stack_trace(cmd,
 | |
|                                           cmds_after_breakpoint=['thread apply all py-bt'])
 | |
|         self.assertIn('Waiting for the GIL', gdb_output)
 | |
| 
 | |
|         # Verify with "py-bt-full":
 | |
|         gdb_output = self.get_stack_trace(cmd,
 | |
|                                           cmds_after_breakpoint=['thread apply all py-bt-full'])
 | |
|         self.assertIn('Waiting for the GIL', gdb_output)
 | |
| 
 | |
|     @unittest.skipIf(python_is_optimized(),
 | |
|                      "Python was compiled with optimizations")
 | |
|     # Some older versions of gdb will fail with
 | |
|     #  "Cannot find new threads: generic error"
 | |
|     # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
 | |
|     def test_gc(self):
 | |
|         'Verify that "py-bt" indicates if a thread is garbage-collecting'
 | |
|         cmd = ('from gc import collect\n'
 | |
|                'id(42)\n'
 | |
|                'def foo():\n'
 | |
|                '    collect()\n'
 | |
|                'def bar():\n'
 | |
|                '    foo()\n'
 | |
|                'bar()\n')
 | |
|         # Verify with "py-bt":
 | |
|         gdb_output = self.get_stack_trace(cmd,
 | |
|                                           cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt'],
 | |
|                                           )
 | |
|         self.assertIn('Garbage-collecting', gdb_output)
 | |
| 
 | |
|         # Verify with "py-bt-full":
 | |
|         gdb_output = self.get_stack_trace(cmd,
 | |
|                                           cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt-full'],
 | |
|                                           )
 | |
|         self.assertIn('Garbage-collecting', gdb_output)
 | |
| 
 | |
|     @unittest.skipIf(python_is_optimized(),
 | |
|                      "Python was compiled with optimizations")
 | |
|     def test_wrapper_call(self):
 | |
|         cmd = textwrap.dedent('''
 | |
|             class MyList(list):
 | |
|                 def __init__(self):
 | |
|                     super(*[]).__init__()   # wrapper_call()
 | |
| 
 | |
|             id("first break point")
 | |
|             l = MyList()
 | |
|         ''')
 | |
|         cmds_after_breakpoint = ['break wrapper_call', 'continue']
 | |
|         if CET_PROTECTION:
 | |
|             # bpo-32962: same case as in get_stack_trace():
 | |
|             # we need an additional 'next' command in order to read
 | |
|             # arguments of the innermost function of the call stack.
 | |
|             cmds_after_breakpoint.append('next')
 | |
|         cmds_after_breakpoint.append('py-bt')
 | |
| 
 | |
|         # Verify with "py-bt":
 | |
|         gdb_output = self.get_stack_trace(cmd,
 | |
|                                           cmds_after_breakpoint=cmds_after_breakpoint)
 | |
|         self.assertRegex(gdb_output,
 | |
|                          r"<method-wrapper u?'__init__' of MyList object at ")
 |