PageRenderTime 49ms CodeModel.GetById 2ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_trace.py

http://unladen-swallow.googlecode.com/
Python | 837 lines | 734 code | 63 blank | 40 comment | 31 complexity | 43d710b2cbd32d7be7422086fa653033 MD5 | raw file
  1# Testing the line trace facility.
  2
  3from test import test_support
  4import unittest
  5import sys
  6import difflib
  7import gc
  8
  9# A very basic example.  If this fails, we're in deep trouble.
 10def basic():
 11    return 1
 12
 13basic.events = [(0, 'call'),
 14                (1, 'line'),
 15                (1, 'return')]
 16
 17# Many of the tests below are tricky because they involve pass statements.
 18# If there is implicit control flow around a pass statement (in an except
 19# clause or else caluse) under what conditions do you set a line number
 20# following that clause?
 21
 22
 23# The entire "while 0:" statement is optimized away.  No code
 24# exists for it, so the line numbers skip directly from "del x"
 25# to "x = 1".
 26def arigo_example():
 27    x = 1
 28    del x
 29    while 0:
 30        pass
 31    x = 1
 32
 33arigo_example.events = [(0, 'call'),
 34                        (1, 'line'),
 35                        (2, 'line'),
 36                        (5, 'line'),
 37                        (5, 'return')]
 38
 39# check that lines consisting of just one instruction get traced:
 40def one_instr_line():
 41    x = 1
 42    del x
 43    x = 1
 44
 45one_instr_line.events = [(0, 'call'),
 46                         (1, 'line'),
 47                         (2, 'line'),
 48                         (3, 'line'),
 49                         (3, 'return')]
 50
 51def no_pop_tops():      # 0
 52    x = 1               # 1
 53    for a in range(2):  # 2
 54        if a:           # 3
 55            x = 1       # 4
 56        else:           # 5
 57            x = 1       # 6
 58
 59no_pop_tops.events = [(0, 'call'),
 60                      (1, 'line'),
 61                      (2, 'line'),
 62                      (3, 'line'),
 63                      (6, 'line'),
 64                      (2, 'line'),
 65                      (3, 'line'),
 66                      (4, 'line'),
 67                      (2, 'line'),
 68                      (2, 'return')]
 69
 70def no_pop_blocks():
 71    y = 1
 72    while not y:
 73        bla
 74    x = 1
 75
 76no_pop_blocks.events = [(0, 'call'),
 77                        (1, 'line'),
 78                        (2, 'line'),
 79                        (4, 'line'),
 80                        (4, 'return')]
 81
 82def called(): # line -3
 83    x = 1
 84
 85def call():   # line 0
 86    called()
 87
 88call.events = [(0, 'call'),
 89               (1, 'line'),
 90               (-3, 'call'),
 91               (-2, 'line'),
 92               (-2, 'return'),
 93               (1, 'return')]
 94
 95def raises():
 96    raise Exception
 97
 98def test_raise():
 99    try:
100        raises()
101    except Exception, exc:
102        x = 1
103
104test_raise.events = [(0, 'call'),
105                     (1, 'line'),
106                     (2, 'line'),
107                     (-3, 'call'),
108                     (-2, 'line'),
109                     (-2, 'exception'),
110                     (-2, 'return'),
111                     (2, 'exception'),
112                     (3, 'line'),
113                     (4, 'line'),
114                     (4, 'return')]
115
116def _settrace_and_return(tracefunc):
117    sys.settrace(tracefunc)
118    sys._getframe().f_back.f_trace = tracefunc
119def settrace_and_return(tracefunc):
120    _settrace_and_return(tracefunc)
121
122settrace_and_return.events = [(1, 'return')]
123
124def _settrace_and_raise(tracefunc):
125    sys.settrace(tracefunc)
126    sys._getframe().f_back.f_trace = tracefunc
127    raise RuntimeError
128def settrace_and_raise(tracefunc):
129    try:
130        _settrace_and_raise(tracefunc)
131    except RuntimeError, exc:
132        pass
133
134settrace_and_raise.events = [(2, 'exception'),
135                             (3, 'line'),
136                             (4, 'line'),
137                             (4, 'return')]
138
139# implicit return example
140# This test is interesting because of the else: pass
141# part of the code.  The code generate for the true
142# part of the if contains a jump past the else branch.
143# The compiler then generates an implicit "return None"
144# Internally, the compiler visits the pass statement
145# and stores its line number for use on the next instruction.
146# The next instruction is the implicit return None.
147def ireturn_example():
148    a = 5
149    b = 5
150    if a == b:
151        b = a+1
152    else:
153        pass
154
155ireturn_example.events = [(0, 'call'),
156                          (1, 'line'),
157                          (2, 'line'),
158                          (3, 'line'),
159                          (4, 'line'),
160                          (6, 'line'),
161                          (6, 'return')]
162
163# Tight loop with while(1) example (SF #765624)
164def tightloop_example():
165    items = range(0, 3)
166    try:
167        i = 0
168        while 1:
169            b = items[i]; i+=1
170    except IndexError:
171        pass
172
173tightloop_example.events = [(0, 'call'),
174                            (1, 'line'),
175                            (2, 'line'),
176                            (3, 'line'),
177                            (4, 'line'),
178                            (5, 'line'),
179                            (5, 'line'),
180                            (5, 'line'),
181                            (5, 'line'),
182                            (5, 'exception'),
183                            (6, 'line'),
184                            (7, 'line'),
185                            (7, 'return')]
186
187def tighterloop_example():
188    items = range(1, 4)
189    try:
190        i = 0
191        while 1: i = items[i]
192    except IndexError:
193        pass
194
195tighterloop_example.events = [(0, 'call'),
196                            (1, 'line'),
197                            (2, 'line'),
198                            (3, 'line'),
199                            (4, 'line'),
200                            (4, 'line'),
201                            (4, 'line'),
202                            (4, 'line'),
203                            (4, 'exception'),
204                            (5, 'line'),
205                            (6, 'line'),
206                            (6, 'return')]
207
208def generator_function():
209    try:
210        yield True
211        "continued"
212    finally:
213        "finally"
214def generator_example():
215    # any() will leave the generator before its end
216    x = any(generator_function())
217
218    # the following lines were not traced
219    for x in range(10):
220        y = x
221
222generator_example.events = ([(0, 'call'),
223                             (2, 'line'),
224                             (-6, 'call'),
225                             (-5, 'line'),
226                             (-4, 'line'),
227                             (-4, 'return'),
228                             (-4, 'call'),
229                             (-4, 'exception'),
230                             (-1, 'line'),
231                             (-1, 'return')] +
232                            [(5, 'line'), (6, 'line')] * 10 +
233                            [(5, 'line'), (5, 'return')])
234
235
236class Tracer:
237    def __init__(self):
238        self.events = []
239    def trace(self, frame, event, arg):
240        self.events.append((frame.f_lineno, event))
241        return self.trace
242    def traceWithGenexp(self, frame, event, arg):
243        (o for o in [1])
244        self.events.append((frame.f_lineno, event))
245        return self.trace
246
247class TraceTestCase(unittest.TestCase):
248
249    # Disable gc collection when tracing, otherwise the
250    # deallocators may be traced as well.
251    def setUp(self):
252        self.using_gc = gc.isenabled()
253        gc.disable()
254
255    def tearDown(self):
256        if self.using_gc:
257            gc.enable()
258
259    def compare_events(self, line_offset, events, expected_events):
260        events = [(l - line_offset, e) for (l, e) in events]
261        if events != expected_events:
262            self.fail(
263                "events did not match expectation:\n" +
264                "\n".join(difflib.ndiff([str(x) for x in expected_events],
265                                        [str(x) for x in events])))
266
267    def run_and_compare(self, func, events):
268        tracer = Tracer()
269        sys.settrace(tracer.trace)
270        func()
271        sys.settrace(None)
272        self.compare_events(func.func_code.co_firstlineno,
273                            tracer.events, events)
274
275    def run_test(self, func):
276        self.run_and_compare(func, func.events)
277
278    def run_test2(self, func):
279        tracer = Tracer()
280        func(tracer.trace)
281        sys.settrace(None)
282        self.compare_events(func.func_code.co_firstlineno,
283                            tracer.events, func.events)
284
285    def set_and_retrieve_none(self):
286        sys.settrace(None)
287        assert sys.gettrace() is None
288
289    def set_and_retrieve_func(self):
290        def fn(*args):
291            pass
292
293        sys.settrace(fn)
294        try:
295            assert sys.gettrace() is fn
296        finally:
297            sys.settrace(None)
298
299    def test_01_basic(self):
300        self.run_test(basic)
301    def test_02_arigo(self):
302        self.run_test(arigo_example)
303    def test_03_one_instr(self):
304        self.run_test(one_instr_line)
305    def test_04_no_pop_blocks(self):
306        self.run_test(no_pop_blocks)
307    def test_05_no_pop_tops(self):
308        self.run_test(no_pop_tops)
309    def test_06_call(self):
310        self.run_test(call)
311    def test_07_raise(self):
312        self.run_test(test_raise)
313
314    def test_08_settrace_and_return(self):
315        self.run_test2(settrace_and_return)
316    def test_09_settrace_and_raise(self):
317        self.run_test2(settrace_and_raise)
318    def test_10_ireturn(self):
319        self.run_test(ireturn_example)
320    def test_11_tightloop(self):
321        self.run_test(tightloop_example)
322    def test_12_tighterloop(self):
323        self.run_test(tighterloop_example)
324
325    def test_13_genexp(self):
326        self.run_test(generator_example)
327        # issue1265: if the trace function contains a generator,
328        # and if the traced function contains another generator
329        # that is not completely exhausted, the trace stopped.
330        # Worse: the 'finally' clause was not invoked.
331        tracer = Tracer()
332        sys.settrace(tracer.traceWithGenexp)
333        generator_example()
334        sys.settrace(None)
335        self.compare_events(generator_example.__code__.co_firstlineno,
336                            tracer.events, generator_example.events)
337
338    def test_14_onliner_if(self):
339        def onliners():
340            if True: False
341            else: True
342            return 0
343        self.run_and_compare(
344            onliners,
345            [(0, 'call'),
346             (1, 'line'),
347             (3, 'line'),
348             (3, 'return')])
349
350    def test_15_loops(self):
351        # issue1750076: "while" expression is skipped by debugger
352        def for_example():
353            for x in range(2):
354                pass
355        self.run_and_compare(
356            for_example,
357            [(0, 'call'),
358             (1, 'line'),
359             (2, 'line'),
360             (1, 'line'),
361             (2, 'line'),
362             (1, 'line'),
363             (1, 'return')])
364
365        def while_example():
366            # While expression should be traced on every loop
367            x = 2
368            while x > 0:
369                x -= 1
370        self.run_and_compare(
371            while_example,
372            [(0, 'call'),
373             (2, 'line'),
374             (3, 'line'),
375             (4, 'line'),
376             (3, 'line'),
377             (4, 'line'),
378             (3, 'line'),
379             (3, 'return')])
380
381    def test_16_blank_lines(self):
382        exec("def f():\n" + "\n" * 256 + "    pass")
383        self.run_and_compare(
384            f,
385            [(0, 'call'),
386             (257, 'line'),
387             (257, 'return')])
388
389    def test_tracing_turned_on_inside_generator(self):
390        def gen():
391            yield 1  # Tracing starts on the re-entry from this yield.
392            yield 2
393        tracer = Tracer()
394        g = gen()
395        v1 = g.next()
396        sys.settrace(tracer.trace)
397        v2 = g.next()
398        try:
399            g.next()
400        except StopIteration:
401            pass
402        else:
403            self.fail('Expected StopIteration')
404        sys.settrace(None)
405        self.compare_events(gen.func_code.co_firstlineno,
406                            tracer.events,
407                            [(1, 'call'),
408                             (2, 'line'),
409                             (2, 'return'),
410                             (2, 'call'),
411                             (2, 'return')])
412        self.assertEquals((v1, v2), (1, 2))
413
414
415class RaisingTraceFuncTestCase(unittest.TestCase):
416    def trace(self, frame, event, arg):
417        """A trace function that raises an exception in response to a
418        specific trace event."""
419        self.output.append(event)
420        if event == self.raiseOnEvent:
421            raise ValueError # just something that isn't RuntimeError
422        else:
423            return self.trace
424
425    def f(self):
426        """The function to trace; raises an exception if that's the case
427        we're testing, so that the 'exception' trace event fires."""
428        if self.raiseOnEvent == 'exception':
429            x = 0
430            y = 1/x
431        else:
432            return 1
433
434    def run_test_for_event(self, event, expected_events):
435        """Tests that an exception raised in response to the given event is
436        handled OK."""
437        self.raiseOnEvent = event
438        try:
439            for i in xrange(sys.getrecursionlimit() + 1):
440                self.output = []
441                sys.settrace(self.trace)
442                try:
443                    self.f()
444                except ValueError:
445                    pass
446                else:
447                    self.fail("exception not thrown!")
448                self.assertEquals(self.output, expected_events)
449        except RuntimeError:
450            self.fail("recursion counter not reset")
451
452    # Test the handling of exceptions raised by each kind of trace event.
453    def test_call(self):
454        self.run_test_for_event('call', ['call'])
455    def test_line(self):
456        self.run_test_for_event('line', ['call', 'line'])
457    def test_return(self):
458        self.run_test_for_event('return', ['call', 'line', 'line', 'return'])
459    def test_exception(self):
460        self.run_test_for_event('exception',
461                                ['call', 'line', 'line', 'line', 'exception'])
462
463    def test_trash_stack(self):
464        def f():
465            for i in range(5):
466                print i  # line tracing will raise an exception at this line
467
468        def g(frame, why, extra):
469            if (why == 'line' and
470                frame.f_lineno == f.func_code.co_firstlineno + 2):
471                raise RuntimeError, "i am crashing"
472            return g
473
474        sys.settrace(g)
475        try:
476            f()
477        except RuntimeError:
478            # the test is really that this doesn't segfault:
479            import gc
480            gc.collect()
481        else:
482            self.fail("exception not propagated")
483
484
485# 'Jump' tests: assigning to frame.f_lineno within a trace function
486# moves the execution position - it's how debuggers implement a Jump
487# command (aka. "Set next statement").
488
489class JumpTracer:
490    """Defines a trace function that jumps from one place to another,
491    with the source and destination lines of the jump being defined by
492    the 'jump' property of the function under test."""
493
494    def __init__(self, function):
495        self.function = function
496        self.jumpFrom = function.jump[0]
497        self.jumpTo = function.jump[1]
498        self.done = False
499
500    def trace(self, frame, event, arg):
501        if not self.done and frame.f_code == self.function.func_code:
502            firstLine = frame.f_code.co_firstlineno
503            if frame.f_lineno == firstLine + self.jumpFrom:
504                # Cope with non-integer self.jumpTo (because of
505                # no_jump_to_non_integers below).
506                try:
507                    frame.f_lineno = firstLine + self.jumpTo
508                except TypeError:
509                    frame.f_lineno = self.jumpTo
510                self.done = True
511        return self.trace
512
513# The first set of 'jump' tests are for things that are allowed:
514
515def jump_simple_forwards(output):
516    output.append(1)
517    output.append(2)
518    output.append(3)
519
520jump_simple_forwards.jump = (1, 3)
521jump_simple_forwards.output = [3]
522
523def jump_simple_backwards(output):
524    output.append(1)
525    output.append(2)
526
527jump_simple_backwards.jump = (2, 1)
528jump_simple_backwards.output = [1, 1, 2]
529
530def jump_out_of_block_forwards(output):
531    for i in 1, 2:
532        output.append(2)
533        for j in [3]:  # Also tests jumping over a block
534            output.append(4)
535    output.append(5)
536
537jump_out_of_block_forwards.jump = (3, 5)
538jump_out_of_block_forwards.output = [2, 5]
539
540def jump_out_of_block_backwards(output):
541    output.append(1)
542    for i in [1]:
543        output.append(3)
544        for j in [2]:  # Also tests jumping over a block
545            output.append(5)
546        output.append(6)
547    output.append(7)
548
549jump_out_of_block_backwards.jump = (6, 1)
550jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
551
552def jump_to_codeless_line(output):
553    output.append(1)
554    # Jumping to this line should skip to the next one.
555    output.append(3)
556
557jump_to_codeless_line.jump = (1, 2)
558jump_to_codeless_line.output = [3]
559
560def jump_to_same_line(output):
561    output.append(1)
562    output.append(2)
563    output.append(3)
564
565jump_to_same_line.jump = (2, 2)
566jump_to_same_line.output = [1, 2, 3]
567
568# Tests jumping within a finally block, and over one.
569def jump_in_nested_finally(output):
570    try:
571        output.append(2)
572    finally:
573        output.append(4)
574        try:
575            output.append(6)
576        finally:
577            output.append(8)
578        output.append(9)
579
580jump_in_nested_finally.jump = (4, 9)
581jump_in_nested_finally.output = [2, 9]
582
583# The second set of 'jump' tests are for things that are not allowed:
584
585def no_jump_too_far_forwards(output):
586    try:
587        output.append(2)
588        output.append(3)
589    except ValueError, e:
590        output.append('after' in str(e))
591
592no_jump_too_far_forwards.jump = (3, 6)
593no_jump_too_far_forwards.output = [2, True]
594
595def no_jump_too_far_backwards(output):
596    try:
597        output.append(2)
598        output.append(3)
599    except ValueError, e:
600        output.append('before' in str(e))
601
602no_jump_too_far_backwards.jump = (3, -1)
603no_jump_too_far_backwards.output = [2, True]
604
605# Test each kind of 'except' line.
606def no_jump_to_except_1(output):
607    try:
608        output.append(2)
609    except:
610        e = sys.exc_info()[1]
611        output.append('except' in str(e))
612
613no_jump_to_except_1.jump = (2, 3)
614no_jump_to_except_1.output = [True]
615
616def no_jump_to_except_2(output):
617    try:
618        output.append(2)
619    except ValueError:
620        e = sys.exc_info()[1]
621        output.append('except' in str(e))
622
623no_jump_to_except_2.jump = (2, 3)
624no_jump_to_except_2.output = [True]
625
626def no_jump_to_except_3(output):
627    try:
628        output.append(2)
629    except ValueError, e:
630        output.append('except' in str(e))
631
632no_jump_to_except_3.jump = (2, 3)
633no_jump_to_except_3.output = [True]
634
635def no_jump_to_except_4(output):
636    try:
637        output.append(2)
638    except (ValueError, RuntimeError), e:
639        output.append('except' in str(e))
640
641no_jump_to_except_4.jump = (2, 3)
642no_jump_to_except_4.output = [True]
643
644def no_jump_forwards_into_block(output):
645    try:
646        output.append(2)
647        for i in 1, 2:
648            output.append(4)
649    except ValueError, e:
650        output.append('into' in str(e))
651
652no_jump_forwards_into_block.jump = (2, 4)
653no_jump_forwards_into_block.output = [True]
654
655def no_jump_backwards_into_block(output):
656    try:
657        for i in 1, 2:
658            output.append(3)
659        output.append(4)
660    except ValueError, e:
661        output.append('into' in str(e))
662
663no_jump_backwards_into_block.jump = (4, 3)
664no_jump_backwards_into_block.output = [3, 3, True]
665
666def no_jump_into_finally_block(output):
667    try:
668        try:
669            output.append(3)
670            x = 1
671        finally:
672            output.append(6)
673    except ValueError, e:
674        output.append('finally' in str(e))
675
676no_jump_into_finally_block.jump = (4, 6)
677no_jump_into_finally_block.output = [3, 6, True]  # The 'finally' still runs
678
679def no_jump_out_of_finally_block(output):
680    try:
681        try:
682            output.append(3)
683        finally:
684            output.append(5)
685            output.append(6)
686    except ValueError, e:
687        output.append('finally' in str(e))
688
689no_jump_out_of_finally_block.jump = (5, 1)
690no_jump_out_of_finally_block.output = [3, True]
691
692# This verifies the line-numbers-must-be-integers rule.
693def no_jump_to_non_integers(output):
694    try:
695        output.append(2)
696    except ValueError, e:
697        output.append('integer' in str(e))
698
699no_jump_to_non_integers.jump = (2, "Spam")
700no_jump_to_non_integers.output = [True]
701
702# This verifies that you can't set f_lineno via _getframe or similar
703# trickery.
704def no_jump_without_trace_function():
705    try:
706        previous_frame = sys._getframe().f_back
707        previous_frame.f_lineno = previous_frame.f_lineno
708    except ValueError, e:
709        # This is the exception we wanted; make sure the error message
710        # talks about trace functions.
711        if 'trace' not in str(e):
712            raise
713    else:
714        # Something's wrong - the expected exception wasn't raised.
715        raise RuntimeError, "Trace-function-less jump failed to fail"
716
717
718class JumpTestCase(unittest.TestCase):
719    def compare_jump_output(self, expected, received):
720        if received != expected:
721            self.fail( "Outputs don't match:\n" +
722                       "Expected: " + repr(expected) + "\n" +
723                       "Received: " + repr(received))
724
725    def run_test(self, func):
726        tracer = JumpTracer(func)
727        sys.settrace(tracer.trace)
728        output = []
729        func(output)
730        sys.settrace(None)
731        self.compare_jump_output(func.output, output)
732
733    def test_01_jump_simple_forwards(self):
734        self.run_test(jump_simple_forwards)
735    def test_02_jump_simple_backwards(self):
736        self.run_test(jump_simple_backwards)
737    def test_03_jump_out_of_block_forwards(self):
738        self.run_test(jump_out_of_block_forwards)
739    def test_04_jump_out_of_block_backwards(self):
740        self.run_test(jump_out_of_block_backwards)
741    def test_05_jump_to_codeless_line(self):
742        self.run_test(jump_to_codeless_line)
743    def test_06_jump_to_same_line(self):
744        self.run_test(jump_to_same_line)
745    def test_07_jump_in_nested_finally(self):
746        self.run_test(jump_in_nested_finally)
747    def test_08_no_jump_too_far_forwards(self):
748        self.run_test(no_jump_too_far_forwards)
749    def test_09_no_jump_too_far_backwards(self):
750        self.run_test(no_jump_too_far_backwards)
751    def test_10_no_jump_to_except_1(self):
752        self.run_test(no_jump_to_except_1)
753    def test_11_no_jump_to_except_2(self):
754        self.run_test(no_jump_to_except_2)
755    def test_12_no_jump_to_except_3(self):
756        self.run_test(no_jump_to_except_3)
757    def test_13_no_jump_to_except_4(self):
758        self.run_test(no_jump_to_except_4)
759    def test_14_no_jump_forwards_into_block(self):
760        self.run_test(no_jump_forwards_into_block)
761    def test_15_no_jump_backwards_into_block(self):
762        self.run_test(no_jump_backwards_into_block)
763    def test_16_no_jump_into_finally_block(self):
764        self.run_test(no_jump_into_finally_block)
765    def test_17_no_jump_out_of_finally_block(self):
766        self.run_test(no_jump_out_of_finally_block)
767    def test_18_no_jump_to_non_integers(self):
768        self.run_test(no_jump_to_non_integers)
769    def test_19_no_jump_without_trace_function(self):
770        no_jump_without_trace_function()
771
772    def test_20_large_function(self):
773        d = {}
774        exec("""def f(output):        # line 0
775            x = 0                     # line 1
776            y = 1                     # line 2
777            '''                       # line 3
778            %s                        # lines 4-1004
779            '''                       # line 1005
780            x += 1                    # line 1006
781            output.append(x)          # line 1007
782            return""" % ('\n' * 1000,), d)
783        f = d['f']
784
785        f.jump = (2, 1007)
786        f.output = [0]
787        self.run_test(f)
788
789    def test_no_jump_out_of_finally_after_backedge(self):
790        def loop_in_finally(output):
791            a = 1  # 1
792            try:  # 2
793                if a == 1:  # 3
794                    try:  # 4
795                        output.append(5)
796                    finally:  # 6
797                        while a == 1:  #7
798                            a = 2  # 8
799                output.append(9)
800            except ValueError, e:
801                output.append('finally' in str(e))
802        # We hit line 7 twice in the above code, once from the top as
803        # we enter the finally block, and again from the bottom as the
804        # loop iterates.  The back-edge that keeps the loop iterating
805        # jumps to halfway into the line, so it doesn't get any code
806        # that exists on line entry.  In one version of the LLVM
807        # tracing implementation, this made the block checking
808        # algorithm in set_f_lineno() fail.
809        class SecondJumpTracer:
810            times_hit = 0
811            def trace(self, frame, event, arg):
812                if frame.f_code == loop_in_finally.func_code:
813                    firstLine = frame.f_code.co_firstlineno
814                    if frame.f_lineno == firstLine + 7:
815                        self.times_hit += 1
816                        if self.times_hit == 2:
817                            # Should raise about jumping out of a finally
818                            # block.  The resulting ValueError is caught in
819                            # loop_in_finally().
820                            frame.f_lineno = firstLine + 3
821                return self.trace
822        tracer = SecondJumpTracer()
823        output = []
824        sys.settrace(tracer.trace)
825        loop_in_finally(output)
826        sys.settrace(None)
827        self.compare_jump_output([5, True], output)
828
829def test_main():
830    test_support.run_unittest(
831        TraceTestCase,
832        RaisingTraceFuncTestCase,
833        JumpTestCase
834    )
835
836if __name__ == "__main__":
837    test_main()