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