Skip to content

Commit eea75e9

Browse files
Add tests for instruction level commands
1 parent ebae223 commit eea75e9

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

Lib/test/test_pdb.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# A test suite for pdb; not very comprehensive at the moment.
22

3+
import dis
34
import doctest
45
import os
56
import pdb
@@ -2351,6 +2352,101 @@ def _create_fake_frozen_module():
23512352
# verify that pdb found the source of the "frozen" function
23522353
self.assertIn('x = "Sentinel string for gh-93696"', stdout, "Sentinel statement not found")
23532354

2355+
def get_func_opnames(self, func_def, func_name):
2356+
extract_code = f"""
2357+
import dis
2358+
for inst in dis.get_instructions({func_name}):
2359+
print(inst.opname)
2360+
"""
2361+
2362+
with redirect_stdout(StringIO()) as s:
2363+
exec(textwrap.dedent(func_def) + textwrap.dedent(extract_code))
2364+
2365+
return s.getvalue().splitlines()
2366+
2367+
def test_list_instruction(self):
2368+
func_def = """
2369+
def f():
2370+
a = [1, 2, 3]
2371+
return a[0]
2372+
"""
2373+
func_exec = """
2374+
f()
2375+
"""
2376+
script = func_def + func_exec
2377+
2378+
commands_li = """
2379+
break f
2380+
c
2381+
li
2382+
"""
2383+
2384+
commands_lli = """
2385+
break f
2386+
c
2387+
lli
2388+
"""
2389+
2390+
# Make sure all the opcodes are listed
2391+
stdout, stderr = self.run_pdb_module(script, commands_li)
2392+
for opname in self.get_func_opnames(func_def, "f"):
2393+
self.assertIn(opname, stdout)
2394+
2395+
stdout, stderr = self.run_pdb_module(script, commands_lli)
2396+
for opname in self.get_func_opnames(func_def, "f"):
2397+
self.assertIn(opname, stdout)
2398+
2399+
def test_instruction_level_control(self):
2400+
func_def = """
2401+
def f():
2402+
a = [1, 2, 3]
2403+
return a[0]
2404+
"""
2405+
func_exec = """
2406+
f()
2407+
"""
2408+
script = func_def + func_exec
2409+
2410+
commands = """
2411+
ni
2412+
li
2413+
"""
2414+
2415+
# Check that after ni, current instruction is displayed
2416+
stdout, stderr = self.run_pdb_module(script, commands)
2417+
lines = [line.strip() for line in stdout.splitlines()]
2418+
for idx, line in enumerate(lines):
2419+
if "-->" in line:
2420+
# Found the current instruction indicator after ni
2421+
# Make sure that is listed in li
2422+
self.assertIn(line, lines[idx+1:])
2423+
break
2424+
2425+
commands = """
2426+
ni
2427+
ni
2428+
ni
2429+
c
2430+
"""
2431+
2432+
stdout, stderr = self.run_pdb_module(script, commands)
2433+
curr_instr_lines = [line.strip() for line in stdout.splitlines() if "-->" in line]
2434+
self.assertEqual(len(curr_instr_lines), 3)
2435+
for line in curr_instr_lines:
2436+
# Make sure ni is moving forward, not stopping at the same instrunction
2437+
self.assertEqual(curr_instr_lines.count(line), 1)
2438+
2439+
# this test is under the assumption that within 10 instructions the function
2440+
# f should be called
2441+
commands = "si\n" * 10 + "c\n"
2442+
2443+
stdout, stderr = self.run_pdb_module(script, commands)
2444+
curr_instr_lines = [line.strip() for line in stdout.splitlines()]
2445+
# Make sure si stepped into the function so the users can see the source
2446+
# code of the function
2447+
self.assertTrue(any("-> a = [1, 2, 3]" in line for line in curr_instr_lines))
2448+
2449+
23542450
class ChecklineTests(unittest.TestCase):
23552451
def setUp(self):
23562452
linecache.clearcache() # Pdb.checkline() uses linecache.getline()

0 commit comments

Comments
 (0)