1# A test suite for pdb; at the moment, this only validates skipping of 2# specified test modules (RFE #5142). 3 4import imp 5import sys 6import os 7import unittest 8import subprocess 9import textwrap 10 11from test import test_support 12# This little helper class is essential for testing pdb under doctest. 13from test_doctest import _FakeInput 14 15 16class PdbTestCase(unittest.TestCase): 17 18 def run_pdb(self, script, commands): 19 """Run 'script' lines with pdb and the pdb 'commands'.""" 20 filename = 'main.py' 21 with open(filename, 'w') as f: 22 f.write(textwrap.dedent(script)) 23 self.addCleanup(test_support.unlink, filename) 24 cmd = [sys.executable, '-m', 'pdb', filename] 25 stdout = stderr = None 26 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 27 stdin=subprocess.PIPE, 28 stderr=subprocess.STDOUT, 29 ) 30 stdout, stderr = proc.communicate(commands) 31 proc.stdout.close() 32 proc.stdin.close() 33 return stdout, stderr 34 35 def test_issue13183(self): 36 script = """ 37 from bar import bar 38 39 def foo(): 40 bar() 41 42 def nope(): 43 pass 44 45 def foobar(): 46 foo() 47 nope() 48 49 foobar() 50 """ 51 commands = """ 52 from bar import bar 53 break bar 54 continue 55 step 56 step 57 quit 58 """ 59 bar = """ 60 def bar(): 61 pass 62 """ 63 with open('bar.py', 'w') as f: 64 f.write(textwrap.dedent(bar)) 65 self.addCleanup(test_support.unlink, 'bar.py') 66 self.addCleanup(test_support.unlink, 'bar.pyc') 67 stdout, stderr = self.run_pdb(script, commands) 68 self.assertTrue( 69 any('main.py(5)foo()->None' in l for l in stdout.splitlines()), 70 'Fail to step into the caller after a return') 71 72 def test_issue16180(self): 73 # A syntax error in the debuggee. 74 script = "def f: pass\n" 75 commands = '' 76 expected = "SyntaxError:" 77 stdout, stderr = self.run_pdb(script, commands) 78 self.assertIn(expected, stdout, 79 '\n\nExpected:\n{}\nGot:\n{}\n' 80 'Fail to handle a syntax error in the debuggee.' 81 .format(expected, stdout)) 82 83 84class PdbTestInput(object): 85 """Context manager that makes testing Pdb in doctests easier.""" 86 87 def __init__(self, input): 88 self.input = input 89 90 def __enter__(self): 91 self.real_stdin = sys.stdin 92 sys.stdin = _FakeInput(self.input) 93 94 def __exit__(self, *exc): 95 sys.stdin = self.real_stdin 96 97 98def write(x): 99 print x 100 101def test_pdb_displayhook(): 102 """This tests the custom displayhook for pdb. 103 104 >>> def test_function(foo, bar): 105 ... import pdb; pdb.Pdb().set_trace() 106 ... pass 107 108 >>> with PdbTestInput([ 109 ... 'foo', 110 ... 'bar', 111 ... 'for i in range(5): write(i)', 112 ... 'continue', 113 ... ]): 114 ... test_function(1, None) 115 > <doctest test.test_pdb.test_pdb_displayhook[0]>(3)test_function() 116 -> pass 117 (Pdb) foo 118 1 119 (Pdb) bar 120 (Pdb) for i in range(5): write(i) 121 0 122 1 123 2 124 3 125 4 126 (Pdb) continue 127 """ 128 129def test_pdb_breakpoint_commands(): 130 """Test basic commands related to breakpoints. 131 132 >>> def test_function(): 133 ... import pdb; pdb.Pdb().set_trace() 134 ... print(1) 135 ... print(2) 136 ... print(3) 137 ... print(4) 138 139 First, need to clear bdb state that might be left over from previous tests. 140 Otherwise, the new breakpoints might get assigned different numbers. 141 142 >>> from bdb import Breakpoint 143 >>> Breakpoint.next = 1 144 >>> Breakpoint.bplist = {} 145 >>> Breakpoint.bpbynumber = [None] 146 147 Now test the breakpoint commands. NORMALIZE_WHITESPACE is needed because 148 the breakpoint list outputs a tab for the "stop only" and "ignore next" 149 lines, which we don't want to put in here. 150 151 >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE 152 ... 'break 3', 153 ... 'disable 1', 154 ... 'ignore 1 10', 155 ... 'condition 1 1 < 2', 156 ... 'break 4', 157 ... 'break 4', 158 ... 'break', 159 ... 'clear 3', 160 ... 'break', 161 ... 'condition 1', 162 ... 'enable 1', 163 ... 'clear 1', 164 ... 'commands 2', 165 ... 'print 42', 166 ... 'end', 167 ... 'continue', # will stop at breakpoint 2 (line 4) 168 ... 'clear', # clear all! 169 ... 'y', 170 ... 'tbreak 5', 171 ... 'continue', # will stop at temporary breakpoint 172 ... 'break', # make sure breakpoint is gone 173 ... 'continue', 174 ... ]): 175 ... test_function() 176 > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(3)test_function() 177 -> print(1) 178 (Pdb) break 3 179 Breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3 180 (Pdb) disable 1 181 (Pdb) ignore 1 10 182 Will ignore next 10 crossings of breakpoint 1. 183 (Pdb) condition 1 1 < 2 184 (Pdb) break 4 185 Breakpoint 2 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4 186 (Pdb) break 4 187 Breakpoint 3 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4 188 (Pdb) break 189 Num Type Disp Enb Where 190 1 breakpoint keep no at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3 191 stop only if 1 < 2 192 ignore next 10 hits 193 2 breakpoint keep yes at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4 194 3 breakpoint keep yes at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4 195 (Pdb) clear 3 196 Deleted breakpoint 3 197 (Pdb) break 198 Num Type Disp Enb Where 199 1 breakpoint keep no at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3 200 stop only if 1 < 2 201 ignore next 10 hits 202 2 breakpoint keep yes at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4 203 (Pdb) condition 1 204 Breakpoint 1 is now unconditional. 205 (Pdb) enable 1 206 (Pdb) clear 1 207 Deleted breakpoint 1 208 (Pdb) commands 2 209 (com) print 42 210 (com) end 211 (Pdb) continue 212 1 213 42 214 > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(4)test_function() 215 -> print(2) 216 (Pdb) clear 217 Clear all breaks? y 218 (Pdb) tbreak 5 219 Breakpoint 4 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:5 220 (Pdb) continue 221 2 222 Deleted breakpoint 4 223 > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(5)test_function() 224 -> print(3) 225 (Pdb) break 226 (Pdb) continue 227 3 228 4 229 """ 230 231 232def test_pdb_skip_modules(): 233 """This illustrates the simple case of module skipping. 234 235 >>> def skip_module(): 236 ... import string 237 ... import pdb; pdb.Pdb(skip=['string*']).set_trace() 238 ... string.lower('FOO') 239 240 >>> with PdbTestInput([ 241 ... 'step', 242 ... 'continue', 243 ... ]): 244 ... skip_module() 245 > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module() 246 -> string.lower('FOO') 247 (Pdb) step 248 --Return-- 249 > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module()->None 250 -> string.lower('FOO') 251 (Pdb) continue 252 """ 253 254 255# Module for testing skipping of module that makes a callback 256mod = imp.new_module('module_to_skip') 257exec 'def foo_pony(callback): x = 1; callback(); return None' in mod.__dict__ 258 259 260def test_pdb_skip_modules_with_callback(): 261 """This illustrates skipping of modules that call into other code. 262 263 >>> def skip_module(): 264 ... def callback(): 265 ... return None 266 ... import pdb; pdb.Pdb(skip=['module_to_skip*']).set_trace() 267 ... mod.foo_pony(callback) 268 269 >>> with PdbTestInput([ 270 ... 'step', 271 ... 'step', 272 ... 'step', 273 ... 'step', 274 ... 'step', 275 ... 'continue', 276 ... ]): 277 ... skip_module() 278 ... pass # provides something to "step" to 279 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module() 280 -> mod.foo_pony(callback) 281 (Pdb) step 282 --Call-- 283 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(2)callback() 284 -> def callback(): 285 (Pdb) step 286 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(3)callback() 287 -> return None 288 (Pdb) step 289 --Return-- 290 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(3)callback()->None 291 -> return None 292 (Pdb) step 293 --Return-- 294 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module()->None 295 -> mod.foo_pony(callback) 296 (Pdb) step 297 > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[1]>(10)<module>() 298 -> pass # provides something to "step" to 299 (Pdb) continue 300 """ 301 302 303def test_pdb_continue_in_bottomframe(): 304 """Test that "continue" and "next" work properly in bottom frame (issue #5294). 305 306 >>> def test_function(): 307 ... import pdb, sys; inst = pdb.Pdb() 308 ... inst.set_trace() 309 ... inst.botframe = sys._getframe() # hackery to get the right botframe 310 ... print(1) 311 ... print(2) 312 ... print(3) 313 ... print(4) 314 315 First, need to clear bdb state that might be left over from previous tests. 316 Otherwise, the new breakpoints might get assigned different numbers. 317 318 >>> from bdb import Breakpoint 319 >>> Breakpoint.next = 1 320 >>> Breakpoint.bplist = {} 321 >>> Breakpoint.bpbynumber = [None] 322 323 >>> with PdbTestInput([ 324 ... 'next', 325 ... 'break 7', 326 ... 'continue', 327 ... 'next', 328 ... 'continue', 329 ... 'continue', 330 ... ]): 331 ... test_function() 332 > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(4)test_function() 333 -> inst.botframe = sys._getframe() # hackery to get the right botframe 334 (Pdb) next 335 > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(5)test_function() 336 -> print(1) 337 (Pdb) break 7 338 Breakpoint 1 at <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>:7 339 (Pdb) continue 340 1 341 2 342 > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(7)test_function() 343 -> print(3) 344 (Pdb) next 345 3 346 > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(8)test_function() 347 -> print(4) 348 (Pdb) continue 349 4 350 """ 351 352class ModuleInitTester(unittest.TestCase): 353 354 def test_filename_correct(self): 355 """ 356 In issue 7750, it was found that if the filename has a sequence that 357 resolves to an escape character in a Python string (such as \t), it 358 will be treated as the escaped character. 359 """ 360 # the test_fn must contain something like \t 361 # on Windows, this will create 'test_mod.py' in the current directory. 362 # on Unix, this will create '.\test_mod.py' in the current directory. 363 test_fn = '.\\test_mod.py' 364 code = 'print("testing pdb")' 365 with open(test_fn, 'w') as f: 366 f.write(code) 367 self.addCleanup(os.remove, test_fn) 368 cmd = [sys.executable, '-m', 'pdb', test_fn,] 369 proc = subprocess.Popen(cmd, 370 stdout=subprocess.PIPE, 371 stdin=subprocess.PIPE, 372 stderr=subprocess.STDOUT, 373 ) 374 stdout, stderr = proc.communicate('quit\n') 375 self.assertIn(code, stdout, "pdb munged the filename") 376 377 378def test_main(): 379 from test import test_pdb 380 test_support.run_doctest(test_pdb, verbosity=True) 381 test_support.run_unittest( 382 PdbTestCase, 383 ModuleInitTester) 384 385if __name__ == '__main__': 386 test_main() 387