PyXR

c:\python24\lib \ test \ test_profilehooks.py



0001 import pprint
0002 import sys
0003 import unittest
0004 
0005 from test import test_support
0006 
0007 
0008 class HookWatcher:
0009     def __init__(self):
0010         self.frames = []
0011         self.events = []
0012 
0013     def callback(self, frame, event, arg):
0014         if (event == "call"
0015             or event == "return"
0016             or event == "exception"):
0017             self.add_event(event, frame)
0018 
0019     def add_event(self, event, frame=None):
0020         """Add an event to the log."""
0021         if frame is None:
0022             frame = sys._getframe(1)
0023 
0024         try:
0025             frameno = self.frames.index(frame)
0026         except ValueError:
0027             frameno = len(self.frames)
0028             self.frames.append(frame)
0029 
0030         self.events.append((frameno, event, ident(frame)))
0031 
0032     def get_events(self):
0033         """Remove calls to add_event()."""
0034         disallowed = [ident(self.add_event.im_func), ident(ident)]
0035         self.frames = None
0036 
0037         return [item for item in self.events if item[2] not in disallowed]
0038 
0039 
0040 class ProfileSimulator(HookWatcher):
0041     def __init__(self, testcase):
0042         self.testcase = testcase
0043         self.stack = []
0044         HookWatcher.__init__(self)
0045 
0046     def callback(self, frame, event, arg):
0047         # Callback registered with sys.setprofile()/sys.settrace()
0048         self.dispatch[event](self, frame)
0049 
0050     def trace_call(self, frame):
0051         self.add_event('call', frame)
0052         self.stack.append(frame)
0053 
0054     def trace_return(self, frame):
0055         self.add_event('return', frame)
0056         self.stack.pop()
0057 
0058     def trace_exception(self, frame):
0059         self.testcase.fail(
0060             "the profiler should never receive exception events")
0061 
0062     def trace_pass(self, frame):
0063         pass
0064 
0065     dispatch = {
0066         'call': trace_call,
0067         'exception': trace_exception,
0068         'return': trace_return,
0069         'c_call': trace_pass,
0070         'c_return': trace_pass,
0071         'c_exception': trace_pass,
0072         }
0073 
0074 
0075 class TestCaseBase(unittest.TestCase):
0076     def check_events(self, callable, expected):
0077         events = capture_events(callable, self.new_watcher())
0078         if events != expected:
0079             self.fail("Expected events:\n%s\nReceived events:\n%s"
0080                       % (pprint.pformat(expected), pprint.pformat(events)))
0081 
0082 
0083 class ProfileHookTestCase(TestCaseBase):
0084     def new_watcher(self):
0085         return HookWatcher()
0086 
0087     def test_simple(self):
0088         def f(p):
0089             pass
0090         f_ident = ident(f)
0091         self.check_events(f, [(1, 'call', f_ident),
0092                               (1, 'return', f_ident),
0093                               ])
0094 
0095     def test_exception(self):
0096         def f(p):
0097             1/0
0098         f_ident = ident(f)
0099         self.check_events(f, [(1, 'call', f_ident),
0100                               (1, 'return', f_ident),
0101                               ])
0102 
0103     def test_caught_exception(self):
0104         def f(p):
0105             try: 1/0
0106             except: pass
0107         f_ident = ident(f)
0108         self.check_events(f, [(1, 'call', f_ident),
0109                               (1, 'return', f_ident),
0110                               ])
0111 
0112     def test_caught_nested_exception(self):
0113         def f(p):
0114             try: 1/0
0115             except: pass
0116         f_ident = ident(f)
0117         self.check_events(f, [(1, 'call', f_ident),
0118                               (1, 'return', f_ident),
0119                               ])
0120 
0121     def test_nested_exception(self):
0122         def f(p):
0123             1/0
0124         f_ident = ident(f)
0125         self.check_events(f, [(1, 'call', f_ident),
0126                               # This isn't what I expected:
0127                               # (0, 'exception', protect_ident),
0128                               # I expected this again:
0129                               (1, 'return', f_ident),
0130                               ])
0131 
0132     def test_exception_in_except_clause(self):
0133         def f(p):
0134             1/0
0135         def g(p):
0136             try:
0137                 f(p)
0138             except:
0139                 try: f(p)
0140                 except: pass
0141         f_ident = ident(f)
0142         g_ident = ident(g)
0143         self.check_events(g, [(1, 'call', g_ident),
0144                               (2, 'call', f_ident),
0145                               (2, 'return', f_ident),
0146                               (3, 'call', f_ident),
0147                               (3, 'return', f_ident),
0148                               (1, 'return', g_ident),
0149                               ])
0150 
0151     def test_exception_propogation(self):
0152         def f(p):
0153             1/0
0154         def g(p):
0155             try: f(p)
0156             finally: p.add_event("falling through")
0157         f_ident = ident(f)
0158         g_ident = ident(g)
0159         self.check_events(g, [(1, 'call', g_ident),
0160                               (2, 'call', f_ident),
0161                               (2, 'return', f_ident),
0162                               (1, 'falling through', g_ident),
0163                               (1, 'return', g_ident),
0164                               ])
0165 
0166     def test_raise_twice(self):
0167         def f(p):
0168             try: 1/0
0169             except: 1/0
0170         f_ident = ident(f)
0171         self.check_events(f, [(1, 'call', f_ident),
0172                               (1, 'return', f_ident),
0173                               ])
0174 
0175     def test_raise_reraise(self):
0176         def f(p):
0177             try: 1/0
0178             except: raise
0179         f_ident = ident(f)
0180         self.check_events(f, [(1, 'call', f_ident),
0181                               (1, 'return', f_ident),
0182                               ])
0183 
0184     def test_raise(self):
0185         def f(p):
0186             raise Exception()
0187         f_ident = ident(f)
0188         self.check_events(f, [(1, 'call', f_ident),
0189                               (1, 'return', f_ident),
0190                               ])
0191 
0192     def test_distant_exception(self):
0193         def f():
0194             1/0
0195         def g():
0196             f()
0197         def h():
0198             g()
0199         def i():
0200             h()
0201         def j(p):
0202             i()
0203         f_ident = ident(f)
0204         g_ident = ident(g)
0205         h_ident = ident(h)
0206         i_ident = ident(i)
0207         j_ident = ident(j)
0208         self.check_events(j, [(1, 'call', j_ident),
0209                               (2, 'call', i_ident),
0210                               (3, 'call', h_ident),
0211                               (4, 'call', g_ident),
0212                               (5, 'call', f_ident),
0213                               (5, 'return', f_ident),
0214                               (4, 'return', g_ident),
0215                               (3, 'return', h_ident),
0216                               (2, 'return', i_ident),
0217                               (1, 'return', j_ident),
0218                               ])
0219 
0220     def test_generator(self):
0221         def f():
0222             for i in range(2):
0223                 yield i
0224         def g(p):
0225             for i in f():
0226                 pass
0227         f_ident = ident(f)
0228         g_ident = ident(g)
0229         self.check_events(g, [(1, 'call', g_ident),
0230                               # call the iterator twice to generate values
0231                               (2, 'call', f_ident),
0232                               (2, 'return', f_ident),
0233                               (2, 'call', f_ident),
0234                               (2, 'return', f_ident),
0235                               # once more; returns end-of-iteration with
0236                               # actually raising an exception
0237                               (2, 'call', f_ident),
0238                               (2, 'return', f_ident),
0239                               (1, 'return', g_ident),
0240                               ])
0241 
0242     def test_stop_iteration(self):
0243         def f():
0244             for i in range(2):
0245                 yield i
0246             raise StopIteration
0247         def g(p):
0248             for i in f():
0249                 pass
0250         f_ident = ident(f)
0251         g_ident = ident(g)
0252         self.check_events(g, [(1, 'call', g_ident),
0253                               # call the iterator twice to generate values
0254                               (2, 'call', f_ident),
0255                               (2, 'return', f_ident),
0256                               (2, 'call', f_ident),
0257                               (2, 'return', f_ident),
0258                               # once more to hit the raise:
0259                               (2, 'call', f_ident),
0260                               (2, 'return', f_ident),
0261                               (1, 'return', g_ident),
0262                               ])
0263 
0264 
0265 class ProfileSimulatorTestCase(TestCaseBase):
0266     def new_watcher(self):
0267         return ProfileSimulator(self)
0268 
0269     def test_simple(self):
0270         def f(p):
0271             pass
0272         f_ident = ident(f)
0273         self.check_events(f, [(1, 'call', f_ident),
0274                               (1, 'return', f_ident),
0275                               ])
0276 
0277     def test_basic_exception(self):
0278         def f(p):
0279             1/0
0280         f_ident = ident(f)
0281         self.check_events(f, [(1, 'call', f_ident),
0282                               (1, 'return', f_ident),
0283                               ])
0284 
0285     def test_caught_exception(self):
0286         def f(p):
0287             try: 1/0
0288             except: pass
0289         f_ident = ident(f)
0290         self.check_events(f, [(1, 'call', f_ident),
0291                               (1, 'return', f_ident),
0292                               ])
0293 
0294     def test_distant_exception(self):
0295         def f():
0296             1/0
0297         def g():
0298             f()
0299         def h():
0300             g()
0301         def i():
0302             h()
0303         def j(p):
0304             i()
0305         f_ident = ident(f)
0306         g_ident = ident(g)
0307         h_ident = ident(h)
0308         i_ident = ident(i)
0309         j_ident = ident(j)
0310         self.check_events(j, [(1, 'call', j_ident),
0311                               (2, 'call', i_ident),
0312                               (3, 'call', h_ident),
0313                               (4, 'call', g_ident),
0314                               (5, 'call', f_ident),
0315                               (5, 'return', f_ident),
0316                               (4, 'return', g_ident),
0317                               (3, 'return', h_ident),
0318                               (2, 'return', i_ident),
0319                               (1, 'return', j_ident),
0320                               ])
0321 
0322 
0323 def ident(function):
0324     if hasattr(function, "f_code"):
0325         code = function.f_code
0326     else:
0327         code = function.func_code
0328     return code.co_firstlineno, code.co_name
0329 
0330 
0331 def protect(f, p):
0332     try: f(p)
0333     except: pass
0334 
0335 protect_ident = ident(protect)
0336 
0337 
0338 def capture_events(callable, p=None):
0339     try:
0340         sys.setprofile()
0341     except TypeError:
0342         pass
0343     else:
0344         raise test_support.TestFailed(
0345             'sys.setprofile() did not raise TypeError')
0346 
0347     if p is None:
0348         p = HookWatcher()
0349     sys.setprofile(p.callback)
0350     protect(callable, p)
0351     sys.setprofile(None)
0352     return p.get_events()[1:-1]
0353 
0354 
0355 def show_events(callable):
0356     import pprint
0357     pprint.pprint(capture_events(callable))
0358 
0359 
0360 def test_main():
0361     test_support.run_unittest(
0362         ProfileHookTestCase,
0363         ProfileSimulatorTestCase
0364     )
0365 
0366 
0367 if __name__ == "__main__":
0368     test_main()
0369 

Generated by PyXR 0.9.4
SourceForge.net Logo