blob: b620a9c8f451b0d7efbe23cec25fd31c895dc285 [file] [log] [blame]
Fred Drake3208d4b2001-09-22 04:28:19 +00001import pprint
2import sys
3import unittest
4
5import test_support
6
7
8class HookWatcher:
9 def __init__(self):
10 self.frames = []
11 self.events = []
12
13 def callback(self, frame, event, arg):
14 self.add_event(event, frame)
15
16 def add_event(self, event, frame=None):
17 """Add an event to the log."""
18 if frame is None:
19 frame = sys._getframe(1)
20
21 try:
22 frameno = self.frames.index(frame)
23 except ValueError:
24 frameno = len(self.frames)
25 self.frames.append(frame)
26
27 self.events.append((frameno, event, ident(frame)))
28
29 def get_events(self):
30 """Remove calls to add_event()."""
Fred Drake2d879012001-09-24 18:44:11 +000031 disallowed = [ident(self.add_event.im_func), ident(ident)]
32 self.frames = None
Fred Drake3208d4b2001-09-22 04:28:19 +000033
Fred Drake2d879012001-09-24 18:44:11 +000034 return [item for item in self.events if item[2] not in disallowed]
Fred Drake3208d4b2001-09-22 04:28:19 +000035
36
37class ProfileHookTestCase(unittest.TestCase):
38
39 def check_events(self, callable, expected):
40 events = capture_events(callable)
41 if events != expected:
42 self.fail("Expected events:\n%s\nReceived events:\n%s"
43 % (pprint.pformat(expected), pprint.pformat(events)))
44
45 def test_simple(self):
46 def f(p):
47 pass
48 f_ident = ident(f)
Fred Drakecc91ac02001-09-25 20:48:14 +000049 self.check_events(f, [(1, 'call', f_ident),
50 (1, 'return', f_ident),
Fred Drake3208d4b2001-09-22 04:28:19 +000051 ])
52
53 def test_exception(self):
54 def f(p):
Fred Drakecc91ac02001-09-25 20:48:14 +000055 1/0
56 f_ident = ident(f)
57 self.check_events(f, [(1, 'call', f_ident),
58 (1, 'exception', f_ident),
59 (0, 'exception', protect_ident),
60 ])
61
62 def test_caught_exception(self):
63 def f(p):
Fred Drake2d879012001-09-24 18:44:11 +000064 try: 1/0
65 except: pass
Fred Drake3208d4b2001-09-22 04:28:19 +000066 f_ident = ident(f)
Fred Drakecc91ac02001-09-25 20:48:14 +000067 self.check_events(f, [(1, 'call', f_ident),
68 (1, 'exception', f_ident),
69 (1, 'return', f_ident),
Fred Drake3208d4b2001-09-22 04:28:19 +000070 ])
71
Fred Drake2d879012001-09-24 18:44:11 +000072 def test_caught_nested_exception(self):
73 def f(p):
74 try: 1/0
75 except: pass
Fred Drake2d879012001-09-24 18:44:11 +000076 f_ident = ident(f)
Fred Drakecc91ac02001-09-25 20:48:14 +000077 self.check_events(f, [(1, 'call', f_ident),
Fred Drake2d879012001-09-24 18:44:11 +000078 (1, 'exception', f_ident),
79 (1, 'return', f_ident),
Fred Drake2d879012001-09-24 18:44:11 +000080 ])
81
Fred Drake3208d4b2001-09-22 04:28:19 +000082 def test_nested_exception(self):
83 def f(p):
84 1/0
Fred Drake3208d4b2001-09-22 04:28:19 +000085 f_ident = ident(f)
Fred Drakecc91ac02001-09-25 20:48:14 +000086 self.check_events(f, [(1, 'call', f_ident),
Fred Drake3208d4b2001-09-22 04:28:19 +000087 (1, 'exception', f_ident),
88 # This isn't what I expected:
Fred Drakecc91ac02001-09-25 20:48:14 +000089 (0, 'exception', protect_ident),
Fred Drake2d879012001-09-24 18:44:11 +000090 # I expected this again:
91 # (1, 'exception', f_ident),
Fred Drake3208d4b2001-09-22 04:28:19 +000092 ])
93
Fred Drake2d879012001-09-24 18:44:11 +000094 def test_exception_in_except_clause(self):
95 def f(p):
96 1/0
97 def g(p):
98 try:
99 f(p)
100 except:
101 try: f(p)
102 except: pass
103 f_ident = ident(f)
104 g_ident = ident(g)
Fred Drakecc91ac02001-09-25 20:48:14 +0000105 self.check_events(g, [(1, 'call', g_ident),
Fred Drake2d879012001-09-24 18:44:11 +0000106 (2, 'call', f_ident),
107 (2, 'exception', f_ident),
Fred Drakecc91ac02001-09-25 20:48:14 +0000108 (1, 'exception', g_ident),
109 (3, 'call', f_ident),
110 (3, 'exception', f_ident),
111 (1, 'exception', g_ident),
112 (1, 'return', g_ident),
Fred Drake2d879012001-09-24 18:44:11 +0000113 ])
114
115 def test_exception_propogation(self):
116 def f(p):
117 1/0
118 def g(p):
119 try: f(p)
120 finally: p.add_event("falling through")
Fred Drake2d879012001-09-24 18:44:11 +0000121 f_ident = ident(f)
122 g_ident = ident(g)
Fred Drakecc91ac02001-09-25 20:48:14 +0000123 self.check_events(g, [(1, 'call', g_ident),
Fred Drake2d879012001-09-24 18:44:11 +0000124 (2, 'call', f_ident),
125 (2, 'exception', f_ident),
126 (1, 'exception', g_ident),
127 (1, 'falling through', g_ident),
Fred Drakecc91ac02001-09-25 20:48:14 +0000128 (0, 'exception', protect_ident),
Fred Drake2d879012001-09-24 18:44:11 +0000129 ])
Fred Drake3208d4b2001-09-22 04:28:19 +0000130
Fred Drakecc91ac02001-09-25 20:48:14 +0000131 def test_raise_twice(self):
132 def f(p):
133 try: 1/0
134 except: 1/0
135 f_ident = ident(f)
136 self.check_events(f, [(1, 'call', f_ident),
137 (1, 'exception', f_ident),
138 (1, 'exception', f_ident),
139 (0, 'exception', protect_ident)
140 ])
141
142 def test_raise_reraise(self):
143 def f(p):
144 try: 1/0
145 except: raise
146 f_ident = ident(f)
147 self.check_events(f, [(1, 'call', f_ident),
148 (1, 'exception', f_ident),
149 (0, 'exception', protect_ident)
150 ])
151
152 def test_raise(self):
153 def f(p):
154 raise Exception()
155 f_ident = ident(f)
156 self.check_events(f, [(1, 'call', f_ident),
157 (1, 'exception', f_ident),
158 (0, 'exception', protect_ident)
159 ])
160
161
Fred Drake3208d4b2001-09-22 04:28:19 +0000162def ident(function):
163 if hasattr(function, "f_code"):
164 code = function.f_code
165 else:
166 code = function.func_code
167 return code.co_firstlineno, code.co_name
168
169
Fred Drakecc91ac02001-09-25 20:48:14 +0000170def protect(f, p):
171 try: f(p)
172 except: pass
173
174protect_ident = ident(protect)
175
176
Fred Drake3208d4b2001-09-22 04:28:19 +0000177def capture_events(callable):
178 p = HookWatcher()
179 sys.setprofile(p.callback)
Fred Drakecc91ac02001-09-25 20:48:14 +0000180 protect(callable, p)
Fred Drake3208d4b2001-09-22 04:28:19 +0000181 sys.setprofile(None)
Fred Drakecc91ac02001-09-25 20:48:14 +0000182 return p.get_events()[1:-1]
Fred Drake3208d4b2001-09-22 04:28:19 +0000183
184
185def show_events(callable):
186 import pprint
187 pprint.pprint(capture_events(callable))
188
189
190def test_main():
191 test_support.run_unittest(ProfileHookTestCase)
192
193
194if __name__ == "__main__":
195 test_main()