blob: ae8f845ee1bdab1dbc29370636e3c6186163a995 [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
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200286 def test_set_and_retrieve_none(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000287 sys.settrace(None)
288 assert sys.gettrace() is None
289
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200290 def test_set_and_retrieve_func(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000291 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:
Andrew Svetlov737fb892012-12-18 21:14:22 +0200425 self.fail("exception not raised!")
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000426 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
R David Murray35837612013-04-19 12:56:57 -0400461 def test_exception_arguments(self):
462 def f():
463 x = 0
464 # this should raise an error
465 x.no_such_attr
466 def g(frame, event, arg):
467 if (event == 'exception'):
468 type, exception, trace = arg
469 self.assertIsInstance(exception, Exception)
470 return g
471
472 existing = sys.gettrace()
473 try:
474 sys.settrace(g)
475 try:
476 f()
477 except AttributeError:
478 # this is expected
479 pass
480 finally:
481 sys.settrace(existing)
482
483
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000484# 'Jump' tests: assigning to frame.f_lineno within a trace function
485# moves the execution position - it's how debuggers implement a Jump
486# command (aka. "Set next statement").
487
488class JumpTracer:
489 """Defines a trace function that jumps from one place to another,
490 with the source and destination lines of the jump being defined by
491 the 'jump' property of the function under test."""
492
493 def __init__(self, function):
494 self.function = function
495 self.jumpFrom = function.jump[0]
496 self.jumpTo = function.jump[1]
497 self.done = False
498
499 def trace(self, frame, event, arg):
Neal Norwitz221085d2007-02-25 20:55:47 +0000500 if not self.done and frame.f_code == self.function.__code__:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000501 firstLine = frame.f_code.co_firstlineno
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000502 if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000503 # Cope with non-integer self.jumpTo (because of
504 # no_jump_to_non_integers below).
505 try:
506 frame.f_lineno = firstLine + self.jumpTo
507 except TypeError:
508 frame.f_lineno = self.jumpTo
509 self.done = True
510 return self.trace
511
512# The first set of 'jump' tests are for things that are allowed:
513
514def jump_simple_forwards(output):
515 output.append(1)
516 output.append(2)
517 output.append(3)
518
519jump_simple_forwards.jump = (1, 3)
520jump_simple_forwards.output = [3]
521
522def jump_simple_backwards(output):
523 output.append(1)
524 output.append(2)
525
526jump_simple_backwards.jump = (2, 1)
527jump_simple_backwards.output = [1, 1, 2]
528
529def jump_out_of_block_forwards(output):
530 for i in 1, 2:
531 output.append(2)
532 for j in [3]: # Also tests jumping over a block
533 output.append(4)
534 output.append(5)
535
536jump_out_of_block_forwards.jump = (3, 5)
537jump_out_of_block_forwards.output = [2, 5]
538
539def jump_out_of_block_backwards(output):
540 output.append(1)
541 for i in [1]:
542 output.append(3)
543 for j in [2]: # Also tests jumping over a block
544 output.append(5)
545 output.append(6)
546 output.append(7)
547
548jump_out_of_block_backwards.jump = (6, 1)
549jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
550
551def jump_to_codeless_line(output):
552 output.append(1)
553 # Jumping to this line should skip to the next one.
554 output.append(3)
555
556jump_to_codeless_line.jump = (1, 2)
557jump_to_codeless_line.output = [3]
558
559def jump_to_same_line(output):
560 output.append(1)
561 output.append(2)
562 output.append(3)
563
564jump_to_same_line.jump = (2, 2)
565jump_to_same_line.output = [1, 2, 3]
566
567# Tests jumping within a finally block, and over one.
568def jump_in_nested_finally(output):
569 try:
570 output.append(2)
571 finally:
572 output.append(4)
573 try:
574 output.append(6)
575 finally:
576 output.append(8)
577 output.append(9)
578
579jump_in_nested_finally.jump = (4, 9)
580jump_in_nested_finally.output = [2, 9]
581
Benjamin Peterson3cda0ed2014-12-13 16:06:19 -0500582def jump_infinite_while_loop(output):
583 output.append(1)
584 while 1:
585 output.append(2)
586 output.append(3)
587
588jump_infinite_while_loop.jump = (3, 4)
589jump_infinite_while_loop.output = [1, 3]
590
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000591# The second set of 'jump' tests are for things that are not allowed:
592
593def no_jump_too_far_forwards(output):
594 try:
595 output.append(2)
596 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000597 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000598 output.append('after' in str(e))
599
600no_jump_too_far_forwards.jump = (3, 6)
601no_jump_too_far_forwards.output = [2, True]
602
603def no_jump_too_far_backwards(output):
604 try:
605 output.append(2)
606 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000607 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000608 output.append('before' in str(e))
609
610no_jump_too_far_backwards.jump = (3, -1)
611no_jump_too_far_backwards.output = [2, True]
612
613# Test each kind of 'except' line.
614def no_jump_to_except_1(output):
615 try:
616 output.append(2)
617 except:
618 e = sys.exc_info()[1]
619 output.append('except' in str(e))
620
621no_jump_to_except_1.jump = (2, 3)
622no_jump_to_except_1.output = [True]
623
624def no_jump_to_except_2(output):
625 try:
626 output.append(2)
627 except ValueError:
628 e = sys.exc_info()[1]
629 output.append('except' in str(e))
630
631no_jump_to_except_2.jump = (2, 3)
632no_jump_to_except_2.output = [True]
633
634def no_jump_to_except_3(output):
635 try:
636 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000637 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000638 output.append('except' in str(e))
639
640no_jump_to_except_3.jump = (2, 3)
641no_jump_to_except_3.output = [True]
642
643def no_jump_to_except_4(output):
644 try:
645 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000646 except (ValueError, RuntimeError) as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000647 output.append('except' in str(e))
648
649no_jump_to_except_4.jump = (2, 3)
650no_jump_to_except_4.output = [True]
651
652def no_jump_forwards_into_block(output):
653 try:
654 output.append(2)
655 for i in 1, 2:
656 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000657 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000658 output.append('into' in str(e))
659
660no_jump_forwards_into_block.jump = (2, 4)
661no_jump_forwards_into_block.output = [True]
662
663def no_jump_backwards_into_block(output):
664 try:
665 for i in 1, 2:
666 output.append(3)
667 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000668 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000669 output.append('into' in str(e))
670
671no_jump_backwards_into_block.jump = (4, 3)
672no_jump_backwards_into_block.output = [3, 3, True]
673
674def no_jump_into_finally_block(output):
675 try:
676 try:
677 output.append(3)
678 x = 1
679 finally:
680 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000681 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000682 output.append('finally' in str(e))
683
684no_jump_into_finally_block.jump = (4, 6)
685no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
686
687def no_jump_out_of_finally_block(output):
688 try:
689 try:
690 output.append(3)
691 finally:
692 output.append(5)
693 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000694 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000695 output.append('finally' in str(e))
696
697no_jump_out_of_finally_block.jump = (5, 1)
698no_jump_out_of_finally_block.output = [3, True]
699
700# This verifies the line-numbers-must-be-integers rule.
701def no_jump_to_non_integers(output):
702 try:
703 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000704 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000705 output.append('integer' in str(e))
706
707no_jump_to_non_integers.jump = (2, "Spam")
708no_jump_to_non_integers.output = [True]
709
Benjamin Petersone42fb302012-04-18 11:14:31 -0400710def jump_across_with(output):
711 with open(support.TESTFN, "wb") as fp:
712 pass
713 with open(support.TESTFN, "wb") as fp:
714 pass
715jump_across_with.jump = (1, 3)
716jump_across_with.output = []
717
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000718# This verifies that you can't set f_lineno via _getframe or similar
719# trickery.
720def no_jump_without_trace_function():
721 try:
722 previous_frame = sys._getframe().f_back
723 previous_frame.f_lineno = previous_frame.f_lineno
Guido van Rossumb940e112007-01-10 16:19:56 +0000724 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000725 # This is the exception we wanted; make sure the error message
726 # talks about trace functions.
727 if 'trace' not in str(e):
728 raise
729 else:
730 # Something's wrong - the expected exception wasn't raised.
Collin Winter3add4d72007-08-29 23:37:32 +0000731 raise RuntimeError("Trace-function-less jump failed to fail")
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000732
733
734class JumpTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000735 def setUp(self):
736 self.addCleanup(sys.settrace, sys.gettrace())
737 sys.settrace(None)
738
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000739 def compare_jump_output(self, expected, received):
740 if received != expected:
741 self.fail( "Outputs don't match:\n" +
742 "Expected: " + repr(expected) + "\n" +
743 "Received: " + repr(received))
744
745 def run_test(self, func):
746 tracer = JumpTracer(func)
747 sys.settrace(tracer.trace)
748 output = []
749 func(output)
750 sys.settrace(None)
751 self.compare_jump_output(func.output, output)
752
753 def test_01_jump_simple_forwards(self):
754 self.run_test(jump_simple_forwards)
755 def test_02_jump_simple_backwards(self):
756 self.run_test(jump_simple_backwards)
757 def test_03_jump_out_of_block_forwards(self):
758 self.run_test(jump_out_of_block_forwards)
759 def test_04_jump_out_of_block_backwards(self):
760 self.run_test(jump_out_of_block_backwards)
761 def test_05_jump_to_codeless_line(self):
762 self.run_test(jump_to_codeless_line)
763 def test_06_jump_to_same_line(self):
764 self.run_test(jump_to_same_line)
765 def test_07_jump_in_nested_finally(self):
766 self.run_test(jump_in_nested_finally)
Benjamin Peterson3cda0ed2014-12-13 16:06:19 -0500767 def test_jump_infinite_while_loop(self):
768 self.run_test(jump_infinite_while_loop)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000769 def test_08_no_jump_too_far_forwards(self):
770 self.run_test(no_jump_too_far_forwards)
771 def test_09_no_jump_too_far_backwards(self):
772 self.run_test(no_jump_too_far_backwards)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000773 def test_10_no_jump_to_except_1(self):
774 self.run_test(no_jump_to_except_1)
775 def test_11_no_jump_to_except_2(self):
776 self.run_test(no_jump_to_except_2)
777 def test_12_no_jump_to_except_3(self):
778 self.run_test(no_jump_to_except_3)
779 def test_13_no_jump_to_except_4(self):
780 self.run_test(no_jump_to_except_4)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000781 def test_14_no_jump_forwards_into_block(self):
782 self.run_test(no_jump_forwards_into_block)
783 def test_15_no_jump_backwards_into_block(self):
784 self.run_test(no_jump_backwards_into_block)
785 def test_16_no_jump_into_finally_block(self):
786 self.run_test(no_jump_into_finally_block)
787 def test_17_no_jump_out_of_finally_block(self):
788 self.run_test(no_jump_out_of_finally_block)
789 def test_18_no_jump_to_non_integers(self):
790 self.run_test(no_jump_to_non_integers)
791 def test_19_no_jump_without_trace_function(self):
Brett Cannon31f59292011-02-21 19:29:56 +0000792 # Must set sys.settrace(None) in setUp(), else condition is not
793 # triggered.
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000794 no_jump_without_trace_function()
Benjamin Petersone42fb302012-04-18 11:14:31 -0400795 def test_jump_across_with(self):
796 self.addCleanup(support.unlink, support.TESTFN)
797 self.run_test(jump_across_with)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000798
Amaury Forgeot d'Arc24e581f2009-06-01 21:28:37 +0000799 def test_20_large_function(self):
800 d = {}
801 exec("""def f(output): # line 0
802 x = 0 # line 1
803 y = 1 # line 2
804 ''' # line 3
805 %s # lines 4-1004
806 ''' # line 1005
807 x += 1 # line 1006
808 output.append(x) # line 1007
809 return""" % ('\n' * 1000,), d)
810 f = d['f']
811
812 f.jump = (2, 1007)
813 f.output = [0]
814 self.run_test(f)
815
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +0000816 def test_jump_to_firstlineno(self):
817 # This tests that PDB can jump back to the first line in a
818 # file. See issue #1689458. It can only be triggered in a
819 # function call if the function is defined on a single line.
820 code = compile("""
821# Comments don't count.
822output.append(2) # firstlineno is here.
823output.append(3)
824output.append(4)
825""", "<fake module>", "exec")
826 class fake_function:
827 __code__ = code
828 jump = (2, 0)
829 tracer = JumpTracer(fake_function)
830 sys.settrace(tracer.trace)
831 namespace = {"output": []}
832 exec(code, namespace)
833 sys.settrace(None)
834 self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
835
836
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000837def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000838 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000839 TraceTestCase,
840 RaisingTraceFuncTestCase,
841 JumpTestCase
842 )
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000843
844if __name__ == "__main__":
845 test_main()