source: python/trunk/Lib/test/test_pdb.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 11.0 KB
Line 
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 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
72class 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
86def write(x):
87 print x
88
89def 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
117def 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
220def 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
244mod = imp.new_module('module_to_skip')
245exec 'def foo_pony(callback): x = 1; callback(); return None' in mod.__dict__
246
247
248def 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
291def 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
340class 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
366def 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
373if __name__ == '__main__':
374 test_main()
Note: See TracBrowser for help on using the repository browser.