##// END OF EJS Templates
Add some debugging prints.
Itamar Turner-Trauring -
Show More
@@ -1,265 +1,273 b''
1 """Tests for debugging machinery.
1 """Tests for debugging machinery.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import sys
7 import sys
8 import warnings
8 import warnings
9 from tempfile import NamedTemporaryFile
9 from tempfile import NamedTemporaryFile
10 from subprocess import check_output
10 from subprocess import check_output
11
11
12 import nose.tools as nt
12 import nose.tools as nt
13
13
14 from IPython.core import debugger
14 from IPython.core import debugger
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Helper classes, from CPython's Pdb test suite
17 # Helper classes, from CPython's Pdb test suite
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 class _FakeInput(object):
20 class _FakeInput(object):
21 """
21 """
22 A fake input stream for pdb's interactive debugger. Whenever a
22 A fake input stream for pdb's interactive debugger. Whenever a
23 line is read, print it (to simulate the user typing it), and then
23 line is read, print it (to simulate the user typing it), and then
24 return it. The set of lines to return is specified in the
24 return it. The set of lines to return is specified in the
25 constructor; they should not have trailing newlines.
25 constructor; they should not have trailing newlines.
26 """
26 """
27 def __init__(self, lines):
27 def __init__(self, lines):
28 self.lines = iter(lines)
28 self.lines = iter(lines)
29
29
30 def readline(self):
30 def readline(self):
31 line = next(self.lines)
31 line = next(self.lines)
32 print(line)
32 print(line)
33 return line+'\n'
33 return line+'\n'
34
34
35 class PdbTestInput(object):
35 class PdbTestInput(object):
36 """Context manager that makes testing Pdb in doctests easier."""
36 """Context manager that makes testing Pdb in doctests easier."""
37
37
38 def __init__(self, input):
38 def __init__(self, input):
39 self.input = input
39 self.input = input
40
40
41 def __enter__(self):
41 def __enter__(self):
42 self.real_stdin = sys.stdin
42 self.real_stdin = sys.stdin
43 sys.stdin = _FakeInput(self.input)
43 sys.stdin = _FakeInput(self.input)
44
44
45 def __exit__(self, *exc):
45 def __exit__(self, *exc):
46 sys.stdin = self.real_stdin
46 sys.stdin = self.real_stdin
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Tests
49 # Tests
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 def test_longer_repr():
52 def test_longer_repr():
53 from reprlib import repr as trepr
53 from reprlib import repr as trepr
54
54
55 a = '1234567890'* 7
55 a = '1234567890'* 7
56 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
56 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
57 a_trunc = "'123456789012...8901234567890'"
57 a_trunc = "'123456789012...8901234567890'"
58 nt.assert_equal(trepr(a), a_trunc)
58 nt.assert_equal(trepr(a), a_trunc)
59 # The creation of our tracer modifies the repr module's repr function
59 # The creation of our tracer modifies the repr module's repr function
60 # in-place, since that global is used directly by the stdlib's pdb module.
60 # in-place, since that global is used directly by the stdlib's pdb module.
61 with warnings.catch_warnings():
61 with warnings.catch_warnings():
62 warnings.simplefilter('ignore', DeprecationWarning)
62 warnings.simplefilter('ignore', DeprecationWarning)
63 debugger.Tracer()
63 debugger.Tracer()
64 nt.assert_equal(trepr(a), ar)
64 nt.assert_equal(trepr(a), ar)
65
65
66 def test_ipdb_magics():
66 def test_ipdb_magics():
67 '''Test calling some IPython magics from ipdb.
67 '''Test calling some IPython magics from ipdb.
68
68
69 First, set up some test functions and classes which we can inspect.
69 First, set up some test functions and classes which we can inspect.
70
70
71 >>> class ExampleClass(object):
71 >>> class ExampleClass(object):
72 ... """Docstring for ExampleClass."""
72 ... """Docstring for ExampleClass."""
73 ... def __init__(self):
73 ... def __init__(self):
74 ... """Docstring for ExampleClass.__init__"""
74 ... """Docstring for ExampleClass.__init__"""
75 ... pass
75 ... pass
76 ... def __str__(self):
76 ... def __str__(self):
77 ... return "ExampleClass()"
77 ... return "ExampleClass()"
78
78
79 >>> def example_function(x, y, z="hello"):
79 >>> def example_function(x, y, z="hello"):
80 ... """Docstring for example_function."""
80 ... """Docstring for example_function."""
81 ... pass
81 ... pass
82
82
83 >>> old_trace = sys.gettrace()
83 >>> old_trace = sys.gettrace()
84
84
85 Create a function which triggers ipdb.
85 Create a function which triggers ipdb.
86
86
87 >>> def trigger_ipdb():
87 >>> def trigger_ipdb():
88 ... a = ExampleClass()
88 ... a = ExampleClass()
89 ... debugger.Pdb().set_trace()
89 ... debugger.Pdb().set_trace()
90
90
91 >>> with PdbTestInput([
91 >>> with PdbTestInput([
92 ... 'pdef example_function',
92 ... 'pdef example_function',
93 ... 'pdoc ExampleClass',
93 ... 'pdoc ExampleClass',
94 ... 'up',
94 ... 'up',
95 ... 'down',
95 ... 'down',
96 ... 'list',
96 ... 'list',
97 ... 'pinfo a',
97 ... 'pinfo a',
98 ... 'll',
98 ... 'll',
99 ... 'continue',
99 ... 'continue',
100 ... ]):
100 ... ]):
101 ... trigger_ipdb()
101 ... trigger_ipdb()
102 --Return--
102 --Return--
103 None
103 None
104 > <doctest ...>(3)trigger_ipdb()
104 > <doctest ...>(3)trigger_ipdb()
105 1 def trigger_ipdb():
105 1 def trigger_ipdb():
106 2 a = ExampleClass()
106 2 a = ExampleClass()
107 ----> 3 debugger.Pdb().set_trace()
107 ----> 3 debugger.Pdb().set_trace()
108 <BLANKLINE>
108 <BLANKLINE>
109 ipdb> pdef example_function
109 ipdb> pdef example_function
110 example_function(x, y, z='hello')
110 example_function(x, y, z='hello')
111 ipdb> pdoc ExampleClass
111 ipdb> pdoc ExampleClass
112 Class docstring:
112 Class docstring:
113 Docstring for ExampleClass.
113 Docstring for ExampleClass.
114 Init docstring:
114 Init docstring:
115 Docstring for ExampleClass.__init__
115 Docstring for ExampleClass.__init__
116 ipdb> up
116 ipdb> up
117 > <doctest ...>(11)<module>()
117 > <doctest ...>(11)<module>()
118 7 'pinfo a',
118 7 'pinfo a',
119 8 'll',
119 8 'll',
120 9 'continue',
120 9 'continue',
121 10 ]):
121 10 ]):
122 ---> 11 trigger_ipdb()
122 ---> 11 trigger_ipdb()
123 <BLANKLINE>
123 <BLANKLINE>
124 ipdb> down
124 ipdb> down
125 None
125 None
126 > <doctest ...>(3)trigger_ipdb()
126 > <doctest ...>(3)trigger_ipdb()
127 1 def trigger_ipdb():
127 1 def trigger_ipdb():
128 2 a = ExampleClass()
128 2 a = ExampleClass()
129 ----> 3 debugger.Pdb().set_trace()
129 ----> 3 debugger.Pdb().set_trace()
130 <BLANKLINE>
130 <BLANKLINE>
131 ipdb> list
131 ipdb> list
132 1 def trigger_ipdb():
132 1 def trigger_ipdb():
133 2 a = ExampleClass()
133 2 a = ExampleClass()
134 ----> 3 debugger.Pdb().set_trace()
134 ----> 3 debugger.Pdb().set_trace()
135 <BLANKLINE>
135 <BLANKLINE>
136 ipdb> pinfo a
136 ipdb> pinfo a
137 Type: ExampleClass
137 Type: ExampleClass
138 String form: ExampleClass()
138 String form: ExampleClass()
139 Namespace: Local...
139 Namespace: Local...
140 Docstring: Docstring for ExampleClass.
140 Docstring: Docstring for ExampleClass.
141 Init docstring: Docstring for ExampleClass.__init__
141 Init docstring: Docstring for ExampleClass.__init__
142 ipdb> ll
142 ipdb> ll
143 1 def trigger_ipdb():
143 1 def trigger_ipdb():
144 2 a = ExampleClass()
144 2 a = ExampleClass()
145 ----> 3 debugger.Pdb().set_trace()
145 ----> 3 debugger.Pdb().set_trace()
146 <BLANKLINE>
146 <BLANKLINE>
147 ipdb> continue
147 ipdb> continue
148
148
149 Restore previous trace function, e.g. for coverage.py
149 Restore previous trace function, e.g. for coverage.py
150
150
151 >>> sys.settrace(old_trace)
151 >>> sys.settrace(old_trace)
152 '''
152 '''
153
153
154 def test_ipdb_magics2():
154 def test_ipdb_magics2():
155 '''Test ipdb with a very short function.
155 '''Test ipdb with a very short function.
156
156
157 >>> old_trace = sys.gettrace()
157 >>> old_trace = sys.gettrace()
158
158
159 >>> def bar():
159 >>> def bar():
160 ... pass
160 ... pass
161
161
162 Run ipdb.
162 Run ipdb.
163
163
164 >>> with PdbTestInput([
164 >>> with PdbTestInput([
165 ... 'continue',
165 ... 'continue',
166 ... ]):
166 ... ]):
167 ... debugger.Pdb().runcall(bar)
167 ... debugger.Pdb().runcall(bar)
168 > <doctest ...>(2)bar()
168 > <doctest ...>(2)bar()
169 1 def bar():
169 1 def bar():
170 ----> 2 pass
170 ----> 2 pass
171 <BLANKLINE>
171 <BLANKLINE>
172 ipdb> continue
172 ipdb> continue
173
173
174 Restore previous trace function, e.g. for coverage.py
174 Restore previous trace function, e.g. for coverage.py
175
175
176 >>> sys.settrace(old_trace)
176 >>> sys.settrace(old_trace)
177 '''
177 '''
178
178
179 def can_quit():
179 def can_quit():
180 '''Test that quit work in ipydb
180 '''Test that quit work in ipydb
181
181
182 >>> old_trace = sys.gettrace()
182 >>> old_trace = sys.gettrace()
183
183
184 >>> def bar():
184 >>> def bar():
185 ... pass
185 ... pass
186
186
187 >>> with PdbTestInput([
187 >>> with PdbTestInput([
188 ... 'quit',
188 ... 'quit',
189 ... ]):
189 ... ]):
190 ... debugger.Pdb().runcall(bar)
190 ... debugger.Pdb().runcall(bar)
191 > <doctest ...>(2)bar()
191 > <doctest ...>(2)bar()
192 1 def bar():
192 1 def bar():
193 ----> 2 pass
193 ----> 2 pass
194 <BLANKLINE>
194 <BLANKLINE>
195 ipdb> quit
195 ipdb> quit
196
196
197 Restore previous trace function, e.g. for coverage.py
197 Restore previous trace function, e.g. for coverage.py
198
198
199 >>> sys.settrace(old_trace)
199 >>> sys.settrace(old_trace)
200 '''
200 '''
201
201
202
202
203 def can_exit():
203 def can_exit():
204 '''Test that quit work in ipydb
204 '''Test that quit work in ipydb
205
205
206 >>> old_trace = sys.gettrace()
206 >>> old_trace = sys.gettrace()
207
207
208 >>> def bar():
208 >>> def bar():
209 ... pass
209 ... pass
210
210
211 >>> with PdbTestInput([
211 >>> with PdbTestInput([
212 ... 'exit',
212 ... 'exit',
213 ... ]):
213 ... ]):
214 ... debugger.Pdb().runcall(bar)
214 ... debugger.Pdb().runcall(bar)
215 > <doctest ...>(2)bar()
215 > <doctest ...>(2)bar()
216 1 def bar():
216 1 def bar():
217 ----> 2 pass
217 ----> 2 pass
218 <BLANKLINE>
218 <BLANKLINE>
219 ipdb> exit
219 ipdb> exit
220
220
221 Restore previous trace function, e.g. for coverage.py
221 Restore previous trace function, e.g. for coverage.py
222
222
223 >>> sys.settrace(old_trace)
223 >>> sys.settrace(old_trace)
224 '''
224 '''
225
225
226
226
227 interruptible_debugger = """\
227 interruptible_debugger = """\
228 import threading
228 import threading
229 import time
229 import time
230 from os import _exit
230 from os import _exit
231
231
232 from IPython.core.debugger import set_trace
232 from IPython.core.debugger import set_trace
233
233
234 def interrupt():
234 def interrupt():
235 time.sleep(0.1)
235 time.sleep(0.1)
236 import os, signal
236 import os, signal
237 os.kill(os.getpid(), signal.SIGINT)
237 os.kill(os.getpid(), signal.SIGINT)
238 threading.Thread(target=interrupt).start()
238 threading.Thread(target=interrupt).start()
239
239
240 # Timeout if the interrupt doesn't happen:
240 # Timeout if the interrupt doesn't happen:
241 def interrupt():
241 def interrupt():
242 time.sleep(2)
242 try:
243 time.sleep(2)
244 except KeyboardInterrupt:
245 return
243 _exit(7)
246 _exit(7)
244 threading.Thread(target=interrupt, daemon=True).start()
247 threading.Thread(target=interrupt, daemon=True).start()
245
248
246 def main():
249 def main():
247 set_trace()
250 set_trace()
248
251
249 if __name__ == '__main__':
252 if __name__ == '__main__':
250 try:
253 try:
254 print("Starting debugger...")
251 main()
255 main()
256 print("Debugger exited without error.")
252 except KeyboardInterrupt:
257 except KeyboardInterrupt:
253 print("PASSED")
258 print("Caught KeyboardInterrupt, PASSED")
259 except Exception as e:
260 print("Got wrong exception...")
261 raise e
254 """
262 """
255
263
256
264
257 def test_interruptible_core_debugger():
265 def test_interruptible_core_debugger():
258 """The debugger can be interrupted."""
266 """The debugger can be interrupted."""
259 with NamedTemporaryFile("w") as f:
267 with NamedTemporaryFile("w") as f:
260 f.write(interruptible_debugger)
268 f.write(interruptible_debugger)
261 f.flush()
269 f.flush()
262 result = check_output([sys.executable, f.name],
270 result = check_output([sys.executable, f.name],
263 encoding=sys.getdefaultencoding())
271 encoding=sys.getdefaultencoding())
264 # Wait for it to start:
272 # Wait for it to start:
265 assert "PASSED" in result
273 assert "PASSED" in result
General Comments 0
You need to be logged in to leave comments. Login now