blob: 1fa43b29ec90c276c4e73e226f7e09554d2ec648 [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
Serhiy Storchaka53f91352017-12-27 00:38:56 +02008from functools import wraps
Serhiy Storchakabc300ce2018-03-18 09:53:08 +02009import asyncio
10
Serhiy Storchaka53f91352017-12-27 00:38:56 +020011
12class tracecontext:
gfyoung531dd7e2017-12-28 00:28:25 -080013 """Context manager that traces its enter and exit."""
Serhiy Storchaka53f91352017-12-27 00:38:56 +020014 def __init__(self, output, value):
15 self.output = output
16 self.value = value
17
18 def __enter__(self):
19 self.output.append(self.value)
20
21 def __exit__(self, *exc_info):
22 self.output.append(-self.value)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000023
Serhiy Storchakabc300ce2018-03-18 09:53:08 +020024class asynctracecontext:
25 """Asynchronous context manager that traces its aenter and aexit."""
26 def __init__(self, output, value):
27 self.output = output
28 self.value = value
29
30 async def __aenter__(self):
31 self.output.append(self.value)
32
33 async def __aexit__(self, *exc_info):
34 self.output.append(-self.value)
35
Serhiy Storchaka702f8f32018-03-23 14:34:35 +020036async def asynciter(iterable):
37 """Convert an iterable to an asynchronous iterator."""
38 for x in iterable:
39 yield x
Serhiy Storchakabc300ce2018-03-18 09:53:08 +020040
41
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000042# A very basic example. If this fails, we're in deep trouble.
43def basic():
44 return 1
45
46basic.events = [(0, 'call'),
47 (1, 'line'),
48 (1, 'return')]
49
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000050# Many of the tests below are tricky because they involve pass statements.
51# If there is implicit control flow around a pass statement (in an except
Mike53f7a7c2017-12-14 14:04:53 +030052# clause or else clause) under what conditions do you set a line number
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000053# following that clause?
54
55
56# The entire "while 0:" statement is optimized away. No code
57# exists for it, so the line numbers skip directly from "del x"
58# to "x = 1".
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000059def arigo_example():
60 x = 1
61 del x
62 while 0:
63 pass
64 x = 1
65
66arigo_example.events = [(0, 'call'),
67 (1, 'line'),
68 (2, 'line'),
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000069 (5, 'line'),
70 (5, 'return')]
71
72# check that lines consisting of just one instruction get traced:
73def one_instr_line():
74 x = 1
75 del x
76 x = 1
77
78one_instr_line.events = [(0, 'call'),
79 (1, 'line'),
80 (2, 'line'),
81 (3, 'line'),
82 (3, 'return')]
83
84def no_pop_tops(): # 0
85 x = 1 # 1
86 for a in range(2): # 2
87 if a: # 3
88 x = 1 # 4
89 else: # 5
90 x = 1 # 6
91
92no_pop_tops.events = [(0, 'call'),
93 (1, 'line'),
94 (2, 'line'),
95 (3, 'line'),
96 (6, 'line'),
97 (2, 'line'),
98 (3, 'line'),
99 (4, 'line'),
100 (2, 'line'),
Michael W. Hudson02ff6a92002-09-11 15:36:32 +0000101 (2, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000102
103def no_pop_blocks():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104 y = 1
105 while not y:
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000106 bla
107 x = 1
108
109no_pop_blocks.events = [(0, 'call'),
110 (1, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000111 (2, 'line'),
112 (4, 'line'),
113 (4, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000114
Michael W. Hudson519a3422002-09-11 14:47:51 +0000115def called(): # line -3
116 x = 1
117
118def call(): # line 0
119 called()
120
121call.events = [(0, 'call'),
122 (1, 'line'),
123 (-3, 'call'),
124 (-2, 'line'),
125 (-2, 'return'),
126 (1, 'return')]
127
128def raises():
129 raise Exception
130
131def test_raise():
132 try:
133 raises()
Guido van Rossumb940e112007-01-10 16:19:56 +0000134 except Exception as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000135 x = 1
136
137test_raise.events = [(0, 'call'),
138 (1, 'line'),
139 (2, 'line'),
140 (-3, 'call'),
141 (-2, 'line'),
142 (-2, 'exception'),
Barry Warsawe2eca0b2005-08-15 18:14:19 +0000143 (-2, 'return'),
Michael W. Hudson519a3422002-09-11 14:47:51 +0000144 (2, 'exception'),
145 (3, 'line'),
146 (4, 'line'),
147 (4, 'return')]
148
149def _settrace_and_return(tracefunc):
150 sys.settrace(tracefunc)
151 sys._getframe().f_back.f_trace = tracefunc
152def settrace_and_return(tracefunc):
153 _settrace_and_return(tracefunc)
Tim Peters3de75262002-11-09 05:26:15 +0000154
Michael W. Hudson519a3422002-09-11 14:47:51 +0000155settrace_and_return.events = [(1, 'return')]
156
157def _settrace_and_raise(tracefunc):
158 sys.settrace(tracefunc)
159 sys._getframe().f_back.f_trace = tracefunc
160 raise RuntimeError
161def settrace_and_raise(tracefunc):
162 try:
163 _settrace_and_raise(tracefunc)
Guido van Rossumb940e112007-01-10 16:19:56 +0000164 except RuntimeError as exc:
Michael W. Hudson519a3422002-09-11 14:47:51 +0000165 pass
Tim Peters3de75262002-11-09 05:26:15 +0000166
Michael W. Hudson519a3422002-09-11 14:47:51 +0000167settrace_and_raise.events = [(2, 'exception'),
168 (3, 'line'),
169 (4, 'line'),
170 (4, 'return')]
171
Nicholas Bastinaea94592004-03-22 18:30:42 +0000172# implicit return example
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000173# This test is interesting because of the else: pass
174# part of the code. The code generate for the true
175# part of the if contains a jump past the else branch.
176# The compiler then generates an implicit "return None"
177# Internally, the compiler visits the pass statement
178# and stores its line number for use on the next instruction.
179# The next instruction is the implicit return None.
Nicholas Bastinaea94592004-03-22 18:30:42 +0000180def ireturn_example():
181 a = 5
182 b = 5
183 if a == b:
184 b = a+1
185 else:
186 pass
187
188ireturn_example.events = [(0, 'call'),
189 (1, 'line'),
190 (2, 'line'),
191 (3, 'line'),
192 (4, 'line'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000193 (6, 'line'),
194 (6, 'return')]
Nicholas Bastinaea94592004-03-22 18:30:42 +0000195
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000196# Tight loop with while(1) example (SF #765624)
197def tightloop_example():
198 items = range(0, 3)
199 try:
200 i = 0
201 while 1:
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000202 b = items[i]; i+=1
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000203 except IndexError:
204 pass
205
206tightloop_example.events = [(0, 'call'),
207 (1, 'line'),
208 (2, 'line'),
209 (3, 'line'),
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000210 (5, 'line'),
211 (5, 'line'),
212 (5, 'line'),
Nicholas Bastinee6c9b82004-03-22 19:23:46 +0000213 (5, 'line'),
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000214 (5, 'exception'),
215 (6, 'line'),
216 (7, 'line'),
217 (7, 'return')]
218
Armin Rigo70693382004-03-22 19:30:39 +0000219def tighterloop_example():
220 items = range(1, 4)
221 try:
222 i = 0
223 while 1: i = items[i]
224 except IndexError:
225 pass
226
227tighterloop_example.events = [(0, 'call'),
228 (1, 'line'),
229 (2, 'line'),
230 (3, 'line'),
231 (4, 'line'),
232 (4, 'line'),
233 (4, 'line'),
234 (4, 'line'),
235 (4, 'exception'),
236 (5, 'line'),
237 (6, 'line'),
238 (6, 'return')]
239
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000240def generator_function():
241 try:
242 yield True
243 "continued"
244 finally:
245 "finally"
246def generator_example():
247 # any() will leave the generator before its end
248 x = any(generator_function())
249
250 # the following lines were not traced
251 for x in range(10):
252 y = x
253
254generator_example.events = ([(0, 'call'),
255 (2, 'line'),
256 (-6, 'call'),
257 (-5, 'line'),
258 (-4, 'line'),
259 (-4, 'return'),
260 (-4, 'call'),
261 (-4, 'exception'),
262 (-1, 'line'),
263 (-1, 'return')] +
264 [(5, 'line'), (6, 'line')] * 10 +
265 [(5, 'line'), (5, 'return')])
266
267
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000268class Tracer:
Nick Coghlan5a851672017-09-08 10:14:16 +1000269 def __init__(self, trace_line_events=None, trace_opcode_events=None):
270 self.trace_line_events = trace_line_events
271 self.trace_opcode_events = trace_opcode_events
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000272 self.events = []
Nick Coghlan5a851672017-09-08 10:14:16 +1000273
274 def _reconfigure_frame(self, frame):
275 if self.trace_line_events is not None:
276 frame.f_trace_lines = self.trace_line_events
277 if self.trace_opcode_events is not None:
278 frame.f_trace_opcodes = self.trace_opcode_events
279
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000280 def trace(self, frame, event, arg):
Nick Coghlan5a851672017-09-08 10:14:16 +1000281 self._reconfigure_frame(frame)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000282 self.events.append((frame.f_lineno, event))
283 return self.trace
Nick Coghlan5a851672017-09-08 10:14:16 +1000284
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000285 def traceWithGenexp(self, frame, event, arg):
Nick Coghlan5a851672017-09-08 10:14:16 +1000286 self._reconfigure_frame(frame)
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000287 (o for o in [1])
288 self.events.append((frame.f_lineno, event))
289 return self.trace
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000290
Nick Coghlan5a851672017-09-08 10:14:16 +1000291
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000292class TraceTestCase(unittest.TestCase):
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000293
294 # Disable gc collection when tracing, otherwise the
295 # deallocators may be traced as well.
296 def setUp(self):
297 self.using_gc = gc.isenabled()
298 gc.disable()
Brett Cannon31f59292011-02-21 19:29:56 +0000299 self.addCleanup(sys.settrace, sys.gettrace())
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000300
301 def tearDown(self):
302 if self.using_gc:
303 gc.enable()
304
Nick Coghlan5a851672017-09-08 10:14:16 +1000305 @staticmethod
306 def make_tracer():
307 """Helper to allow test subclasses to configure tracers differently"""
308 return Tracer()
309
Michael W. Hudson519a3422002-09-11 14:47:51 +0000310 def compare_events(self, line_offset, events, expected_events):
Tim Peters3de75262002-11-09 05:26:15 +0000311 events = [(l - line_offset, e) for (l, e) in events]
Michael W. Hudson519a3422002-09-11 14:47:51 +0000312 if events != expected_events:
313 self.fail(
314 "events did not match expectation:\n" +
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000315 "\n".join(difflib.ndiff([str(x) for x in expected_events],
316 [str(x) for x in events])))
Tim Peters3de75262002-11-09 05:26:15 +0000317
Christian Heimes2202f872008-02-06 14:31:34 +0000318 def run_and_compare(self, func, events):
Nick Coghlan5a851672017-09-08 10:14:16 +1000319 tracer = self.make_tracer()
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000320 sys.settrace(tracer.trace)
321 func()
322 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000323 self.compare_events(func.__code__.co_firstlineno,
Christian Heimes2202f872008-02-06 14:31:34 +0000324 tracer.events, events)
325
326 def run_test(self, func):
327 self.run_and_compare(func, func.events)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000328
329 def run_test2(self, func):
Nick Coghlan5a851672017-09-08 10:14:16 +1000330 tracer = self.make_tracer()
Michael W. Hudson519a3422002-09-11 14:47:51 +0000331 func(tracer.trace)
332 sys.settrace(None)
Neal Norwitz221085d2007-02-25 20:55:47 +0000333 self.compare_events(func.__code__.co_firstlineno,
Michael W. Hudson519a3422002-09-11 14:47:51 +0000334 tracer.events, func.events)
Tim Peters3de75262002-11-09 05:26:15 +0000335
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200336 def test_set_and_retrieve_none(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000337 sys.settrace(None)
338 assert sys.gettrace() is None
339
Amaury Forgeot d'Arc3e961a52011-10-05 22:36:05 +0200340 def test_set_and_retrieve_func(self):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000341 def fn(*args):
342 pass
343
344 sys.settrace(fn)
345 try:
346 assert sys.gettrace() is fn
347 finally:
348 sys.settrace(None)
349
Nicholas Bastinaea94592004-03-22 18:30:42 +0000350 def test_01_basic(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000351 self.run_test(basic)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000352 def test_02_arigo(self):
353 self.run_test(arigo_example)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000354 def test_03_one_instr(self):
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000355 self.run_test(one_instr_line)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000356 def test_04_no_pop_blocks(self):
357 self.run_test(no_pop_blocks)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000358 def test_05_no_pop_tops(self):
359 self.run_test(no_pop_tops)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000360 def test_06_call(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000361 self.run_test(call)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000362 def test_07_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000363 self.run_test(test_raise)
364
Nicholas Bastinaea94592004-03-22 18:30:42 +0000365 def test_08_settrace_and_return(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000366 self.run_test2(settrace_and_return)
Nicholas Bastinaea94592004-03-22 18:30:42 +0000367 def test_09_settrace_and_raise(self):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000368 self.run_test2(settrace_and_raise)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000369 def test_10_ireturn(self):
370 self.run_test(ireturn_example)
Nicholas Bastinfa7bec72004-03-22 19:21:47 +0000371 def test_11_tightloop(self):
372 self.run_test(tightloop_example)
Armin Rigo70693382004-03-22 19:30:39 +0000373 def test_12_tighterloop(self):
374 self.run_test(tighterloop_example)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000375
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000376 def test_13_genexp(self):
377 self.run_test(generator_example)
378 # issue1265: if the trace function contains a generator,
379 # and if the traced function contains another generator
380 # that is not completely exhausted, the trace stopped.
381 # Worse: the 'finally' clause was not invoked.
Nick Coghlan5a851672017-09-08 10:14:16 +1000382 tracer = self.make_tracer()
Amaury Forgeot d'Arcf05149a2007-11-13 01:05:30 +0000383 sys.settrace(tracer.traceWithGenexp)
384 generator_example()
385 sys.settrace(None)
386 self.compare_events(generator_example.__code__.co_firstlineno,
387 tracer.events, generator_example.events)
388
Christian Heimes2202f872008-02-06 14:31:34 +0000389 def test_14_onliner_if(self):
390 def onliners():
Victor Stinner51d8c522016-02-08 17:57:02 +0100391 if True: x=False
392 else: x=True
Christian Heimes2202f872008-02-06 14:31:34 +0000393 return 0
394 self.run_and_compare(
395 onliners,
396 [(0, 'call'),
397 (1, 'line'),
398 (3, 'line'),
399 (3, 'return')])
400
401 def test_15_loops(self):
402 # issue1750076: "while" expression is skipped by debugger
403 def for_example():
404 for x in range(2):
405 pass
406 self.run_and_compare(
407 for_example,
408 [(0, 'call'),
409 (1, 'line'),
410 (2, 'line'),
411 (1, 'line'),
412 (2, 'line'),
413 (1, 'line'),
414 (1, 'return')])
415
416 def while_example():
417 # While expression should be traced on every loop
418 x = 2
419 while x > 0:
420 x -= 1
421 self.run_and_compare(
422 while_example,
423 [(0, 'call'),
424 (2, 'line'),
425 (3, 'line'),
426 (4, 'line'),
427 (3, 'line'),
428 (4, 'line'),
429 (3, 'line'),
430 (3, 'return')])
431
432 def test_16_blank_lines(self):
433 namespace = {}
434 exec("def f():\n" + "\n" * 256 + " pass", namespace)
435 self.run_and_compare(
436 namespace["f"],
437 [(0, 'call'),
438 (257, 'line'),
439 (257, 'return')])
440
Serhiy Storchaka64a263a2016-06-04 20:32:36 +0300441 def test_17_none_f_trace(self):
442 # Issue 20041: fix TypeError when f_trace is set to None.
443 def func():
444 sys._getframe().f_trace = None
445 lineno = 2
446 self.run_and_compare(func,
447 [(0, 'call'),
448 (1, 'line')])
449
Christian Heimes2202f872008-02-06 14:31:34 +0000450
Nick Coghlan5a851672017-09-08 10:14:16 +1000451class SkipLineEventsTraceTestCase(TraceTestCase):
452 """Repeat the trace tests, but with per-line events skipped"""
453
454 def compare_events(self, line_offset, events, expected_events):
455 skip_line_events = [e for e in expected_events if e[1] != 'line']
456 super().compare_events(line_offset, events, skip_line_events)
457
458 @staticmethod
459 def make_tracer():
460 return Tracer(trace_line_events=False)
461
462
463@support.cpython_only
464class TraceOpcodesTestCase(TraceTestCase):
465 """Repeat the trace tests, but with per-opcodes events enabled"""
466
467 def compare_events(self, line_offset, events, expected_events):
468 skip_opcode_events = [e for e in events if e[1] != 'opcode']
469 if len(events) > 1:
470 self.assertLess(len(skip_opcode_events), len(events),
471 msg="No 'opcode' events received by the tracer")
472 super().compare_events(line_offset, skip_opcode_events, expected_events)
473
474 @staticmethod
475 def make_tracer():
476 return Tracer(trace_opcode_events=True)
477
478
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000479class RaisingTraceFuncTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000480 def setUp(self):
481 self.addCleanup(sys.settrace, sys.gettrace())
482
Michael W. Hudson006c7522002-11-08 13:08:46 +0000483 def trace(self, frame, event, arg):
484 """A trace function that raises an exception in response to a
485 specific trace event."""
486 if event == self.raiseOnEvent:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000487 raise ValueError # just something that isn't RuntimeError
Michael W. Hudson006c7522002-11-08 13:08:46 +0000488 else:
489 return self.trace
Tim Peters3de75262002-11-09 05:26:15 +0000490
Michael W. Hudson006c7522002-11-08 13:08:46 +0000491 def f(self):
492 """The function to trace; raises an exception if that's the case
493 we're testing, so that the 'exception' trace event fires."""
494 if self.raiseOnEvent == 'exception':
495 x = 0
496 y = 1/x
497 else:
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000498 return 1
Tim Peters3de75262002-11-09 05:26:15 +0000499
Michael W. Hudson006c7522002-11-08 13:08:46 +0000500 def run_test_for_event(self, event):
501 """Tests that an exception raised in response to the given event is
502 handled OK."""
503 self.raiseOnEvent = event
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000504 try:
Guido van Rossum805365e2007-05-07 22:24:25 +0000505 for i in range(sys.getrecursionlimit() + 1):
Michael W. Hudson006c7522002-11-08 13:08:46 +0000506 sys.settrace(self.trace)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000507 try:
Michael W. Hudson006c7522002-11-08 13:08:46 +0000508 self.f()
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000509 except ValueError:
510 pass
511 else:
Andrew Svetlov737fb892012-12-18 21:14:22 +0200512 self.fail("exception not raised!")
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000513 except RuntimeError:
514 self.fail("recursion counter not reset")
Tim Peters3de75262002-11-09 05:26:15 +0000515
Michael W. Hudson006c7522002-11-08 13:08:46 +0000516 # Test the handling of exceptions raised by each kind of trace event.
517 def test_call(self):
518 self.run_test_for_event('call')
519 def test_line(self):
520 self.run_test_for_event('line')
521 def test_return(self):
522 self.run_test_for_event('return')
523 def test_exception(self):
524 self.run_test_for_event('exception')
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000525
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000526 def test_trash_stack(self):
527 def f():
528 for i in range(5):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000529 print(i) # line tracing will raise an exception at this line
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000530
531 def g(frame, why, extra):
532 if (why == 'line' and
Neal Norwitz221085d2007-02-25 20:55:47 +0000533 frame.f_lineno == f.__code__.co_firstlineno + 2):
Collin Winter3add4d72007-08-29 23:37:32 +0000534 raise RuntimeError("i am crashing")
Michael W. Hudson58ee2af2003-04-29 16:18:47 +0000535 return g
536
537 sys.settrace(g)
538 try:
539 f()
540 except RuntimeError:
541 # the test is really that this doesn't segfault:
542 import gc
543 gc.collect()
544 else:
545 self.fail("exception not propagated")
546
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000547
R David Murray35837612013-04-19 12:56:57 -0400548 def test_exception_arguments(self):
549 def f():
550 x = 0
551 # this should raise an error
552 x.no_such_attr
553 def g(frame, event, arg):
554 if (event == 'exception'):
555 type, exception, trace = arg
556 self.assertIsInstance(exception, Exception)
557 return g
558
559 existing = sys.gettrace()
560 try:
561 sys.settrace(g)
562 try:
563 f()
564 except AttributeError:
565 # this is expected
566 pass
567 finally:
568 sys.settrace(existing)
569
570
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000571# 'Jump' tests: assigning to frame.f_lineno within a trace function
572# moves the execution position - it's how debuggers implement a Jump
573# command (aka. "Set next statement").
574
575class JumpTracer:
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200576 """Defines a trace function that jumps from one place to another."""
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000577
xdegayeb8e9d6c2018-03-13 18:31:31 +0100578 def __init__(self, function, jumpFrom, jumpTo, event='line',
579 decorated=False):
580 self.code = function.__code__
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200581 self.jumpFrom = jumpFrom
582 self.jumpTo = jumpTo
xdegayeb8e9d6c2018-03-13 18:31:31 +0100583 self.event = event
584 self.firstLine = None if decorated else self.code.co_firstlineno
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000585 self.done = False
586
587 def trace(self, frame, event, arg):
xdegayeb8e9d6c2018-03-13 18:31:31 +0100588 if self.done:
589 return
590 # frame.f_code.co_firstlineno is the first line of the decorator when
591 # 'function' is decorated and the decorator may be written using
592 # multiple physical lines when it is too long. Use the first line
593 # trace event in 'function' to find the first line of 'function'.
594 if (self.firstLine is None and frame.f_code == self.code and
595 event == 'line'):
596 self.firstLine = frame.f_lineno - 1
597 if (event == self.event and self.firstLine and
598 frame.f_lineno == self.firstLine + self.jumpFrom):
599 f = frame
600 while f is not None and f.f_code != self.code:
601 f = f.f_back
602 if f is not None:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000603 # Cope with non-integer self.jumpTo (because of
604 # no_jump_to_non_integers below).
605 try:
xdegayeb8e9d6c2018-03-13 18:31:31 +0100606 frame.f_lineno = self.firstLine + self.jumpTo
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000607 except TypeError:
608 frame.f_lineno = self.jumpTo
609 self.done = True
610 return self.trace
611
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000612# This verifies the line-numbers-must-be-integers rule.
613def no_jump_to_non_integers(output):
614 try:
615 output.append(2)
Guido van Rossumb940e112007-01-10 16:19:56 +0000616 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000617 output.append('integer' in str(e))
618
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000619# This verifies that you can't set f_lineno via _getframe or similar
620# trickery.
621def no_jump_without_trace_function():
622 try:
623 previous_frame = sys._getframe().f_back
624 previous_frame.f_lineno = previous_frame.f_lineno
Guido van Rossumb940e112007-01-10 16:19:56 +0000625 except ValueError as e:
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000626 # This is the exception we wanted; make sure the error message
627 # talks about trace functions.
628 if 'trace' not in str(e):
629 raise
630 else:
631 # Something's wrong - the expected exception wasn't raised.
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200632 raise AssertionError("Trace-function-less jump failed to fail")
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000633
634
635class JumpTestCase(unittest.TestCase):
Brett Cannon31f59292011-02-21 19:29:56 +0000636 def setUp(self):
637 self.addCleanup(sys.settrace, sys.gettrace())
638 sys.settrace(None)
639
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000640 def compare_jump_output(self, expected, received):
641 if received != expected:
642 self.fail( "Outputs don't match:\n" +
643 "Expected: " + repr(expected) + "\n" +
644 "Received: " + repr(received))
645
xdegayeb8e9d6c2018-03-13 18:31:31 +0100646 def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
647 event='line', decorated=False):
648 tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000649 sys.settrace(tracer.trace)
650 output = []
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200651 if error is None:
652 func(output)
653 else:
654 with self.assertRaisesRegex(*error):
655 func(output)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000656 sys.settrace(None)
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200657 self.compare_jump_output(expected, output)
Michael W. Hudsoncfd38842002-12-17 16:15:34 +0000658
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200659 def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
660 event='line', decorated=False):
661 tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
662 sys.settrace(tracer.trace)
663 output = []
664 if error is None:
665 asyncio.run(func(output))
666 else:
667 with self.assertRaisesRegex(*error):
668 asyncio.run(func(output))
669 sys.settrace(None)
670 self.compare_jump_output(expected, output)
671
xdegayeb8e9d6c2018-03-13 18:31:31 +0100672 def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200673 """Decorator that creates a test that makes a jump
674 from one place to another in the following code.
675 """
676 def decorator(func):
677 @wraps(func)
678 def test(self):
xdegayeb8e9d6c2018-03-13 18:31:31 +0100679 self.run_test(func, jumpFrom, jumpTo, expected,
680 error=error, event=event, decorated=True)
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200681 return test
682 return decorator
683
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200684 def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
685 """Decorator that creates a test that makes a jump
686 from one place to another in the following asynchronous code.
687 """
688 def decorator(func):
689 @wraps(func)
690 def test(self):
691 self.run_async_test(func, jumpFrom, jumpTo, expected,
692 error=error, event=event, decorated=True)
693 return test
694 return decorator
695
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200696 ## The first set of 'jump' tests are for things that are allowed:
697
698 @jump_test(1, 3, [3])
699 def test_jump_simple_forwards(output):
700 output.append(1)
701 output.append(2)
702 output.append(3)
703
704 @jump_test(2, 1, [1, 1, 2])
705 def test_jump_simple_backwards(output):
706 output.append(1)
707 output.append(2)
708
709 @jump_test(3, 5, [2, 5])
710 def test_jump_out_of_block_forwards(output):
711 for i in 1, 2:
712 output.append(2)
713 for j in [3]: # Also tests jumping over a block
714 output.append(4)
715 output.append(5)
716
717 @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7])
718 def test_jump_out_of_block_backwards(output):
719 output.append(1)
720 for i in [1]:
721 output.append(3)
722 for j in [2]: # Also tests jumping over a block
723 output.append(5)
724 output.append(6)
725 output.append(7)
726
Serhiy Storchaka702f8f32018-03-23 14:34:35 +0200727 @async_jump_test(4, 5, [3, 5])
728 async def test_jump_out_of_async_for_block_forwards(output):
729 for i in [1]:
730 async for i in asynciter([1, 2]):
731 output.append(3)
732 output.append(4)
733 output.append(5)
734
735 @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6])
736 async def test_jump_out_of_async_for_block_backwards(output):
737 for i in [1]:
738 output.append(2)
739 async for i in asynciter([1]):
740 output.append(4)
741 output.append(5)
742 output.append(6)
743
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200744 @jump_test(1, 2, [3])
745 def test_jump_to_codeless_line(output):
746 output.append(1)
747 # Jumping to this line should skip to the next one.
748 output.append(3)
749
750 @jump_test(2, 2, [1, 2, 3])
751 def test_jump_to_same_line(output):
752 output.append(1)
753 output.append(2)
754 output.append(3)
755
756 # Tests jumping within a finally block, and over one.
757 @jump_test(4, 9, [2, 9])
758 def test_jump_in_nested_finally(output):
759 try:
760 output.append(2)
761 finally:
762 output.append(4)
763 try:
764 output.append(6)
765 finally:
766 output.append(8)
767 output.append(9)
768
769 @jump_test(6, 7, [2, 7], (ZeroDivisionError, ''))
770 def test_jump_in_nested_finally_2(output):
771 try:
772 output.append(2)
773 1/0
774 return
775 finally:
776 output.append(6)
777 output.append(7)
778 output.append(8)
779
780 @jump_test(6, 11, [2, 11], (ZeroDivisionError, ''))
781 def test_jump_in_nested_finally_3(output):
782 try:
783 output.append(2)
784 1/0
785 return
786 finally:
787 output.append(6)
788 try:
789 output.append(8)
790 finally:
791 output.append(10)
792 output.append(11)
793 output.append(12)
794
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200795 @jump_test(5, 11, [2, 4, 12])
796 def test_jump_over_return_try_finally_in_finally_block(output):
797 try:
798 output.append(2)
799 finally:
800 output.append(4)
801 output.append(5)
802 return
803 try:
804 output.append(8)
805 finally:
806 output.append(10)
807 pass
808 output.append(12)
809
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200810 @jump_test(3, 4, [1, 4])
811 def test_jump_infinite_while_loop(output):
812 output.append(1)
813 while True:
814 output.append(3)
815 output.append(4)
816
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200817 @jump_test(2, 4, [4, 4])
818 def test_jump_forwards_into_while_block(output):
819 i = 1
820 output.append(2)
821 while i <= 2:
822 output.append(4)
823 i += 1
824
825 @jump_test(5, 3, [3, 3, 3, 5])
826 def test_jump_backwards_into_while_block(output):
827 i = 1
828 while i <= 2:
829 output.append(3)
830 i += 1
831 output.append(5)
832
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200833 @jump_test(2, 3, [1, 3])
834 def test_jump_forwards_out_of_with_block(output):
835 with tracecontext(output, 1):
836 output.append(2)
837 output.append(3)
838
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200839 @async_jump_test(2, 3, [1, 3])
840 async def test_jump_forwards_out_of_async_with_block(output):
841 async with asynctracecontext(output, 1):
842 output.append(2)
843 output.append(3)
844
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200845 @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
846 def test_jump_backwards_out_of_with_block(output):
847 output.append(1)
848 with tracecontext(output, 2):
849 output.append(3)
850
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200851 @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
852 async def test_jump_backwards_out_of_async_with_block(output):
853 output.append(1)
854 async with asynctracecontext(output, 2):
855 output.append(3)
856
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200857 @jump_test(2, 5, [5])
858 def test_jump_forwards_out_of_try_finally_block(output):
859 try:
860 output.append(2)
861 finally:
862 output.append(4)
863 output.append(5)
864
865 @jump_test(3, 1, [1, 1, 3, 5])
866 def test_jump_backwards_out_of_try_finally_block(output):
867 output.append(1)
868 try:
869 output.append(3)
870 finally:
871 output.append(5)
872
873 @jump_test(2, 6, [6])
874 def test_jump_forwards_out_of_try_except_block(output):
875 try:
876 output.append(2)
877 except:
878 output.append(4)
879 raise
880 output.append(6)
881
882 @jump_test(3, 1, [1, 1, 3])
883 def test_jump_backwards_out_of_try_except_block(output):
884 output.append(1)
885 try:
886 output.append(3)
887 except:
888 output.append(5)
889 raise
890
891 @jump_test(5, 7, [4, 7, 8])
892 def test_jump_between_except_blocks(output):
893 try:
894 1/0
895 except ZeroDivisionError:
896 output.append(4)
897 output.append(5)
898 except FloatingPointError:
899 output.append(7)
900 output.append(8)
901
902 @jump_test(5, 6, [4, 6, 7])
903 def test_jump_within_except_block(output):
904 try:
905 1/0
906 except:
907 output.append(4)
908 output.append(5)
909 output.append(6)
910 output.append(7)
911
Serhiy Storchakae8ed9652018-01-01 19:39:38 +0200912 @jump_test(2, 4, [1, 4, 5, -4])
913 def test_jump_across_with(output):
914 output.append(1)
915 with tracecontext(output, 2):
916 output.append(3)
917 with tracecontext(output, 4):
918 output.append(5)
919
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200920 @async_jump_test(2, 4, [1, 4, 5, -4])
921 async def test_jump_across_async_with(output):
922 output.append(1)
923 async with asynctracecontext(output, 2):
924 output.append(3)
925 async with asynctracecontext(output, 4):
926 output.append(5)
927
Serhiy Storchaka26c9f562018-03-11 08:32:47 +0200928 @jump_test(4, 5, [1, 3, 5, 6])
929 def test_jump_out_of_with_block_within_for_block(output):
930 output.append(1)
931 for i in [1]:
932 with tracecontext(output, 3):
933 output.append(4)
934 output.append(5)
935 output.append(6)
936
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200937 @async_jump_test(4, 5, [1, 3, 5, 6])
938 async def test_jump_out_of_async_with_block_within_for_block(output):
939 output.append(1)
940 for i in [1]:
941 async with asynctracecontext(output, 3):
942 output.append(4)
943 output.append(5)
944 output.append(6)
945
Serhiy Storchaka26c9f562018-03-11 08:32:47 +0200946 @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
947 def test_jump_out_of_with_block_within_with_block(output):
948 output.append(1)
949 with tracecontext(output, 2):
950 with tracecontext(output, 3):
951 output.append(4)
952 output.append(5)
953 output.append(6)
954
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200955 @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
956 async def test_jump_out_of_async_with_block_within_with_block(output):
957 output.append(1)
958 with tracecontext(output, 2):
959 async with asynctracecontext(output, 3):
960 output.append(4)
961 output.append(5)
962 output.append(6)
963
Serhiy Storchaka26c9f562018-03-11 08:32:47 +0200964 @jump_test(5, 6, [2, 4, 6, 7])
965 def test_jump_out_of_with_block_within_finally_block(output):
966 try:
967 output.append(2)
968 finally:
969 with tracecontext(output, 4):
970 output.append(5)
971 output.append(6)
972 output.append(7)
973
Serhiy Storchakabc300ce2018-03-18 09:53:08 +0200974 @async_jump_test(5, 6, [2, 4, 6, 7])
975 async def test_jump_out_of_async_with_block_within_finally_block(output):
976 try:
977 output.append(2)
978 finally:
979 async with asynctracecontext(output, 4):
980 output.append(5)
981 output.append(6)
982 output.append(7)
983
Serhiy Storchaka53f91352017-12-27 00:38:56 +0200984 @jump_test(8, 11, [1, 3, 5, 11, 12])
985 def test_jump_out_of_complex_nested_blocks(output):
986 output.append(1)
987 for i in [1]:
988 output.append(3)
989 for j in [1, 2]:
990 output.append(5)
991 try:
992 for k in [1, 2]:
993 output.append(8)
994 finally:
995 output.append(10)
996 output.append(11)
997 output.append(12)
998
999 @jump_test(3, 5, [1, 2, 5])
1000 def test_jump_out_of_with_assignment(output):
1001 output.append(1)
1002 with tracecontext(output, 2) \
1003 as x:
1004 output.append(4)
1005 output.append(5)
1006
Serhiy Storchakabc300ce2018-03-18 09:53:08 +02001007 @async_jump_test(3, 5, [1, 2, 5])
1008 async def test_jump_out_of_async_with_assignment(output):
1009 output.append(1)
1010 async with asynctracecontext(output, 2) \
1011 as x:
1012 output.append(4)
1013 output.append(5)
1014
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001015 @jump_test(3, 6, [1, 6, 8, 9])
1016 def test_jump_over_return_in_try_finally_block(output):
1017 output.append(1)
1018 try:
1019 output.append(3)
1020 if not output: # always false
1021 return
1022 output.append(6)
1023 finally:
1024 output.append(8)
1025 output.append(9)
1026
1027 @jump_test(5, 8, [1, 3, 8, 10, 11, 13])
1028 def test_jump_over_break_in_try_finally_block(output):
1029 output.append(1)
1030 while True:
1031 output.append(3)
1032 try:
1033 output.append(5)
1034 if not output: # always false
1035 break
1036 output.append(8)
1037 finally:
1038 output.append(10)
1039 output.append(11)
1040 break
1041 output.append(13)
1042
Serhiy Storchakae8ed9652018-01-01 19:39:38 +02001043 @jump_test(1, 7, [7, 8])
1044 def test_jump_over_for_block_before_else(output):
1045 output.append(1)
1046 if not output: # always false
1047 for i in [3]:
1048 output.append(4)
1049 else:
1050 output.append(6)
1051 output.append(7)
1052 output.append(8)
1053
Serhiy Storchaka702f8f32018-03-23 14:34:35 +02001054 @async_jump_test(1, 7, [7, 8])
1055 async def test_jump_over_async_for_block_before_else(output):
1056 output.append(1)
1057 if not output: # always false
1058 async for i in asynciter([3]):
1059 output.append(4)
1060 else:
1061 output.append(6)
1062 output.append(7)
1063 output.append(8)
1064
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001065 # The second set of 'jump' tests are for things that are not allowed:
1066
1067 @jump_test(2, 3, [1], (ValueError, 'after'))
1068 def test_no_jump_too_far_forwards(output):
1069 output.append(1)
1070 output.append(2)
1071
1072 @jump_test(2, -2, [1], (ValueError, 'before'))
1073 def test_no_jump_too_far_backwards(output):
1074 output.append(1)
1075 output.append(2)
1076
1077 # Test each kind of 'except' line.
1078 @jump_test(2, 3, [4], (ValueError, 'except'))
1079 def test_no_jump_to_except_1(output):
1080 try:
1081 output.append(2)
1082 except:
1083 output.append(4)
1084 raise
1085
1086 @jump_test(2, 3, [4], (ValueError, 'except'))
1087 def test_no_jump_to_except_2(output):
1088 try:
1089 output.append(2)
1090 except ValueError:
1091 output.append(4)
1092 raise
1093
1094 @jump_test(2, 3, [4], (ValueError, 'except'))
1095 def test_no_jump_to_except_3(output):
1096 try:
1097 output.append(2)
1098 except ValueError as e:
1099 output.append(4)
1100 raise e
1101
1102 @jump_test(2, 3, [4], (ValueError, 'except'))
1103 def test_no_jump_to_except_4(output):
1104 try:
1105 output.append(2)
1106 except (ValueError, RuntimeError) as e:
1107 output.append(4)
1108 raise e
1109
1110 @jump_test(1, 3, [], (ValueError, 'into'))
1111 def test_no_jump_forwards_into_for_block(output):
1112 output.append(1)
1113 for i in 1, 2:
1114 output.append(3)
1115
Serhiy Storchaka702f8f32018-03-23 14:34:35 +02001116 @async_jump_test(1, 3, [], (ValueError, 'into'))
1117 async def test_no_jump_forwards_into_async_for_block(output):
1118 output.append(1)
1119 async for i in asynciter([1, 2]):
1120 output.append(3)
1121
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001122 @jump_test(3, 2, [2, 2], (ValueError, 'into'))
1123 def test_no_jump_backwards_into_for_block(output):
1124 for i in 1, 2:
1125 output.append(2)
1126 output.append(3)
1127
Serhiy Storchaka702f8f32018-03-23 14:34:35 +02001128 @async_jump_test(3, 2, [2, 2], (ValueError, 'into'))
1129 async def test_no_jump_backwards_into_async_for_block(output):
1130 async for i in asynciter([1, 2]):
1131 output.append(2)
1132 output.append(3)
1133
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001134 @jump_test(1, 3, [], (ValueError, 'into'))
1135 def test_no_jump_forwards_into_with_block(output):
1136 output.append(1)
1137 with tracecontext(output, 2):
1138 output.append(3)
1139
Serhiy Storchakabc300ce2018-03-18 09:53:08 +02001140 @async_jump_test(1, 3, [], (ValueError, 'into'))
1141 async def test_no_jump_forwards_into_async_with_block(output):
1142 output.append(1)
1143 async with asynctracecontext(output, 2):
1144 output.append(3)
1145
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001146 @jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1147 def test_no_jump_backwards_into_with_block(output):
1148 with tracecontext(output, 1):
1149 output.append(2)
1150 output.append(3)
1151
Serhiy Storchakabc300ce2018-03-18 09:53:08 +02001152 @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1153 async def test_no_jump_backwards_into_async_with_block(output):
1154 async with asynctracecontext(output, 1):
1155 output.append(2)
1156 output.append(3)
1157
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001158 @jump_test(1, 3, [], (ValueError, 'into'))
1159 def test_no_jump_forwards_into_try_finally_block(output):
1160 output.append(1)
1161 try:
1162 output.append(3)
1163 finally:
1164 output.append(5)
1165
1166 @jump_test(5, 2, [2, 4], (ValueError, 'into'))
1167 def test_no_jump_backwards_into_try_finally_block(output):
1168 try:
1169 output.append(2)
1170 finally:
1171 output.append(4)
1172 output.append(5)
1173
1174 @jump_test(1, 3, [], (ValueError, 'into'))
1175 def test_no_jump_forwards_into_try_except_block(output):
1176 output.append(1)
1177 try:
1178 output.append(3)
1179 except:
1180 output.append(5)
1181 raise
1182
1183 @jump_test(6, 2, [2], (ValueError, 'into'))
1184 def test_no_jump_backwards_into_try_except_block(output):
1185 try:
1186 output.append(2)
1187 except:
1188 output.append(4)
1189 raise
1190 output.append(6)
1191
1192 # 'except' with a variable creates an implicit finally block
1193 @jump_test(5, 7, [4], (ValueError, 'into'))
1194 def test_no_jump_between_except_blocks_2(output):
1195 try:
1196 1/0
1197 except ZeroDivisionError:
1198 output.append(4)
1199 output.append(5)
1200 except FloatingPointError as e:
1201 output.append(7)
1202 output.append(8)
1203
1204 @jump_test(3, 6, [2, 5, 6], (ValueError, 'finally'))
1205 def test_no_jump_into_finally_block(output):
1206 try:
1207 output.append(2)
1208 output.append(3)
1209 finally: # still executed if the jump is failed
1210 output.append(5)
1211 output.append(6)
1212 output.append(7)
1213
1214 @jump_test(1, 5, [], (ValueError, 'finally'))
1215 def test_no_jump_into_finally_block_2(output):
1216 output.append(1)
1217 try:
1218 output.append(3)
1219 finally:
1220 output.append(5)
1221
1222 @jump_test(5, 1, [1, 3], (ValueError, 'finally'))
1223 def test_no_jump_out_of_finally_block(output):
1224 output.append(1)
1225 try:
1226 output.append(3)
1227 finally:
1228 output.append(5)
1229
Serhiy Storchakae8ed9652018-01-01 19:39:38 +02001230 @jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
1231 def test_no_jump_between_with_blocks(output):
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001232 output.append(1)
1233 with tracecontext(output, 2):
1234 output.append(3)
1235 with tracecontext(output, 4):
1236 output.append(5)
1237
Serhiy Storchakabc300ce2018-03-18 09:53:08 +02001238 @async_jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
1239 async def test_no_jump_between_async_with_blocks(output):
1240 output.append(1)
1241 async with asynctracecontext(output, 2):
1242 output.append(3)
1243 async with asynctracecontext(output, 4):
1244 output.append(5)
1245
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +02001246 @jump_test(5, 7, [2, 4], (ValueError, 'finally'))
1247 def test_no_jump_over_return_out_of_finally_block(output):
1248 try:
1249 output.append(2)
1250 finally:
1251 output.append(4)
1252 output.append(5)
1253 return
1254 output.append(7)
1255
Serhiy Storchakae8ed9652018-01-01 19:39:38 +02001256 @jump_test(7, 4, [1, 6], (ValueError, 'into'))
1257 def test_no_jump_into_for_block_before_else(output):
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001258 output.append(1)
Serhiy Storchakae8ed9652018-01-01 19:39:38 +02001259 if not output: # always false
1260 for i in [3]:
1261 output.append(4)
1262 else:
1263 output.append(6)
1264 output.append(7)
1265 output.append(8)
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001266
Serhiy Storchaka702f8f32018-03-23 14:34:35 +02001267 @async_jump_test(7, 4, [1, 6], (ValueError, 'into'))
1268 async def test_no_jump_into_async_for_block_before_else(output):
1269 output.append(1)
1270 if not output: # always false
1271 async for i in asynciter([3]):
1272 output.append(4)
1273 else:
1274 output.append(6)
1275 output.append(7)
1276 output.append(8)
1277
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001278 def test_no_jump_to_non_integers(self):
1279 self.run_test(no_jump_to_non_integers, 2, "Spam", [True])
1280
1281 def test_no_jump_without_trace_function(self):
Brett Cannon31f59292011-02-21 19:29:56 +00001282 # Must set sys.settrace(None) in setUp(), else condition is not
1283 # triggered.
Michael W. Hudsoncfd38842002-12-17 16:15:34 +00001284 no_jump_without_trace_function()
1285
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001286 def test_large_function(self):
Amaury Forgeot d'Arc24e581f2009-06-01 21:28:37 +00001287 d = {}
1288 exec("""def f(output): # line 0
1289 x = 0 # line 1
1290 y = 1 # line 2
1291 ''' # line 3
1292 %s # lines 4-1004
1293 ''' # line 1005
1294 x += 1 # line 1006
1295 output.append(x) # line 1007
1296 return""" % ('\n' * 1000,), d)
1297 f = d['f']
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001298 self.run_test(f, 2, 1007, [0])
Amaury Forgeot d'Arc24e581f2009-06-01 21:28:37 +00001299
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +00001300 def test_jump_to_firstlineno(self):
1301 # This tests that PDB can jump back to the first line in a
1302 # file. See issue #1689458. It can only be triggered in a
1303 # function call if the function is defined on a single line.
1304 code = compile("""
1305# Comments don't count.
1306output.append(2) # firstlineno is here.
1307output.append(3)
1308output.append(4)
1309""", "<fake module>", "exec")
1310 class fake_function:
1311 __code__ = code
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001312 tracer = JumpTracer(fake_function, 2, 0)
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +00001313 sys.settrace(tracer.trace)
1314 namespace = {"output": []}
1315 exec(code, namespace)
1316 sys.settrace(None)
1317 self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
1318
xdegayeb8e9d6c2018-03-13 18:31:31 +01001319 @jump_test(2, 3, [1], event='call', error=(ValueError, "can't jump from"
1320 " the 'call' trace event of a new frame"))
1321 def test_no_jump_from_call(output):
1322 output.append(1)
1323 def nested():
1324 output.append(3)
1325 nested()
1326 output.append(5)
1327
1328 @jump_test(2, 1, [1], event='return', error=(ValueError,
1329 "can only jump from a 'line' trace event"))
1330 def test_no_jump_from_return_event(output):
1331 output.append(1)
1332 return
1333
1334 @jump_test(2, 1, [1], event='exception', error=(ValueError,
1335 "can only jump from a 'line' trace event"))
1336 def test_no_jump_from_exception_event(output):
1337 output.append(1)
1338 1 / 0
1339
1340 @jump_test(3, 2, [2], event='return', error=(ValueError,
1341 "can't jump from a yield statement"))
1342 def test_no_jump_from_yield(output):
1343 def gen():
1344 output.append(2)
1345 yield 3
1346 next(gen())
1347 output.append(5)
1348
Jeffrey Yasskin4db6ff62009-05-20 19:09:05 +00001349
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00001350if __name__ == "__main__":
Serhiy Storchaka53f91352017-12-27 00:38:56 +02001351 unittest.main()