summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_profilehooks.py117
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"):