home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 2004 #2 / K-CD-2-2004.ISO / OpenOffice Sv / f_0397 / python-core-2.2.2 / lib / test / test_profilehooks.py < prev    next >
Encoding:
Python Source  |  2003-07-18  |  10.6 KB  |  361 lines

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