Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v8plus / lib / python2.4 / test / test_profilehooks.py
CommitLineData
920dae64
AT
1import pprint
2import sys
3import unittest
4
5from test import 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 if (event == "call"
15 or event == "return"
16 or event == "exception"):
17 self.add_event(event, frame)
18
19 def add_event(self, event, frame=None):
20 """Add an event to the log."""
21 if frame is None:
22 frame = sys._getframe(1)
23
24 try:
25 frameno = self.frames.index(frame)
26 except ValueError:
27 frameno = len(self.frames)
28 self.frames.append(frame)
29
30 self.events.append((frameno, event, ident(frame)))
31
32 def get_events(self):
33 """Remove calls to add_event()."""
34 disallowed = [ident(self.add_event.im_func), ident(ident)]
35 self.frames = None
36
37 return [item for item in self.events if item[2] not in disallowed]
38
39
40class ProfileSimulator(HookWatcher):
41 def __init__(self, testcase):
42 self.testcase = testcase
43 self.stack = []
44 HookWatcher.__init__(self)
45
46 def callback(self, frame, event, arg):
47 # Callback registered with sys.setprofile()/sys.settrace()
48 self.dispatch[event](self, frame)
49
50 def trace_call(self, frame):
51 self.add_event('call', frame)
52 self.stack.append(frame)
53
54 def trace_return(self, frame):
55 self.add_event('return', frame)
56 self.stack.pop()
57
58 def trace_exception(self, frame):
59 self.testcase.fail(
60 "the profiler should never receive exception events")
61
62 def trace_pass(self, frame):
63 pass
64
65 dispatch = {
66 'call': trace_call,
67 'exception': trace_exception,
68 'return': trace_return,
69 'c_call': trace_pass,
70 'c_return': trace_pass,
71 'c_exception': trace_pass,
72 }
73
74
75class TestCaseBase(unittest.TestCase):
76 def check_events(self, callable, expected):
77 events = capture_events(callable, self.new_watcher())
78 if events != expected:
79 self.fail("Expected events:\n%s\nReceived events:\n%s"
80 % (pprint.pformat(expected), pprint.pformat(events)))
81
82
83class ProfileHookTestCase(TestCaseBase):
84 def new_watcher(self):
85 return HookWatcher()
86
87 def test_simple(self):
88 def f(p):
89 pass
90 f_ident = ident(f)
91 self.check_events(f, [(1, 'call', f_ident),
92 (1, 'return', f_ident),
93 ])
94
95 def test_exception(self):
96 def f(p):
97 1/0
98 f_ident = ident(f)
99 self.check_events(f, [(1, 'call', f_ident),
100 (1, 'return', f_ident),
101 ])
102
103 def test_caught_exception(self):
104 def f(p):
105 try: 1/0
106 except: pass
107 f_ident = ident(f)
108 self.check_events(f, [(1, 'call', f_ident),
109 (1, 'return', f_ident),
110 ])
111
112 def test_caught_nested_exception(self):
113 def f(p):
114 try: 1/0
115 except: pass
116 f_ident = ident(f)
117 self.check_events(f, [(1, 'call', f_ident),
118 (1, 'return', f_ident),
119 ])
120
121 def test_nested_exception(self):
122 def f(p):
123 1/0
124 f_ident = ident(f)
125 self.check_events(f, [(1, 'call', f_ident),
126 # This isn't what I expected:
127 # (0, 'exception', protect_ident),
128 # I expected this again:
129 (1, 'return', f_ident),
130 ])
131
132 def test_exception_in_except_clause(self):
133 def f(p):
134 1/0
135 def g(p):
136 try:
137 f(p)
138 except:
139 try: f(p)
140 except: pass
141 f_ident = ident(f)
142 g_ident = ident(g)
143 self.check_events(g, [(1, 'call', g_ident),
144 (2, 'call', f_ident),
145 (2, 'return', f_ident),
146 (3, 'call', f_ident),
147 (3, 'return', f_ident),
148 (1, 'return', g_ident),
149 ])
150
151 def test_exception_propogation(self):
152 def f(p):
153 1/0
154 def g(p):
155 try: f(p)
156 finally: p.add_event("falling through")
157 f_ident = ident(f)
158 g_ident = ident(g)
159 self.check_events(g, [(1, 'call', g_ident),
160 (2, 'call', f_ident),
161 (2, 'return', f_ident),
162 (1, 'falling through', g_ident),
163 (1, 'return', g_ident),
164 ])
165
166 def test_raise_twice(self):
167 def f(p):
168 try: 1/0
169 except: 1/0
170 f_ident = ident(f)
171 self.check_events(f, [(1, 'call', f_ident),
172 (1, 'return', f_ident),
173 ])
174
175 def test_raise_reraise(self):
176 def f(p):
177 try: 1/0
178 except: raise
179 f_ident = ident(f)
180 self.check_events(f, [(1, 'call', f_ident),
181 (1, 'return', f_ident),
182 ])
183
184 def test_raise(self):
185 def f(p):
186 raise Exception()
187 f_ident = ident(f)
188 self.check_events(f, [(1, 'call', f_ident),
189 (1, 'return', f_ident),
190 ])
191
192 def test_distant_exception(self):
193 def f():
194 1/0
195 def g():
196 f()
197 def h():
198 g()
199 def i():
200 h()
201 def j(p):
202 i()
203 f_ident = ident(f)
204 g_ident = ident(g)
205 h_ident = ident(h)
206 i_ident = ident(i)
207 j_ident = ident(j)
208 self.check_events(j, [(1, 'call', j_ident),
209 (2, 'call', i_ident),
210 (3, 'call', h_ident),
211 (4, 'call', g_ident),
212 (5, 'call', f_ident),
213 (5, 'return', f_ident),
214 (4, 'return', g_ident),
215 (3, 'return', h_ident),
216 (2, 'return', i_ident),
217 (1, 'return', j_ident),
218 ])
219
220 def test_generator(self):
221 def f():
222 for i in range(2):
223 yield i
224 def g(p):
225 for i in f():
226 pass
227 f_ident = ident(f)
228 g_ident = ident(g)
229 self.check_events(g, [(1, 'call', g_ident),
230 # call the iterator twice to generate values
231 (2, 'call', f_ident),
232 (2, 'return', f_ident),
233 (2, 'call', f_ident),
234 (2, 'return', f_ident),
235 # once more; returns end-of-iteration with
236 # actually raising an exception
237 (2, 'call', f_ident),
238 (2, 'return', f_ident),
239 (1, 'return', g_ident),
240 ])
241
242 def test_stop_iteration(self):
243 def f():
244 for i in range(2):
245 yield i
246 raise StopIteration
247 def g(p):
248 for i in f():
249 pass
250 f_ident = ident(f)
251 g_ident = ident(g)
252 self.check_events(g, [(1, 'call', g_ident),
253 # call the iterator twice to generate values
254 (2, 'call', f_ident),
255 (2, 'return', f_ident),
256 (2, 'call', f_ident),
257 (2, 'return', f_ident),
258 # once more to hit the raise:
259 (2, 'call', f_ident),
260 (2, 'return', f_ident),
261 (1, 'return', g_ident),
262 ])
263
264
265class ProfileSimulatorTestCase(TestCaseBase):
266 def new_watcher(self):
267 return ProfileSimulator(self)
268
269 def test_simple(self):
270 def f(p):
271 pass
272 f_ident = ident(f)
273 self.check_events(f, [(1, 'call', f_ident),
274 (1, 'return', f_ident),
275 ])
276
277 def test_basic_exception(self):
278 def f(p):
279 1/0
280 f_ident = ident(f)
281 self.check_events(f, [(1, 'call', f_ident),
282 (1, 'return', f_ident),
283 ])
284
285 def test_caught_exception(self):
286 def f(p):
287 try: 1/0
288 except: pass
289 f_ident = ident(f)
290 self.check_events(f, [(1, 'call', f_ident),
291 (1, 'return', f_ident),
292 ])
293
294 def test_distant_exception(self):
295 def f():
296 1/0
297 def g():
298 f()
299 def h():
300 g()
301 def i():
302 h()
303 def j(p):
304 i()
305 f_ident = ident(f)
306 g_ident = ident(g)
307 h_ident = ident(h)
308 i_ident = ident(i)
309 j_ident = ident(j)
310 self.check_events(j, [(1, 'call', j_ident),
311 (2, 'call', i_ident),
312 (3, 'call', h_ident),
313 (4, 'call', g_ident),
314 (5, 'call', f_ident),
315 (5, 'return', f_ident),
316 (4, 'return', g_ident),
317 (3, 'return', h_ident),
318 (2, 'return', i_ident),
319 (1, 'return', j_ident),
320 ])
321
322
323def ident(function):
324 if hasattr(function, "f_code"):
325 code = function.f_code
326 else:
327 code = function.func_code
328 return code.co_firstlineno, code.co_name
329
330
331def protect(f, p):
332 try: f(p)
333 except: pass
334
335protect_ident = ident(protect)
336
337
338def capture_events(callable, p=None):
339 try:
340 sys.setprofile()
341 except TypeError:
342 pass
343 else:
344 raise test_support.TestFailed(
345 'sys.setprofile() did not raise TypeError')
346
347 if p is None:
348 p = HookWatcher()
349 sys.setprofile(p.callback)
350 protect(callable, p)
351 sys.setprofile(None)
352 return p.get_events()[1:-1]
353
354
355def show_events(callable):
356 import pprint
357 pprint.pprint(capture_events(callable))
358
359
360def test_main():
361 test_support.run_unittest(
362 ProfileHookTestCase,
363 ProfileSimulatorTestCase
364 )
365
366
367if __name__ == "__main__":
368 test_main()