Reverted r83143: svnmerge failed to add new names
diff --git a/Lib/test/test_profilehooks.py b/Lib/test/test_profilehooks.py
new file mode 100644
index 0000000..296c997
--- /dev/null
+++ b/Lib/test/test_profilehooks.py
@@ -0,0 +1,385 @@
+import pprint
+import sys
+import unittest
+
+from test import support
+
+class TestGetProfile(unittest.TestCase):
+    def setUp(self):
+        sys.setprofile(None)
+
+    def tearDown(self):
+        sys.setprofile(None)
+
+    def test_empty(self):
+        assert sys.getprofile() == None
+
+    def test_setget(self):
+        def fn(*args):
+            pass
+
+        sys.setprofile(fn)
+        assert sys.getprofile() == fn
+
+class HookWatcher:
+    def __init__(self):
+        self.frames = []
+        self.events = []
+
+    def callback(self, frame, event, arg):
+        if (event == "call"
+            or event == "return"
+            or event == "exception"):
+            self.add_event(event, frame)
+
+    def add_event(self, event, frame=None):
+        """Add an event to the log."""
+        if frame is None:
+            frame = sys._getframe(1)
+
+        try:
+            frameno = self.frames.index(frame)
+        except ValueError:
+            frameno = len(self.frames)
+            self.frames.append(frame)
+
+        self.events.append((frameno, event, ident(frame)))
+
+    def get_events(self):
+        """Remove calls to add_event()."""
+        disallowed = [ident(self.add_event.__func__), ident(ident)]
+        self.frames = None
+
+        return [item for item in self.events if item[2] not in disallowed]
+
+
+class ProfileSimulator(HookWatcher):
+    def __init__(self, testcase):
+        self.testcase = testcase
+        self.stack = []
+        HookWatcher.__init__(self)
+
+    def callback(self, frame, event, arg):
+        # Callback registered with sys.setprofile()/sys.settrace()
+        self.dispatch[event](self, frame)
+
+    def trace_call(self, frame):
+        self.add_event('call', frame)
+        self.stack.append(frame)
+
+    def trace_return(self, frame):
+        self.add_event('return', frame)
+        self.stack.pop()
+
+    def trace_exception(self, frame):
+        self.testcase.fail(
+            "the profiler should never receive exception events")
+
+    def trace_pass(self, frame):
+        pass
+
+    dispatch = {
+        'call': trace_call,
+        'exception': trace_exception,
+        'return': trace_return,
+        'c_call': trace_pass,
+        'c_return': trace_pass,
+        'c_exception': trace_pass,
+        }
+
+
+class TestCaseBase(unittest.TestCase):
+    def check_events(self, callable, expected):
+        events = capture_events(callable, self.new_watcher())
+        if events != expected:
+            self.fail("Expected events:\n%s\nReceived events:\n%s"
+                      % (pprint.pformat(expected), pprint.pformat(events)))
+
+
+class ProfileHookTestCase(TestCaseBase):
+    def new_watcher(self):
+        return HookWatcher()
+
+    def test_simple(self):
+        def f(p):
+            pass
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_exception(self):
+        def f(p):
+            1/0
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_caught_exception(self):
+        def f(p):
+            try: 1/0
+            except: pass
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_caught_nested_exception(self):
+        def f(p):
+            try: 1/0
+            except: pass
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_nested_exception(self):
+        def f(p):
+            1/0
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              # This isn't what I expected:
+                              # (0, 'exception', protect_ident),
+                              # I expected this again:
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_exception_in_except_clause(self):
+        def f(p):
+            1/0
+        def g(p):
+            try:
+                f(p)
+            except:
+                try: f(p)
+                except: pass
+        f_ident = ident(f)
+        g_ident = ident(g)
+        self.check_events(g, [(1, 'call', g_ident),
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (3, 'call', f_ident),
+                              (3, 'return', f_ident),
+                              (1, 'return', g_ident),
+                              ])
+
+    def test_exception_propogation(self):
+        def f(p):
+            1/0
+        def g(p):
+            try: f(p)
+            finally: p.add_event("falling through")
+        f_ident = ident(f)
+        g_ident = ident(g)
+        self.check_events(g, [(1, 'call', g_ident),
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (1, 'falling through', g_ident),
+                              (1, 'return', g_ident),
+                              ])
+
+    def test_raise_twice(self):
+        def f(p):
+            try: 1/0
+            except: 1/0
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_raise_reraise(self):
+        def f(p):
+            try: 1/0
+            except: raise
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_raise(self):
+        def f(p):
+            raise Exception()
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_distant_exception(self):
+        def f():
+            1/0
+        def g():
+            f()
+        def h():
+            g()
+        def i():
+            h()
+        def j(p):
+            i()
+        f_ident = ident(f)
+        g_ident = ident(g)
+        h_ident = ident(h)
+        i_ident = ident(i)
+        j_ident = ident(j)
+        self.check_events(j, [(1, 'call', j_ident),
+                              (2, 'call', i_ident),
+                              (3, 'call', h_ident),
+                              (4, 'call', g_ident),
+                              (5, 'call', f_ident),
+                              (5, 'return', f_ident),
+                              (4, 'return', g_ident),
+                              (3, 'return', h_ident),
+                              (2, 'return', i_ident),
+                              (1, 'return', j_ident),
+                              ])
+
+    def test_generator(self):
+        def f():
+            for i in range(2):
+                yield i
+        def g(p):
+            for i in f():
+                pass
+        f_ident = ident(f)
+        g_ident = ident(g)
+        self.check_events(g, [(1, 'call', g_ident),
+                              # call the iterator twice to generate values
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              # once more; returns end-of-iteration with
+                              # actually raising an exception
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (1, 'return', g_ident),
+                              ])
+
+    def test_stop_iteration(self):
+        def f():
+            for i in range(2):
+                yield i
+            raise StopIteration
+        def g(p):
+            for i in f():
+                pass
+        f_ident = ident(f)
+        g_ident = ident(g)
+        self.check_events(g, [(1, 'call', g_ident),
+                              # call the iterator twice to generate values
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              # once more to hit the raise:
+                              (2, 'call', f_ident),
+                              (2, 'return', f_ident),
+                              (1, 'return', g_ident),
+                              ])
+
+
+class ProfileSimulatorTestCase(TestCaseBase):
+    def new_watcher(self):
+        return ProfileSimulator(self)
+
+    def test_simple(self):
+        def f(p):
+            pass
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_basic_exception(self):
+        def f(p):
+            1/0
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_caught_exception(self):
+        def f(p):
+            try: 1/0
+            except: pass
+        f_ident = ident(f)
+        self.check_events(f, [(1, 'call', f_ident),
+                              (1, 'return', f_ident),
+                              ])
+
+    def test_distant_exception(self):
+        def f():
+            1/0
+        def g():
+            f()
+        def h():
+            g()
+        def i():
+            h()
+        def j(p):
+            i()
+        f_ident = ident(f)
+        g_ident = ident(g)
+        h_ident = ident(h)
+        i_ident = ident(i)
+        j_ident = ident(j)
+        self.check_events(j, [(1, 'call', j_ident),
+                              (2, 'call', i_ident),
+                              (3, 'call', h_ident),
+                              (4, 'call', g_ident),
+                              (5, 'call', f_ident),
+                              (5, 'return', f_ident),
+                              (4, 'return', g_ident),
+                              (3, 'return', h_ident),
+                              (2, 'return', i_ident),
+                              (1, 'return', j_ident),
+                              ])
+
+
+def ident(function):
+    if hasattr(function, "f_code"):
+        code = function.f_code
+    else:
+        code = function.__code__
+    return code.co_firstlineno, code.co_name
+
+
+def protect(f, p):
+    try: f(p)
+    except: pass
+
+protect_ident = ident(protect)
+
+
+def capture_events(callable, p=None):
+    try:
+        sys.setprofile()
+    except TypeError:
+        pass
+    else:
+        raise support.TestFailed(
+            'sys.setprofile() did not raise TypeError')
+
+    if p is None:
+        p = HookWatcher()
+    sys.setprofile(p.callback)
+    protect(callable, p)
+    sys.setprofile(None)
+    return p.get_events()[1:-1]
+
+
+def show_events(callable):
+    import pprint
+    pprint.pprint(capture_events(callable))
+
+
+def test_main():
+    support.run_unittest(
+        TestGetProfile,
+        ProfileHookTestCase,
+        ProfileSimulatorTestCase
+    )
+
+
+if __name__ == "__main__":
+    test_main()
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 398243a..24f17fb 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -164,8 +164,8 @@
         # can't check more than the type, as the user might have changed it
         self.assertTrue(isinstance(sys.getdefaultencoding(), str))
 
-    # testing sys.settrace() is done in test_sys_settrace.py
-    # testing sys.setprofile() is done in test_sys_setprofile.py
+    # testing sys.settrace() is done in test_trace.py
+    # testing sys.setprofile() is done in test_profile.py
 
     def test_setcheckinterval(self):
         self.assertRaises(TypeError, sys.setcheckinterval)
diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py
new file mode 100644
index 0000000..43134e9
--- /dev/null
+++ b/Lib/test/test_trace.py
@@ -0,0 +1,790 @@
+# Testing the line trace facility.
+
+from test import support
+import unittest
+import sys
+import difflib
+import gc
+
+# A very basic example.  If this fails, we're in deep trouble.
+def basic():
+    return 1
+
+basic.events = [(0, 'call'),
+                (1, 'line'),
+                (1, 'return')]
+
+# Many of the tests below are tricky because they involve pass statements.
+# If there is implicit control flow around a pass statement (in an except
+# clause or else caluse) under what conditions do you set a line number
+# following that clause?
+
+
+# The entire "while 0:" statement is optimized away.  No code
+# exists for it, so the line numbers skip directly from "del x"
+# to "x = 1".
+def arigo_example():
+    x = 1
+    del x
+    while 0:
+        pass
+    x = 1
+
+arigo_example.events = [(0, 'call'),
+                        (1, 'line'),
+                        (2, 'line'),
+                        (5, 'line'),
+                        (5, 'return')]
+
+# check that lines consisting of just one instruction get traced:
+def one_instr_line():
+    x = 1
+    del x
+    x = 1
+
+one_instr_line.events = [(0, 'call'),
+                         (1, 'line'),
+                         (2, 'line'),
+                         (3, 'line'),
+                         (3, 'return')]
+
+def no_pop_tops():      # 0
+    x = 1               # 1
+    for a in range(2):  # 2
+        if a:           # 3
+            x = 1       # 4
+        else:           # 5
+            x = 1       # 6
+
+no_pop_tops.events = [(0, 'call'),
+                      (1, 'line'),
+                      (2, 'line'),
+                      (3, 'line'),
+                      (6, 'line'),
+                      (2, 'line'),
+                      (3, 'line'),
+                      (4, 'line'),
+                      (2, 'line'),
+                      (2, 'return')]
+
+def no_pop_blocks():
+    y = 1
+    while not y:
+        bla
+    x = 1
+
+no_pop_blocks.events = [(0, 'call'),
+                        (1, 'line'),
+                        (2, 'line'),
+                        (4, 'line'),
+                        (4, 'return')]
+
+def called(): # line -3
+    x = 1
+
+def call():   # line 0
+    called()
+
+call.events = [(0, 'call'),
+               (1, 'line'),
+               (-3, 'call'),
+               (-2, 'line'),
+               (-2, 'return'),
+               (1, 'return')]
+
+def raises():
+    raise Exception
+
+def test_raise():
+    try:
+        raises()
+    except Exception as exc:
+        x = 1
+
+test_raise.events = [(0, 'call'),
+                     (1, 'line'),
+                     (2, 'line'),
+                     (-3, 'call'),
+                     (-2, 'line'),
+                     (-2, 'exception'),
+                     (-2, 'return'),
+                     (2, 'exception'),
+                     (3, 'line'),
+                     (4, 'line'),
+                     (4, 'return')]
+
+def _settrace_and_return(tracefunc):
+    sys.settrace(tracefunc)
+    sys._getframe().f_back.f_trace = tracefunc
+def settrace_and_return(tracefunc):
+    _settrace_and_return(tracefunc)
+
+settrace_and_return.events = [(1, 'return')]
+
+def _settrace_and_raise(tracefunc):
+    sys.settrace(tracefunc)
+    sys._getframe().f_back.f_trace = tracefunc
+    raise RuntimeError
+def settrace_and_raise(tracefunc):
+    try:
+        _settrace_and_raise(tracefunc)
+    except RuntimeError as exc:
+        pass
+
+settrace_and_raise.events = [(2, 'exception'),
+                             (3, 'line'),
+                             (4, 'line'),
+                             (4, 'return')]
+
+# implicit return example
+# This test is interesting because of the else: pass
+# part of the code.  The code generate for the true
+# part of the if contains a jump past the else branch.
+# The compiler then generates an implicit "return None"
+# Internally, the compiler visits the pass statement
+# and stores its line number for use on the next instruction.
+# The next instruction is the implicit return None.
+def ireturn_example():
+    a = 5
+    b = 5
+    if a == b:
+        b = a+1
+    else:
+        pass
+
+ireturn_example.events = [(0, 'call'),
+                          (1, 'line'),
+                          (2, 'line'),
+                          (3, 'line'),
+                          (4, 'line'),
+                          (6, 'line'),
+                          (6, 'return')]
+
+# Tight loop with while(1) example (SF #765624)
+def tightloop_example():
+    items = range(0, 3)
+    try:
+        i = 0
+        while 1:
+            b = items[i]; i+=1
+    except IndexError:
+        pass
+
+tightloop_example.events = [(0, 'call'),
+                            (1, 'line'),
+                            (2, 'line'),
+                            (3, 'line'),
+                            (4, 'line'),
+                            (5, 'line'),
+                            (5, 'line'),
+                            (5, 'line'),
+                            (5, 'line'),
+                            (5, 'exception'),
+                            (6, 'line'),
+                            (7, 'line'),
+                            (7, 'return')]
+
+def tighterloop_example():
+    items = range(1, 4)
+    try:
+        i = 0
+        while 1: i = items[i]
+    except IndexError:
+        pass
+
+tighterloop_example.events = [(0, 'call'),
+                            (1, 'line'),
+                            (2, 'line'),
+                            (3, 'line'),
+                            (4, 'line'),
+                            (4, 'line'),
+                            (4, 'line'),
+                            (4, 'line'),
+                            (4, 'exception'),
+                            (5, 'line'),
+                            (6, 'line'),
+                            (6, 'return')]
+
+def generator_function():
+    try:
+        yield True
+        "continued"
+    finally:
+        "finally"
+def generator_example():
+    # any() will leave the generator before its end
+    x = any(generator_function())
+
+    # the following lines were not traced
+    for x in range(10):
+        y = x
+
+generator_example.events = ([(0, 'call'),
+                             (2, 'line'),
+                             (-6, 'call'),
+                             (-5, 'line'),
+                             (-4, 'line'),
+                             (-4, 'return'),
+                             (-4, 'call'),
+                             (-4, 'exception'),
+                             (-1, 'line'),
+                             (-1, 'return')] +
+                            [(5, 'line'), (6, 'line')] * 10 +
+                            [(5, 'line'), (5, 'return')])
+
+
+class Tracer:
+    def __init__(self):
+        self.events = []
+    def trace(self, frame, event, arg):
+        self.events.append((frame.f_lineno, event))
+        return self.trace
+    def traceWithGenexp(self, frame, event, arg):
+        (o for o in [1])
+        self.events.append((frame.f_lineno, event))
+        return self.trace
+
+class TraceTestCase(unittest.TestCase):
+
+    # Disable gc collection when tracing, otherwise the
+    # deallocators may be traced as well.
+    def setUp(self):
+        self.using_gc = gc.isenabled()
+        gc.disable()
+
+    def tearDown(self):
+        if self.using_gc:
+            gc.enable()
+
+    def compare_events(self, line_offset, events, expected_events):
+        events = [(l - line_offset, e) for (l, e) in events]
+        if events != expected_events:
+            self.fail(
+                "events did not match expectation:\n" +
+                "\n".join(difflib.ndiff([str(x) for x in expected_events],
+                                        [str(x) for x in events])))
+
+    def run_and_compare(self, func, events):
+        tracer = Tracer()
+        sys.settrace(tracer.trace)
+        func()
+        sys.settrace(None)
+        self.compare_events(func.__code__.co_firstlineno,
+                            tracer.events, events)
+
+    def run_test(self, func):
+        self.run_and_compare(func, func.events)
+
+    def run_test2(self, func):
+        tracer = Tracer()
+        func(tracer.trace)
+        sys.settrace(None)
+        self.compare_events(func.__code__.co_firstlineno,
+                            tracer.events, func.events)
+
+    def set_and_retrieve_none(self):
+        sys.settrace(None)
+        assert sys.gettrace() is None
+
+    def set_and_retrieve_func(self):
+        def fn(*args):
+            pass
+
+        sys.settrace(fn)
+        try:
+            assert sys.gettrace() is fn
+        finally:
+            sys.settrace(None)
+
+    def test_01_basic(self):
+        self.run_test(basic)
+    def test_02_arigo(self):
+        self.run_test(arigo_example)
+    def test_03_one_instr(self):
+        self.run_test(one_instr_line)
+    def test_04_no_pop_blocks(self):
+        self.run_test(no_pop_blocks)
+    def test_05_no_pop_tops(self):
+        self.run_test(no_pop_tops)
+    def test_06_call(self):
+        self.run_test(call)
+    def test_07_raise(self):
+        self.run_test(test_raise)
+
+    def test_08_settrace_and_return(self):
+        self.run_test2(settrace_and_return)
+    def test_09_settrace_and_raise(self):
+        self.run_test2(settrace_and_raise)
+    def test_10_ireturn(self):
+        self.run_test(ireturn_example)
+    def test_11_tightloop(self):
+        self.run_test(tightloop_example)
+    def test_12_tighterloop(self):
+        self.run_test(tighterloop_example)
+
+    def test_13_genexp(self):
+        self.run_test(generator_example)
+        # issue1265: if the trace function contains a generator,
+        # and if the traced function contains another generator
+        # that is not completely exhausted, the trace stopped.
+        # Worse: the 'finally' clause was not invoked.
+        tracer = Tracer()
+        sys.settrace(tracer.traceWithGenexp)
+        generator_example()
+        sys.settrace(None)
+        self.compare_events(generator_example.__code__.co_firstlineno,
+                            tracer.events, generator_example.events)
+
+    def test_14_onliner_if(self):
+        def onliners():
+            if True: False
+            else: True
+            return 0
+        self.run_and_compare(
+            onliners,
+            [(0, 'call'),
+             (1, 'line'),
+             (3, 'line'),
+             (3, 'return')])
+
+    def test_15_loops(self):
+        # issue1750076: "while" expression is skipped by debugger
+        def for_example():
+            for x in range(2):
+                pass
+        self.run_and_compare(
+            for_example,
+            [(0, 'call'),
+             (1, 'line'),
+             (2, 'line'),
+             (1, 'line'),
+             (2, 'line'),
+             (1, 'line'),
+             (1, 'return')])
+
+        def while_example():
+            # While expression should be traced on every loop
+            x = 2
+            while x > 0:
+                x -= 1
+        self.run_and_compare(
+            while_example,
+            [(0, 'call'),
+             (2, 'line'),
+             (3, 'line'),
+             (4, 'line'),
+             (3, 'line'),
+             (4, 'line'),
+             (3, 'line'),
+             (3, 'return')])
+
+    def test_16_blank_lines(self):
+        namespace = {}
+        exec("def f():\n" + "\n" * 256 + "    pass", namespace)
+        self.run_and_compare(
+            namespace["f"],
+            [(0, 'call'),
+             (257, 'line'),
+             (257, 'return')])
+
+
+class RaisingTraceFuncTestCase(unittest.TestCase):
+    def trace(self, frame, event, arg):
+        """A trace function that raises an exception in response to a
+        specific trace event."""
+        if event == self.raiseOnEvent:
+            raise ValueError # just something that isn't RuntimeError
+        else:
+            return self.trace
+
+    def f(self):
+        """The function to trace; raises an exception if that's the case
+        we're testing, so that the 'exception' trace event fires."""
+        if self.raiseOnEvent == 'exception':
+            x = 0
+            y = 1/x
+        else:
+            return 1
+
+    def run_test_for_event(self, event):
+        """Tests that an exception raised in response to the given event is
+        handled OK."""
+        self.raiseOnEvent = event
+        try:
+            for i in range(sys.getrecursionlimit() + 1):
+                sys.settrace(self.trace)
+                try:
+                    self.f()
+                except ValueError:
+                    pass
+                else:
+                    self.fail("exception not thrown!")
+        except RuntimeError:
+            self.fail("recursion counter not reset")
+
+    # Test the handling of exceptions raised by each kind of trace event.
+    def test_call(self):
+        self.run_test_for_event('call')
+    def test_line(self):
+        self.run_test_for_event('line')
+    def test_return(self):
+        self.run_test_for_event('return')
+    def test_exception(self):
+        self.run_test_for_event('exception')
+
+    def test_trash_stack(self):
+        def f():
+            for i in range(5):
+                print(i)  # line tracing will raise an exception at this line
+
+        def g(frame, why, extra):
+            if (why == 'line' and
+                frame.f_lineno == f.__code__.co_firstlineno + 2):
+                raise RuntimeError("i am crashing")
+            return g
+
+        sys.settrace(g)
+        try:
+            f()
+        except RuntimeError:
+            # the test is really that this doesn't segfault:
+            import gc
+            gc.collect()
+        else:
+            self.fail("exception not propagated")
+
+
+# 'Jump' tests: assigning to frame.f_lineno within a trace function
+# moves the execution position - it's how debuggers implement a Jump
+# command (aka. "Set next statement").
+
+class JumpTracer:
+    """Defines a trace function that jumps from one place to another,
+    with the source and destination lines of the jump being defined by
+    the 'jump' property of the function under test."""
+
+    def __init__(self, function):
+        self.function = function
+        self.jumpFrom = function.jump[0]
+        self.jumpTo = function.jump[1]
+        self.done = False
+
+    def trace(self, frame, event, arg):
+        if not self.done and frame.f_code == self.function.__code__:
+            firstLine = frame.f_code.co_firstlineno
+            if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
+                # Cope with non-integer self.jumpTo (because of
+                # no_jump_to_non_integers below).
+                try:
+                    frame.f_lineno = firstLine + self.jumpTo
+                except TypeError:
+                    frame.f_lineno = self.jumpTo
+                self.done = True
+        return self.trace
+
+# The first set of 'jump' tests are for things that are allowed:
+
+def jump_simple_forwards(output):
+    output.append(1)
+    output.append(2)
+    output.append(3)
+
+jump_simple_forwards.jump = (1, 3)
+jump_simple_forwards.output = [3]
+
+def jump_simple_backwards(output):
+    output.append(1)
+    output.append(2)
+
+jump_simple_backwards.jump = (2, 1)
+jump_simple_backwards.output = [1, 1, 2]
+
+def jump_out_of_block_forwards(output):
+    for i in 1, 2:
+        output.append(2)
+        for j in [3]:  # Also tests jumping over a block
+            output.append(4)
+    output.append(5)
+
+jump_out_of_block_forwards.jump = (3, 5)
+jump_out_of_block_forwards.output = [2, 5]
+
+def jump_out_of_block_backwards(output):
+    output.append(1)
+    for i in [1]:
+        output.append(3)
+        for j in [2]:  # Also tests jumping over a block
+            output.append(5)
+        output.append(6)
+    output.append(7)
+
+jump_out_of_block_backwards.jump = (6, 1)
+jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
+
+def jump_to_codeless_line(output):
+    output.append(1)
+    # Jumping to this line should skip to the next one.
+    output.append(3)
+
+jump_to_codeless_line.jump = (1, 2)
+jump_to_codeless_line.output = [3]
+
+def jump_to_same_line(output):
+    output.append(1)
+    output.append(2)
+    output.append(3)
+
+jump_to_same_line.jump = (2, 2)
+jump_to_same_line.output = [1, 2, 3]
+
+# Tests jumping within a finally block, and over one.
+def jump_in_nested_finally(output):
+    try:
+        output.append(2)
+    finally:
+        output.append(4)
+        try:
+            output.append(6)
+        finally:
+            output.append(8)
+        output.append(9)
+
+jump_in_nested_finally.jump = (4, 9)
+jump_in_nested_finally.output = [2, 9]
+
+# The second set of 'jump' tests are for things that are not allowed:
+
+def no_jump_too_far_forwards(output):
+    try:
+        output.append(2)
+        output.append(3)
+    except ValueError as e:
+        output.append('after' in str(e))
+
+no_jump_too_far_forwards.jump = (3, 6)
+no_jump_too_far_forwards.output = [2, True]
+
+def no_jump_too_far_backwards(output):
+    try:
+        output.append(2)
+        output.append(3)
+    except ValueError as e:
+        output.append('before' in str(e))
+
+no_jump_too_far_backwards.jump = (3, -1)
+no_jump_too_far_backwards.output = [2, True]
+
+# Test each kind of 'except' line.
+def no_jump_to_except_1(output):
+    try:
+        output.append(2)
+    except:
+        e = sys.exc_info()[1]
+        output.append('except' in str(e))
+
+no_jump_to_except_1.jump = (2, 3)
+no_jump_to_except_1.output = [True]
+
+def no_jump_to_except_2(output):
+    try:
+        output.append(2)
+    except ValueError:
+        e = sys.exc_info()[1]
+        output.append('except' in str(e))
+
+no_jump_to_except_2.jump = (2, 3)
+no_jump_to_except_2.output = [True]
+
+def no_jump_to_except_3(output):
+    try:
+        output.append(2)
+    except ValueError as e:
+        output.append('except' in str(e))
+
+no_jump_to_except_3.jump = (2, 3)
+no_jump_to_except_3.output = [True]
+
+def no_jump_to_except_4(output):
+    try:
+        output.append(2)
+    except (ValueError, RuntimeError) as e:
+        output.append('except' in str(e))
+
+no_jump_to_except_4.jump = (2, 3)
+no_jump_to_except_4.output = [True]
+
+def no_jump_forwards_into_block(output):
+    try:
+        output.append(2)
+        for i in 1, 2:
+            output.append(4)
+    except ValueError as e:
+        output.append('into' in str(e))
+
+no_jump_forwards_into_block.jump = (2, 4)
+no_jump_forwards_into_block.output = [True]
+
+def no_jump_backwards_into_block(output):
+    try:
+        for i in 1, 2:
+            output.append(3)
+        output.append(4)
+    except ValueError as e:
+        output.append('into' in str(e))
+
+no_jump_backwards_into_block.jump = (4, 3)
+no_jump_backwards_into_block.output = [3, 3, True]
+
+def no_jump_into_finally_block(output):
+    try:
+        try:
+            output.append(3)
+            x = 1
+        finally:
+            output.append(6)
+    except ValueError as e:
+        output.append('finally' in str(e))
+
+no_jump_into_finally_block.jump = (4, 6)
+no_jump_into_finally_block.output = [3, 6, True]  # The 'finally' still runs
+
+def no_jump_out_of_finally_block(output):
+    try:
+        try:
+            output.append(3)
+        finally:
+            output.append(5)
+            output.append(6)
+    except ValueError as e:
+        output.append('finally' in str(e))
+
+no_jump_out_of_finally_block.jump = (5, 1)
+no_jump_out_of_finally_block.output = [3, True]
+
+# This verifies the line-numbers-must-be-integers rule.
+def no_jump_to_non_integers(output):
+    try:
+        output.append(2)
+    except ValueError as e:
+        output.append('integer' in str(e))
+
+no_jump_to_non_integers.jump = (2, "Spam")
+no_jump_to_non_integers.output = [True]
+
+# This verifies that you can't set f_lineno via _getframe or similar
+# trickery.
+def no_jump_without_trace_function():
+    try:
+        previous_frame = sys._getframe().f_back
+        previous_frame.f_lineno = previous_frame.f_lineno
+    except ValueError as e:
+        # This is the exception we wanted; make sure the error message
+        # talks about trace functions.
+        if 'trace' not in str(e):
+            raise
+    else:
+        # Something's wrong - the expected exception wasn't raised.
+        raise RuntimeError("Trace-function-less jump failed to fail")
+
+
+class JumpTestCase(unittest.TestCase):
+    def compare_jump_output(self, expected, received):
+        if received != expected:
+            self.fail( "Outputs don't match:\n" +
+                       "Expected: " + repr(expected) + "\n" +
+                       "Received: " + repr(received))
+
+    def run_test(self, func):
+        tracer = JumpTracer(func)
+        sys.settrace(tracer.trace)
+        output = []
+        func(output)
+        sys.settrace(None)
+        self.compare_jump_output(func.output, output)
+
+    def test_01_jump_simple_forwards(self):
+        self.run_test(jump_simple_forwards)
+    def test_02_jump_simple_backwards(self):
+        self.run_test(jump_simple_backwards)
+    def test_03_jump_out_of_block_forwards(self):
+        self.run_test(jump_out_of_block_forwards)
+    def test_04_jump_out_of_block_backwards(self):
+        self.run_test(jump_out_of_block_backwards)
+    def test_05_jump_to_codeless_line(self):
+        self.run_test(jump_to_codeless_line)
+    def test_06_jump_to_same_line(self):
+        self.run_test(jump_to_same_line)
+    def test_07_jump_in_nested_finally(self):
+        self.run_test(jump_in_nested_finally)
+    def test_08_no_jump_too_far_forwards(self):
+        self.run_test(no_jump_too_far_forwards)
+    def test_09_no_jump_too_far_backwards(self):
+        self.run_test(no_jump_too_far_backwards)
+    def test_10_no_jump_to_except_1(self):
+        self.run_test(no_jump_to_except_1)
+    def test_11_no_jump_to_except_2(self):
+        self.run_test(no_jump_to_except_2)
+    def test_12_no_jump_to_except_3(self):
+        self.run_test(no_jump_to_except_3)
+    def test_13_no_jump_to_except_4(self):
+        self.run_test(no_jump_to_except_4)
+    def test_14_no_jump_forwards_into_block(self):
+        self.run_test(no_jump_forwards_into_block)
+    def test_15_no_jump_backwards_into_block(self):
+        self.run_test(no_jump_backwards_into_block)
+    def test_16_no_jump_into_finally_block(self):
+        self.run_test(no_jump_into_finally_block)
+    def test_17_no_jump_out_of_finally_block(self):
+        self.run_test(no_jump_out_of_finally_block)
+    def test_18_no_jump_to_non_integers(self):
+        self.run_test(no_jump_to_non_integers)
+    def test_19_no_jump_without_trace_function(self):
+        no_jump_without_trace_function()
+
+    def test_20_large_function(self):
+        d = {}
+        exec("""def f(output):        # line 0
+            x = 0                     # line 1
+            y = 1                     # line 2
+            '''                       # line 3
+            %s                        # lines 4-1004
+            '''                       # line 1005
+            x += 1                    # line 1006
+            output.append(x)          # line 1007
+            return""" % ('\n' * 1000,), d)
+        f = d['f']
+
+        f.jump = (2, 1007)
+        f.output = [0]
+        self.run_test(f)
+
+    def test_jump_to_firstlineno(self):
+        # This tests that PDB can jump back to the first line in a
+        # file.  See issue #1689458.  It can only be triggered in a
+        # function call if the function is defined on a single line.
+        code = compile("""
+# Comments don't count.
+output.append(2)  # firstlineno is here.
+output.append(3)
+output.append(4)
+""", "<fake module>", "exec")
+        class fake_function:
+            __code__ = code
+            jump = (2, 0)
+        tracer = JumpTracer(fake_function)
+        sys.settrace(tracer.trace)
+        namespace = {"output": []}
+        exec(code, namespace)
+        sys.settrace(None)
+        self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
+
+
+def test_main():
+    support.run_unittest(
+        TraceTestCase,
+        RaisingTraceFuncTestCase,
+        JumpTestCase
+    )
+
+if __name__ == "__main__":
+    test_main()