5 from test
import test_support
7 class TestGetProfile(unittest
.TestCase
):
15 assert sys
.getprofile() is None
17 def test_setget(self
):
22 assert sys
.getprofile() == fn
29 def callback(self
, frame
, event
, arg
):
32 or event
== "exception"):
33 self
.add_event(event
, frame
)
35 def add_event(self
, event
, frame
=None):
36 """Add an event to the log."""
38 frame
= sys
._getframe
(1)
41 frameno
= self
.frames
.index(frame
)
43 frameno
= len(self
.frames
)
44 self
.frames
.append(frame
)
46 self
.events
.append((frameno
, event
, ident(frame
)))
49 """Remove calls to add_event()."""
50 disallowed
= [ident(self
.add_event
.im_func
), ident(ident
)]
53 return [item
for item
in self
.events
if item
[2] not in disallowed
]
56 class ProfileSimulator(HookWatcher
):
57 def __init__(self
, testcase
):
58 self
.testcase
= testcase
60 HookWatcher
.__init
__(self
)
62 def callback(self
, frame
, event
, arg
):
63 # Callback registered with sys.setprofile()/sys.settrace()
64 self
.dispatch
[event
](self
, frame
)
66 def trace_call(self
, frame
):
67 self
.add_event('call', frame
)
68 self
.stack
.append(frame
)
70 def trace_return(self
, frame
):
71 self
.add_event('return', frame
)
74 def trace_exception(self
, frame
):
76 "the profiler should never receive exception events")
78 def trace_pass(self
, frame
):
83 'exception': trace_exception
,
84 'return': trace_return
,
86 'c_return': trace_pass
,
87 'c_exception': trace_pass
,
91 class TestCaseBase(unittest
.TestCase
):
92 def check_events(self
, callable, expected
):
93 events
= capture_events(callable, self
.new_watcher())
94 if events
!= expected
:
95 self
.fail("Expected events:\n%s\nReceived events:\n%s"
96 % (pprint
.pformat(expected
), pprint
.pformat(events
)))
99 class ProfileHookTestCase(TestCaseBase
):
100 def new_watcher(self
):
103 def test_simple(self
):
107 self
.check_events(f
, [(1, 'call', f_ident
),
108 (1, 'return', f_ident
),
111 def test_exception(self
):
115 self
.check_events(f
, [(1, 'call', f_ident
),
116 (1, 'return', f_ident
),
119 def test_caught_exception(self
):
124 self
.check_events(f
, [(1, 'call', f_ident
),
125 (1, 'return', f_ident
),
128 def test_caught_nested_exception(self
):
133 self
.check_events(f
, [(1, 'call', f_ident
),
134 (1, 'return', f_ident
),
137 def test_nested_exception(self
):
141 self
.check_events(f
, [(1, 'call', f_ident
),
142 # This isn't what I expected:
143 # (0, 'exception', protect_ident),
144 # I expected this again:
145 (1, 'return', f_ident
),
148 def test_exception_in_except_clause(self
):
159 self
.check_events(g
, [(1, 'call', g_ident
),
160 (2, 'call', f_ident
),
161 (2, 'return', f_ident
),
162 (3, 'call', f_ident
),
163 (3, 'return', f_ident
),
164 (1, 'return', g_ident
),
167 def test_exception_propogation(self
):
172 finally: p
.add_event("falling through")
175 self
.check_events(g
, [(1, 'call', g_ident
),
176 (2, 'call', f_ident
),
177 (2, 'return', f_ident
),
178 (1, 'falling through', g_ident
),
179 (1, 'return', g_ident
),
182 def test_raise_twice(self
):
187 self
.check_events(f
, [(1, 'call', f_ident
),
188 (1, 'return', f_ident
),
191 def test_raise_reraise(self
):
196 self
.check_events(f
, [(1, 'call', f_ident
),
197 (1, 'return', f_ident
),
200 def test_raise(self
):
204 self
.check_events(f
, [(1, 'call', f_ident
),
205 (1, 'return', f_ident
),
208 def test_distant_exception(self
):
224 self
.check_events(j
, [(1, 'call', j_ident
),
225 (2, 'call', i_ident
),
226 (3, 'call', h_ident
),
227 (4, 'call', g_ident
),
228 (5, 'call', f_ident
),
229 (5, 'return', f_ident
),
230 (4, 'return', g_ident
),
231 (3, 'return', h_ident
),
232 (2, 'return', i_ident
),
233 (1, 'return', j_ident
),
236 def test_generator(self
):
245 self
.check_events(g
, [(1, 'call', g_ident
),
246 # call the iterator twice to generate values
247 (2, 'call', f_ident
),
248 (2, 'return', f_ident
),
249 (2, 'call', f_ident
),
250 (2, 'return', f_ident
),
251 # once more; returns end-of-iteration with
252 # actually raising an exception
253 (2, 'call', f_ident
),
254 (2, 'return', f_ident
),
255 (1, 'return', g_ident
),
258 def test_stop_iteration(self
):
268 self
.check_events(g
, [(1, 'call', g_ident
),
269 # call the iterator twice to generate values
270 (2, 'call', f_ident
),
271 (2, 'return', f_ident
),
272 (2, 'call', f_ident
),
273 (2, 'return', f_ident
),
274 # once more to hit the raise:
275 (2, 'call', f_ident
),
276 (2, 'return', f_ident
),
277 (1, 'return', g_ident
),
281 class ProfileSimulatorTestCase(TestCaseBase
):
282 def new_watcher(self
):
283 return ProfileSimulator(self
)
285 def test_simple(self
):
289 self
.check_events(f
, [(1, 'call', f_ident
),
290 (1, 'return', f_ident
),
293 def test_basic_exception(self
):
297 self
.check_events(f
, [(1, 'call', f_ident
),
298 (1, 'return', f_ident
),
301 def test_caught_exception(self
):
306 self
.check_events(f
, [(1, 'call', f_ident
),
307 (1, 'return', f_ident
),
310 def test_distant_exception(self
):
326 self
.check_events(j
, [(1, 'call', j_ident
),
327 (2, 'call', i_ident
),
328 (3, 'call', h_ident
),
329 (4, 'call', g_ident
),
330 (5, 'call', f_ident
),
331 (5, 'return', f_ident
),
332 (4, 'return', g_ident
),
333 (3, 'return', h_ident
),
334 (2, 'return', i_ident
),
335 (1, 'return', j_ident
),
340 if hasattr(function
, "f_code"):
341 code
= function
.f_code
343 code
= function
.func_code
344 return code
.co_firstlineno
, code
.co_name
351 protect_ident
= ident(protect
)
354 def capture_events(callable, p
=None):
360 raise test_support
.TestFailed(
361 'sys.setprofile() did not raise TypeError')
365 sys
.setprofile(p
.callback
)
368 return p
.get_events()[1:-1]
371 def show_events(callable):
373 pprint
.pprint(capture_events(callable))
377 test_support
.run_unittest(
380 ProfileSimulatorTestCase
384 if __name__
== "__main__":