blob: acb8e29f196f5fafffe7e752f340613c30f015f3 [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:
237 def __init__(self):
238 self.events = []
239 def trace(self, frame, event, arg):
240 self.events.append((frame.f_lineno, event))
241 return self.trace
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000242 def traceWithGenexp(self, frame, event, arg):
243 (o for o in [1])
244 self.events.append((frame.f_lineno, event))
245 return self.trace
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000246
247class TraceTestCase(unittest.TestCase):
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000248
249 # Disable gc collection when tracing, otherwise the
250 # deallocators may be traced as well.
251 def setUp(self):
252 self.using_gc = gc.isenabled()
253 gc.disable()
Brett Cannon31f59292011-02-21 19:29:56 +0000254 self.addCleanup(sys.settrace, sys.gettrace())
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000255
256 def tearDown(self):
257 if self.using_gc:
258 gc.enable()
259
Michael W. Hudson519a3422002-09-11 14:47:51 +0000260 def compare_events(self, line_offset, events, expected_events):
Tim Peters3de75262002-11-09 05:26:15 +0000261 events = [(l - line_offset, e) for (l, e) in events]
Michael W. Hudson519a3422002-09-11 14:47:51 +0000262 if events != expected_events:
263 self.fail(
264 "events did not match expectation:\n" +
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000265 "\n".join(difflib.ndiff([str(x) for x in expected_events],
266 [str(x) for x in events])))
Tim Peters3de75262002-11-09 05:26:15 +0000267
Christian Heimes2202f872008-02-06 14:31:34 +0000268 def run_and_compare(self, func, events):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000269 tracer = Tracer()
270 sys.settrace(tracer.trace)
271 func()
272 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000273 self.compare_events(func.__code__.co_firstlineno,
Christian Heimes2202f872008-02-06 14:31:34 +0000274 tracer.events, events)
275
276 def run_test(self, func):
277 self.run_and_compare(func, func.events)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000278
279 def run_test2(self, func):
280 tracer = Tracer()
281 func(tracer.trace)
282 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000283 self.compare_events(func.__code__.co_firstlineno,
Michael W. Hudson519a3422002-09-11 14:47:51 +0000284 tracer.events, func.events)
Tim Peters3de75262002-11-09 05:26:15 +0000285
Christian Heimes9bd667a2008-01-20 15:14:11 +0000286 def set_and_retrieve_none(self):
287 sys.settrace(None)
288 assert sys.gettrace() is None
289
290 def set_and_retrieve_func(self):
291 def fn(*args):
292 pass
293
294 sys.settrace(fn)
295 try:
296 assert sys.gettrace() is fn
297 finally:
298 sys.settrace(None)
299
Nicholas Bastinaea94592004-03-22 18:30:42 +0000300 def test_01_basic(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000301 self.run_test(basic)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000302 def test_02_arigo(self):
303 self.run_test(arigo_example)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000304 def test_03_one_instr(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000305 self.run_test(one_instr_line)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000306 def test_04_no_pop_blocks(self):
307 self.run_test(no_pop_blocks)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000308 def test_05_no_pop_tops(self):
309 self.run_test(no_pop_tops)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000310 def test_06_call(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000311 self.run_test(call)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000312 def test_07_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000313 self.run_test(test_raise)
314
Nicholas Bastinaea94592004-03-22 18:30:42 +0000315 def test_08_settrace_and_return(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000316 self.run_test2(settrace_and_return)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000317 def test_09_settrace_and_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000318 self.run_test2(settrace_and_raise)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000319 def test_10_ireturn(self):
320 self.run_test(ireturn_example)
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000321 def test_11_tightloop(self):
322 self.run_test(tightloop_example)
Armin Rigo70693382004-03-22 19:30:39 +0000323 def test_12_tighterloop(self):
324 self.run_test(tighterloop_example)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000325
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000326 def test_13_genexp(self):
327 self.run_test(generator_example)
328 # issue1265: if the trace function contains a generator,
329 # and if the traced function contains another generator
330 # that is not completely exhausted, the trace stopped.
331 # Worse: the 'finally' clause was not invoked.
332 tracer = Tracer()
333 sys.settrace(tracer.traceWithGenexp)
334 generator_example()
335 sys.settrace(None)
336 self.compare_events(generator_example.__code__.co_firstlineno,
337 tracer.events, generator_example.events)
338
Christian Heimes2202f872008-02-06 14:31:34 +0000339 def test_14_onliner_if(self):
340 def onliners():
341 if True: False
342 else: True
343 return 0
344 self.run_and_compare(
345 onliners,
346 [(0, 'call'),
347 (1, 'line'),
348 (3, 'line'),
349 (3, 'return')])
350
351 def test_15_loops(self):
352 # issue1750076: "while" expression is skipped by debugger
353 def for_example():
354 for x in range(2):
355 pass
356 self.run_and_compare(
357 for_example,
358 [(0, 'call'),
359 (1, 'line'),
360 (2, 'line'),
361 (1, 'line'),
362 (2, 'line'),
363 (1, 'line'),
364 (1, 'return')])
365
366 def while_example():
367 # While expression should be traced on every loop
368 x = 2
369 while x > 0:
370 x -= 1
371 self.run_and_compare(
372 while_example,
373 [(0, 'call'),
374 (2, 'line'),
375 (3, 'line'),
376 (4, 'line'),
377 (3, 'line'),
378 (4, 'line'),
379 (3, 'line'),
380 (3, 'return')])
381
382 def test_16_blank_lines(self):
383 namespace = {}
384 exec("def f():\n" + "\n" * 256 + " pass", namespace)
385 self.run_and_compare(
386 namespace["f"],
387 [(0, 'call'),
388 (257, 'line'),
389 (257, 'return')])
390
391
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000392class RaisingTraceFuncTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000393 def setUp(self):
394 self.addCleanup(sys.settrace, sys.gettrace())
395
Michael W. Hudson006c7522002-11-08 13:08:46 +0000396 def trace(self, frame, event, arg):
397 """A trace function that raises an exception in response to a
398 specific trace event."""
399 if event == self.raiseOnEvent:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000400 raise ValueError # just something that isn't RuntimeError
Michael W. Hudson006c7522002-11-08 13:08:46 +0000401 else:
402 return self.trace
Tim Peters3de75262002-11-09 05:26:15 +0000403
Michael W. Hudson006c7522002-11-08 13:08:46 +0000404 def f(self):
405 """The function to trace; raises an exception if that's the case
406 we're testing, so that the 'exception' trace event fires."""
407 if self.raiseOnEvent == 'exception':
408 x = 0
409 y = 1/x
410 else:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000411 return 1
Tim Peters3de75262002-11-09 05:26:15 +0000412
Michael W. Hudson006c7522002-11-08 13:08:46 +0000413 def run_test_for_event(self, event):
414 """Tests that an exception raised in response to the given event is
415 handled OK."""
416 self.raiseOnEvent = event
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000417 try:
Guido van Rossum805365e2007-05-07 22:24:25 +0000418 for i in range(sys.getrecursionlimit() + 1):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000419 sys.settrace(self.trace)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000420 try:
Michael W. Hudson006c7522002-11-08 13:08:46 +0000421 self.f()
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000422 except ValueError:
423 pass
424 else:
425 self.fail("exception not thrown!")
426 except RuntimeError:
427 self.fail("recursion counter not reset")
Tim Peters3de75262002-11-09 05:26:15 +0000428
Michael W. Hudson006c7522002-11-08 13:08:46 +0000429 # Test the handling of exceptions raised by each kind of trace event.
430 def test_call(self):
431 self.run_test_for_event('call')
432 def test_line(self):
433 self.run_test_for_event('line')
434 def test_return(self):
435 self.run_test_for_event('return')
436 def test_exception(self):
437 self.run_test_for_event('exception')
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000438
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000439 def test_trash_stack(self):
440 def f():
441 for i in range(5):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000442 print(i) # line tracing will raise an exception at this line
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000443
444 def g(frame, why, extra):
445 if (why == 'line' and
Neal Norwitz221085d2007-02-25 20:55:47 +0000446 frame.f_lineno == f.__code__.co_firstlineno + 2):
Collin Winter3add4d72007-08-29 23:37:32 +0000447 raise RuntimeError("i am crashing")
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000448 return g
449
450 sys.settrace(g)
451 try:
452 f()
453 except RuntimeError:
454 # the test is really that this doesn't segfault:
455 import gc
456 gc.collect()
457 else:
458 self.fail("exception not propagated")
459
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000460
461# 'Jump' tests: assigning to frame.f_lineno within a trace function
462# moves the execution position - it's how debuggers implement a Jump
463# command (aka. "Set next statement").
464
465class JumpTracer:
466 """Defines a trace function that jumps from one place to another,
467 with the source and destination lines of the jump being defined by
468 the 'jump' property of the function under test."""
469
470 def __init__(self, function):
471 self.function = function
472 self.jumpFrom = function.jump[0]
473 self.jumpTo = function.jump[1]
474 self.done = False
475
476 def trace(self, frame, event, arg):
Neal Norwitz221085d2007-02-25 20:55:47 +0000477 if not self.done and frame.f_code == self.function.__code__:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000478 firstLine = frame.f_code.co_firstlineno
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000479 if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000480 # Cope with non-integer self.jumpTo (because of
481 # no_jump_to_non_integers below).
482 try:
483 frame.f_lineno = firstLine + self.jumpTo
484 except TypeError:
485 frame.f_lineno = self.jumpTo
486 self.done = True
487 return self.trace
488
489# The first set of 'jump' tests are for things that are allowed:
490
491def jump_simple_forwards(output):
492 output.append(1)
493 output.append(2)
494 output.append(3)
495
496jump_simple_forwards.jump = (1, 3)
497jump_simple_forwards.output = [3]
498
499def jump_simple_backwards(output):
500 output.append(1)
501 output.append(2)
502
503jump_simple_backwards.jump = (2, 1)
504jump_simple_backwards.output = [1, 1, 2]
505
506def jump_out_of_block_forwards(output):
507 for i in 1, 2:
508 output.append(2)
509 for j in [3]: # Also tests jumping over a block
510 output.append(4)
511 output.append(5)
512
513jump_out_of_block_forwards.jump = (3, 5)
514jump_out_of_block_forwards.output = [2, 5]
515
516def jump_out_of_block_backwards(output):
517 output.append(1)
518 for i in [1]:
519 output.append(3)
520 for j in [2]: # Also tests jumping over a block
521 output.append(5)
522 output.append(6)
523 output.append(7)
524
525jump_out_of_block_backwards.jump = (6, 1)
526jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
527
528def jump_to_codeless_line(output):
529 output.append(1)
530 # Jumping to this line should skip to the next one.
531 output.append(3)
532
533jump_to_codeless_line.jump = (1, 2)
534jump_to_codeless_line.output = [3]
535
536def jump_to_same_line(output):
537 output.append(1)
538 output.append(2)
539 output.append(3)
540
541jump_to_same_line.jump = (2, 2)
542jump_to_same_line.output = [1, 2, 3]
543
544# Tests jumping within a finally block, and over one.
545def jump_in_nested_finally(output):
546 try:
547 output.append(2)
548 finally:
549 output.append(4)
550 try:
551 output.append(6)
552 finally:
553 output.append(8)
554 output.append(9)
555
556jump_in_nested_finally.jump = (4, 9)
557jump_in_nested_finally.output = [2, 9]
558
559# The second set of 'jump' tests are for things that are not allowed:
560
561def no_jump_too_far_forwards(output):
562 try:
563 output.append(2)
564 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000565 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000566 output.append('after' in str(e))
567
568no_jump_too_far_forwards.jump = (3, 6)
569no_jump_too_far_forwards.output = [2, True]
570
571def no_jump_too_far_backwards(output):
572 try:
573 output.append(2)
574 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000575 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000576 output.append('before' in str(e))
577
578no_jump_too_far_backwards.jump = (3, -1)
579no_jump_too_far_backwards.output = [2, True]
580
581# Test each kind of 'except' line.
582def no_jump_to_except_1(output):
583 try:
584 output.append(2)
585 except:
586 e = sys.exc_info()[1]
587 output.append('except' in str(e))
588
589no_jump_to_except_1.jump = (2, 3)
590no_jump_to_except_1.output = [True]
591
592def no_jump_to_except_2(output):
593 try:
594 output.append(2)
595 except ValueError:
596 e = sys.exc_info()[1]
597 output.append('except' in str(e))
598
599no_jump_to_except_2.jump = (2, 3)
600no_jump_to_except_2.output = [True]
601
602def no_jump_to_except_3(output):
603 try:
604 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000605 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000606 output.append('except' in str(e))
607
608no_jump_to_except_3.jump = (2, 3)
609no_jump_to_except_3.output = [True]
610
611def no_jump_to_except_4(output):
612 try:
613 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000614 except (ValueError, RuntimeError) as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000615 output.append('except' in str(e))
616
617no_jump_to_except_4.jump = (2, 3)
618no_jump_to_except_4.output = [True]
619
620def no_jump_forwards_into_block(output):
621 try:
622 output.append(2)
623 for i in 1, 2:
624 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000625 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000626 output.append('into' in str(e))
627
628no_jump_forwards_into_block.jump = (2, 4)
629no_jump_forwards_into_block.output = [True]
630
631def no_jump_backwards_into_block(output):
632 try:
633 for i in 1, 2:
634 output.append(3)
635 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000636 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000637 output.append('into' in str(e))
638
639no_jump_backwards_into_block.jump = (4, 3)
640no_jump_backwards_into_block.output = [3, 3, True]
641
642def no_jump_into_finally_block(output):
643 try:
644 try:
645 output.append(3)
646 x = 1
647 finally:
648 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000649 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000650 output.append('finally' in str(e))
651
652no_jump_into_finally_block.jump = (4, 6)
653no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
654
655def no_jump_out_of_finally_block(output):
656 try:
657 try:
658 output.append(3)
659 finally:
660 output.append(5)
661 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000662 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000663 output.append('finally' in str(e))
664
665no_jump_out_of_finally_block.jump = (5, 1)
666no_jump_out_of_finally_block.output = [3, True]
667
668# This verifies the line-numbers-must-be-integers rule.
669def no_jump_to_non_integers(output):
670 try:
671 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000672 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000673 output.append('integer' in str(e))
674
675no_jump_to_non_integers.jump = (2, "Spam")
676no_jump_to_non_integers.output = [True]
677
678# This verifies that you can't set f_lineno via _getframe or similar
679# trickery.
680def no_jump_without_trace_function():
681 try:
682 previous_frame = sys._getframe().f_back
683 previous_frame.f_lineno = previous_frame.f_lineno
Guido van Rossumb940e112007-01-10 16:19:56 +0000684 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000685 # This is the exception we wanted; make sure the error message
686 # talks about trace functions.
687 if 'trace' not in str(e):
688 raise
689 else:
690 # Something's wrong - the expected exception wasn't raised.
Collin Winter3add4d72007-08-29 23:37:32 +0000691 raise RuntimeError("Trace-function-less jump failed to fail")
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000692
693
694class JumpTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000695 def setUp(self):
696 self.addCleanup(sys.settrace, sys.gettrace())
697 sys.settrace(None)
698
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000699 def compare_jump_output(self, expected, received):
700 if received != expected:
701 self.fail( "Outputs don't match:\n" +
702 "Expected: " + repr(expected) + "\n" +
703 "Received: " + repr(received))
704
705 def run_test(self, func):
706 tracer = JumpTracer(func)
707 sys.settrace(tracer.trace)
708 output = []
709 func(output)
710 sys.settrace(None)
711 self.compare_jump_output(func.output, output)
712
713 def test_01_jump_simple_forwards(self):
714 self.run_test(jump_simple_forwards)
715 def test_02_jump_simple_backwards(self):
716 self.run_test(jump_simple_backwards)
717 def test_03_jump_out_of_block_forwards(self):
718 self.run_test(jump_out_of_block_forwards)
719 def test_04_jump_out_of_block_backwards(self):
720 self.run_test(jump_out_of_block_backwards)
721 def test_05_jump_to_codeless_line(self):
722 self.run_test(jump_to_codeless_line)
723 def test_06_jump_to_same_line(self):
724 self.run_test(jump_to_same_line)
725 def test_07_jump_in_nested_finally(self):
726 self.run_test(jump_in_nested_finally)
727 def test_08_no_jump_too_far_forwards(self):
728 self.run_test(no_jump_too_far_forwards)
729 def test_09_no_jump_too_far_backwards(self):
730 self.run_test(no_jump_too_far_backwards)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000731 def test_10_no_jump_to_except_1(self):
732 self.run_test(no_jump_to_except_1)
733 def test_11_no_jump_to_except_2(self):
734 self.run_test(no_jump_to_except_2)
735 def test_12_no_jump_to_except_3(self):
736 self.run_test(no_jump_to_except_3)
737 def test_13_no_jump_to_except_4(self):
738 self.run_test(no_jump_to_except_4)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000739 def test_14_no_jump_forwards_into_block(self):
740 self.run_test(no_jump_forwards_into_block)
741 def test_15_no_jump_backwards_into_block(self):
742 self.run_test(no_jump_backwards_into_block)
743 def test_16_no_jump_into_finally_block(self):
744 self.run_test(no_jump_into_finally_block)
745 def test_17_no_jump_out_of_finally_block(self):
746 self.run_test(no_jump_out_of_finally_block)
747 def test_18_no_jump_to_non_integers(self):
748 self.run_test(no_jump_to_non_integers)
749 def test_19_no_jump_without_trace_function(self):
Brett Cannon31f59292011-02-21 19:29:56 +0000750 # Must set sys.settrace(None) in setUp(), else condition is not
751 # triggered.
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000752 no_jump_without_trace_function()
753
Amaury Forgeot d'Arc24e581f2009-06-01 21:28:37 +0000754 def test_20_large_function(self):
755 d = {}
756 exec("""def f(output): # line 0
757 x = 0 # line 1
758 y = 1 # line 2
759 ''' # line 3
760 %s # lines 4-1004
761 ''' # line 1005
762 x += 1 # line 1006
763 output.append(x) # line 1007
764 return""" % ('\n' * 1000,), d)
765 f = d['f']
766
767 f.jump = (2, 1007)
768 f.output = [0]
769 self.run_test(f)
770
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000771 def test_jump_to_firstlineno(self):
772 # This tests that PDB can jump back to the first line in a
773 # file. See issue #1689458. It can only be triggered in a
774 # function call if the function is defined on a single line.
775 code = compile("""
776# Comments don't count.
777output.append(2) # firstlineno is here.
778output.append(3)
779output.append(4)
780""", "<fake module>", "exec")
781 class fake_function:
782 __code__ = code
783 jump = (2, 0)
784 tracer = JumpTracer(fake_function)
785 sys.settrace(tracer.trace)
786 namespace = {"output": []}
787 exec(code, namespace)
788 sys.settrace(None)
789 self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
790
791
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000792def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000793 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000794 TraceTestCase,
795 RaisingTraceFuncTestCase,
796 JumpTestCase
797 )
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000798
799if __name__ == "__main__":
800 test_main()