##// END OF EJS Templates
Skip: no pexpect on win32
Matthias Bussonnier -
Show More
@@ -1,389 +1,390 b''
1 1 """Tests for debugging machinery.
2 2 """
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import bdb
8 8 import builtins
9 9 import os
10 10 import signal
11 11 import subprocess
12 12 import sys
13 13 import time
14 14 import warnings
15 15 from subprocess import PIPE, CalledProcessError, check_output
16 16 from tempfile import NamedTemporaryFile
17 17 from textwrap import dedent
18 18 from unittest.mock import patch
19 19
20 20 import nose.tools as nt
21 21
22 22 from IPython.core import debugger
23 23 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
24 24 from IPython.testing.decorators import skip_win32
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Helper classes, from CPython's Pdb test suite
28 28 #-----------------------------------------------------------------------------
29 29
30 30 class _FakeInput(object):
31 31 """
32 32 A fake input stream for pdb's interactive debugger. Whenever a
33 33 line is read, print it (to simulate the user typing it), and then
34 34 return it. The set of lines to return is specified in the
35 35 constructor; they should not have trailing newlines.
36 36 """
37 37 def __init__(self, lines):
38 38 self.lines = iter(lines)
39 39
40 40 def readline(self):
41 41 line = next(self.lines)
42 42 print(line)
43 43 return line+'\n'
44 44
45 45 class PdbTestInput(object):
46 46 """Context manager that makes testing Pdb in doctests easier."""
47 47
48 48 def __init__(self, input):
49 49 self.input = input
50 50
51 51 def __enter__(self):
52 52 self.real_stdin = sys.stdin
53 53 sys.stdin = _FakeInput(self.input)
54 54
55 55 def __exit__(self, *exc):
56 56 sys.stdin = self.real_stdin
57 57
58 58 #-----------------------------------------------------------------------------
59 59 # Tests
60 60 #-----------------------------------------------------------------------------
61 61
62 62 def test_longer_repr():
63 63 from reprlib import repr as trepr
64 64
65 65 a = '1234567890'* 7
66 66 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
67 67 a_trunc = "'123456789012...8901234567890'"
68 68 nt.assert_equal(trepr(a), a_trunc)
69 69 # The creation of our tracer modifies the repr module's repr function
70 70 # in-place, since that global is used directly by the stdlib's pdb module.
71 71 with warnings.catch_warnings():
72 72 warnings.simplefilter('ignore', DeprecationWarning)
73 73 debugger.Tracer()
74 74 nt.assert_equal(trepr(a), ar)
75 75
76 76 def test_ipdb_magics():
77 77 '''Test calling some IPython magics from ipdb.
78 78
79 79 First, set up some test functions and classes which we can inspect.
80 80
81 81 >>> class ExampleClass(object):
82 82 ... """Docstring for ExampleClass."""
83 83 ... def __init__(self):
84 84 ... """Docstring for ExampleClass.__init__"""
85 85 ... pass
86 86 ... def __str__(self):
87 87 ... return "ExampleClass()"
88 88
89 89 >>> def example_function(x, y, z="hello"):
90 90 ... """Docstring for example_function."""
91 91 ... pass
92 92
93 93 >>> old_trace = sys.gettrace()
94 94
95 95 Create a function which triggers ipdb.
96 96
97 97 >>> def trigger_ipdb():
98 98 ... a = ExampleClass()
99 99 ... debugger.Pdb().set_trace()
100 100
101 101 >>> with PdbTestInput([
102 102 ... 'pdef example_function',
103 103 ... 'pdoc ExampleClass',
104 104 ... 'up',
105 105 ... 'down',
106 106 ... 'list',
107 107 ... 'pinfo a',
108 108 ... 'll',
109 109 ... 'continue',
110 110 ... ]):
111 111 ... trigger_ipdb()
112 112 --Return--
113 113 None
114 114 > <doctest ...>(3)trigger_ipdb()
115 115 1 def trigger_ipdb():
116 116 2 a = ExampleClass()
117 117 ----> 3 debugger.Pdb().set_trace()
118 118 <BLANKLINE>
119 119 ipdb> pdef example_function
120 120 example_function(x, y, z='hello')
121 121 ipdb> pdoc ExampleClass
122 122 Class docstring:
123 123 Docstring for ExampleClass.
124 124 Init docstring:
125 125 Docstring for ExampleClass.__init__
126 126 ipdb> up
127 127 > <doctest ...>(11)<module>()
128 128 7 'pinfo a',
129 129 8 'll',
130 130 9 'continue',
131 131 10 ]):
132 132 ---> 11 trigger_ipdb()
133 133 <BLANKLINE>
134 134 ipdb> down
135 135 None
136 136 > <doctest ...>(3)trigger_ipdb()
137 137 1 def trigger_ipdb():
138 138 2 a = ExampleClass()
139 139 ----> 3 debugger.Pdb().set_trace()
140 140 <BLANKLINE>
141 141 ipdb> list
142 142 1 def trigger_ipdb():
143 143 2 a = ExampleClass()
144 144 ----> 3 debugger.Pdb().set_trace()
145 145 <BLANKLINE>
146 146 ipdb> pinfo a
147 147 Type: ExampleClass
148 148 String form: ExampleClass()
149 149 Namespace: Local...
150 150 Docstring: Docstring for ExampleClass.
151 151 Init docstring: Docstring for ExampleClass.__init__
152 152 ipdb> ll
153 153 1 def trigger_ipdb():
154 154 2 a = ExampleClass()
155 155 ----> 3 debugger.Pdb().set_trace()
156 156 <BLANKLINE>
157 157 ipdb> continue
158 158
159 159 Restore previous trace function, e.g. for coverage.py
160 160
161 161 >>> sys.settrace(old_trace)
162 162 '''
163 163
164 164 def test_ipdb_magics2():
165 165 '''Test ipdb with a very short function.
166 166
167 167 >>> old_trace = sys.gettrace()
168 168
169 169 >>> def bar():
170 170 ... pass
171 171
172 172 Run ipdb.
173 173
174 174 >>> with PdbTestInput([
175 175 ... 'continue',
176 176 ... ]):
177 177 ... debugger.Pdb().runcall(bar)
178 178 > <doctest ...>(2)bar()
179 179 1 def bar():
180 180 ----> 2 pass
181 181 <BLANKLINE>
182 182 ipdb> continue
183 183
184 184 Restore previous trace function, e.g. for coverage.py
185 185
186 186 >>> sys.settrace(old_trace)
187 187 '''
188 188
189 189 def can_quit():
190 190 '''Test that quit work in ipydb
191 191
192 192 >>> old_trace = sys.gettrace()
193 193
194 194 >>> def bar():
195 195 ... pass
196 196
197 197 >>> with PdbTestInput([
198 198 ... 'quit',
199 199 ... ]):
200 200 ... debugger.Pdb().runcall(bar)
201 201 > <doctest ...>(2)bar()
202 202 1 def bar():
203 203 ----> 2 pass
204 204 <BLANKLINE>
205 205 ipdb> quit
206 206
207 207 Restore previous trace function, e.g. for coverage.py
208 208
209 209 >>> sys.settrace(old_trace)
210 210 '''
211 211
212 212
213 213 def can_exit():
214 214 '''Test that quit work in ipydb
215 215
216 216 >>> old_trace = sys.gettrace()
217 217
218 218 >>> def bar():
219 219 ... pass
220 220
221 221 >>> with PdbTestInput([
222 222 ... 'exit',
223 223 ... ]):
224 224 ... debugger.Pdb().runcall(bar)
225 225 > <doctest ...>(2)bar()
226 226 1 def bar():
227 227 ----> 2 pass
228 228 <BLANKLINE>
229 229 ipdb> exit
230 230
231 231 Restore previous trace function, e.g. for coverage.py
232 232
233 233 >>> sys.settrace(old_trace)
234 234 '''
235 235
236 236
237 237 def test_interruptible_core_debugger():
238 238 """The debugger can be interrupted.
239 239
240 240 The presumption is there is some mechanism that causes a KeyboardInterrupt
241 241 (this is implemented in ipykernel). We want to ensure the
242 242 KeyboardInterrupt cause debugging to cease.
243 243 """
244 244 def raising_input(msg="", called=[0]):
245 245 called[0] += 1
246 246 if called[0] == 1:
247 247 raise KeyboardInterrupt()
248 248 else:
249 249 raise AssertionError("input() should only be called once!")
250 250
251 251 with patch.object(builtins, "input", raising_input):
252 252 debugger.InterruptiblePdb().set_trace()
253 253 # The way this test will fail is by set_trace() never exiting,
254 254 # resulting in a timeout by the test runner. The alternative
255 255 # implementation would involve a subprocess, but that adds issues with
256 256 # interrupting subprocesses that are rather complex, so it's simpler
257 257 # just to do it this way.
258 258
259 259 @skip_win32
260 260 def test_xmode_skip():
261 261 """that xmode skip frames
262 262
263 263 Not as a doctest as pytest does not run doctests.
264 264 """
265 265 import pexpect
266 266 env = os.environ.copy()
267 267 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
268 268
269 269 child = pexpect.spawn(
270 270 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
271 271 )
272 272 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
273 273
274 274 child.expect("IPython")
275 275 child.expect("\n")
276 276 child.expect_exact("In [1]")
277 277
278 278 block = dedent(
279 279 """
280 280 def f():
281 281 __tracebackhide__ = True
282 282 g()
283 283
284 284 def g():
285 285 raise ValueError
286 286
287 287 f()
288 288 """
289 289 )
290 290
291 291 for line in block.splitlines():
292 292 child.sendline(line)
293 293 child.expect_exact(line)
294 294 child.expect_exact("skipping")
295 295
296 296 block = dedent(
297 297 """
298 298 def f():
299 299 __tracebackhide__ = True
300 300 g()
301 301
302 302 def g():
303 303 from IPython.core.debugger import set_trace
304 304 set_trace()
305 305
306 306 f()
307 307 """
308 308 )
309 309
310 310 for line in block.splitlines():
311 311 child.sendline(line)
312 312 child.expect_exact(line)
313 313
314 314 child.expect("ipdb>")
315 315 child.sendline("w")
316 316 child.expect("hidden")
317 317 child.expect("ipdb>")
318 318 child.sendline("skip_hidden false")
319 319 child.sendline("w")
320 320 child.expect("__traceba")
321 321 child.expect("ipdb>")
322 322
323 323 child.close()
324 324
325 325
326 @skip_win32
326 327 def test_where_erase_value():
327 328 """Test that `where` does not access f_locals and erase values."""
328 329 import pexpect
329 330
330 331 env = os.environ.copy()
331 332 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
332 333
333 334 child = pexpect.spawn(
334 335 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
335 336 )
336 337 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
337 338
338 339 child.expect("IPython")
339 340 child.expect("\n")
340 341 child.expect_exact("In [1]")
341 342
342 343 block = dedent(
343 344 """
344 345 def simple_f():
345 346 myvar = 1
346 347 print(myvar)
347 348 1/0
348 349 print(myvar)
349 350 simple_f() """
350 351 )
351 352
352 353 for line in block.splitlines():
353 354 child.sendline(line)
354 355 child.expect_exact(line)
355 356 child.expect_exact("ZeroDivisionError")
356 357 child.expect_exact("In [2]:")
357 358
358 359 child.sendline("%debug")
359 360
360 361 ##
361 362 child.expect("ipdb>")
362 363
363 364 child.sendline("myvar")
364 365 child.expect("1")
365 366
366 367 ##
367 368 child.expect("ipdb>")
368 369
369 370 child.sendline("myvar = 2")
370 371
371 372 ##
372 373 child.expect_exact("ipdb>")
373 374
374 375 child.sendline("myvar")
375 376
376 377 child.expect_exact("2")
377 378
378 379 ##
379 380 child.expect("ipdb>")
380 381 child.sendline("where")
381 382
382 383 ##
383 384 child.expect("ipdb>")
384 385 child.sendline("myvar")
385 386
386 387 child.expect_exact("2")
387 388 child.expect("ipdb>")
388 389
389 390 child.close()
General Comments 0
You need to be logged in to leave comments. Login now