blob: df8c56f7582291ce278ed6a45a7e29f03aabb838 [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
Amaury Forgeot d'Arc48ebc262008-04-24 20:10:26 +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
Jeremy Hyltoned40ea12006-04-04 14:26:39 +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():
Jeremy Hyltoned40ea12006-04-04 14:26:39 +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'),
Jeremy Hyltoned40ea12006-04-04 14:26:39 +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()
101 except Exception, exc:
102 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)
131 except RuntimeError, exc:
132 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
Jeremy Hyltoned40ea12006-04-04 14:26:39 +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'),
Jeremy Hyltoned40ea12006-04-04 14:26:39 +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'Arc0d75f092007-11-13 21:54:28 +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'Arc0d75f092007-11-13 21:54:28 +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):
Amaury Forgeot d'Arc48ebc262008-04-24 20:10:26 +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()
254
255 def tearDown(self):
256 if self.using_gc:
257 gc.enable()
258
Michael W. Hudson519a3422002-09-11 14:47:51 +0000259 def compare_events(self, line_offset, events, expected_events):
Tim Peters3de75262002-11-09 05:26:15 +0000260 events = [(l - line_offset, e) for (l, e) in events]
Michael W. Hudson519a3422002-09-11 14:47:51 +0000261 if events != expected_events:
262 self.fail(
263 "events did not match expectation:\n" +
Amaury Forgeot d'Arc0d75f092007-11-13 21:54:28 +0000264 "\n".join(difflib.ndiff([str(x) for x in expected_events],
265 [str(x) for x in events])))
Tim Peters3de75262002-11-09 05:26:15 +0000266
Amaury Forgeot d'Arc6fd03bb2008-02-04 21:45:05 +0000267 def run_and_compare(self, func, events):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000268 tracer = Tracer()
269 sys.settrace(tracer.trace)
270 func()
271 sys.settrace(None)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000272 self.compare_events(func.func_code.co_firstlineno,
Amaury Forgeot d'Arc6fd03bb2008-02-04 21:45:05 +0000273 tracer.events, events)
274
275 def run_test(self, func):
276 self.run_and_compare(func, func.events)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000277
278 def run_test2(self, func):
279 tracer = Tracer()
280 func(tracer.trace)
281 sys.settrace(None)
282 self.compare_events(func.func_code.co_firstlineno,
283 tracer.events, func.events)
Tim Peters3de75262002-11-09 05:26:15 +0000284
Georg Brandl56112892008-01-20 13:59:46 +0000285 def set_and_retrieve_none(self):
286 sys.settrace(None)
287 assert sys.gettrace() is None
288
289 def set_and_retrieve_func(self):
290 def fn(*args):
291 pass
292
293 sys.settrace(fn)
294 try:
295 assert sys.gettrace() is fn
296 finally:
297 sys.settrace(None)
298
Nicholas Bastinaea94592004-03-22 18:30:42 +0000299 def test_01_basic(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000300 self.run_test(basic)
Jeremy Hyltoned40ea12006-04-04 14:26:39 +0000301 def test_02_arigo(self):
302 self.run_test(arigo_example)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000303 def test_03_one_instr(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000304 self.run_test(one_instr_line)
Jeremy Hyltoned40ea12006-04-04 14:26:39 +0000305 def test_04_no_pop_blocks(self):
306 self.run_test(no_pop_blocks)
Neal Norwitz4ffedad2006-08-04 04:58:47 +0000307 def test_05_no_pop_tops(self):
308 self.run_test(no_pop_tops)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000309 def test_06_call(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000310 self.run_test(call)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000311 def test_07_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000312 self.run_test(test_raise)
313
Nicholas Bastinaea94592004-03-22 18:30:42 +0000314 def test_08_settrace_and_return(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000315 self.run_test2(settrace_and_return)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000316 def test_09_settrace_and_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000317 self.run_test2(settrace_and_raise)
Jeremy Hyltoned40ea12006-04-04 14:26:39 +0000318 def test_10_ireturn(self):
319 self.run_test(ireturn_example)
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000320 def test_11_tightloop(self):
321 self.run_test(tightloop_example)
Armin Rigo70693382004-03-22 19:30:39 +0000322 def test_12_tighterloop(self):
323 self.run_test(tighterloop_example)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000324
Amaury Forgeot d'Arc0d75f092007-11-13 21:54:28 +0000325 def test_13_genexp(self):
326 self.run_test(generator_example)
327 # issue1265: if the trace function contains a generator,
328 # and if the traced function contains another generator
329 # that is not completely exhausted, the trace stopped.
330 # Worse: the 'finally' clause was not invoked.
331 tracer = Tracer()
332 sys.settrace(tracer.traceWithGenexp)
333 generator_example()
334 sys.settrace(None)
335 self.compare_events(generator_example.__code__.co_firstlineno,
336 tracer.events, generator_example.events)
337
Amaury Forgeot d'Arc6fd03bb2008-02-04 21:45:05 +0000338 def test_14_onliner_if(self):
339 def onliners():
340 if True: False
341 else: True
342 return 0
343 self.run_and_compare(
344 onliners,
345 [(0, 'call'),
346 (1, 'line'),
347 (3, 'line'),
348 (3, 'return')])
349
350 def test_15_loops(self):
351 # issue1750076: "while" expression is skipped by debugger
352 def for_example():
353 for x in range(2):
354 pass
355 self.run_and_compare(
356 for_example,
357 [(0, 'call'),
358 (1, 'line'),
359 (2, 'line'),
360 (1, 'line'),
361 (2, 'line'),
362 (1, 'line'),
363 (1, 'return')])
364
365 def while_example():
366 # While expression should be traced on every loop
367 x = 2
368 while x > 0:
369 x -= 1
370 self.run_and_compare(
371 while_example,
372 [(0, 'call'),
373 (2, 'line'),
374 (3, 'line'),
375 (4, 'line'),
376 (3, 'line'),
377 (4, 'line'),
378 (3, 'line'),
379 (3, 'return')])
380
Amaury Forgeot d'Arc99af7db2008-02-05 00:26:21 +0000381 def test_16_blank_lines(self):
382 exec("def f():\n" + "\n" * 256 + " pass")
383 self.run_and_compare(
384 f,
385 [(0, 'call'),
386 (257, 'line'),
387 (257, 'return')])
388
389
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000390class RaisingTraceFuncTestCase(unittest.TestCase):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000391 def trace(self, frame, event, arg):
392 """A trace function that raises an exception in response to a
393 specific trace event."""
394 if event == self.raiseOnEvent:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000395 raise ValueError # just something that isn't RuntimeError
Michael W. Hudson006c7522002-11-08 13:08:46 +0000396 else:
397 return self.trace
Tim Peters3de75262002-11-09 05:26:15 +0000398
Michael W. Hudson006c7522002-11-08 13:08:46 +0000399 def f(self):
400 """The function to trace; raises an exception if that's the case
401 we're testing, so that the 'exception' trace event fires."""
402 if self.raiseOnEvent == 'exception':
403 x = 0
Ezio Melottidde5b942010-02-03 05:37:26 +0000404 y = 1 // x
Michael W. Hudson006c7522002-11-08 13:08:46 +0000405 else:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000406 return 1
Tim Peters3de75262002-11-09 05:26:15 +0000407
Michael W. Hudson006c7522002-11-08 13:08:46 +0000408 def run_test_for_event(self, event):
409 """Tests that an exception raised in response to the given event is
410 handled OK."""
411 self.raiseOnEvent = event
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000412 try:
413 for i in xrange(sys.getrecursionlimit() + 1):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000414 sys.settrace(self.trace)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000415 try:
Michael W. Hudson006c7522002-11-08 13:08:46 +0000416 self.f()
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000417 except ValueError:
418 pass
419 else:
420 self.fail("exception not thrown!")
421 except RuntimeError:
422 self.fail("recursion counter not reset")
Tim Peters3de75262002-11-09 05:26:15 +0000423
Michael W. Hudson006c7522002-11-08 13:08:46 +0000424 # Test the handling of exceptions raised by each kind of trace event.
425 def test_call(self):
426 self.run_test_for_event('call')
427 def test_line(self):
428 self.run_test_for_event('line')
429 def test_return(self):
430 self.run_test_for_event('return')
431 def test_exception(self):
432 self.run_test_for_event('exception')
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000433
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000434 def test_trash_stack(self):
435 def f():
436 for i in range(5):
437 print i # line tracing will raise an exception at this line
438
439 def g(frame, why, extra):
440 if (why == 'line' and
441 frame.f_lineno == f.func_code.co_firstlineno + 2):
442 raise RuntimeError, "i am crashing"
443 return g
444
445 sys.settrace(g)
446 try:
447 f()
448 except RuntimeError:
449 # the test is really that this doesn't segfault:
450 import gc
451 gc.collect()
452 else:
453 self.fail("exception not propagated")
454
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000455
456# 'Jump' tests: assigning to frame.f_lineno within a trace function
457# moves the execution position - it's how debuggers implement a Jump
458# command (aka. "Set next statement").
459
460class JumpTracer:
461 """Defines a trace function that jumps from one place to another,
462 with the source and destination lines of the jump being defined by
463 the 'jump' property of the function under test."""
464
465 def __init__(self, function):
466 self.function = function
467 self.jumpFrom = function.jump[0]
468 self.jumpTo = function.jump[1]
469 self.done = False
470
471 def trace(self, frame, event, arg):
472 if not self.done and frame.f_code == self.function.func_code:
473 firstLine = frame.f_code.co_firstlineno
Jeffrey Yasskin61328ee2009-05-18 21:14:54 +0000474 if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000475 # Cope with non-integer self.jumpTo (because of
476 # no_jump_to_non_integers below).
477 try:
478 frame.f_lineno = firstLine + self.jumpTo
479 except TypeError:
480 frame.f_lineno = self.jumpTo
481 self.done = True
482 return self.trace
483
484# The first set of 'jump' tests are for things that are allowed:
485
486def jump_simple_forwards(output):
487 output.append(1)
488 output.append(2)
489 output.append(3)
490
491jump_simple_forwards.jump = (1, 3)
492jump_simple_forwards.output = [3]
493
494def jump_simple_backwards(output):
495 output.append(1)
496 output.append(2)
497
498jump_simple_backwards.jump = (2, 1)
499jump_simple_backwards.output = [1, 1, 2]
500
501def jump_out_of_block_forwards(output):
502 for i in 1, 2:
503 output.append(2)
504 for j in [3]: # Also tests jumping over a block
505 output.append(4)
506 output.append(5)
507
508jump_out_of_block_forwards.jump = (3, 5)
509jump_out_of_block_forwards.output = [2, 5]
510
511def jump_out_of_block_backwards(output):
512 output.append(1)
513 for i in [1]:
514 output.append(3)
515 for j in [2]: # Also tests jumping over a block
516 output.append(5)
517 output.append(6)
518 output.append(7)
519
520jump_out_of_block_backwards.jump = (6, 1)
521jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
522
523def jump_to_codeless_line(output):
524 output.append(1)
525 # Jumping to this line should skip to the next one.
526 output.append(3)
527
528jump_to_codeless_line.jump = (1, 2)
529jump_to_codeless_line.output = [3]
530
531def jump_to_same_line(output):
532 output.append(1)
533 output.append(2)
534 output.append(3)
535
536jump_to_same_line.jump = (2, 2)
537jump_to_same_line.output = [1, 2, 3]
538
539# Tests jumping within a finally block, and over one.
540def jump_in_nested_finally(output):
541 try:
542 output.append(2)
543 finally:
544 output.append(4)
545 try:
546 output.append(6)
547 finally:
548 output.append(8)
549 output.append(9)
550
551jump_in_nested_finally.jump = (4, 9)
552jump_in_nested_finally.output = [2, 9]
553
554# The second set of 'jump' tests are for things that are not allowed:
555
556def no_jump_too_far_forwards(output):
557 try:
558 output.append(2)
559 output.append(3)
560 except ValueError, e:
561 output.append('after' in str(e))
562
563no_jump_too_far_forwards.jump = (3, 6)
564no_jump_too_far_forwards.output = [2, True]
565
566def no_jump_too_far_backwards(output):
567 try:
568 output.append(2)
569 output.append(3)
570 except ValueError, e:
571 output.append('before' in str(e))
572
573no_jump_too_far_backwards.jump = (3, -1)
574no_jump_too_far_backwards.output = [2, True]
575
576# Test each kind of 'except' line.
577def no_jump_to_except_1(output):
578 try:
579 output.append(2)
580 except:
581 e = sys.exc_info()[1]
582 output.append('except' in str(e))
583
584no_jump_to_except_1.jump = (2, 3)
585no_jump_to_except_1.output = [True]
586
587def no_jump_to_except_2(output):
588 try:
589 output.append(2)
590 except ValueError:
591 e = sys.exc_info()[1]
592 output.append('except' in str(e))
593
594no_jump_to_except_2.jump = (2, 3)
595no_jump_to_except_2.output = [True]
596
597def no_jump_to_except_3(output):
598 try:
599 output.append(2)
600 except ValueError, e:
601 output.append('except' in str(e))
602
603no_jump_to_except_3.jump = (2, 3)
604no_jump_to_except_3.output = [True]
605
606def no_jump_to_except_4(output):
607 try:
608 output.append(2)
609 except (ValueError, RuntimeError), e:
610 output.append('except' in str(e))
611
612no_jump_to_except_4.jump = (2, 3)
613no_jump_to_except_4.output = [True]
614
615def no_jump_forwards_into_block(output):
616 try:
617 output.append(2)
618 for i in 1, 2:
619 output.append(4)
620 except ValueError, e:
621 output.append('into' in str(e))
622
623no_jump_forwards_into_block.jump = (2, 4)
624no_jump_forwards_into_block.output = [True]
625
626def no_jump_backwards_into_block(output):
627 try:
628 for i in 1, 2:
629 output.append(3)
630 output.append(4)
631 except ValueError, e:
632 output.append('into' in str(e))
633
634no_jump_backwards_into_block.jump = (4, 3)
635no_jump_backwards_into_block.output = [3, 3, True]
636
637def no_jump_into_finally_block(output):
638 try:
639 try:
640 output.append(3)
641 x = 1
642 finally:
643 output.append(6)
644 except ValueError, e:
645 output.append('finally' in str(e))
646
647no_jump_into_finally_block.jump = (4, 6)
648no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
649
650def no_jump_out_of_finally_block(output):
651 try:
652 try:
653 output.append(3)
654 finally:
655 output.append(5)
656 output.append(6)
657 except ValueError, e:
658 output.append('finally' in str(e))
659
660no_jump_out_of_finally_block.jump = (5, 1)
661no_jump_out_of_finally_block.output = [3, True]
662
663# This verifies the line-numbers-must-be-integers rule.
664def no_jump_to_non_integers(output):
665 try:
666 output.append(2)
667 except ValueError, e:
668 output.append('integer' in str(e))
669
670no_jump_to_non_integers.jump = (2, "Spam")
671no_jump_to_non_integers.output = [True]
672
673# This verifies that you can't set f_lineno via _getframe or similar
674# trickery.
675def no_jump_without_trace_function():
676 try:
677 previous_frame = sys._getframe().f_back
678 previous_frame.f_lineno = previous_frame.f_lineno
679 except ValueError, e:
680 # This is the exception we wanted; make sure the error message
681 # talks about trace functions.
682 if 'trace' not in str(e):
683 raise
684 else:
685 # Something's wrong - the expected exception wasn't raised.
686 raise RuntimeError, "Trace-function-less jump failed to fail"
687
688
689class JumpTestCase(unittest.TestCase):
690 def compare_jump_output(self, expected, received):
691 if received != expected:
692 self.fail( "Outputs don't match:\n" +
693 "Expected: " + repr(expected) + "\n" +
694 "Received: " + repr(received))
695
696 def run_test(self, func):
697 tracer = JumpTracer(func)
698 sys.settrace(tracer.trace)
699 output = []
700 func(output)
701 sys.settrace(None)
702 self.compare_jump_output(func.output, output)
703
704 def test_01_jump_simple_forwards(self):
705 self.run_test(jump_simple_forwards)
706 def test_02_jump_simple_backwards(self):
707 self.run_test(jump_simple_backwards)
708 def test_03_jump_out_of_block_forwards(self):
709 self.run_test(jump_out_of_block_forwards)
710 def test_04_jump_out_of_block_backwards(self):
711 self.run_test(jump_out_of_block_backwards)
712 def test_05_jump_to_codeless_line(self):
713 self.run_test(jump_to_codeless_line)
714 def test_06_jump_to_same_line(self):
715 self.run_test(jump_to_same_line)
716 def test_07_jump_in_nested_finally(self):
717 self.run_test(jump_in_nested_finally)
718 def test_08_no_jump_too_far_forwards(self):
719 self.run_test(no_jump_too_far_forwards)
720 def test_09_no_jump_too_far_backwards(self):
721 self.run_test(no_jump_too_far_backwards)
Jeremy Hyltoned40ea12006-04-04 14:26:39 +0000722 def test_10_no_jump_to_except_1(self):
723 self.run_test(no_jump_to_except_1)
724 def test_11_no_jump_to_except_2(self):
725 self.run_test(no_jump_to_except_2)
726 def test_12_no_jump_to_except_3(self):
727 self.run_test(no_jump_to_except_3)
728 def test_13_no_jump_to_except_4(self):
729 self.run_test(no_jump_to_except_4)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000730 def test_14_no_jump_forwards_into_block(self):
731 self.run_test(no_jump_forwards_into_block)
732 def test_15_no_jump_backwards_into_block(self):
733 self.run_test(no_jump_backwards_into_block)
734 def test_16_no_jump_into_finally_block(self):
735 self.run_test(no_jump_into_finally_block)
736 def test_17_no_jump_out_of_finally_block(self):
737 self.run_test(no_jump_out_of_finally_block)
738 def test_18_no_jump_to_non_integers(self):
739 self.run_test(no_jump_to_non_integers)
740 def test_19_no_jump_without_trace_function(self):
741 no_jump_without_trace_function()
742
Amaury Forgeot d'Arcb02ceda2009-06-01 20:53:18 +0000743 def test_20_large_function(self):
744 d = {}
745 exec("""def f(output): # line 0
746 x = 0 # line 1
747 y = 1 # line 2
748 ''' # line 3
749 %s # lines 4-1004
750 ''' # line 1005
751 x += 1 # line 1006
752 output.append(x) # line 1007
753 return""" % ('\n' * 1000,), d)
754 f = d['f']
755
756 f.jump = (2, 1007)
757 f.output = [0]
758 self.run_test(f)
759
Jeffrey Yasskinc8d30fe2009-05-20 17:57:57 +0000760 def test_jump_to_firstlineno(self):
761 # This tests that PDB can jump back to the first line in a
762 # file. See issue #1689458. It can only be triggered in a
763 # function call if the function is defined on a single line.
764 code = compile("""
765# Comments don't count.
766output.append(2) # firstlineno is here.
767output.append(3)
768output.append(4)
769""", "<fake module>", "exec")
770 class fake_function:
771 func_code = code
772 jump = (2, 0)
773 tracer = JumpTracer(fake_function)
774 sys.settrace(tracer.trace)
775 namespace = {"output": []}
776 exec code in namespace
777 sys.settrace(None)
778 self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
779
780
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000781def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000782 test_support.run_unittest(
783 TraceTestCase,
784 RaisingTraceFuncTestCase,
785 JumpTestCase
786 )
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000787
788if __name__ == "__main__":
789 test_main()