diff options
Diffstat (limited to 'Lib/test/test_profilehooks.py')
-rw-r--r-- | Lib/test/test_profilehooks.py | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/Lib/test/test_profilehooks.py b/Lib/test/test_profilehooks.py index 579443e..33c3f53 100644 --- a/Lib/test/test_profilehooks.py +++ b/Lib/test/test_profilehooks.py @@ -1,3 +1,5 @@ +from __future__ import generators + import pprint import sys import unittest @@ -40,6 +42,7 @@ class ProfileSimulator(HookWatcher): 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): @@ -55,6 +58,8 @@ class ProfileSimulator(HookWatcher): self.add_event('propogate-from', self.stack[-1]) self.stack.pop() else: + # Either an exception was raised in Python or a C function + # raised an exception; this does not represent propogation. self.add_event('ignore', frame) dispatch = { @@ -192,6 +197,79 @@ class ProfileHookTestCase(TestCaseBase): (0, 'exception', protect_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, 'exception', f_ident), + (4, 'exception', g_ident), + (3, 'exception', h_ident), + (2, 'exception', i_ident), + (1, 'exception', j_ident), + (0, 'exception', protect_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, 'exception', f_ident), + (1, 'return', g_ident), + ]) + class ProfileSimulatorTestCase(TestCaseBase): def new_watcher(self): @@ -214,6 +292,45 @@ class ProfileSimulatorTestCase(TestCaseBase): (1, 'propogate-from', 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, 'ignore', 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, 'ignore', f_ident), + (5, 'propogate-from', f_ident), + (4, 'propogate-from', g_ident), + (3, 'propogate-from', h_ident), + (2, 'propogate-from', i_ident), + (1, 'propogate-from', j_ident), + ]) + def ident(function): if hasattr(function, "f_code"): |