1# Testing the line trace facility.
2
3from test import support
4import unittest
5from unittest.mock import MagicMock
6import sys
7import difflib
8import gc
9from functools import wraps
10import asyncio
11from test.support import import_helper
12
13support.requires_working_socket(module=True)
14
15class tracecontext:
16    """Context manager that traces its enter and exit."""
17    def __init__(self, output, value):
18        self.output = output
19        self.value = value
20
21    def __enter__(self):
22        self.output.append(self.value)
23
24    def __exit__(self, *exc_info):
25        self.output.append(-self.value)
26
27class asynctracecontext:
28    """Asynchronous context manager that traces its aenter and aexit."""
29    def __init__(self, output, value):
30        self.output = output
31        self.value = value
32
33    async def __aenter__(self):
34        self.output.append(self.value)
35
36    async def __aexit__(self, *exc_info):
37        self.output.append(-self.value)
38
39async def asynciter(iterable):
40    """Convert an iterable to an asynchronous iterator."""
41    for x in iterable:
42        yield x
43
44
45# A very basic example.  If this fails, we're in deep trouble.
46def basic():
47    return 1
48
49basic.events = [(0, 'call'),
50                (1, 'line'),
51                (1, 'return')]
52
53# Many of the tests below are tricky because they involve pass statements.
54# If there is implicit control flow around a pass statement (in an except
55# clause or else clause) under what conditions do you set a line number
56# following that clause?
57
58
59# Some constructs like "while 0:", "if 0:" or "if 1:...else:..." could be optimized
60# away.  Make sure that those lines aren't skipped.
61def arigo_example0():
62    x = 1
63    del x
64    while 0:
65        pass
66    x = 1
67
68arigo_example0.events = [(0, 'call'),
69                        (1, 'line'),
70                        (2, 'line'),
71                        (3, 'line'),
72                        (5, 'line'),
73                        (5, 'return')]
74
75def arigo_example1():
76    x = 1
77    del x
78    if 0:
79        pass
80    x = 1
81
82arigo_example1.events = [(0, 'call'),
83                        (1, 'line'),
84                        (2, 'line'),
85                        (3, 'line'),
86                        (5, 'line'),
87                        (5, 'return')]
88
89def arigo_example2():
90    x = 1
91    del x
92    if 1:
93        x = 1
94    else:
95        pass
96    return None
97
98arigo_example2.events = [(0, 'call'),
99                        (1, 'line'),
100                        (2, 'line'),
101                        (3, 'line'),
102                        (4, 'line'),
103                        (7, 'line'),
104                        (7, 'return')]
105
106
107# check that lines consisting of just one instruction get traced:
108def one_instr_line():
109    x = 1
110    del x
111    x = 1
112
113one_instr_line.events = [(0, 'call'),
114                         (1, 'line'),
115                         (2, 'line'),
116                         (3, 'line'),
117                         (3, 'return')]
118
119def no_pop_tops():      # 0
120    x = 1               # 1
121    for a in range(2):  # 2
122        if a:           # 3
123            x = 1       # 4
124        else:           # 5
125            x = 1       # 6
126
127no_pop_tops.events = [(0, 'call'),
128                      (1, 'line'),
129                      (2, 'line'),
130                      (3, 'line'),
131                      (6, 'line'),
132                      (2, 'line'),
133                      (3, 'line'),
134                      (4, 'line'),
135                      (2, 'line'),
136                      (2, 'return')]
137
138def no_pop_blocks():
139    y = 1
140    while not y:
141        bla
142    x = 1
143
144no_pop_blocks.events = [(0, 'call'),
145                        (1, 'line'),
146                        (2, 'line'),
147                        (4, 'line'),
148                        (4, 'return')]
149
150def called(): # line -3
151    x = 1
152
153def call():   # line 0
154    called()
155
156call.events = [(0, 'call'),
157               (1, 'line'),
158               (-3, 'call'),
159               (-2, 'line'),
160               (-2, 'return'),
161               (1, 'return')]
162
163def raises():
164    raise Exception
165
166def test_raise():
167    try:
168        raises()
169    except Exception:
170        pass
171
172test_raise.events = [(0, 'call'),
173                     (1, 'line'),
174                     (2, 'line'),
175                     (-3, 'call'),
176                     (-2, 'line'),
177                     (-2, 'exception'),
178                     (-2, 'return'),
179                     (2, 'exception'),
180                     (3, 'line'),
181                     (4, 'line'),
182                     (4, 'return')]
183
184def _settrace_and_return(tracefunc):
185    sys.settrace(tracefunc)
186    sys._getframe().f_back.f_trace = tracefunc
187def settrace_and_return(tracefunc):
188    _settrace_and_return(tracefunc)
189
190settrace_and_return.events = [(1, 'return')]
191
192def _settrace_and_raise(tracefunc):
193    sys.settrace(tracefunc)
194    sys._getframe().f_back.f_trace = tracefunc
195    raise RuntimeError
196def settrace_and_raise(tracefunc):
197    try:
198        _settrace_and_raise(tracefunc)
199    except RuntimeError:
200        pass
201
202settrace_and_raise.events = [(2, 'exception'),
203                             (3, 'line'),
204                             (4, 'line'),
205                             (4, 'return')]
206
207# implicit return example
208# This test is interesting because of the else: pass
209# part of the code.  The code generate for the true
210# part of the if contains a jump past the else branch.
211# The compiler then generates an implicit "return None"
212# Internally, the compiler visits the pass statement
213# and stores its line number for use on the next instruction.
214# The next instruction is the implicit return None.
215def ireturn_example():
216    a = 5
217    b = 5
218    if a == b:
219        b = a+1
220    else:
221        pass
222
223ireturn_example.events = [(0, 'call'),
224                          (1, 'line'),
225                          (2, 'line'),
226                          (3, 'line'),
227                          (4, 'line'),
228                          (4, 'return')]
229
230# Tight loop with while(1) example (SF #765624)
231def tightloop_example():
232    items = range(0, 3)
233    try:
234        i = 0
235        while 1:
236            b = items[i]; i+=1
237    except IndexError:
238        pass
239
240tightloop_example.events = [(0, 'call'),
241                            (1, 'line'),
242                            (2, 'line'),
243                            (3, 'line'),
244                            (4, 'line'),
245                            (5, 'line'),
246                            (4, 'line'),
247                            (5, 'line'),
248                            (4, 'line'),
249                            (5, 'line'),
250                            (4, 'line'),
251                            (5, 'line'),
252                            (5, 'exception'),
253                            (6, 'line'),
254                            (7, 'line'),
255                            (7, 'return')]
256
257def tighterloop_example():
258    items = range(1, 4)
259    try:
260        i = 0
261        while 1: i = items[i]
262    except IndexError:
263        pass
264
265tighterloop_example.events = [(0, 'call'),
266                            (1, 'line'),
267                            (2, 'line'),
268                            (3, 'line'),
269                            (4, 'line'),
270                            (4, 'line'),
271                            (4, 'line'),
272                            (4, 'line'),
273                            (4, 'exception'),
274                            (5, 'line'),
275                            (6, 'line'),
276                            (6, 'return')]
277
278def generator_function():
279    try:
280        yield True
281        "continued"
282    finally:
283        "finally"
284def generator_example():
285    # any() will leave the generator before its end
286    x = any(generator_function())
287
288    # the following lines were not traced
289    for x in range(10):
290        y = x
291
292generator_example.events = ([(0, 'call'),
293                             (2, 'line'),
294                             (-6, 'call'),
295                             (-5, 'line'),
296                             (-4, 'line'),
297                             (-4, 'return'),
298                             (-4, 'call'),
299                             (-4, 'exception'),
300                             (-1, 'line'),
301                             (-1, 'return')] +
302                            [(5, 'line'), (6, 'line')] * 10 +
303                            [(5, 'line'), (5, 'return')])
304
305
306class Tracer:
307    def __init__(self, trace_line_events=None, trace_opcode_events=None):
308        self.trace_line_events = trace_line_events
309        self.trace_opcode_events = trace_opcode_events
310        self.events = []
311
312    def _reconfigure_frame(self, frame):
313        if self.trace_line_events is not None:
314            frame.f_trace_lines = self.trace_line_events
315        if self.trace_opcode_events is not None:
316            frame.f_trace_opcodes = self.trace_opcode_events
317
318    def trace(self, frame, event, arg):
319        self._reconfigure_frame(frame)
320        self.events.append((frame.f_lineno, event))
321        return self.trace
322
323    def traceWithGenexp(self, frame, event, arg):
324        self._reconfigure_frame(frame)
325        (o for o in [1])
326        self.events.append((frame.f_lineno, event))
327        return self.trace
328
329
330class TraceTestCase(unittest.TestCase):
331
332    # Disable gc collection when tracing, otherwise the
333    # deallocators may be traced as well.
334    def setUp(self):
335        self.using_gc = gc.isenabled()
336        gc.disable()
337        self.addCleanup(sys.settrace, sys.gettrace())
338
339    def tearDown(self):
340        if self.using_gc:
341            gc.enable()
342
343    @staticmethod
344    def make_tracer():
345        """Helper to allow test subclasses to configure tracers differently"""
346        return Tracer()
347
348    def compare_events(self, line_offset, events, expected_events):
349        events = [(l - line_offset, e) for (l, e) in events]
350        if events != expected_events:
351            self.fail(
352                "events did not match expectation:\n" +
353                "\n".join(difflib.ndiff([str(x) for x in expected_events],
354                                        [str(x) for x in events])))
355
356    def run_and_compare(self, func, events):
357        tracer = self.make_tracer()
358        sys.settrace(tracer.trace)
359        func()
360        sys.settrace(None)
361        self.compare_events(func.__code__.co_firstlineno,
362                            tracer.events, events)
363
364    def run_test(self, func):
365        self.run_and_compare(func, func.events)
366
367    def run_test2(self, func):
368        tracer = self.make_tracer()
369        func(tracer.trace)
370        sys.settrace(None)
371        self.compare_events(func.__code__.co_firstlineno,
372                            tracer.events, func.events)
373
374    def test_set_and_retrieve_none(self):
375        sys.settrace(None)
376        assert sys.gettrace() is None
377
378    def test_set_and_retrieve_func(self):
379        def fn(*args):
380            pass
381
382        sys.settrace(fn)
383        try:
384            assert sys.gettrace() is fn
385        finally:
386            sys.settrace(None)
387
388    def test_01_basic(self):
389        self.run_test(basic)
390    def test_02_arigo0(self):
391        self.run_test(arigo_example0)
392    def test_02_arigo1(self):
393        self.run_test(arigo_example1)
394    def test_02_arigo2(self):
395        self.run_test(arigo_example2)
396    def test_03_one_instr(self):
397        self.run_test(one_instr_line)
398    def test_04_no_pop_blocks(self):
399        self.run_test(no_pop_blocks)
400    def test_05_no_pop_tops(self):
401        self.run_test(no_pop_tops)
402    def test_06_call(self):
403        self.run_test(call)
404    def test_07_raise(self):
405        self.run_test(test_raise)
406
407    def test_08_settrace_and_return(self):
408        self.run_test2(settrace_and_return)
409    def test_09_settrace_and_raise(self):
410        self.run_test2(settrace_and_raise)
411    def test_10_ireturn(self):
412        self.run_test(ireturn_example)
413    def test_11_tightloop(self):
414        self.run_test(tightloop_example)
415    def test_12_tighterloop(self):
416        self.run_test(tighterloop_example)
417
418    def test_13_genexp(self):
419        self.run_test(generator_example)
420        # issue1265: if the trace function contains a generator,
421        # and if the traced function contains another generator
422        # that is not completely exhausted, the trace stopped.
423        # Worse: the 'finally' clause was not invoked.
424        tracer = self.make_tracer()
425        sys.settrace(tracer.traceWithGenexp)
426        generator_example()
427        sys.settrace(None)
428        self.compare_events(generator_example.__code__.co_firstlineno,
429                            tracer.events, generator_example.events)
430
431    def test_14_onliner_if(self):
432        def onliners():
433            if True: x=False
434            else: x=True
435            return 0
436        self.run_and_compare(
437            onliners,
438            [(0, 'call'),
439             (1, 'line'),
440             (3, 'line'),
441             (3, 'return')])
442
443    def test_15_loops(self):
444        # issue1750076: "while" expression is skipped by debugger
445        def for_example():
446            for x in range(2):
447                pass
448        self.run_and_compare(
449            for_example,
450            [(0, 'call'),
451             (1, 'line'),
452             (2, 'line'),
453             (1, 'line'),
454             (2, 'line'),
455             (1, 'line'),
456             (1, 'return')])
457
458        def while_example():
459            # While expression should be traced on every loop
460            x = 2
461            while x > 0:
462                x -= 1
463        self.run_and_compare(
464            while_example,
465            [(0, 'call'),
466             (2, 'line'),
467             (3, 'line'),
468             (4, 'line'),
469             (3, 'line'),
470             (4, 'line'),
471             (3, 'line'),
472             (3, 'return')])
473
474    def test_16_blank_lines(self):
475        namespace = {}
476        exec("def f():\n" + "\n" * 256 + "    pass", namespace)
477        self.run_and_compare(
478            namespace["f"],
479            [(0, 'call'),
480             (257, 'line'),
481             (257, 'return')])
482
483    def test_17_none_f_trace(self):
484        # Issue 20041: fix TypeError when f_trace is set to None.
485        def func():
486            sys._getframe().f_trace = None
487            lineno = 2
488        self.run_and_compare(func,
489            [(0, 'call'),
490             (1, 'line')])
491
492    def test_18_except_with_name(self):
493        def func():
494            try:
495                try:
496                    raise Exception
497                except Exception as e:
498                    raise
499                    x = "Something"
500                    y = "Something"
501            except Exception:
502                pass
503
504        self.run_and_compare(func,
505            [(0, 'call'),
506             (1, 'line'),
507             (2, 'line'),
508             (3, 'line'),
509             (3, 'exception'),
510             (4, 'line'),
511             (5, 'line'),
512             (8, 'line'),
513             (9, 'line'),
514             (9, 'return')])
515
516    def test_19_except_with_finally(self):
517        def func():
518            try:
519                try:
520                    raise Exception
521                finally:
522                    y = "Something"
523            except Exception:
524                b = 23
525
526        self.run_and_compare(func,
527            [(0, 'call'),
528             (1, 'line'),
529             (2, 'line'),
530             (3, 'line'),
531             (3, 'exception'),
532             (5, 'line'),
533             (6, 'line'),
534             (7, 'line'),
535             (7, 'return')])
536
537    def test_20_async_for_loop(self):
538        class AsyncIteratorWrapper:
539            def __init__(self, obj):
540                self._it = iter(obj)
541
542            def __aiter__(self):
543                return self
544
545            async def __anext__(self):
546                try:
547                    return next(self._it)
548                except StopIteration:
549                    raise StopAsyncIteration
550
551        async def doit_async():
552            async for letter in AsyncIteratorWrapper("abc"):
553                x = letter
554            y = 42
555
556        def run(tracer):
557            x = doit_async()
558            try:
559                sys.settrace(tracer)
560                x.send(None)
561            finally:
562                sys.settrace(None)
563
564        tracer = self.make_tracer()
565        events = [
566                (0, 'call'),
567                (1, 'line'),
568                (-12, 'call'),
569                (-11, 'line'),
570                (-11, 'return'),
571                (-9, 'call'),
572                (-8, 'line'),
573                (-8, 'return'),
574                (-6, 'call'),
575                (-5, 'line'),
576                (-4, 'line'),
577                (-4, 'return'),
578                (1, 'exception'),
579                (2, 'line'),
580                (1, 'line'),
581                (-6, 'call'),
582                (-5, 'line'),
583                (-4, 'line'),
584                (-4, 'return'),
585                (1, 'exception'),
586                (2, 'line'),
587                (1, 'line'),
588                (-6, 'call'),
589                (-5, 'line'),
590                (-4, 'line'),
591                (-4, 'return'),
592                (1, 'exception'),
593                (2, 'line'),
594                (1, 'line'),
595                (-6, 'call'),
596                (-5, 'line'),
597                (-4, 'line'),
598                (-4, 'exception'),
599                (-3, 'line'),
600                (-2, 'line'),
601                (-2, 'exception'),
602                (-2, 'return'),
603                (1, 'exception'),
604                (3, 'line'),
605                (3, 'return')]
606        try:
607            run(tracer.trace)
608        except Exception:
609            pass
610        self.compare_events(doit_async.__code__.co_firstlineno,
611                            tracer.events, events)
612
613    def test_async_for_backwards_jump_has_no_line(self):
614        async def arange(n):
615            for i in range(n):
616                yield i
617        async def f():
618            async for i in arange(3):
619                if i > 100:
620                    break # should never be traced
621
622        tracer = self.make_tracer()
623        coro = f()
624        try:
625            sys.settrace(tracer.trace)
626            coro.send(None)
627        except Exception:
628            pass
629        finally:
630            sys.settrace(None)
631
632        events = [
633            (0, 'call'),
634            (1, 'line'),
635            (-3, 'call'),
636            (-2, 'line'),
637            (-1, 'line'),
638            (-1, 'return'),
639            (1, 'exception'),
640            (2, 'line'),
641            (1, 'line'),
642            (-1, 'call'),
643            (-2, 'line'),
644            (-1, 'line'),
645            (-1, 'return'),
646            (1, 'exception'),
647            (2, 'line'),
648            (1, 'line'),
649            (-1, 'call'),
650            (-2, 'line'),
651            (-1, 'line'),
652            (-1, 'return'),
653            (1, 'exception'),
654            (2, 'line'),
655            (1, 'line'),
656            (-1, 'call'),
657            (-2, 'line'),
658            (-2, 'return'),
659            (1, 'exception'),
660            (1, 'return'),
661        ]
662        self.compare_events(f.__code__.co_firstlineno,
663                            tracer.events, events)
664
665    def test_21_repeated_pass(self):
666        def func():
667            pass
668            pass
669
670        self.run_and_compare(func,
671            [(0, 'call'),
672             (1, 'line'),
673             (2, 'line'),
674             (2, 'return')])
675
676    def test_loop_in_try_except(self):
677        # https://bugs.python.org/issue41670
678
679        def func():
680            try:
681                for i in []: pass
682                return 1
683            except:
684                return 2
685
686        self.run_and_compare(func,
687            [(0, 'call'),
688             (1, 'line'),
689             (2, 'line'),
690             (3, 'line'),
691             (3, 'return')])
692
693    def test_try_except_no_exception(self):
694
695        def func():
696            try:
697                2
698            except:
699                4
700            else:
701                6
702                if False:
703                    8
704                else:
705                    10
706                if func.__name__ == 'Fred':
707                    12
708            finally:
709                14
710
711        self.run_and_compare(func,
712            [(0, 'call'),
713             (1, 'line'),
714             (2, 'line'),
715             (6, 'line'),
716             (7, 'line'),
717             (10, 'line'),
718             (11, 'line'),
719             (14, 'line'),
720             (14, 'return')])
721
722    def test_try_exception_in_else(self):
723
724        def func():
725            try:
726                try:
727                    3
728                except:
729                    5
730                else:
731                    7
732                    raise Exception
733                finally:
734                    10
735            except:
736                12
737            finally:
738                14
739
740        self.run_and_compare(func,
741            [(0, 'call'),
742             (1, 'line'),
743             (2, 'line'),
744             (3, 'line'),
745             (7, 'line'),
746             (8, 'line'),
747             (8, 'exception'),
748             (10, 'line'),
749             (11, 'line'),
750             (12, 'line'),
751             (14, 'line'),
752             (14, 'return')])
753
754    def test_nested_loops(self):
755
756        def func():
757            for i in range(2):
758                for j in range(2):
759                    a = i + j
760            return a == 1
761
762        self.run_and_compare(func,
763            [(0, 'call'),
764             (1, 'line'),
765             (2, 'line'),
766             (3, 'line'),
767             (2, 'line'),
768             (3, 'line'),
769             (2, 'line'),
770             (1, 'line'),
771             (2, 'line'),
772             (3, 'line'),
773             (2, 'line'),
774             (3, 'line'),
775             (2, 'line'),
776             (1, 'line'),
777             (4, 'line'),
778             (4, 'return')])
779
780    def test_if_break(self):
781
782        def func():
783            seq = [1, 0]
784            while seq:
785                n = seq.pop()
786                if n:
787                    break   # line 5
788            else:
789                n = 99
790            return n        # line 8
791
792        self.run_and_compare(func,
793            [(0, 'call'),
794             (1, 'line'),
795             (2, 'line'),
796             (3, 'line'),
797             (4, 'line'),
798             (2, 'line'),
799             (3, 'line'),
800             (4, 'line'),
801             (5, 'line'),
802             (8, 'line'),
803             (8, 'return')])
804
805    def test_break_through_finally(self):
806
807        def func():
808            a, c, d, i = 1, 1, 1, 99
809            try:
810                for i in range(3):
811                    try:
812                        a = 5
813                        if i > 0:
814                            break                   # line 7
815                        a = 8
816                    finally:
817                        c = 10
818            except:
819                d = 12                              # line 12
820            assert a == 5 and c == 10 and d == 1    # line 13
821
822        self.run_and_compare(func,
823            [(0, 'call'),
824             (1, 'line'),
825             (2, 'line'),
826             (3, 'line'),
827             (4, 'line'),
828             (5, 'line'),
829             (6, 'line'),
830             (8, 'line'),
831             (10, 'line'),
832             (3, 'line'),
833             (4, 'line'),
834             (5, 'line'),
835             (6, 'line'),
836             (7, 'line'),
837             (10, 'line'),
838             (13, 'line'),
839             (13, 'return')])
840
841    def test_continue_through_finally(self):
842
843        def func():
844            a, b, c, d, i = 1, 1, 1, 1, 99
845            try:
846                for i in range(2):
847                    try:
848                        a = 5
849                        if i > 0:
850                            continue                # line 7
851                        b = 8
852                    finally:
853                        c = 10
854            except:
855                d = 12                              # line 12
856            assert (a, b, c, d) == (5, 8, 10, 1)    # line 13
857
858        self.run_and_compare(func,
859            [(0, 'call'),
860             (1, 'line'),
861             (2, 'line'),
862             (3, 'line'),
863             (4, 'line'),
864             (5, 'line'),
865             (6, 'line'),
866             (8, 'line'),
867             (10, 'line'),
868             (3, 'line'),
869             (4, 'line'),
870             (5, 'line'),
871             (6, 'line'),
872             (7, 'line'),
873             (10, 'line'),
874             (3, 'line'),
875             (13, 'line'),
876             (13, 'return')])
877
878    def test_return_through_finally(self):
879
880        def func():
881            try:
882                return 2
883            finally:
884                4
885
886        self.run_and_compare(func,
887            [(0, 'call'),
888             (1, 'line'),
889             (2, 'line'),
890             (4, 'line'),
891             (4, 'return')])
892
893    def test_try_except_with_wrong_type(self):
894
895        def func():
896            try:
897                2/0
898            except IndexError:
899                4
900            finally:
901                return 6
902
903        self.run_and_compare(func,
904            [(0, 'call'),
905             (1, 'line'),
906             (2, 'line'),
907             (2, 'exception'),
908             (3, 'line'),
909             (6, 'line'),
910             (6, 'return')])
911
912    def test_break_to_continue1(self):
913
914        def func():
915            TRUE = 1
916            x = [1]
917            while x:
918                x.pop()
919                while TRUE:
920                    break
921                continue
922
923        self.run_and_compare(func,
924            [(0, 'call'),
925             (1, 'line'),
926             (2, 'line'),
927             (3, 'line'),
928             (4, 'line'),
929             (5, 'line'),
930             (6, 'line'),
931             (7, 'line'),
932             (3, 'line'),
933             (3, 'return')])
934
935    def test_break_to_continue2(self):
936
937        def func():
938            TRUE = 1
939            x = [1]
940            while x:
941                x.pop()
942                while TRUE:
943                    break
944                else:
945                    continue
946
947        self.run_and_compare(func,
948            [(0, 'call'),
949             (1, 'line'),
950             (2, 'line'),
951             (3, 'line'),
952             (4, 'line'),
953             (5, 'line'),
954             (6, 'line'),
955             (3, 'line'),
956             (3, 'return')])
957
958    def test_break_to_break(self):
959
960        def func():
961            TRUE = 1
962            while TRUE:
963                while TRUE:
964                    break
965                break
966
967        self.run_and_compare(func,
968            [(0, 'call'),
969             (1, 'line'),
970             (2, 'line'),
971             (3, 'line'),
972             (4, 'line'),
973             (5, 'line'),
974             (5, 'return')])
975
976    def test_nested_ifs(self):
977
978        def func():
979            a = b = 1
980            if a == 1:
981                if b == 1:
982                    x = 4
983                else:
984                    y = 6
985            else:
986                z = 8
987
988        self.run_and_compare(func,
989            [(0, 'call'),
990             (1, 'line'),
991             (2, 'line'),
992             (3, 'line'),
993             (4, 'line'),
994             (4, 'return')])
995
996    def test_nested_ifs_with_and(self):
997
998        def func():
999            if A:
1000                if B:
1001                    if C:
1002                        if D:
1003                            return False
1004                else:
1005                    return False
1006            elif E and F:
1007                return True
1008
1009        A = B = True
1010        C = False
1011
1012        self.run_and_compare(func,
1013            [(0, 'call'),
1014             (1, 'line'),
1015             (2, 'line'),
1016             (3, 'line'),
1017             (3, 'return')])
1018
1019    def test_nested_try_if(self):
1020
1021        def func():
1022            x = "hello"
1023            try:
1024                3/0
1025            except ZeroDivisionError:
1026                if x == 'raise':
1027                    raise ValueError()   # line 6
1028            f = 7
1029
1030        self.run_and_compare(func,
1031            [(0, 'call'),
1032             (1, 'line'),
1033             (2, 'line'),
1034             (3, 'line'),
1035             (3, 'exception'),
1036             (4, 'line'),
1037             (5, 'line'),
1038             (7, 'line'),
1039             (7, 'return')])
1040
1041    def test_if_false_in_with(self):
1042
1043        class C:
1044            def __enter__(self):
1045                return self
1046            def __exit__(*args):
1047                pass
1048
1049        def func():
1050            with C():
1051                if False:
1052                    pass
1053
1054        self.run_and_compare(func,
1055            [(0, 'call'),
1056             (1, 'line'),
1057             (-5, 'call'),
1058             (-4, 'line'),
1059             (-4, 'return'),
1060             (2, 'line'),
1061             (1, 'line'),
1062             (-3, 'call'),
1063             (-2, 'line'),
1064             (-2, 'return'),
1065             (1, 'return')])
1066
1067    def test_if_false_in_try_except(self):
1068
1069        def func():
1070            try:
1071                if False:
1072                    pass
1073            except Exception:
1074                X
1075
1076        self.run_and_compare(func,
1077            [(0, 'call'),
1078             (1, 'line'),
1079             (2, 'line'),
1080             (2, 'return')])
1081
1082    def test_implicit_return_in_class(self):
1083
1084        def func():
1085            class A:
1086                if 3 < 9:
1087                    a = 1
1088                else:
1089                    a = 2
1090
1091        self.run_and_compare(func,
1092            [(0, 'call'),
1093             (1, 'line'),
1094             (1, 'call'),
1095             (1, 'line'),
1096             (2, 'line'),
1097             (3, 'line'),
1098             (3, 'return'),
1099             (1, 'return')])
1100
1101    def test_try_in_try(self):
1102        def func():
1103            try:
1104                try:
1105                    pass
1106                except Exception as ex:
1107                    pass
1108            except Exception:
1109                pass
1110
1111        self.run_and_compare(func,
1112            [(0, 'call'),
1113             (1, 'line'),
1114             (2, 'line'),
1115             (3, 'line'),
1116             (3, 'return')])
1117
1118    def test_try_in_try_with_exception(self):
1119
1120        def func():
1121            try:
1122                try:
1123                    raise TypeError
1124                except ValueError as ex:
1125                    5
1126            except TypeError:
1127                7
1128
1129        self.run_and_compare(func,
1130            [(0, 'call'),
1131             (1, 'line'),
1132             (2, 'line'),
1133             (3, 'line'),
1134             (3, 'exception'),
1135             (4, 'line'),
1136             (6, 'line'),
1137             (7, 'line'),
1138             (7, 'return')])
1139
1140        def func():
1141            try:
1142                try:
1143                    raise ValueError
1144                except ValueError as ex:
1145                    5
1146            except TypeError:
1147                7
1148
1149        self.run_and_compare(func,
1150            [(0, 'call'),
1151             (1, 'line'),
1152             (2, 'line'),
1153             (3, 'line'),
1154             (3, 'exception'),
1155             (4, 'line'),
1156             (5, 'line'),
1157             (5, 'return')])
1158
1159    def test_if_in_if_in_if(self):
1160        def func(a=0, p=1, z=1):
1161            if p:
1162                if a:
1163                    if z:
1164                        pass
1165                    else:
1166                        pass
1167            else:
1168                pass
1169
1170        self.run_and_compare(func,
1171            [(0, 'call'),
1172             (1, 'line'),
1173             (2, 'line'),
1174             (2, 'return')])
1175
1176    def test_early_exit_with(self):
1177
1178        class C:
1179            def __enter__(self):
1180                return self
1181            def __exit__(*args):
1182                pass
1183
1184        def func_break():
1185            for i in (1,2):
1186                with C():
1187                    break
1188            pass
1189
1190        def func_return():
1191            with C():
1192                return
1193
1194        self.run_and_compare(func_break,
1195            [(0, 'call'),
1196             (1, 'line'),
1197             (2, 'line'),
1198             (-5, 'call'),
1199             (-4, 'line'),
1200             (-4, 'return'),
1201             (3, 'line'),
1202             (2, 'line'),
1203             (-3, 'call'),
1204             (-2, 'line'),
1205             (-2, 'return'),
1206             (4, 'line'),
1207             (4, 'return')])
1208
1209        self.run_and_compare(func_return,
1210            [(0, 'call'),
1211             (1, 'line'),
1212             (-11, 'call'),
1213             (-10, 'line'),
1214             (-10, 'return'),
1215             (2, 'line'),
1216             (1, 'line'),
1217             (-9, 'call'),
1218             (-8, 'line'),
1219             (-8, 'return'),
1220             (1, 'return')])
1221
1222    def test_flow_converges_on_same_line(self):
1223
1224        def foo(x):
1225            if x:
1226                try:
1227                    1/(x - 1)
1228                except ZeroDivisionError:
1229                    pass
1230            return x
1231
1232        def func():
1233            for i in range(2):
1234                foo(i)
1235
1236        self.run_and_compare(func,
1237            [(0, 'call'),
1238             (1, 'line'),
1239             (2, 'line'),
1240             (-8, 'call'),
1241             (-7, 'line'),
1242             (-2, 'line'),
1243             (-2, 'return'),
1244             (1, 'line'),
1245             (2, 'line'),
1246             (-8, 'call'),
1247             (-7, 'line'),
1248             (-6, 'line'),
1249             (-5, 'line'),
1250             (-5, 'exception'),
1251             (-4, 'line'),
1252             (-3, 'line'),
1253             (-2, 'line'),
1254             (-2, 'return'),
1255             (1, 'line'),
1256             (1, 'return')])
1257
1258    def test_no_tracing_of_named_except_cleanup(self):
1259
1260        def func():
1261            x = 0
1262            try:
1263                1/x
1264            except ZeroDivisionError as error:
1265                if x:
1266                    raise
1267            return "done"
1268
1269        self.run_and_compare(func,
1270        [(0, 'call'),
1271            (1, 'line'),
1272            (2, 'line'),
1273            (3, 'line'),
1274            (3, 'exception'),
1275            (4, 'line'),
1276            (5, 'line'),
1277            (7, 'line'),
1278            (7, 'return')])
1279
1280    def test_tracing_exception_raised_in_with(self):
1281
1282        class NullCtx:
1283            def __enter__(self):
1284                return self
1285            def __exit__(self, *excinfo):
1286                pass
1287
1288        def func():
1289            try:
1290                with NullCtx():
1291                    1/0
1292            except ZeroDivisionError:
1293                pass
1294
1295        self.run_and_compare(func,
1296            [(0, 'call'),
1297             (1, 'line'),
1298             (2, 'line'),
1299             (-5, 'call'),
1300             (-4, 'line'),
1301             (-4, 'return'),
1302             (3, 'line'),
1303             (3, 'exception'),
1304             (2, 'line'),
1305             (-3, 'call'),
1306             (-2, 'line'),
1307             (-2, 'return'),
1308             (4, 'line'),
1309             (5, 'line'),
1310             (5, 'return')])
1311
1312    def test_try_except_star_no_exception(self):
1313
1314        def func():
1315            try:
1316                2
1317            except* Exception:
1318                4
1319            else:
1320                6
1321                if False:
1322                    8
1323                else:
1324                    10
1325                if func.__name__ == 'Fred':
1326                    12
1327            finally:
1328                14
1329
1330        self.run_and_compare(func,
1331            [(0, 'call'),
1332             (1, 'line'),
1333             (2, 'line'),
1334             (6, 'line'),
1335             (7, 'line'),
1336             (10, 'line'),
1337             (11, 'line'),
1338             (14, 'line'),
1339             (14, 'return')])
1340
1341    def test_try_except_star_named_no_exception(self):
1342
1343        def func():
1344            try:
1345                2
1346            except* Exception as e:
1347                4
1348            else:
1349                6
1350            finally:
1351                8
1352
1353        self.run_and_compare(func,
1354            [(0, 'call'),
1355             (1, 'line'),
1356             (2, 'line'),
1357             (6, 'line'),
1358             (8, 'line'),
1359             (8, 'return')])
1360
1361    def test_try_except_star_exception_caught(self):
1362
1363        def func():
1364            try:
1365                raise ValueError(2)
1366            except* ValueError:
1367                4
1368            else:
1369                6
1370            finally:
1371                8
1372
1373        self.run_and_compare(func,
1374            [(0, 'call'),
1375             (1, 'line'),
1376             (2, 'line'),
1377             (2, 'exception'),
1378             (3, 'line'),
1379             (4, 'line'),
1380             (8, 'line'),
1381             (8, 'return')])
1382
1383    def test_try_except_star_named_exception_caught(self):
1384
1385        def func():
1386            try:
1387                raise ValueError(2)
1388            except* ValueError as e:
1389                4
1390            else:
1391                6
1392            finally:
1393                8
1394
1395        self.run_and_compare(func,
1396            [(0, 'call'),
1397             (1, 'line'),
1398             (2, 'line'),
1399             (2, 'exception'),
1400             (3, 'line'),
1401             (4, 'line'),
1402             (8, 'line'),
1403             (8, 'return')])
1404
1405    def test_try_except_star_exception_not_caught(self):
1406
1407        def func():
1408            try:
1409                try:
1410                    raise ValueError(3)
1411                except* TypeError:
1412                    5
1413            except ValueError:
1414                7
1415
1416        self.run_and_compare(func,
1417            [(0, 'call'),
1418             (1, 'line'),
1419             (2, 'line'),
1420             (3, 'line'),
1421             (3, 'exception'),
1422             (4, 'line'),
1423             (6, 'line'),
1424             (7, 'line'),
1425             (7, 'return')])
1426
1427    def test_try_except_star_named_exception_not_caught(self):
1428
1429        def func():
1430            try:
1431                try:
1432                    raise ValueError(3)
1433                except* TypeError as e:
1434                    5
1435            except ValueError:
1436                7
1437
1438        self.run_and_compare(func,
1439            [(0, 'call'),
1440             (1, 'line'),
1441             (2, 'line'),
1442             (3, 'line'),
1443             (3, 'exception'),
1444             (4, 'line'),
1445             (6, 'line'),
1446             (7, 'line'),
1447             (7, 'return')])
1448
1449    def test_try_except_star_nested(self):
1450
1451        def func():
1452            try:
1453                try:
1454                    raise ExceptionGroup(
1455                        'eg',
1456                        [ValueError(5), TypeError('bad type')])
1457                except* TypeError as e:
1458                    7
1459                except* OSError:
1460                    9
1461                except* ValueError:
1462                    raise
1463            except* ValueError:
1464                try:
1465                    raise TypeError(14)
1466                except* OSError:
1467                    16
1468                except* TypeError as e:
1469                    18
1470            return 0
1471
1472        self.run_and_compare(func,
1473            [(0, 'call'),
1474             (1, 'line'),
1475             (2, 'line'),
1476             (3, 'line'),
1477             (4, 'line'),
1478             (5, 'line'),
1479             (3, 'line'),
1480             (3, 'exception'),
1481             (6, 'line'),
1482             (7, 'line'),
1483             (8, 'line'),
1484             (10, 'line'),
1485             (11, 'line'),
1486             (12, 'line'),
1487             (13, 'line'),
1488             (14, 'line'),
1489             (14, 'exception'),
1490             (15, 'line'),
1491             (17, 'line'),
1492             (18, 'line'),
1493             (19, 'line'),
1494             (19, 'return')])
1495
1496    def test_notrace_lambda(self):
1497        #Regression test for issue 46314
1498
1499        def func():
1500            1
1501            lambda x: 2
1502            3
1503
1504        self.run_and_compare(func,
1505            [(0, 'call'),
1506             (1, 'line'),
1507             (2, 'line'),
1508             (3, 'line'),
1509             (3, 'return')])
1510
1511    def test_class_creation_with_docstrings(self):
1512
1513        def func():
1514            class Class_1:
1515                ''' the docstring. 2'''
1516                def __init__(self):
1517                    ''' Another docstring. 4'''
1518                    self.a = 5
1519
1520        self.run_and_compare(func,
1521            [(0, 'call'),
1522             (1, 'line'),
1523             (1, 'call'),
1524             (1, 'line'),
1525             (2, 'line'),
1526             (3, 'line'),
1527             (3, 'return'),
1528             (1, 'return')])
1529
1530    @support.cpython_only
1531    def test_no_line_event_after_creating_generator(self):
1532        # Spurious line events before call events only show up with C tracer
1533
1534        # Skip this test if the _testcapi module isn't available.
1535        _testcapi = import_helper.import_module('_testcapi')
1536
1537        def gen():
1538            yield 1
1539
1540        def func():
1541            for _ in (
1542                gen()
1543            ):
1544                pass
1545
1546        EXPECTED_EVENTS = [
1547            (0, 'call'),
1548            (2, 'line'),
1549            (1, 'line'),
1550            (-3, 'call'),
1551            (-2, 'line'),
1552            (-2, 'return'),
1553            (4, 'line'),
1554            (1, 'line'),
1555            (-2, 'call'),
1556            (-2, 'return'),
1557            (1, 'return'),
1558        ]
1559
1560        # C level events should be the same as expected and the same as Python level.
1561
1562        events = []
1563        # Turning on and off tracing must be on same line to avoid unwanted LINE events.
1564        _testcapi.settrace_to_record(events); func(); sys.settrace(None)
1565        start_line = func.__code__.co_firstlineno
1566        events = [
1567            (line-start_line, EVENT_NAMES[what])
1568            for (what, line, arg) in events
1569        ]
1570        self.assertEqual(events, EXPECTED_EVENTS)
1571
1572        self.run_and_compare(func, EXPECTED_EVENTS)
1573
1574    def test_settrace_error(self):
1575
1576        raised = False
1577        def error_once(frame, event, arg):
1578            nonlocal raised
1579            if not raised:
1580                raised = True
1581                raise Exception
1582            return error
1583
1584        try:
1585            sys._getframe().f_trace = error_once
1586            sys.settrace(error_once)
1587            len([])
1588        except Exception as ex:
1589            count = 0
1590            tb = ex.__traceback__
1591            print(tb)
1592            while tb:
1593                if tb.tb_frame.f_code.co_name == "test_settrace_error":
1594                    count += 1
1595                tb = tb.tb_next
1596            if count == 0:
1597                self.fail("Traceback is missing frame")
1598            elif count > 1:
1599                self.fail("Traceback has frame more than once")
1600        else:
1601            self.fail("No exception raised")
1602        finally:
1603            sys.settrace(None)
1604
1605    @support.cpython_only
1606    def test_testcapi_settrace_error(self):
1607
1608        # Skip this test if the _testcapi module isn't available.
1609        _testcapi = import_helper.import_module('_testcapi')
1610
1611        try:
1612            _testcapi.settrace_to_error([])
1613            len([])
1614        except Exception as ex:
1615            count = 0
1616            tb = ex.__traceback__
1617            while tb:
1618                if tb.tb_frame.f_code.co_name == "test_testcapi_settrace_error":
1619                    count += 1
1620                tb = tb.tb_next
1621            if count == 0:
1622                self.fail("Traceback is missing frame")
1623            elif count > 1:
1624                self.fail("Traceback has frame more than once")
1625        else:
1626            self.fail("No exception raised")
1627        finally:
1628            sys.settrace(None)
1629
1630    def test_very_large_function(self):
1631        # There is a separate code path when the number of lines > (1 << 15).
1632        d = {}
1633        exec("""def f():              # line 0
1634            x = 0                     # line 1
1635            y = 1                     # line 2
1636            %s                        # lines 3 through (1 << 16)
1637            x += 1                    #
1638            return""" % ('\n' * (1 << 16),), d)
1639        f = d['f']
1640
1641        EXPECTED_EVENTS = [
1642            (0, 'call'),
1643            (1, 'line'),
1644            (2, 'line'),
1645            (65540, 'line'),
1646            (65541, 'line'),
1647            (65541, 'return'),
1648        ]
1649
1650        self.run_and_compare(f, EXPECTED_EVENTS)
1651
1652
1653EVENT_NAMES = [
1654    'call',
1655    'exception',
1656    'line',
1657    'return'
1658]
1659
1660
1661class SkipLineEventsTraceTestCase(TraceTestCase):
1662    """Repeat the trace tests, but with per-line events skipped"""
1663
1664    def compare_events(self, line_offset, events, expected_events):
1665        skip_line_events = [e for e in expected_events if e[1] != 'line']
1666        super().compare_events(line_offset, events, skip_line_events)
1667
1668    @staticmethod
1669    def make_tracer():
1670        return Tracer(trace_line_events=False)
1671
1672
1673@support.cpython_only
1674class TraceOpcodesTestCase(TraceTestCase):
1675    """Repeat the trace tests, but with per-opcodes events enabled"""
1676
1677    def compare_events(self, line_offset, events, expected_events):
1678        skip_opcode_events = [e for e in events if e[1] != 'opcode']
1679        if len(events) > 1:
1680            self.assertLess(len(skip_opcode_events), len(events),
1681                            msg="No 'opcode' events received by the tracer")
1682        super().compare_events(line_offset, skip_opcode_events, expected_events)
1683
1684    @staticmethod
1685    def make_tracer():
1686        return Tracer(trace_opcode_events=True)
1687
1688
1689class RaisingTraceFuncTestCase(unittest.TestCase):
1690    def setUp(self):
1691        self.addCleanup(sys.settrace, sys.gettrace())
1692
1693    def trace(self, frame, event, arg):
1694        """A trace function that raises an exception in response to a
1695        specific trace event."""
1696        if event == self.raiseOnEvent:
1697            raise ValueError # just something that isn't RuntimeError
1698        else:
1699            return self.trace
1700
1701    def f(self):
1702        """The function to trace; raises an exception if that's the case
1703        we're testing, so that the 'exception' trace event fires."""
1704        if self.raiseOnEvent == 'exception':
1705            x = 0
1706            y = 1/x
1707        else:
1708            return 1
1709
1710    def run_test_for_event(self, event):
1711        """Tests that an exception raised in response to the given event is
1712        handled OK."""
1713        self.raiseOnEvent = event
1714        try:
1715            for i in range(sys.getrecursionlimit() + 1):
1716                sys.settrace(self.trace)
1717                try:
1718                    self.f()
1719                except ValueError:
1720                    pass
1721                else:
1722                    self.fail("exception not raised!")
1723        except RuntimeError:
1724            self.fail("recursion counter not reset")
1725
1726    # Test the handling of exceptions raised by each kind of trace event.
1727    def test_call(self):
1728        self.run_test_for_event('call')
1729    def test_line(self):
1730        self.run_test_for_event('line')
1731    def test_return(self):
1732        self.run_test_for_event('return')
1733    def test_exception(self):
1734        self.run_test_for_event('exception')
1735
1736    def test_trash_stack(self):
1737        def f():
1738            for i in range(5):
1739                print(i)  # line tracing will raise an exception at this line
1740
1741        def g(frame, why, extra):
1742            if (why == 'line' and
1743                frame.f_lineno == f.__code__.co_firstlineno + 2):
1744                raise RuntimeError("i am crashing")
1745            return g
1746
1747        sys.settrace(g)
1748        try:
1749            f()
1750        except RuntimeError:
1751            # the test is really that this doesn't segfault:
1752            import gc
1753            gc.collect()
1754        else:
1755            self.fail("exception not propagated")
1756
1757
1758    def test_exception_arguments(self):
1759        def f():
1760            x = 0
1761            # this should raise an error
1762            x.no_such_attr
1763        def g(frame, event, arg):
1764            if (event == 'exception'):
1765                type, exception, trace = arg
1766                self.assertIsInstance(exception, Exception)
1767            return g
1768
1769        existing = sys.gettrace()
1770        try:
1771            sys.settrace(g)
1772            try:
1773                f()
1774            except AttributeError:
1775                # this is expected
1776                pass
1777        finally:
1778            sys.settrace(existing)
1779
1780    def test_line_event_raises_before_opcode_event(self):
1781        exception = ValueError("BOOM!")
1782        def trace(frame, event, arg):
1783            if event == "line":
1784                raise exception
1785            frame.f_trace_opcodes = True
1786            return trace
1787        def f():
1788            pass
1789        with self.assertRaises(ValueError) as caught:
1790            sys.settrace(trace)
1791            f()
1792        self.assertIs(caught.exception, exception)
1793
1794
1795# 'Jump' tests: assigning to frame.f_lineno within a trace function
1796# moves the execution position - it's how debuggers implement a Jump
1797# command (aka. "Set next statement").
1798
1799class JumpTracer:
1800    """Defines a trace function that jumps from one place to another."""
1801
1802    def __init__(self, function, jumpFrom, jumpTo, event='line',
1803                 decorated=False):
1804        self.code = function.__code__
1805        self.jumpFrom = jumpFrom
1806        self.jumpTo = jumpTo
1807        self.event = event
1808        self.firstLine = None if decorated else self.code.co_firstlineno
1809        self.done = False
1810
1811    def trace(self, frame, event, arg):
1812        if self.done:
1813            return
1814        # frame.f_code.co_firstlineno is the first line of the decorator when
1815        # 'function' is decorated and the decorator may be written using
1816        # multiple physical lines when it is too long. Use the first line
1817        # trace event in 'function' to find the first line of 'function'.
1818        if (self.firstLine is None and frame.f_code == self.code and
1819                event == 'line'):
1820            self.firstLine = frame.f_lineno - 1
1821        if (event == self.event and self.firstLine is not None and
1822                frame.f_lineno == self.firstLine + self.jumpFrom):
1823            f = frame
1824            while f is not None and f.f_code != self.code:
1825                f = f.f_back
1826            if f is not None:
1827                # Cope with non-integer self.jumpTo (because of
1828                # no_jump_to_non_integers below).
1829                try:
1830                    frame.f_lineno = self.firstLine + self.jumpTo
1831                except TypeError:
1832                    frame.f_lineno = self.jumpTo
1833                self.done = True
1834        return self.trace
1835
1836# This verifies the line-numbers-must-be-integers rule.
1837def no_jump_to_non_integers(output):
1838    try:
1839        output.append(2)
1840    except ValueError as e:
1841        output.append('integer' in str(e))
1842
1843# This verifies that you can't set f_lineno via _getframe or similar
1844# trickery.
1845def no_jump_without_trace_function():
1846    try:
1847        previous_frame = sys._getframe().f_back
1848        previous_frame.f_lineno = previous_frame.f_lineno
1849    except ValueError as e:
1850        # This is the exception we wanted; make sure the error message
1851        # talks about trace functions.
1852        if 'trace' not in str(e):
1853            raise
1854    else:
1855        # Something's wrong - the expected exception wasn't raised.
1856        raise AssertionError("Trace-function-less jump failed to fail")
1857
1858
1859class JumpTestCase(unittest.TestCase):
1860    def setUp(self):
1861        self.addCleanup(sys.settrace, sys.gettrace())
1862        sys.settrace(None)
1863
1864    def compare_jump_output(self, expected, received):
1865        if received != expected:
1866            self.fail( "Outputs don't match:\n" +
1867                       "Expected: " + repr(expected) + "\n" +
1868                       "Received: " + repr(received))
1869
1870    def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
1871                 event='line', decorated=False):
1872        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
1873        sys.settrace(tracer.trace)
1874        output = []
1875        if error is None:
1876            func(output)
1877        else:
1878            with self.assertRaisesRegex(*error):
1879                func(output)
1880        sys.settrace(None)
1881        self.compare_jump_output(expected, output)
1882
1883    def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
1884                 event='line', decorated=False):
1885        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
1886        sys.settrace(tracer.trace)
1887        output = []
1888        if error is None:
1889            asyncio.run(func(output))
1890        else:
1891            with self.assertRaisesRegex(*error):
1892                asyncio.run(func(output))
1893        sys.settrace(None)
1894        asyncio.set_event_loop_policy(None)
1895        self.compare_jump_output(expected, output)
1896
1897    def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1898        """Decorator that creates a test that makes a jump
1899        from one place to another in the following code.
1900        """
1901        def decorator(func):
1902            @wraps(func)
1903            def test(self):
1904                self.run_test(func, jumpFrom, jumpTo, expected,
1905                              error=error, event=event, decorated=True)
1906            return test
1907        return decorator
1908
1909    def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1910        """Decorator that creates a test that makes a jump
1911        from one place to another in the following asynchronous code.
1912        """
1913        def decorator(func):
1914            @wraps(func)
1915            def test(self):
1916                self.run_async_test(func, jumpFrom, jumpTo, expected,
1917                              error=error, event=event, decorated=True)
1918            return test
1919        return decorator
1920
1921    ## The first set of 'jump' tests are for things that are allowed:
1922
1923    @jump_test(1, 3, [3])
1924    def test_jump_simple_forwards(output):
1925        output.append(1)
1926        output.append(2)
1927        output.append(3)
1928
1929    @jump_test(2, 1, [1, 1, 2])
1930    def test_jump_simple_backwards(output):
1931        output.append(1)
1932        output.append(2)
1933
1934    @jump_test(3, 5, [2, 5])
1935    def test_jump_out_of_block_forwards(output):
1936        for i in 1, 2:
1937            output.append(2)
1938            for j in [3]:  # Also tests jumping over a block
1939                output.append(4)
1940        output.append(5)
1941
1942    @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7])
1943    def test_jump_out_of_block_backwards(output):
1944        output.append(1)
1945        for i in [1]:
1946            output.append(3)
1947            for j in [2]:  # Also tests jumping over a block
1948                output.append(5)
1949            output.append(6)
1950        output.append(7)
1951
1952    @async_jump_test(4, 5, [3, 5])
1953    async def test_jump_out_of_async_for_block_forwards(output):
1954        for i in [1]:
1955            async for i in asynciter([1, 2]):
1956                output.append(3)
1957                output.append(4)
1958            output.append(5)
1959
1960    @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6])
1961    async def test_jump_out_of_async_for_block_backwards(output):
1962        for i in [1]:
1963            output.append(2)
1964            async for i in asynciter([1]):
1965                output.append(4)
1966                output.append(5)
1967            output.append(6)
1968
1969    @jump_test(1, 2, [3])
1970    def test_jump_to_codeless_line(output):
1971        output.append(1)
1972        # Jumping to this line should skip to the next one.
1973        output.append(3)
1974
1975    @jump_test(2, 2, [1, 2, 3])
1976    def test_jump_to_same_line(output):
1977        output.append(1)
1978        output.append(2)
1979        output.append(3)
1980
1981    # Tests jumping within a finally block, and over one.
1982    @jump_test(4, 9, [2, 9])
1983    def test_jump_in_nested_finally(output):
1984        try:
1985            output.append(2)
1986        finally:
1987            output.append(4)
1988            try:
1989                output.append(6)
1990            finally:
1991                output.append(8)
1992            output.append(9)
1993
1994    @jump_test(6, 7, [2, 7], (ZeroDivisionError, ''))
1995    def test_jump_in_nested_finally_2(output):
1996        try:
1997            output.append(2)
1998            1/0
1999            return
2000        finally:
2001            output.append(6)
2002            output.append(7)
2003        output.append(8)
2004
2005    @jump_test(6, 11, [2, 11], (ZeroDivisionError, ''))
2006    def test_jump_in_nested_finally_3(output):
2007        try:
2008            output.append(2)
2009            1/0
2010            return
2011        finally:
2012            output.append(6)
2013            try:
2014                output.append(8)
2015            finally:
2016                output.append(10)
2017            output.append(11)
2018        output.append(12)
2019
2020    @jump_test(5, 11, [2, 4], (ValueError, 'exception'))
2021    def test_no_jump_over_return_try_finally_in_finally_block(output):
2022        try:
2023            output.append(2)
2024        finally:
2025            output.append(4)
2026            output.append(5)
2027            return
2028            try:
2029                output.append(8)
2030            finally:
2031                output.append(10)
2032            pass
2033        output.append(12)
2034
2035    @jump_test(3, 4, [1], (ValueError, 'after'))
2036    def test_no_jump_infinite_while_loop(output):
2037        output.append(1)
2038        while True:
2039            output.append(3)
2040        output.append(4)
2041
2042    @jump_test(2, 4, [4, 4])
2043    def test_jump_forwards_into_while_block(output):
2044        i = 1
2045        output.append(2)
2046        while i <= 2:
2047            output.append(4)
2048            i += 1
2049
2050    @jump_test(5, 3, [3, 3, 3, 5])
2051    def test_jump_backwards_into_while_block(output):
2052        i = 1
2053        while i <= 2:
2054            output.append(3)
2055            i += 1
2056        output.append(5)
2057
2058    @jump_test(2, 3, [1, 3])
2059    def test_jump_forwards_out_of_with_block(output):
2060        with tracecontext(output, 1):
2061            output.append(2)
2062        output.append(3)
2063
2064    @async_jump_test(2, 3, [1, 3])
2065    async def test_jump_forwards_out_of_async_with_block(output):
2066        async with asynctracecontext(output, 1):
2067            output.append(2)
2068        output.append(3)
2069
2070    @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
2071    def test_jump_backwards_out_of_with_block(output):
2072        output.append(1)
2073        with tracecontext(output, 2):
2074            output.append(3)
2075
2076    @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
2077    async def test_jump_backwards_out_of_async_with_block(output):
2078        output.append(1)
2079        async with asynctracecontext(output, 2):
2080            output.append(3)
2081
2082    @jump_test(2, 5, [5])
2083    def test_jump_forwards_out_of_try_finally_block(output):
2084        try:
2085            output.append(2)
2086        finally:
2087            output.append(4)
2088        output.append(5)
2089
2090    @jump_test(3, 1, [1, 1, 3, 5])
2091    def test_jump_backwards_out_of_try_finally_block(output):
2092        output.append(1)
2093        try:
2094            output.append(3)
2095        finally:
2096            output.append(5)
2097
2098    @jump_test(2, 6, [6])
2099    def test_jump_forwards_out_of_try_except_block(output):
2100        try:
2101            output.append(2)
2102        except:
2103            output.append(4)
2104            raise
2105        output.append(6)
2106
2107    @jump_test(3, 1, [1, 1, 3])
2108    def test_jump_backwards_out_of_try_except_block(output):
2109        output.append(1)
2110        try:
2111            output.append(3)
2112        except:
2113            output.append(5)
2114            raise
2115
2116    @jump_test(5, 7, [4, 7, 8])
2117    def test_jump_between_except_blocks(output):
2118        try:
2119            1/0
2120        except ZeroDivisionError:
2121            output.append(4)
2122            output.append(5)
2123        except FloatingPointError:
2124            output.append(7)
2125        output.append(8)
2126
2127    @jump_test(5, 7, [4, 7, 8])
2128    def test_jump_from_except_to_finally(output):
2129        try:
2130            1/0
2131        except ZeroDivisionError:
2132            output.append(4)
2133            output.append(5)
2134        finally:
2135            output.append(7)
2136        output.append(8)
2137
2138    @jump_test(5, 6, [4, 6, 7])
2139    def test_jump_within_except_block(output):
2140        try:
2141            1/0
2142        except:
2143            output.append(4)
2144            output.append(5)
2145            output.append(6)
2146        output.append(7)
2147
2148    @jump_test(6, 1, [1, 5, 1, 5])
2149    def test_jump_over_try_except(output):
2150        output.append(1)
2151        try:
2152            1 / 0
2153        except ZeroDivisionError as e:
2154            output.append(5)
2155        x = 42  # has to be a two-instruction block
2156
2157    @jump_test(2, 4, [1, 4, 5, -4])
2158    def test_jump_across_with(output):
2159        output.append(1)
2160        with tracecontext(output, 2):
2161            output.append(3)
2162        with tracecontext(output, 4):
2163            output.append(5)
2164
2165    @async_jump_test(2, 4, [1, 4, 5, -4])
2166    async def test_jump_across_async_with(output):
2167        output.append(1)
2168        async with asynctracecontext(output, 2):
2169            output.append(3)
2170        async with asynctracecontext(output, 4):
2171            output.append(5)
2172
2173    @jump_test(4, 5, [1, 3, 5, 6])
2174    def test_jump_out_of_with_block_within_for_block(output):
2175        output.append(1)
2176        for i in [1]:
2177            with tracecontext(output, 3):
2178                output.append(4)
2179            output.append(5)
2180        output.append(6)
2181
2182    @async_jump_test(4, 5, [1, 3, 5, 6])
2183    async def test_jump_out_of_async_with_block_within_for_block(output):
2184        output.append(1)
2185        for i in [1]:
2186            async with asynctracecontext(output, 3):
2187                output.append(4)
2188            output.append(5)
2189        output.append(6)
2190
2191    @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
2192    def test_jump_out_of_with_block_within_with_block(output):
2193        output.append(1)
2194        with tracecontext(output, 2):
2195            with tracecontext(output, 3):
2196                output.append(4)
2197            output.append(5)
2198        output.append(6)
2199
2200    @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
2201    async def test_jump_out_of_async_with_block_within_with_block(output):
2202        output.append(1)
2203        with tracecontext(output, 2):
2204            async with asynctracecontext(output, 3):
2205                output.append(4)
2206            output.append(5)
2207        output.append(6)
2208
2209    @jump_test(5, 6, [2, 4, 6, 7])
2210    def test_jump_out_of_with_block_within_finally_block(output):
2211        try:
2212            output.append(2)
2213        finally:
2214            with tracecontext(output, 4):
2215                output.append(5)
2216            output.append(6)
2217        output.append(7)
2218
2219    @async_jump_test(5, 6, [2, 4, 6, 7])
2220    async def test_jump_out_of_async_with_block_within_finally_block(output):
2221        try:
2222            output.append(2)
2223        finally:
2224            async with asynctracecontext(output, 4):
2225                output.append(5)
2226            output.append(6)
2227        output.append(7)
2228
2229    @jump_test(8, 11, [1, 3, 5, 11, 12])
2230    def test_jump_out_of_complex_nested_blocks(output):
2231        output.append(1)
2232        for i in [1]:
2233            output.append(3)
2234            for j in [1, 2]:
2235                output.append(5)
2236                try:
2237                    for k in [1, 2]:
2238                        output.append(8)
2239                finally:
2240                    output.append(10)
2241            output.append(11)
2242        output.append(12)
2243
2244    @jump_test(3, 5, [1, 2, 5])
2245    def test_jump_out_of_with_assignment(output):
2246        output.append(1)
2247        with tracecontext(output, 2) \
2248                as x:
2249            output.append(4)
2250        output.append(5)
2251
2252    @async_jump_test(3, 5, [1, 2, 5])
2253    async def test_jump_out_of_async_with_assignment(output):
2254        output.append(1)
2255        async with asynctracecontext(output, 2) \
2256                as x:
2257            output.append(4)
2258        output.append(5)
2259
2260    @jump_test(3, 6, [1, 6, 8, 9])
2261    def test_jump_over_return_in_try_finally_block(output):
2262        output.append(1)
2263        try:
2264            output.append(3)
2265            if not output: # always false
2266                return
2267            output.append(6)
2268        finally:
2269            output.append(8)
2270        output.append(9)
2271
2272    @jump_test(5, 8, [1, 3, 8, 10, 11, 13])
2273    def test_jump_over_break_in_try_finally_block(output):
2274        output.append(1)
2275        while True:
2276            output.append(3)
2277            try:
2278                output.append(5)
2279                if not output: # always false
2280                    break
2281                output.append(8)
2282            finally:
2283                output.append(10)
2284            output.append(11)
2285            break
2286        output.append(13)
2287
2288    @jump_test(1, 7, [7, 8])
2289    def test_jump_over_for_block_before_else(output):
2290        output.append(1)
2291        if not output:  # always false
2292            for i in [3]:
2293                output.append(4)
2294        else:
2295            output.append(6)
2296            output.append(7)
2297        output.append(8)
2298
2299    @async_jump_test(1, 7, [7, 8])
2300    async def test_jump_over_async_for_block_before_else(output):
2301        output.append(1)
2302        if not output:  # always false
2303            async for i in asynciter([3]):
2304                output.append(4)
2305        else:
2306            output.append(6)
2307            output.append(7)
2308        output.append(8)
2309
2310    # The second set of 'jump' tests are for things that are not allowed:
2311
2312    @jump_test(2, 3, [1], (ValueError, 'after'))
2313    def test_no_jump_too_far_forwards(output):
2314        output.append(1)
2315        output.append(2)
2316
2317    @jump_test(2, -2, [1], (ValueError, 'before'))
2318    def test_no_jump_too_far_backwards(output):
2319        output.append(1)
2320        output.append(2)
2321
2322    # Test each kind of 'except' line.
2323    @jump_test(2, 3, [4], (ValueError, 'except'))
2324    def test_no_jump_to_except_1(output):
2325        try:
2326            output.append(2)
2327        except:
2328            output.append(4)
2329            raise
2330
2331    @jump_test(2, 3, [4], (ValueError, 'except'))
2332    def test_no_jump_to_except_2(output):
2333        try:
2334            output.append(2)
2335        except ValueError:
2336            output.append(4)
2337            raise
2338
2339    @jump_test(2, 3, [4], (ValueError, 'except'))
2340    def test_no_jump_to_except_3(output):
2341        try:
2342            output.append(2)
2343        except ValueError as e:
2344            output.append(4)
2345            raise e
2346
2347    @jump_test(2, 3, [4], (ValueError, 'except'))
2348    def test_no_jump_to_except_4(output):
2349        try:
2350            output.append(2)
2351        except (ValueError, RuntimeError) as e:
2352            output.append(4)
2353            raise e
2354
2355    @jump_test(1, 3, [], (ValueError, 'into'))
2356    def test_no_jump_forwards_into_for_block(output):
2357        output.append(1)
2358        for i in 1, 2:
2359            output.append(3)
2360
2361    @async_jump_test(1, 3, [], (ValueError, 'into'))
2362    async def test_no_jump_forwards_into_async_for_block(output):
2363        output.append(1)
2364        async for i in asynciter([1, 2]):
2365            output.append(3)
2366        pass
2367
2368    @jump_test(3, 2, [2, 2], (ValueError, 'into'))
2369    def test_no_jump_backwards_into_for_block(output):
2370        for i in 1, 2:
2371            output.append(2)
2372        output.append(3)
2373
2374    @async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop"))
2375    async def test_no_jump_backwards_into_async_for_block(output):
2376        async for i in asynciter([1, 2]):
2377            output.append(2)
2378        output.append(3)
2379
2380    @jump_test(1, 3, [], (ValueError, 'stack'))
2381    def test_no_jump_forwards_into_with_block(output):
2382        output.append(1)
2383        with tracecontext(output, 2):
2384            output.append(3)
2385
2386    @async_jump_test(1, 3, [], (ValueError, 'stack'))
2387    async def test_no_jump_forwards_into_async_with_block(output):
2388        output.append(1)
2389        async with asynctracecontext(output, 2):
2390            output.append(3)
2391
2392    @jump_test(3, 2, [1, 2, -1], (ValueError, 'stack'))
2393    def test_no_jump_backwards_into_with_block(output):
2394        with tracecontext(output, 1):
2395            output.append(2)
2396        output.append(3)
2397
2398    @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'stack'))
2399    async def test_no_jump_backwards_into_async_with_block(output):
2400        async with asynctracecontext(output, 1):
2401            output.append(2)
2402        output.append(3)
2403
2404    @jump_test(1, 3, [3, 5])
2405    def test_jump_forwards_into_try_finally_block(output):
2406        output.append(1)
2407        try:
2408            output.append(3)
2409        finally:
2410            output.append(5)
2411
2412    @jump_test(5, 2, [2, 4, 2, 4, 5])
2413    def test_jump_backwards_into_try_finally_block(output):
2414        try:
2415            output.append(2)
2416        finally:
2417            output.append(4)
2418        output.append(5)
2419
2420    @jump_test(1, 3, [3])
2421    def test_jump_forwards_into_try_except_block(output):
2422        output.append(1)
2423        try:
2424            output.append(3)
2425        except:
2426            output.append(5)
2427            raise
2428
2429    @jump_test(6, 2, [2, 2, 6])
2430    def test_jump_backwards_into_try_except_block(output):
2431        try:
2432            output.append(2)
2433        except:
2434            output.append(4)
2435            raise
2436        output.append(6)
2437
2438    # 'except' with a variable creates an implicit finally block
2439    @jump_test(5, 7, [4, 7, 8])
2440    def test_jump_between_except_blocks_2(output):
2441        try:
2442            1/0
2443        except ZeroDivisionError:
2444            output.append(4)
2445            output.append(5)
2446        except FloatingPointError as e:
2447            output.append(7)
2448        output.append(8)
2449
2450    @jump_test(1, 5, [5])
2451    def test_jump_into_finally_block(output):
2452        output.append(1)
2453        try:
2454            output.append(3)
2455        finally:
2456            output.append(5)
2457
2458    @jump_test(3, 6, [2, 6, 7])
2459    def test_jump_into_finally_block_from_try_block(output):
2460        try:
2461            output.append(2)
2462            output.append(3)
2463        finally:  # still executed if the jump is failed
2464            output.append(5)
2465            output.append(6)
2466        output.append(7)
2467
2468    @jump_test(5, 1, [1, 3, 1, 3, 5])
2469    def test_jump_out_of_finally_block(output):
2470        output.append(1)
2471        try:
2472            output.append(3)
2473        finally:
2474            output.append(5)
2475
2476    @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception"))
2477    def test_no_jump_into_bare_except_block(output):
2478        output.append(1)
2479        try:
2480            output.append(3)
2481        except:
2482            output.append(5)
2483
2484    @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception"))
2485    def test_no_jump_into_qualified_except_block(output):
2486        output.append(1)
2487        try:
2488            output.append(3)
2489        except Exception:
2490            output.append(5)
2491
2492    @jump_test(3, 6, [2, 5, 6], (ValueError, "can't jump into an 'except' block as there's no exception"))
2493    def test_no_jump_into_bare_except_block_from_try_block(output):
2494        try:
2495            output.append(2)
2496            output.append(3)
2497        except:  # executed if the jump is failed
2498            output.append(5)
2499            output.append(6)
2500            raise
2501        output.append(8)
2502
2503    @jump_test(3, 6, [2], (ValueError, "can't jump into an 'except' block as there's no exception"))
2504    def test_no_jump_into_qualified_except_block_from_try_block(output):
2505        try:
2506            output.append(2)
2507            output.append(3)
2508        except ZeroDivisionError:
2509            output.append(5)
2510            output.append(6)
2511            raise
2512        output.append(8)
2513
2514    @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7])
2515    def test_jump_out_of_bare_except_block(output):
2516        output.append(1)
2517        try:
2518            output.append(3)
2519            1/0
2520        except:
2521            output.append(6)
2522            output.append(7)
2523
2524    @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7])
2525    def test_jump_out_of_qualified_except_block(output):
2526        output.append(1)
2527        try:
2528            output.append(3)
2529            1/0
2530        except Exception:
2531            output.append(6)
2532            output.append(7)
2533
2534    @jump_test(3, 5, [1, 2, 5, -2])
2535    def test_jump_between_with_blocks(output):
2536        output.append(1)
2537        with tracecontext(output, 2):
2538            output.append(3)
2539        with tracecontext(output, 4):
2540            output.append(5)
2541
2542    @async_jump_test(3, 5, [1, 2, 5, -2])
2543    async def test_jump_between_async_with_blocks(output):
2544        output.append(1)
2545        async with asynctracecontext(output, 2):
2546            output.append(3)
2547        async with asynctracecontext(output, 4):
2548            output.append(5)
2549
2550    @jump_test(5, 7, [2, 4], (ValueError, "after"))
2551    def test_no_jump_over_return_out_of_finally_block(output):
2552        try:
2553            output.append(2)
2554        finally:
2555            output.append(4)
2556            output.append(5)
2557            return
2558        output.append(7)
2559
2560    @jump_test(7, 4, [1, 6], (ValueError, 'into'))
2561    def test_no_jump_into_for_block_before_else(output):
2562        output.append(1)
2563        if not output:  # always false
2564            for i in [3]:
2565                output.append(4)
2566        else:
2567            output.append(6)
2568            output.append(7)
2569        output.append(8)
2570
2571    @async_jump_test(7, 4, [1, 6], (ValueError, 'into'))
2572    async def test_no_jump_into_async_for_block_before_else(output):
2573        output.append(1)
2574        if not output:  # always false
2575            async for i in asynciter([3]):
2576                output.append(4)
2577        else:
2578            output.append(6)
2579            output.append(7)
2580        output.append(8)
2581
2582    def test_no_jump_to_non_integers(self):
2583        self.run_test(no_jump_to_non_integers, 2, "Spam", [True])
2584
2585    def test_no_jump_without_trace_function(self):
2586        # Must set sys.settrace(None) in setUp(), else condition is not
2587        # triggered.
2588        no_jump_without_trace_function()
2589
2590    def test_large_function(self):
2591        d = {}
2592        exec("""def f(output):        # line 0
2593            x = 0                     # line 1
2594            y = 1                     # line 2
2595            '''                       # line 3
2596            %s                        # lines 4-1004
2597            '''                       # line 1005
2598            x += 1                    # line 1006
2599            output.append(x)          # line 1007
2600            return""" % ('\n' * 1000,), d)
2601        f = d['f']
2602        self.run_test(f, 2, 1007, [0])
2603
2604    def test_jump_to_firstlineno(self):
2605        # This tests that PDB can jump back to the first line in a
2606        # file.  See issue #1689458.  It can only be triggered in a
2607        # function call if the function is defined on a single line.
2608        code = compile("""
2609# Comments don't count.
2610output.append(2)  # firstlineno is here.
2611output.append(3)
2612output.append(4)
2613""", "<fake module>", "exec")
2614        class fake_function:
2615            __code__ = code
2616        tracer = JumpTracer(fake_function, 4, 1)
2617        sys.settrace(tracer.trace)
2618        namespace = {"output": []}
2619        exec(code, namespace)
2620        sys.settrace(None)
2621        self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
2622
2623    @jump_test(2, 3, [1], event='call', error=(ValueError, "can't jump from"
2624               " the 'call' trace event of a new frame"))
2625    def test_no_jump_from_call(output):
2626        output.append(1)
2627        def nested():
2628            output.append(3)
2629        nested()
2630        output.append(5)
2631
2632    @jump_test(2, 1, [1], event='return', error=(ValueError,
2633               "can only jump from a 'line' trace event"))
2634    def test_no_jump_from_return_event(output):
2635        output.append(1)
2636        return
2637
2638    @jump_test(2, 1, [1], event='exception', error=(ValueError,
2639               "can only jump from a 'line' trace event"))
2640    def test_no_jump_from_exception_event(output):
2641        output.append(1)
2642        1 / 0
2643
2644    @jump_test(3, 2, [2, 5], event='return')
2645    def test_jump_from_yield(output):
2646        def gen():
2647            output.append(2)
2648            yield 3
2649        next(gen())
2650        output.append(5)
2651
2652    @jump_test(2, 3, [1, 3])
2653    def test_jump_forward_over_listcomp(output):
2654        output.append(1)
2655        x = [i for i in range(10)]
2656        output.append(3)
2657
2658    # checking for segfaults.
2659    # See https://github.com/python/cpython/issues/92311
2660    @jump_test(3, 1, [])
2661    def test_jump_backward_over_listcomp(output):
2662        a = 1
2663        x = [i for i in range(10)]
2664        c = 3
2665
2666    @jump_test(8, 2, [2, 7, 2])
2667    def test_jump_backward_over_listcomp_v2(output):
2668        flag = False
2669        output.append(2)
2670        if flag:
2671            return
2672        x = [i for i in range(5)]
2673        flag = 6
2674        output.append(7)
2675        output.append(8)
2676
2677    @async_jump_test(2, 3, [1, 3])
2678    async def test_jump_forward_over_async_listcomp(output):
2679        output.append(1)
2680        x = [i async for i in asynciter(range(10))]
2681        output.append(3)
2682
2683    @async_jump_test(3, 1, [])
2684    async def test_jump_backward_over_async_listcomp(output):
2685        a = 1
2686        x = [i async for i in asynciter(range(10))]
2687        c = 3
2688
2689    @async_jump_test(8, 2, [2, 7, 2])
2690    async def test_jump_backward_over_async_listcomp_v2(output):
2691        flag = False
2692        output.append(2)
2693        if flag:
2694            return
2695        x = [i async for i in asynciter(range(5))]
2696        flag = 6
2697        output.append(7)
2698        output.append(8)
2699
2700    # checking for segfaults.
2701    @jump_test(3, 7, [], error=(ValueError, "stack"))
2702    def test_jump_with_null_on_stack_load_global(output):
2703        a = 1
2704        print(
2705            output.append(3)
2706        )
2707        output.append(5)
2708        (
2709            ( # 7
2710                a
2711                +
2712                10
2713            )
2714            +
2715            13
2716        )
2717        output.append(15)
2718
2719    # checking for segfaults.
2720    @jump_test(4, 8, [], error=(ValueError, "stack"))
2721    def test_jump_with_null_on_stack_push_null(output):
2722        a = 1
2723        f = print
2724        f(
2725            output.append(4)
2726        )
2727        output.append(6)
2728        (
2729            ( # 8
2730                a
2731                +
2732                11
2733            )
2734            +
2735            14
2736        )
2737        output.append(16)
2738
2739    # checking for segfaults.
2740    @jump_test(3, 7, [], error=(ValueError, "stack"))
2741    def test_jump_with_null_on_stack_load_attr(output):
2742        a = 1
2743        list.append(
2744            output, 3
2745        )
2746        output.append(5)
2747        (
2748            ( # 7
2749                a
2750                +
2751                10
2752            )
2753            +
2754            13
2755        )
2756        output.append(15)
2757
2758    @jump_test(2, 3, [1, 3])
2759    def test_jump_extended_args_unpack_ex_simple(output):
2760        output.append(1)
2761        _, *_, _ = output.append(2) or "Spam"
2762        output.append(3)
2763
2764    @jump_test(3, 4, [1, 4, 4, 5])
2765    def test_jump_extended_args_unpack_ex_tricky(output):
2766        output.append(1)
2767        (
2768            _, *_, _
2769        ) = output.append(4) or "Spam"
2770        output.append(5)
2771
2772    def test_jump_extended_args_for_iter(self):
2773        # In addition to failing when extended arg handling is broken, this can
2774        # also hang for a *very* long time:
2775        source = [
2776            "def f(output):",
2777            "    output.append(1)",
2778            "    for _ in spam:",
2779            *(f"        output.append({i})" for i in range(3, 100_000)),
2780            f"    output.append(100_000)",
2781        ]
2782        namespace = {}
2783        exec("\n".join(source), namespace)
2784        f = namespace["f"]
2785        self.run_test(f,  2, 100_000, [1, 100_000])
2786
2787    @jump_test(2, 3, [1, 3])
2788    def test_jump_or_pop(output):
2789        output.append(1)
2790        _ = output.append(2) and "Spam"
2791        output.append(3)
2792
2793
2794class TestExtendedArgs(unittest.TestCase):
2795
2796    def setUp(self):
2797        self.addCleanup(sys.settrace, sys.gettrace())
2798        sys.settrace(None)
2799
2800    def count_traces(self, func):
2801        # warmup
2802        for _ in range(20):
2803            func()
2804
2805        counts = {"call": 0, "line": 0, "return": 0}
2806        def trace(frame, event, arg):
2807            counts[event] += 1
2808            return trace
2809
2810        sys.settrace(trace)
2811        func()
2812        sys.settrace(None)
2813
2814        return counts
2815
2816    def test_trace_unpack_long_sequence(self):
2817        ns = {}
2818        code = "def f():\n  (" + "y,\n   "*300 + ") = range(300)"
2819        exec(code, ns)
2820        counts = self.count_traces(ns["f"])
2821        self.assertEqual(counts, {'call': 1, 'line': 301, 'return': 1})
2822
2823    def test_trace_lots_of_globals(self):
2824        code = """if 1:
2825            def f():
2826                return (
2827                    {}
2828                )
2829        """.format("\n+\n".join(f"var{i}\n" for i in range(1000)))
2830        ns = {f"var{i}": i for i in range(1000)}
2831        exec(code, ns)
2832        counts = self.count_traces(ns["f"])
2833        self.assertEqual(counts, {'call': 1, 'line': 2000, 'return': 1})
2834
2835
2836class TestEdgeCases(unittest.TestCase):
2837
2838    def setUp(self):
2839        self.addCleanup(sys.settrace, sys.gettrace())
2840        sys.settrace(None)
2841
2842    def test_reentrancy(self):
2843        def foo(*args):
2844            ...
2845
2846        def bar(*args):
2847            ...
2848
2849        class A:
2850            def __call__(self, *args):
2851                pass
2852
2853            def __del__(self):
2854                sys.settrace(bar)
2855
2856        sys.settrace(A())
2857        with support.catch_unraisable_exception() as cm:
2858            sys.settrace(foo)
2859            self.assertEqual(cm.unraisable.object, A.__del__)
2860            self.assertIsInstance(cm.unraisable.exc_value, RuntimeError)
2861
2862        self.assertEqual(sys.gettrace(), foo)
2863
2864
2865    def test_same_object(self):
2866        def foo(*args):
2867            ...
2868
2869        sys.settrace(foo)
2870        del foo
2871        sys.settrace(sys.gettrace())
2872
2873
2874if __name__ == "__main__":
2875    unittest.main()
2876