blob: ed9e6d4f492fecc45cff041a6709efb0f07617ab [file] [log] [blame]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00001# Testing the line trace facility.
2
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003from test import support
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00004import unittest
5import sys
6import difflib
Christian Heimes81ee3ef2008-05-04 22:42:01 +00007import gc
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00008
9# A very basic example. If this fails, we're in deep trouble.
10def basic():
11 return 1
12
13basic.events = [(0, 'call'),
14 (1, 'line'),
15 (1, 'return')]
16
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000017# Many of the tests below are tricky because they involve pass statements.
18# If there is implicit control flow around a pass statement (in an except
19# clause or else caluse) under what conditions do you set a line number
20# following that clause?
21
22
23# The entire "while 0:" statement is optimized away. No code
24# exists for it, so the line numbers skip directly from "del x"
25# to "x = 1".
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000026def arigo_example():
27 x = 1
28 del x
29 while 0:
30 pass
31 x = 1
32
33arigo_example.events = [(0, 'call'),
34 (1, 'line'),
35 (2, 'line'),
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000036 (5, 'line'),
37 (5, 'return')]
38
39# check that lines consisting of just one instruction get traced:
40def one_instr_line():
41 x = 1
42 del x
43 x = 1
44
45one_instr_line.events = [(0, 'call'),
46 (1, 'line'),
47 (2, 'line'),
48 (3, 'line'),
49 (3, 'return')]
50
51def no_pop_tops(): # 0
52 x = 1 # 1
53 for a in range(2): # 2
54 if a: # 3
55 x = 1 # 4
56 else: # 5
57 x = 1 # 6
58
59no_pop_tops.events = [(0, 'call'),
60 (1, 'line'),
61 (2, 'line'),
62 (3, 'line'),
63 (6, 'line'),
64 (2, 'line'),
65 (3, 'line'),
66 (4, 'line'),
67 (2, 'line'),
Michael W. Hudson02ff6a92002-09-11 15:36:32 +000068 (2, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000069
70def no_pop_blocks():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000071 y = 1
72 while not y:
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000073 bla
74 x = 1
75
76no_pop_blocks.events = [(0, 'call'),
77 (1, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000078 (2, 'line'),
79 (4, 'line'),
80 (4, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000081
Michael W. Hudson519a3422002-09-11 14:47:51 +000082def called(): # line -3
83 x = 1
84
85def call(): # line 0
86 called()
87
88call.events = [(0, 'call'),
89 (1, 'line'),
90 (-3, 'call'),
91 (-2, 'line'),
92 (-2, 'return'),
93 (1, 'return')]
94
95def raises():
96 raise Exception
97
98def test_raise():
99 try:
100 raises()
Guido van Rossumb940e112007-01-10 16:19:56 +0000101 except Exception as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000102 x = 1
103
104test_raise.events = [(0, 'call'),
105 (1, 'line'),
106 (2, 'line'),
107 (-3, 'call'),
108 (-2, 'line'),
109 (-2, 'exception'),
Barry Warsawe2eca0b2005-08-15 18:14:19 +0000110 (-2, 'return'),
Michael W. Hudson519a3422002-09-11 14:47:51 +0000111 (2, 'exception'),
112 (3, 'line'),
113 (4, 'line'),
114 (4, 'return')]
115
116def _settrace_and_return(tracefunc):
117 sys.settrace(tracefunc)
118 sys._getframe().f_back.f_trace = tracefunc
119def settrace_and_return(tracefunc):
120 _settrace_and_return(tracefunc)
Tim Peters3de75262002-11-09 05:26:15 +0000121
Michael W. Hudson519a3422002-09-11 14:47:51 +0000122settrace_and_return.events = [(1, 'return')]
123
124def _settrace_and_raise(tracefunc):
125 sys.settrace(tracefunc)
126 sys._getframe().f_back.f_trace = tracefunc
127 raise RuntimeError
128def settrace_and_raise(tracefunc):
129 try:
130 _settrace_and_raise(tracefunc)
Guido van Rossumb940e112007-01-10 16:19:56 +0000131 except RuntimeError as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000132 pass
Tim Peters3de75262002-11-09 05:26:15 +0000133
Michael W. Hudson519a3422002-09-11 14:47:51 +0000134settrace_and_raise.events = [(2, 'exception'),
135 (3, 'line'),
136 (4, 'line'),
137 (4, 'return')]
138
Nicholas Bastinaea94592004-03-22 18:30:42 +0000139# implicit return example
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000140# This test is interesting because of the else: pass
141# part of the code. The code generate for the true
142# part of the if contains a jump past the else branch.
143# The compiler then generates an implicit "return None"
144# Internally, the compiler visits the pass statement
145# and stores its line number for use on the next instruction.
146# The next instruction is the implicit return None.
Nicholas Bastinaea94592004-03-22 18:30:42 +0000147def ireturn_example():
148 a = 5
149 b = 5
150 if a == b:
151 b = a+1
152 else:
153 pass
154
155ireturn_example.events = [(0, 'call'),
156 (1, 'line'),
157 (2, 'line'),
158 (3, 'line'),
159 (4, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000160 (6, 'line'),
161 (6, 'return')]
Nicholas Bastinaea94592004-03-22 18:30:42 +0000162
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000163# Tight loop with while(1) example (SF #765624)
164def tightloop_example():
165 items = range(0, 3)
166 try:
167 i = 0
168 while 1:
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000169 b = items[i]; i+=1
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000170 except IndexError:
171 pass
172
173tightloop_example.events = [(0, 'call'),
174 (1, 'line'),
175 (2, 'line'),
176 (3, 'line'),
177 (4, 'line'),
178 (5, 'line'),
179 (5, 'line'),
180 (5, 'line'),
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000181 (5, 'line'),
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000182 (5, 'exception'),
183 (6, 'line'),
184 (7, 'line'),
185 (7, 'return')]
186
Armin Rigo70693382004-03-22 19:30:39 +0000187def tighterloop_example():
188 items = range(1, 4)
189 try:
190 i = 0
191 while 1: i = items[i]
192 except IndexError:
193 pass
194
195tighterloop_example.events = [(0, 'call'),
196 (1, 'line'),
197 (2, 'line'),
198 (3, 'line'),
199 (4, 'line'),
200 (4, 'line'),
201 (4, 'line'),
202 (4, 'line'),
203 (4, 'exception'),
204 (5, 'line'),
205 (6, 'line'),
206 (6, 'return')]
207
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000208def generator_function():
209 try:
210 yield True
211 "continued"
212 finally:
213 "finally"
214def generator_example():
215 # any() will leave the generator before its end
216 x = any(generator_function())
217
218 # the following lines were not traced
219 for x in range(10):
220 y = x
221
222generator_example.events = ([(0, 'call'),
223 (2, 'line'),
224 (-6, 'call'),
225 (-5, 'line'),
226 (-4, 'line'),
227 (-4, 'return'),
228 (-4, 'call'),
229 (-4, 'exception'),
230 (-1, 'line'),
231 (-1, 'return')] +
232 [(5, 'line'), (6, 'line')] * 10 +
233 [(5, 'line'), (5, 'return')])
234
235
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000236class Tracer:
Nick Coghlan5a851672017-09-08 10:14:16 +1000237 def __init__(self, trace_line_events=None, trace_opcode_events=None):
238 self.trace_line_events = trace_line_events
239 self.trace_opcode_events = trace_opcode_events
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000240 self.events = []
Nick Coghlan5a851672017-09-08 10:14:16 +1000241
242 def _reconfigure_frame(self, frame):
243 if self.trace_line_events is not None:
244 frame.f_trace_lines = self.trace_line_events
245 if self.trace_opcode_events is not None:
246 frame.f_trace_opcodes = self.trace_opcode_events
247
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000248 def trace(self, frame, event, arg):
Nick Coghlan5a851672017-09-08 10:14:16 +1000249 self._reconfigure_frame(frame)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000250 self.events.append((frame.f_lineno, event))
251 return self.trace
Nick Coghlan5a851672017-09-08 10:14:16 +1000252
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000253 def traceWithGenexp(self, frame, event, arg):
Nick Coghlan5a851672017-09-08 10:14:16 +1000254 self._reconfigure_frame(frame)
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000255 (o for o in [1])
256 self.events.append((frame.f_lineno, event))
257 return self.trace
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000258
Nick Coghlan5a851672017-09-08 10:14:16 +1000259
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000260class TraceTestCase(unittest.TestCase):
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000261
262 # Disable gc collection when tracing, otherwise the
263 # deallocators may be traced as well.
264 def setUp(self):
265 self.using_gc = gc.isenabled()
266 gc.disable()
Brett Cannon31f59292011-02-21 19:29:56 +0000267 self.addCleanup(sys.settrace, sys.gettrace())
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000268
269 def tearDown(self):
270 if self.using_gc:
271 gc.enable()
272
Nick Coghlan5a851672017-09-08 10:14:16 +1000273 @staticmethod
274 def make_tracer():
275 """Helper to allow test subclasses to configure tracers differently"""
276 return Tracer()
277
Michael W. Hudson519a3422002-09-11 14:47:51 +0000278 def compare_events(self, line_offset, events, expected_events):
Tim Peters3de75262002-11-09 05:26:15 +0000279 events = [(l - line_offset, e) for (l, e) in events]
Michael W. Hudson519a3422002-09-11 14:47:51 +0000280 if events != expected_events:
281 self.fail(
282 "events did not match expectation:\n" +
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000283 "\n".join(difflib.ndiff([str(x) for x in expected_events],
284 [str(x) for x in events])))
Tim Peters3de75262002-11-09 05:26:15 +0000285
Christian Heimes2202f872008-02-06 14:31:34 +0000286 def run_and_compare(self, func, events):
Nick Coghlan5a851672017-09-08 10:14:16 +1000287 tracer = self.make_tracer()
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000288 sys.settrace(tracer.trace)
289 func()
290 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000291 self.compare_events(func.__code__.co_firstlineno,
Christian Heimes2202f872008-02-06 14:31:34 +0000292 tracer.events, events)
293
294 def run_test(self, func):
295 self.run_and_compare(func, func.events)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000296
297 def run_test2(self, func):
Nick Coghlan5a851672017-09-08 10:14:16 +1000298 tracer = self.make_tracer()
Michael W. Hudson519a3422002-09-11 14:47:51 +0000299 func(tracer.trace)
300 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000301 self.compare_events(func.__code__.co_firstlineno,
Michael W. Hudson519a3422002-09-11 14:47:51 +0000302 tracer.events, func.events)
Tim Peters3de75262002-11-09 05:26:15 +0000303
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200304 def test_set_and_retrieve_none(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000305 sys.settrace(None)
306 assert sys.gettrace() is None
307
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200308 def test_set_and_retrieve_func(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000309 def fn(*args):
310 pass
311
312 sys.settrace(fn)
313 try:
314 assert sys.gettrace() is fn
315 finally:
316 sys.settrace(None)
317
Nicholas Bastinaea94592004-03-22 18:30:42 +0000318 def test_01_basic(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000319 self.run_test(basic)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000320 def test_02_arigo(self):
321 self.run_test(arigo_example)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000322 def test_03_one_instr(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000323 self.run_test(one_instr_line)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000324 def test_04_no_pop_blocks(self):
325 self.run_test(no_pop_blocks)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000326 def test_05_no_pop_tops(self):
327 self.run_test(no_pop_tops)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000328 def test_06_call(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000329 self.run_test(call)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000330 def test_07_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000331 self.run_test(test_raise)
332
Nicholas Bastinaea94592004-03-22 18:30:42 +0000333 def test_08_settrace_and_return(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000334 self.run_test2(settrace_and_return)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000335 def test_09_settrace_and_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000336 self.run_test2(settrace_and_raise)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000337 def test_10_ireturn(self):
338 self.run_test(ireturn_example)
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000339 def test_11_tightloop(self):
340 self.run_test(tightloop_example)
Armin Rigo70693382004-03-22 19:30:39 +0000341 def test_12_tighterloop(self):
342 self.run_test(tighterloop_example)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000343
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000344 def test_13_genexp(self):
345 self.run_test(generator_example)
346 # issue1265: if the trace function contains a generator,
347 # and if the traced function contains another generator
348 # that is not completely exhausted, the trace stopped.
349 # Worse: the 'finally' clause was not invoked.
Nick Coghlan5a851672017-09-08 10:14:16 +1000350 tracer = self.make_tracer()
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000351 sys.settrace(tracer.traceWithGenexp)
352 generator_example()
353 sys.settrace(None)
354 self.compare_events(generator_example.__code__.co_firstlineno,
355 tracer.events, generator_example.events)
356
Christian Heimes2202f872008-02-06 14:31:34 +0000357 def test_14_onliner_if(self):
358 def onliners():
Victor Stinner51d8c522016-02-08 17:57:02 +0100359 if True: x=False
360 else: x=True
Christian Heimes2202f872008-02-06 14:31:34 +0000361 return 0
362 self.run_and_compare(
363 onliners,
364 [(0, 'call'),
365 (1, 'line'),
366 (3, 'line'),
367 (3, 'return')])
368
369 def test_15_loops(self):
370 # issue1750076: "while" expression is skipped by debugger
371 def for_example():
372 for x in range(2):
373 pass
374 self.run_and_compare(
375 for_example,
376 [(0, 'call'),
377 (1, 'line'),
378 (2, 'line'),
379 (1, 'line'),
380 (2, 'line'),
381 (1, 'line'),
382 (1, 'return')])
383
384 def while_example():
385 # While expression should be traced on every loop
386 x = 2
387 while x > 0:
388 x -= 1
389 self.run_and_compare(
390 while_example,
391 [(0, 'call'),
392 (2, 'line'),
393 (3, 'line'),
394 (4, 'line'),
395 (3, 'line'),
396 (4, 'line'),
397 (3, 'line'),
398 (3, 'return')])
399
400 def test_16_blank_lines(self):
401 namespace = {}
402 exec("def f():\n" + "\n" * 256 + " pass", namespace)
403 self.run_and_compare(
404 namespace["f"],
405 [(0, 'call'),
406 (257, 'line'),
407 (257, 'return')])
408
Serhiy Storchaka64a263a2016-06-04 20:32:36 +0300409 def test_17_none_f_trace(self):
410 # Issue 20041: fix TypeError when f_trace is set to None.
411 def func():
412 sys._getframe().f_trace = None
413 lineno = 2
414 self.run_and_compare(func,
415 [(0, 'call'),
416 (1, 'line')])
417
Christian Heimes2202f872008-02-06 14:31:34 +0000418
Nick Coghlan5a851672017-09-08 10:14:16 +1000419class SkipLineEventsTraceTestCase(TraceTestCase):
420 """Repeat the trace tests, but with per-line events skipped"""
421
422 def compare_events(self, line_offset, events, expected_events):
423 skip_line_events = [e for e in expected_events if e[1] != 'line']
424 super().compare_events(line_offset, events, skip_line_events)
425
426 @staticmethod
427 def make_tracer():
428 return Tracer(trace_line_events=False)
429
430
431@support.cpython_only
432class TraceOpcodesTestCase(TraceTestCase):
433 """Repeat the trace tests, but with per-opcodes events enabled"""
434
435 def compare_events(self, line_offset, events, expected_events):
436 skip_opcode_events = [e for e in events if e[1] != 'opcode']
437 if len(events) > 1:
438 self.assertLess(len(skip_opcode_events), len(events),
439 msg="No 'opcode' events received by the tracer")
440 super().compare_events(line_offset, skip_opcode_events, expected_events)
441
442 @staticmethod
443 def make_tracer():
444 return Tracer(trace_opcode_events=True)
445
446
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000447class RaisingTraceFuncTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000448 def setUp(self):
449 self.addCleanup(sys.settrace, sys.gettrace())
450
Michael W. Hudson006c7522002-11-08 13:08:46 +0000451 def trace(self, frame, event, arg):
452 """A trace function that raises an exception in response to a
453 specific trace event."""
454 if event == self.raiseOnEvent:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000455 raise ValueError # just something that isn't RuntimeError
Michael W. Hudson006c7522002-11-08 13:08:46 +0000456 else:
457 return self.trace
Tim Peters3de75262002-11-09 05:26:15 +0000458
Michael W. Hudson006c7522002-11-08 13:08:46 +0000459 def f(self):
460 """The function to trace; raises an exception if that's the case
461 we're testing, so that the 'exception' trace event fires."""
462 if self.raiseOnEvent == 'exception':
463 x = 0
464 y = 1/x
465 else:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000466 return 1
Tim Peters3de75262002-11-09 05:26:15 +0000467
Michael W. Hudson006c7522002-11-08 13:08:46 +0000468 def run_test_for_event(self, event):
469 """Tests that an exception raised in response to the given event is
470 handled OK."""
471 self.raiseOnEvent = event
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000472 try:
Guido van Rossum805365e2007-05-07 22:24:25 +0000473 for i in range(sys.getrecursionlimit() + 1):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000474 sys.settrace(self.trace)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000475 try:
Michael W. Hudson006c7522002-11-08 13:08:46 +0000476 self.f()
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000477 except ValueError:
478 pass
479 else:
Andrew Svetlov737fb892012-12-18 21:14:22 +0200480 self.fail("exception not raised!")
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000481 except RuntimeError:
482 self.fail("recursion counter not reset")
Tim Peters3de75262002-11-09 05:26:15 +0000483
Michael W. Hudson006c7522002-11-08 13:08:46 +0000484 # Test the handling of exceptions raised by each kind of trace event.
485 def test_call(self):
486 self.run_test_for_event('call')
487 def test_line(self):
488 self.run_test_for_event('line')
489 def test_return(self):
490 self.run_test_for_event('return')
491 def test_exception(self):
492 self.run_test_for_event('exception')
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000493
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000494 def test_trash_stack(self):
495 def f():
496 for i in range(5):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000497 print(i) # line tracing will raise an exception at this line
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000498
499 def g(frame, why, extra):
500 if (why == 'line' and
Neal Norwitz221085d2007-02-25 20:55:47 +0000501 frame.f_lineno == f.__code__.co_firstlineno + 2):
Collin Winter3add4d72007-08-29 23:37:32 +0000502 raise RuntimeError("i am crashing")
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000503 return g
504
505 sys.settrace(g)
506 try:
507 f()
508 except RuntimeError:
509 # the test is really that this doesn't segfault:
510 import gc
511 gc.collect()
512 else:
513 self.fail("exception not propagated")
514
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000515
R David Murray35837612013-04-19 12:56:57 -0400516 def test_exception_arguments(self):
517 def f():
518 x = 0
519 # this should raise an error
520 x.no_such_attr
521 def g(frame, event, arg):
522 if (event == 'exception'):
523 type, exception, trace = arg
524 self.assertIsInstance(exception, Exception)
525 return g
526
527 existing = sys.gettrace()
528 try:
529 sys.settrace(g)
530 try:
531 f()
532 except AttributeError:
533 # this is expected
534 pass
535 finally:
536 sys.settrace(existing)
537
538
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000539# 'Jump' tests: assigning to frame.f_lineno within a trace function
540# moves the execution position - it's how debuggers implement a Jump
541# command (aka. "Set next statement").
542
543class JumpTracer:
544 """Defines a trace function that jumps from one place to another,
545 with the source and destination lines of the jump being defined by
546 the 'jump' property of the function under test."""
547
548 def __init__(self, function):
549 self.function = function
550 self.jumpFrom = function.jump[0]
551 self.jumpTo = function.jump[1]
552 self.done = False
553
554 def trace(self, frame, event, arg):
Neal Norwitz221085d2007-02-25 20:55:47 +0000555 if not self.done and frame.f_code == self.function.__code__:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000556 firstLine = frame.f_code.co_firstlineno
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000557 if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000558 # Cope with non-integer self.jumpTo (because of
559 # no_jump_to_non_integers below).
560 try:
561 frame.f_lineno = firstLine + self.jumpTo
562 except TypeError:
563 frame.f_lineno = self.jumpTo
564 self.done = True
565 return self.trace
566
567# The first set of 'jump' tests are for things that are allowed:
568
569def jump_simple_forwards(output):
570 output.append(1)
571 output.append(2)
572 output.append(3)
573
574jump_simple_forwards.jump = (1, 3)
575jump_simple_forwards.output = [3]
576
577def jump_simple_backwards(output):
578 output.append(1)
579 output.append(2)
580
581jump_simple_backwards.jump = (2, 1)
582jump_simple_backwards.output = [1, 1, 2]
583
584def jump_out_of_block_forwards(output):
585 for i in 1, 2:
586 output.append(2)
587 for j in [3]: # Also tests jumping over a block
588 output.append(4)
589 output.append(5)
590
591jump_out_of_block_forwards.jump = (3, 5)
592jump_out_of_block_forwards.output = [2, 5]
593
594def jump_out_of_block_backwards(output):
595 output.append(1)
596 for i in [1]:
597 output.append(3)
598 for j in [2]: # Also tests jumping over a block
599 output.append(5)
600 output.append(6)
601 output.append(7)
602
603jump_out_of_block_backwards.jump = (6, 1)
604jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
605
606def jump_to_codeless_line(output):
607 output.append(1)
608 # Jumping to this line should skip to the next one.
609 output.append(3)
610
611jump_to_codeless_line.jump = (1, 2)
612jump_to_codeless_line.output = [3]
613
614def jump_to_same_line(output):
615 output.append(1)
616 output.append(2)
617 output.append(3)
618
619jump_to_same_line.jump = (2, 2)
620jump_to_same_line.output = [1, 2, 3]
621
622# Tests jumping within a finally block, and over one.
623def jump_in_nested_finally(output):
624 try:
625 output.append(2)
626 finally:
627 output.append(4)
628 try:
629 output.append(6)
630 finally:
631 output.append(8)
632 output.append(9)
633
634jump_in_nested_finally.jump = (4, 9)
635jump_in_nested_finally.output = [2, 9]
636
Benjamin Peterson3cda0ed2014-12-13 16:06:19 -0500637def jump_infinite_while_loop(output):
638 output.append(1)
639 while 1:
640 output.append(2)
641 output.append(3)
642
643jump_infinite_while_loop.jump = (3, 4)
644jump_infinite_while_loop.output = [1, 3]
645
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000646# The second set of 'jump' tests are for things that are not allowed:
647
648def no_jump_too_far_forwards(output):
649 try:
650 output.append(2)
651 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000652 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000653 output.append('after' in str(e))
654
655no_jump_too_far_forwards.jump = (3, 6)
656no_jump_too_far_forwards.output = [2, True]
657
658def no_jump_too_far_backwards(output):
659 try:
660 output.append(2)
661 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000662 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000663 output.append('before' in str(e))
664
665no_jump_too_far_backwards.jump = (3, -1)
666no_jump_too_far_backwards.output = [2, True]
667
668# Test each kind of 'except' line.
669def no_jump_to_except_1(output):
670 try:
671 output.append(2)
672 except:
673 e = sys.exc_info()[1]
674 output.append('except' in str(e))
675
676no_jump_to_except_1.jump = (2, 3)
677no_jump_to_except_1.output = [True]
678
679def no_jump_to_except_2(output):
680 try:
681 output.append(2)
682 except ValueError:
683 e = sys.exc_info()[1]
684 output.append('except' in str(e))
685
686no_jump_to_except_2.jump = (2, 3)
687no_jump_to_except_2.output = [True]
688
689def no_jump_to_except_3(output):
690 try:
691 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000692 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000693 output.append('except' in str(e))
694
695no_jump_to_except_3.jump = (2, 3)
696no_jump_to_except_3.output = [True]
697
698def no_jump_to_except_4(output):
699 try:
700 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000701 except (ValueError, RuntimeError) as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000702 output.append('except' in str(e))
703
704no_jump_to_except_4.jump = (2, 3)
705no_jump_to_except_4.output = [True]
706
707def no_jump_forwards_into_block(output):
708 try:
709 output.append(2)
710 for i in 1, 2:
711 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000712 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000713 output.append('into' in str(e))
714
715no_jump_forwards_into_block.jump = (2, 4)
716no_jump_forwards_into_block.output = [True]
717
718def no_jump_backwards_into_block(output):
719 try:
720 for i in 1, 2:
721 output.append(3)
722 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000723 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000724 output.append('into' in str(e))
725
726no_jump_backwards_into_block.jump = (4, 3)
727no_jump_backwards_into_block.output = [3, 3, True]
728
729def no_jump_into_finally_block(output):
730 try:
731 try:
732 output.append(3)
733 x = 1
734 finally:
735 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000736 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000737 output.append('finally' in str(e))
738
739no_jump_into_finally_block.jump = (4, 6)
740no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
741
742def no_jump_out_of_finally_block(output):
743 try:
744 try:
745 output.append(3)
746 finally:
747 output.append(5)
748 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000749 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000750 output.append('finally' in str(e))
751
752no_jump_out_of_finally_block.jump = (5, 1)
753no_jump_out_of_finally_block.output = [3, True]
754
755# This verifies the line-numbers-must-be-integers rule.
756def no_jump_to_non_integers(output):
757 try:
758 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000759 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000760 output.append('integer' in str(e))
761
762no_jump_to_non_integers.jump = (2, "Spam")
763no_jump_to_non_integers.output = [True]
764
Benjamin Petersone42fb302012-04-18 11:14:31 -0400765def jump_across_with(output):
766 with open(support.TESTFN, "wb") as fp:
767 pass
768 with open(support.TESTFN, "wb") as fp:
769 pass
770jump_across_with.jump = (1, 3)
771jump_across_with.output = []
772
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000773# This verifies that you can't set f_lineno via _getframe or similar
774# trickery.
775def no_jump_without_trace_function():
776 try:
777 previous_frame = sys._getframe().f_back
778 previous_frame.f_lineno = previous_frame.f_lineno
Guido van Rossumb940e112007-01-10 16:19:56 +0000779 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000780 # This is the exception we wanted; make sure the error message
781 # talks about trace functions.
782 if 'trace' not in str(e):
783 raise
784 else:
785 # Something's wrong - the expected exception wasn't raised.
Collin Winter3add4d72007-08-29 23:37:32 +0000786 raise RuntimeError("Trace-function-less jump failed to fail")
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000787
788
789class JumpTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000790 def setUp(self):
791 self.addCleanup(sys.settrace, sys.gettrace())
792 sys.settrace(None)
793
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000794 def compare_jump_output(self, expected, received):
795 if received != expected:
796 self.fail( "Outputs don't match:\n" +
797 "Expected: " + repr(expected) + "\n" +
798 "Received: " + repr(received))
799
800 def run_test(self, func):
801 tracer = JumpTracer(func)
802 sys.settrace(tracer.trace)
803 output = []
804 func(output)
805 sys.settrace(None)
806 self.compare_jump_output(func.output, output)
807
808 def test_01_jump_simple_forwards(self):
809 self.run_test(jump_simple_forwards)
810 def test_02_jump_simple_backwards(self):
811 self.run_test(jump_simple_backwards)
812 def test_03_jump_out_of_block_forwards(self):
813 self.run_test(jump_out_of_block_forwards)
814 def test_04_jump_out_of_block_backwards(self):
815 self.run_test(jump_out_of_block_backwards)
816 def test_05_jump_to_codeless_line(self):
817 self.run_test(jump_to_codeless_line)
818 def test_06_jump_to_same_line(self):
819 self.run_test(jump_to_same_line)
820 def test_07_jump_in_nested_finally(self):
821 self.run_test(jump_in_nested_finally)
Benjamin Peterson3cda0ed2014-12-13 16:06:19 -0500822 def test_jump_infinite_while_loop(self):
823 self.run_test(jump_infinite_while_loop)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000824 def test_08_no_jump_too_far_forwards(self):
825 self.run_test(no_jump_too_far_forwards)
826 def test_09_no_jump_too_far_backwards(self):
827 self.run_test(no_jump_too_far_backwards)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000828 def test_10_no_jump_to_except_1(self):
829 self.run_test(no_jump_to_except_1)
830 def test_11_no_jump_to_except_2(self):
831 self.run_test(no_jump_to_except_2)
832 def test_12_no_jump_to_except_3(self):
833 self.run_test(no_jump_to_except_3)
834 def test_13_no_jump_to_except_4(self):
835 self.run_test(no_jump_to_except_4)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000836 def test_14_no_jump_forwards_into_block(self):
837 self.run_test(no_jump_forwards_into_block)
838 def test_15_no_jump_backwards_into_block(self):
839 self.run_test(no_jump_backwards_into_block)
840 def test_16_no_jump_into_finally_block(self):
841 self.run_test(no_jump_into_finally_block)
842 def test_17_no_jump_out_of_finally_block(self):
843 self.run_test(no_jump_out_of_finally_block)
844 def test_18_no_jump_to_non_integers(self):
845 self.run_test(no_jump_to_non_integers)
846 def test_19_no_jump_without_trace_function(self):
Brett Cannon31f59292011-02-21 19:29:56 +0000847 # Must set sys.settrace(None) in setUp(), else condition is not
848 # triggered.
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000849 no_jump_without_trace_function()
Benjamin Petersone42fb302012-04-18 11:14:31 -0400850 def test_jump_across_with(self):
851 self.addCleanup(support.unlink, support.TESTFN)
852 self.run_test(jump_across_with)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000853
Amaury Forgeot d'Arc24e581f2009-06-01 21:28:37 +0000854 def test_20_large_function(self):
855 d = {}
856 exec("""def f(output): # line 0
857 x = 0 # line 1
858 y = 1 # line 2
859 ''' # line 3
860 %s # lines 4-1004
861 ''' # line 1005
862 x += 1 # line 1006
863 output.append(x) # line 1007
864 return""" % ('\n' * 1000,), d)
865 f = d['f']
866
867 f.jump = (2, 1007)
868 f.output = [0]
869 self.run_test(f)
870
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000871 def test_jump_to_firstlineno(self):
872 # This tests that PDB can jump back to the first line in a
873 # file. See issue #1689458. It can only be triggered in a
874 # function call if the function is defined on a single line.
875 code = compile("""
876# Comments don't count.
877output.append(2) # firstlineno is here.
878output.append(3)
879output.append(4)
880""", "<fake module>", "exec")
881 class fake_function:
882 __code__ = code
883 jump = (2, 0)
884 tracer = JumpTracer(fake_function)
885 sys.settrace(tracer.trace)
886 namespace = {"output": []}
887 exec(code, namespace)
888 sys.settrace(None)
889 self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
890
891
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000892def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000893 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000894 TraceTestCase,
Nick Coghlan5a851672017-09-08 10:14:16 +1000895 SkipLineEventsTraceTestCase,
896 TraceOpcodesTestCase,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000897 RaisingTraceFuncTestCase,
898 JumpTestCase
899 )
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000900
901if __name__ == "__main__":
902 test_main()