blob: 635e1bccbeb8b3e4efb7e98c8774e20804ab1ae2 [file] [log] [blame]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00001# Testing the line trace facility.
2
3from test import test_support
4import unittest
5import sys
6import difflib
7
8# A very basic example. If this fails, we're in deep trouble.
9def basic():
10 return 1
11
12basic.events = [(0, 'call'),
13 (1, 'line'),
14 (1, 'return')]
15
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000016# Many of the tests below are tricky because they involve pass statements.
17# If there is implicit control flow around a pass statement (in an except
18# clause or else caluse) under what conditions do you set a line number
19# following that clause?
20
21
22# The entire "while 0:" statement is optimized away. No code
23# exists for it, so the line numbers skip directly from "del x"
24# to "x = 1".
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000025def arigo_example():
26 x = 1
27 del x
28 while 0:
29 pass
30 x = 1
31
32arigo_example.events = [(0, 'call'),
33 (1, 'line'),
34 (2, 'line'),
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000035 (5, 'line'),
36 (5, 'return')]
37
38# check that lines consisting of just one instruction get traced:
39def one_instr_line():
40 x = 1
41 del x
42 x = 1
43
44one_instr_line.events = [(0, 'call'),
45 (1, 'line'),
46 (2, 'line'),
47 (3, 'line'),
48 (3, 'return')]
49
50def no_pop_tops(): # 0
51 x = 1 # 1
52 for a in range(2): # 2
53 if a: # 3
54 x = 1 # 4
55 else: # 5
56 x = 1 # 6
57
58no_pop_tops.events = [(0, 'call'),
59 (1, 'line'),
60 (2, 'line'),
61 (3, 'line'),
62 (6, 'line'),
63 (2, 'line'),
64 (3, 'line'),
65 (4, 'line'),
66 (2, 'line'),
Michael W. Hudson02ff6a92002-09-11 15:36:32 +000067 (2, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000068
69def no_pop_blocks():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000070 y = 1
71 while not y:
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000072 bla
73 x = 1
74
75no_pop_blocks.events = [(0, 'call'),
76 (1, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000077 (2, 'line'),
78 (4, 'line'),
79 (4, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000080
Michael W. Hudson519a3422002-09-11 14:47:51 +000081def called(): # line -3
82 x = 1
83
84def call(): # line 0
85 called()
86
87call.events = [(0, 'call'),
88 (1, 'line'),
89 (-3, 'call'),
90 (-2, 'line'),
91 (-2, 'return'),
92 (1, 'return')]
93
94def raises():
95 raise Exception
96
97def test_raise():
98 try:
99 raises()
Guido van Rossumb940e112007-01-10 16:19:56 +0000100 except Exception as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000101 x = 1
102
103test_raise.events = [(0, 'call'),
104 (1, 'line'),
105 (2, 'line'),
106 (-3, 'call'),
107 (-2, 'line'),
108 (-2, 'exception'),
Barry Warsawe2eca0b2005-08-15 18:14:19 +0000109 (-2, 'return'),
Michael W. Hudson519a3422002-09-11 14:47:51 +0000110 (2, 'exception'),
111 (3, 'line'),
112 (4, 'line'),
113 (4, 'return')]
114
115def _settrace_and_return(tracefunc):
116 sys.settrace(tracefunc)
117 sys._getframe().f_back.f_trace = tracefunc
118def settrace_and_return(tracefunc):
119 _settrace_and_return(tracefunc)
Tim Peters3de75262002-11-09 05:26:15 +0000120
Michael W. Hudson519a3422002-09-11 14:47:51 +0000121settrace_and_return.events = [(1, 'return')]
122
123def _settrace_and_raise(tracefunc):
124 sys.settrace(tracefunc)
125 sys._getframe().f_back.f_trace = tracefunc
126 raise RuntimeError
127def settrace_and_raise(tracefunc):
128 try:
129 _settrace_and_raise(tracefunc)
Guido van Rossumb940e112007-01-10 16:19:56 +0000130 except RuntimeError as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000131 pass
Tim Peters3de75262002-11-09 05:26:15 +0000132
Michael W. Hudson519a3422002-09-11 14:47:51 +0000133settrace_and_raise.events = [(2, 'exception'),
134 (3, 'line'),
135 (4, 'line'),
136 (4, 'return')]
137
Nicholas Bastinaea94592004-03-22 18:30:42 +0000138# implicit return example
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139# This test is interesting because of the else: pass
140# part of the code. The code generate for the true
141# part of the if contains a jump past the else branch.
142# The compiler then generates an implicit "return None"
143# Internally, the compiler visits the pass statement
144# and stores its line number for use on the next instruction.
145# The next instruction is the implicit return None.
Nicholas Bastinaea94592004-03-22 18:30:42 +0000146def ireturn_example():
147 a = 5
148 b = 5
149 if a == b:
150 b = a+1
151 else:
152 pass
153
154ireturn_example.events = [(0, 'call'),
155 (1, 'line'),
156 (2, 'line'),
157 (3, 'line'),
158 (4, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000159 (6, 'line'),
160 (6, 'return')]
Nicholas Bastinaea94592004-03-22 18:30:42 +0000161
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000162# Tight loop with while(1) example (SF #765624)
163def tightloop_example():
164 items = range(0, 3)
165 try:
166 i = 0
167 while 1:
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000168 b = items[i]; i+=1
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000169 except IndexError:
170 pass
171
172tightloop_example.events = [(0, 'call'),
173 (1, 'line'),
174 (2, 'line'),
175 (3, 'line'),
176 (4, 'line'),
177 (5, 'line'),
178 (5, 'line'),
179 (5, 'line'),
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000180 (5, 'line'),
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000181 (5, 'exception'),
182 (6, 'line'),
183 (7, 'line'),
184 (7, 'return')]
185
Armin Rigo70693382004-03-22 19:30:39 +0000186def tighterloop_example():
187 items = range(1, 4)
188 try:
189 i = 0
190 while 1: i = items[i]
191 except IndexError:
192 pass
193
194tighterloop_example.events = [(0, 'call'),
195 (1, 'line'),
196 (2, 'line'),
197 (3, 'line'),
198 (4, 'line'),
199 (4, 'line'),
200 (4, 'line'),
201 (4, 'line'),
202 (4, 'exception'),
203 (5, 'line'),
204 (6, 'line'),
205 (6, 'return')]
206
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000207def generator_function():
208 try:
209 yield True
210 "continued"
211 finally:
212 "finally"
213def generator_example():
214 # any() will leave the generator before its end
215 x = any(generator_function())
216
217 # the following lines were not traced
218 for x in range(10):
219 y = x
220
221generator_example.events = ([(0, 'call'),
222 (2, 'line'),
223 (-6, 'call'),
224 (-5, 'line'),
225 (-4, 'line'),
226 (-4, 'return'),
227 (-4, 'call'),
228 (-4, 'exception'),
229 (-1, 'line'),
230 (-1, 'return')] +
231 [(5, 'line'), (6, 'line')] * 10 +
232 [(5, 'line'), (5, 'return')])
233
234
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000235class Tracer:
236 def __init__(self):
237 self.events = []
238 def trace(self, frame, event, arg):
239 self.events.append((frame.f_lineno, event))
240 return self.trace
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000241 def traceWithGenexp(self, frame, event, arg):
242 (o for o in [1])
243 self.events.append((frame.f_lineno, event))
244 return self.trace
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000245
246class TraceTestCase(unittest.TestCase):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000247 def compare_events(self, line_offset, events, expected_events):
Tim Peters3de75262002-11-09 05:26:15 +0000248 events = [(l - line_offset, e) for (l, e) in events]
Michael W. Hudson519a3422002-09-11 14:47:51 +0000249 if events != expected_events:
250 self.fail(
251 "events did not match expectation:\n" +
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000252 "\n".join(difflib.ndiff([str(x) for x in expected_events],
253 [str(x) for x in events])))
Tim Peters3de75262002-11-09 05:26:15 +0000254
Christian Heimes2202f872008-02-06 14:31:34 +0000255 def run_and_compare(self, func, events):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000256 tracer = Tracer()
257 sys.settrace(tracer.trace)
258 func()
259 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000260 self.compare_events(func.__code__.co_firstlineno,
Christian Heimes2202f872008-02-06 14:31:34 +0000261 tracer.events, events)
262
263 def run_test(self, func):
264 self.run_and_compare(func, func.events)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000265
266 def run_test2(self, func):
267 tracer = Tracer()
268 func(tracer.trace)
269 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000270 self.compare_events(func.__code__.co_firstlineno,
Michael W. Hudson519a3422002-09-11 14:47:51 +0000271 tracer.events, func.events)
Tim Peters3de75262002-11-09 05:26:15 +0000272
Christian Heimes9bd667a2008-01-20 15:14:11 +0000273 def set_and_retrieve_none(self):
274 sys.settrace(None)
275 assert sys.gettrace() is None
276
277 def set_and_retrieve_func(self):
278 def fn(*args):
279 pass
280
281 sys.settrace(fn)
282 try:
283 assert sys.gettrace() is fn
284 finally:
285 sys.settrace(None)
286
Nicholas Bastinaea94592004-03-22 18:30:42 +0000287 def test_01_basic(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000288 self.run_test(basic)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000289 def test_02_arigo(self):
290 self.run_test(arigo_example)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000291 def test_03_one_instr(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000292 self.run_test(one_instr_line)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000293 def test_04_no_pop_blocks(self):
294 self.run_test(no_pop_blocks)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000295 def test_05_no_pop_tops(self):
296 self.run_test(no_pop_tops)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000297 def test_06_call(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000298 self.run_test(call)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000299 def test_07_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000300 self.run_test(test_raise)
301
Nicholas Bastinaea94592004-03-22 18:30:42 +0000302 def test_08_settrace_and_return(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000303 self.run_test2(settrace_and_return)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000304 def test_09_settrace_and_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000305 self.run_test2(settrace_and_raise)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000306 def test_10_ireturn(self):
307 self.run_test(ireturn_example)
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000308 def test_11_tightloop(self):
309 self.run_test(tightloop_example)
Armin Rigo70693382004-03-22 19:30:39 +0000310 def test_12_tighterloop(self):
311 self.run_test(tighterloop_example)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000312
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000313 def test_13_genexp(self):
314 self.run_test(generator_example)
315 # issue1265: if the trace function contains a generator,
316 # and if the traced function contains another generator
317 # that is not completely exhausted, the trace stopped.
318 # Worse: the 'finally' clause was not invoked.
319 tracer = Tracer()
320 sys.settrace(tracer.traceWithGenexp)
321 generator_example()
322 sys.settrace(None)
323 self.compare_events(generator_example.__code__.co_firstlineno,
324 tracer.events, generator_example.events)
325
Christian Heimes2202f872008-02-06 14:31:34 +0000326 def test_14_onliner_if(self):
327 def onliners():
328 if True: False
329 else: True
330 return 0
331 self.run_and_compare(
332 onliners,
333 [(0, 'call'),
334 (1, 'line'),
335 (3, 'line'),
336 (3, 'return')])
337
338 def test_15_loops(self):
339 # issue1750076: "while" expression is skipped by debugger
340 def for_example():
341 for x in range(2):
342 pass
343 self.run_and_compare(
344 for_example,
345 [(0, 'call'),
346 (1, 'line'),
347 (2, 'line'),
348 (1, 'line'),
349 (2, 'line'),
350 (1, 'line'),
351 (1, 'return')])
352
353 def while_example():
354 # While expression should be traced on every loop
355 x = 2
356 while x > 0:
357 x -= 1
358 self.run_and_compare(
359 while_example,
360 [(0, 'call'),
361 (2, 'line'),
362 (3, 'line'),
363 (4, 'line'),
364 (3, 'line'),
365 (4, 'line'),
366 (3, 'line'),
367 (3, 'return')])
368
369 def test_16_blank_lines(self):
370 namespace = {}
371 exec("def f():\n" + "\n" * 256 + " pass", namespace)
372 self.run_and_compare(
373 namespace["f"],
374 [(0, 'call'),
375 (257, 'line'),
376 (257, 'return')])
377
378
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000379class RaisingTraceFuncTestCase(unittest.TestCase):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000380 def trace(self, frame, event, arg):
381 """A trace function that raises an exception in response to a
382 specific trace event."""
383 if event == self.raiseOnEvent:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000384 raise ValueError # just something that isn't RuntimeError
Michael W. Hudson006c7522002-11-08 13:08:46 +0000385 else:
386 return self.trace
Tim Peters3de75262002-11-09 05:26:15 +0000387
Michael W. Hudson006c7522002-11-08 13:08:46 +0000388 def f(self):
389 """The function to trace; raises an exception if that's the case
390 we're testing, so that the 'exception' trace event fires."""
391 if self.raiseOnEvent == 'exception':
392 x = 0
393 y = 1/x
394 else:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000395 return 1
Tim Peters3de75262002-11-09 05:26:15 +0000396
Michael W. Hudson006c7522002-11-08 13:08:46 +0000397 def run_test_for_event(self, event):
398 """Tests that an exception raised in response to the given event is
399 handled OK."""
400 self.raiseOnEvent = event
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000401 try:
Guido van Rossum805365e2007-05-07 22:24:25 +0000402 for i in range(sys.getrecursionlimit() + 1):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000403 sys.settrace(self.trace)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000404 try:
Michael W. Hudson006c7522002-11-08 13:08:46 +0000405 self.f()
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000406 except ValueError:
407 pass
408 else:
409 self.fail("exception not thrown!")
410 except RuntimeError:
411 self.fail("recursion counter not reset")
Tim Peters3de75262002-11-09 05:26:15 +0000412
Michael W. Hudson006c7522002-11-08 13:08:46 +0000413 # Test the handling of exceptions raised by each kind of trace event.
414 def test_call(self):
415 self.run_test_for_event('call')
416 def test_line(self):
417 self.run_test_for_event('line')
418 def test_return(self):
419 self.run_test_for_event('return')
420 def test_exception(self):
421 self.run_test_for_event('exception')
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000422
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000423 def test_trash_stack(self):
424 def f():
425 for i in range(5):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000426 print(i) # line tracing will raise an exception at this line
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000427
428 def g(frame, why, extra):
429 if (why == 'line' and
Neal Norwitz221085d2007-02-25 20:55:47 +0000430 frame.f_lineno == f.__code__.co_firstlineno + 2):
Collin Winter3add4d72007-08-29 23:37:32 +0000431 raise RuntimeError("i am crashing")
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000432 return g
433
434 sys.settrace(g)
435 try:
436 f()
437 except RuntimeError:
438 # the test is really that this doesn't segfault:
439 import gc
440 gc.collect()
441 else:
442 self.fail("exception not propagated")
443
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000444
445# 'Jump' tests: assigning to frame.f_lineno within a trace function
446# moves the execution position - it's how debuggers implement a Jump
447# command (aka. "Set next statement").
448
449class JumpTracer:
450 """Defines a trace function that jumps from one place to another,
451 with the source and destination lines of the jump being defined by
452 the 'jump' property of the function under test."""
453
454 def __init__(self, function):
455 self.function = function
456 self.jumpFrom = function.jump[0]
457 self.jumpTo = function.jump[1]
458 self.done = False
459
460 def trace(self, frame, event, arg):
Neal Norwitz221085d2007-02-25 20:55:47 +0000461 if not self.done and frame.f_code == self.function.__code__:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000462 firstLine = frame.f_code.co_firstlineno
463 if frame.f_lineno == firstLine + self.jumpFrom:
464 # Cope with non-integer self.jumpTo (because of
465 # no_jump_to_non_integers below).
466 try:
467 frame.f_lineno = firstLine + self.jumpTo
468 except TypeError:
469 frame.f_lineno = self.jumpTo
470 self.done = True
471 return self.trace
472
473# The first set of 'jump' tests are for things that are allowed:
474
475def jump_simple_forwards(output):
476 output.append(1)
477 output.append(2)
478 output.append(3)
479
480jump_simple_forwards.jump = (1, 3)
481jump_simple_forwards.output = [3]
482
483def jump_simple_backwards(output):
484 output.append(1)
485 output.append(2)
486
487jump_simple_backwards.jump = (2, 1)
488jump_simple_backwards.output = [1, 1, 2]
489
490def jump_out_of_block_forwards(output):
491 for i in 1, 2:
492 output.append(2)
493 for j in [3]: # Also tests jumping over a block
494 output.append(4)
495 output.append(5)
496
497jump_out_of_block_forwards.jump = (3, 5)
498jump_out_of_block_forwards.output = [2, 5]
499
500def jump_out_of_block_backwards(output):
501 output.append(1)
502 for i in [1]:
503 output.append(3)
504 for j in [2]: # Also tests jumping over a block
505 output.append(5)
506 output.append(6)
507 output.append(7)
508
509jump_out_of_block_backwards.jump = (6, 1)
510jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
511
512def jump_to_codeless_line(output):
513 output.append(1)
514 # Jumping to this line should skip to the next one.
515 output.append(3)
516
517jump_to_codeless_line.jump = (1, 2)
518jump_to_codeless_line.output = [3]
519
520def jump_to_same_line(output):
521 output.append(1)
522 output.append(2)
523 output.append(3)
524
525jump_to_same_line.jump = (2, 2)
526jump_to_same_line.output = [1, 2, 3]
527
528# Tests jumping within a finally block, and over one.
529def jump_in_nested_finally(output):
530 try:
531 output.append(2)
532 finally:
533 output.append(4)
534 try:
535 output.append(6)
536 finally:
537 output.append(8)
538 output.append(9)
539
540jump_in_nested_finally.jump = (4, 9)
541jump_in_nested_finally.output = [2, 9]
542
543# The second set of 'jump' tests are for things that are not allowed:
544
545def no_jump_too_far_forwards(output):
546 try:
547 output.append(2)
548 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000549 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000550 output.append('after' in str(e))
551
552no_jump_too_far_forwards.jump = (3, 6)
553no_jump_too_far_forwards.output = [2, True]
554
555def no_jump_too_far_backwards(output):
556 try:
557 output.append(2)
558 output.append(3)
Guido van Rossumb940e112007-01-10 16:19:56 +0000559 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000560 output.append('before' in str(e))
561
562no_jump_too_far_backwards.jump = (3, -1)
563no_jump_too_far_backwards.output = [2, True]
564
565# Test each kind of 'except' line.
566def no_jump_to_except_1(output):
567 try:
568 output.append(2)
569 except:
570 e = sys.exc_info()[1]
571 output.append('except' in str(e))
572
573no_jump_to_except_1.jump = (2, 3)
574no_jump_to_except_1.output = [True]
575
576def no_jump_to_except_2(output):
577 try:
578 output.append(2)
579 except ValueError:
580 e = sys.exc_info()[1]
581 output.append('except' in str(e))
582
583no_jump_to_except_2.jump = (2, 3)
584no_jump_to_except_2.output = [True]
585
586def no_jump_to_except_3(output):
587 try:
588 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000589 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000590 output.append('except' in str(e))
591
592no_jump_to_except_3.jump = (2, 3)
593no_jump_to_except_3.output = [True]
594
595def no_jump_to_except_4(output):
596 try:
597 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000598 except (ValueError, RuntimeError) as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000599 output.append('except' in str(e))
600
601no_jump_to_except_4.jump = (2, 3)
602no_jump_to_except_4.output = [True]
603
604def no_jump_forwards_into_block(output):
605 try:
606 output.append(2)
607 for i in 1, 2:
608 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000609 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000610 output.append('into' in str(e))
611
612no_jump_forwards_into_block.jump = (2, 4)
613no_jump_forwards_into_block.output = [True]
614
615def no_jump_backwards_into_block(output):
616 try:
617 for i in 1, 2:
618 output.append(3)
619 output.append(4)
Guido van Rossumb940e112007-01-10 16:19:56 +0000620 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000621 output.append('into' in str(e))
622
623no_jump_backwards_into_block.jump = (4, 3)
624no_jump_backwards_into_block.output = [3, 3, True]
625
626def no_jump_into_finally_block(output):
627 try:
628 try:
629 output.append(3)
630 x = 1
631 finally:
632 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000633 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000634 output.append('finally' in str(e))
635
636no_jump_into_finally_block.jump = (4, 6)
637no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
638
639def no_jump_out_of_finally_block(output):
640 try:
641 try:
642 output.append(3)
643 finally:
644 output.append(5)
645 output.append(6)
Guido van Rossumb940e112007-01-10 16:19:56 +0000646 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000647 output.append('finally' in str(e))
648
649no_jump_out_of_finally_block.jump = (5, 1)
650no_jump_out_of_finally_block.output = [3, True]
651
652# This verifies the line-numbers-must-be-integers rule.
653def no_jump_to_non_integers(output):
654 try:
655 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000656 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000657 output.append('integer' in str(e))
658
659no_jump_to_non_integers.jump = (2, "Spam")
660no_jump_to_non_integers.output = [True]
661
662# This verifies that you can't set f_lineno via _getframe or similar
663# trickery.
664def no_jump_without_trace_function():
665 try:
666 previous_frame = sys._getframe().f_back
667 previous_frame.f_lineno = previous_frame.f_lineno
Guido van Rossumb940e112007-01-10 16:19:56 +0000668 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000669 # This is the exception we wanted; make sure the error message
670 # talks about trace functions.
671 if 'trace' not in str(e):
672 raise
673 else:
674 # Something's wrong - the expected exception wasn't raised.
Collin Winter3add4d72007-08-29 23:37:32 +0000675 raise RuntimeError("Trace-function-less jump failed to fail")
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000676
677
678class JumpTestCase(unittest.TestCase):
679 def compare_jump_output(self, expected, received):
680 if received != expected:
681 self.fail( "Outputs don't match:\n" +
682 "Expected: " + repr(expected) + "\n" +
683 "Received: " + repr(received))
684
685 def run_test(self, func):
686 tracer = JumpTracer(func)
687 sys.settrace(tracer.trace)
688 output = []
689 func(output)
690 sys.settrace(None)
691 self.compare_jump_output(func.output, output)
692
693 def test_01_jump_simple_forwards(self):
694 self.run_test(jump_simple_forwards)
695 def test_02_jump_simple_backwards(self):
696 self.run_test(jump_simple_backwards)
697 def test_03_jump_out_of_block_forwards(self):
698 self.run_test(jump_out_of_block_forwards)
699 def test_04_jump_out_of_block_backwards(self):
700 self.run_test(jump_out_of_block_backwards)
701 def test_05_jump_to_codeless_line(self):
702 self.run_test(jump_to_codeless_line)
703 def test_06_jump_to_same_line(self):
704 self.run_test(jump_to_same_line)
705 def test_07_jump_in_nested_finally(self):
706 self.run_test(jump_in_nested_finally)
707 def test_08_no_jump_too_far_forwards(self):
708 self.run_test(no_jump_too_far_forwards)
709 def test_09_no_jump_too_far_backwards(self):
710 self.run_test(no_jump_too_far_backwards)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000711 def test_10_no_jump_to_except_1(self):
712 self.run_test(no_jump_to_except_1)
713 def test_11_no_jump_to_except_2(self):
714 self.run_test(no_jump_to_except_2)
715 def test_12_no_jump_to_except_3(self):
716 self.run_test(no_jump_to_except_3)
717 def test_13_no_jump_to_except_4(self):
718 self.run_test(no_jump_to_except_4)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000719 def test_14_no_jump_forwards_into_block(self):
720 self.run_test(no_jump_forwards_into_block)
721 def test_15_no_jump_backwards_into_block(self):
722 self.run_test(no_jump_backwards_into_block)
723 def test_16_no_jump_into_finally_block(self):
724 self.run_test(no_jump_into_finally_block)
725 def test_17_no_jump_out_of_finally_block(self):
726 self.run_test(no_jump_out_of_finally_block)
727 def test_18_no_jump_to_non_integers(self):
728 self.run_test(no_jump_to_non_integers)
729 def test_19_no_jump_without_trace_function(self):
730 no_jump_without_trace_function()
731
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000732def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000733 test_support.run_unittest(
734 TraceTestCase,
735 RaisingTraceFuncTestCase,
736 JumpTestCase
737 )
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000738
739if __name__ == "__main__":
740 test_main()