From 9d12ceb63616b3c334f9eb64312aa7af9ad328ff Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Wed, 28 Jul 2010 14:33:17 +0000 Subject: Redo r83142 merge manually. QOTD: svnmerge isn't really your best friend --- Lib/test/test_profilehooks.py | 385 ---------------------------------------- Lib/test/test_sys.py | 4 +- Lib/test/test_sys_setprofile.py | 385 ++++++++++++++++++++++++++++++++++++++++ Lib/test/test_sys_settrace.py | 214 ++++++++++++++++++++++ Lib/test/test_trace.py | 214 ---------------------- 5 files changed, 601 insertions(+), 601 deletions(-) delete mode 100644 Lib/test/test_profilehooks.py create mode 100644 Lib/test/test_sys_setprofile.py create mode 100644 Lib/test/test_sys_settrace.py delete mode 100644 Lib/test/test_trace.py diff --git a/Lib/test/test_profilehooks.py b/Lib/test/test_profilehooks.py deleted file mode 100644 index 4083d11..0000000 --- a/Lib/test/test_profilehooks.py +++ /dev/null @@ -1,385 +0,0 @@ -import pprint -import sys -import unittest - -from test import test_support - -class TestGetProfile(unittest.TestCase): - def setUp(self): - sys.setprofile(None) - - def tearDown(self): - sys.setprofile(None) - - def test_empty(self): - assert sys.getprofile() is None - - def test_setget(self): - def fn(*args): - pass - - sys.setprofile(fn) - assert sys.getprofile() == fn - -class HookWatcher: - def __init__(self): - self.frames = [] - self.events = [] - - def callback(self, frame, event, arg): - if (event == "call" - or event == "return" - or event == "exception"): - self.add_event(event, frame) - - def add_event(self, event, frame=None): - """Add an event to the log.""" - if frame is None: - frame = sys._getframe(1) - - try: - frameno = self.frames.index(frame) - except ValueError: - frameno = len(self.frames) - self.frames.append(frame) - - self.events.append((frameno, event, ident(frame))) - - def get_events(self): - """Remove calls to add_event().""" - disallowed = [ident(self.add_event.im_func), ident(ident)] - self.frames = None - - return [item for item in self.events if item[2] not in disallowed] - - -class ProfileSimulator(HookWatcher): - def __init__(self, testcase): - self.testcase = testcase - self.stack = [] - HookWatcher.__init__(self) - - def callback(self, frame, event, arg): - # Callback registered with sys.setprofile()/sys.settrace() - self.dispatch[event](self, frame) - - def trace_call(self, frame): - self.add_event('call', frame) - self.stack.append(frame) - - def trace_return(self, frame): - self.add_event('return', frame) - self.stack.pop() - - def trace_exception(self, frame): - self.testcase.fail( - "the profiler should never receive exception events") - - def trace_pass(self, frame): - pass - - dispatch = { - 'call': trace_call, - 'exception': trace_exception, - 'return': trace_return, - 'c_call': trace_pass, - 'c_return': trace_pass, - 'c_exception': trace_pass, - } - - -class TestCaseBase(unittest.TestCase): - def check_events(self, callable, expected): - events = capture_events(callable, self.new_watcher()) - if events != expected: - self.fail("Expected events:\n%s\nReceived events:\n%s" - % (pprint.pformat(expected), pprint.pformat(events))) - - -class ProfileHookTestCase(TestCaseBase): - def new_watcher(self): - return HookWatcher() - - def test_simple(self): - def f(p): - pass - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_exception(self): - def f(p): - 1./0 - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_caught_exception(self): - def f(p): - try: 1./0 - except: pass - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_caught_nested_exception(self): - def f(p): - try: 1./0 - except: pass - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_nested_exception(self): - def f(p): - 1./0 - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - # This isn't what I expected: - # (0, 'exception', protect_ident), - # I expected this again: - (1, 'return', f_ident), - ]) - - def test_exception_in_except_clause(self): - def f(p): - 1./0 - def g(p): - try: - f(p) - except: - try: f(p) - except: pass - f_ident = ident(f) - g_ident = ident(g) - self.check_events(g, [(1, 'call', g_ident), - (2, 'call', f_ident), - (2, 'return', f_ident), - (3, 'call', f_ident), - (3, 'return', f_ident), - (1, 'return', g_ident), - ]) - - def test_exception_propogation(self): - def f(p): - 1./0 - def g(p): - try: f(p) - finally: p.add_event("falling through") - f_ident = ident(f) - g_ident = ident(g) - self.check_events(g, [(1, 'call', g_ident), - (2, 'call', f_ident), - (2, 'return', f_ident), - (1, 'falling through', g_ident), - (1, 'return', g_ident), - ]) - - def test_raise_twice(self): - def f(p): - try: 1./0 - except: 1./0 - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_raise_reraise(self): - def f(p): - try: 1./0 - except: raise - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_raise(self): - def f(p): - raise Exception() - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_distant_exception(self): - def f(): - 1./0 - def g(): - f() - def h(): - g() - def i(): - h() - def j(p): - i() - f_ident = ident(f) - g_ident = ident(g) - h_ident = ident(h) - i_ident = ident(i) - j_ident = ident(j) - self.check_events(j, [(1, 'call', j_ident), - (2, 'call', i_ident), - (3, 'call', h_ident), - (4, 'call', g_ident), - (5, 'call', f_ident), - (5, 'return', f_ident), - (4, 'return', g_ident), - (3, 'return', h_ident), - (2, 'return', i_ident), - (1, 'return', j_ident), - ]) - - def test_generator(self): - def f(): - for i in range(2): - yield i - def g(p): - for i in f(): - pass - f_ident = ident(f) - g_ident = ident(g) - self.check_events(g, [(1, 'call', g_ident), - # call the iterator twice to generate values - (2, 'call', f_ident), - (2, 'return', f_ident), - (2, 'call', f_ident), - (2, 'return', f_ident), - # once more; returns end-of-iteration with - # actually raising an exception - (2, 'call', f_ident), - (2, 'return', f_ident), - (1, 'return', g_ident), - ]) - - def test_stop_iteration(self): - def f(): - for i in range(2): - yield i - raise StopIteration - def g(p): - for i in f(): - pass - f_ident = ident(f) - g_ident = ident(g) - self.check_events(g, [(1, 'call', g_ident), - # call the iterator twice to generate values - (2, 'call', f_ident), - (2, 'return', f_ident), - (2, 'call', f_ident), - (2, 'return', f_ident), - # once more to hit the raise: - (2, 'call', f_ident), - (2, 'return', f_ident), - (1, 'return', g_ident), - ]) - - -class ProfileSimulatorTestCase(TestCaseBase): - def new_watcher(self): - return ProfileSimulator(self) - - def test_simple(self): - def f(p): - pass - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_basic_exception(self): - def f(p): - 1./0 - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_caught_exception(self): - def f(p): - try: 1./0 - except: pass - f_ident = ident(f) - self.check_events(f, [(1, 'call', f_ident), - (1, 'return', f_ident), - ]) - - def test_distant_exception(self): - def f(): - 1./0 - def g(): - f() - def h(): - g() - def i(): - h() - def j(p): - i() - f_ident = ident(f) - g_ident = ident(g) - h_ident = ident(h) - i_ident = ident(i) - j_ident = ident(j) - self.check_events(j, [(1, 'call', j_ident), - (2, 'call', i_ident), - (3, 'call', h_ident), - (4, 'call', g_ident), - (5, 'call', f_ident), - (5, 'return', f_ident), - (4, 'return', g_ident), - (3, 'return', h_ident), - (2, 'return', i_ident), - (1, 'return', j_ident), - ]) - - -def ident(function): - if hasattr(function, "f_code"): - code = function.f_code - else: - code = function.func_code - return code.co_firstlineno, code.co_name - - -def protect(f, p): - try: f(p) - except: pass - -protect_ident = ident(protect) - - -def capture_events(callable, p=None): - try: - sys.setprofile() - except TypeError: - pass - else: - raise test_support.TestFailed( - 'sys.setprofile() did not raise TypeError') - - if p is None: - p = HookWatcher() - sys.setprofile(p.callback) - protect(callable, p) - sys.setprofile(None) - return p.get_events()[1:-1] - - -def show_events(callable): - import pprint - pprint.pprint(capture_events(callable)) - - -def test_main(): - test_support.run_unittest( - TestGetProfile, - ProfileHookTestCase, - ProfileSimulatorTestCase - ) - - -if __name__ == "__main__": - test_main() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b17827c..53cdcb2 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -205,8 +205,8 @@ class SysModuleTest(unittest.TestCase): # can't check more than the type, as the user might have changed it self.assertIsInstance(sys.getdefaultencoding(), str) - # testing sys.settrace() is done in test_trace.py - # testing sys.setprofile() is done in test_profile.py + # testing sys.settrace() is done in test_sys_settrace.py + # testing sys.setprofile() is done in test_sys_setprofile.py def test_setcheckinterval(self): self.assertRaises(TypeError, sys.setcheckinterval) diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py new file mode 100644 index 0000000..4083d11 --- /dev/null +++ b/Lib/test/test_sys_setprofile.py @@ -0,0 +1,385 @@ +import pprint +import sys +import unittest + +from test import test_support + +class TestGetProfile(unittest.TestCase): + def setUp(self): + sys.setprofile(None) + + def tearDown(self): + sys.setprofile(None) + + def test_empty(self): + assert sys.getprofile() is None + + def test_setget(self): + def fn(*args): + pass + + sys.setprofile(fn) + assert sys.getprofile() == fn + +class HookWatcher: + def __init__(self): + self.frames = [] + self.events = [] + + def callback(self, frame, event, arg): + if (event == "call" + or event == "return" + or event == "exception"): + self.add_event(event, frame) + + def add_event(self, event, frame=None): + """Add an event to the log.""" + if frame is None: + frame = sys._getframe(1) + + try: + frameno = self.frames.index(frame) + except ValueError: + frameno = len(self.frames) + self.frames.append(frame) + + self.events.append((frameno, event, ident(frame))) + + def get_events(self): + """Remove calls to add_event().""" + disallowed = [ident(self.add_event.im_func), ident(ident)] + self.frames = None + + return [item for item in self.events if item[2] not in disallowed] + + +class ProfileSimulator(HookWatcher): + def __init__(self, testcase): + self.testcase = testcase + self.stack = [] + HookWatcher.__init__(self) + + def callback(self, frame, event, arg): + # Callback registered with sys.setprofile()/sys.settrace() + self.dispatch[event](self, frame) + + def trace_call(self, frame): + self.add_event('call', frame) + self.stack.append(frame) + + def trace_return(self, frame): + self.add_event('return', frame) + self.stack.pop() + + def trace_exception(self, frame): + self.testcase.fail( + "the profiler should never receive exception events") + + def trace_pass(self, frame): + pass + + dispatch = { + 'call': trace_call, + 'exception': trace_exception, + 'return': trace_return, + 'c_call': trace_pass, + 'c_return': trace_pass, + 'c_exception': trace_pass, + } + + +class TestCaseBase(unittest.TestCase): + def check_events(self, callable, expected): + events = capture_events(callable, self.new_watcher()) + if events != expected: + self.fail("Expected events:\n%s\nReceived events:\n%s" + % (pprint.pformat(expected), pprint.pformat(events))) + + +class ProfileHookTestCase(TestCaseBase): + def new_watcher(self): + return HookWatcher() + + def test_simple(self): + def f(p): + pass + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_exception(self): + def f(p): + 1./0 + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_caught_exception(self): + def f(p): + try: 1./0 + except: pass + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_caught_nested_exception(self): + def f(p): + try: 1./0 + except: pass + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_nested_exception(self): + def f(p): + 1./0 + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + # This isn't what I expected: + # (0, 'exception', protect_ident), + # I expected this again: + (1, 'return', f_ident), + ]) + + def test_exception_in_except_clause(self): + def f(p): + 1./0 + def g(p): + try: + f(p) + except: + try: f(p) + except: pass + f_ident = ident(f) + g_ident = ident(g) + self.check_events(g, [(1, 'call', g_ident), + (2, 'call', f_ident), + (2, 'return', f_ident), + (3, 'call', f_ident), + (3, 'return', f_ident), + (1, 'return', g_ident), + ]) + + def test_exception_propogation(self): + def f(p): + 1./0 + def g(p): + try: f(p) + finally: p.add_event("falling through") + f_ident = ident(f) + g_ident = ident(g) + self.check_events(g, [(1, 'call', g_ident), + (2, 'call', f_ident), + (2, 'return', f_ident), + (1, 'falling through', g_ident), + (1, 'return', g_ident), + ]) + + def test_raise_twice(self): + def f(p): + try: 1./0 + except: 1./0 + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_raise_reraise(self): + def f(p): + try: 1./0 + except: raise + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_raise(self): + def f(p): + raise Exception() + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_distant_exception(self): + def f(): + 1./0 + def g(): + f() + def h(): + g() + def i(): + h() + def j(p): + i() + f_ident = ident(f) + g_ident = ident(g) + h_ident = ident(h) + i_ident = ident(i) + j_ident = ident(j) + self.check_events(j, [(1, 'call', j_ident), + (2, 'call', i_ident), + (3, 'call', h_ident), + (4, 'call', g_ident), + (5, 'call', f_ident), + (5, 'return', f_ident), + (4, 'return', g_ident), + (3, 'return', h_ident), + (2, 'return', i_ident), + (1, 'return', j_ident), + ]) + + def test_generator(self): + def f(): + for i in range(2): + yield i + def g(p): + for i in f(): + pass + f_ident = ident(f) + g_ident = ident(g) + self.check_events(g, [(1, 'call', g_ident), + # call the iterator twice to generate values + (2, 'call', f_ident), + (2, 'return', f_ident), + (2, 'call', f_ident), + (2, 'return', f_ident), + # once more; returns end-of-iteration with + # actually raising an exception + (2, 'call', f_ident), + (2, 'return', f_ident), + (1, 'return', g_ident), + ]) + + def test_stop_iteration(self): + def f(): + for i in range(2): + yield i + raise StopIteration + def g(p): + for i in f(): + pass + f_ident = ident(f) + g_ident = ident(g) + self.check_events(g, [(1, 'call', g_ident), + # call the iterator twice to generate values + (2, 'call', f_ident), + (2, 'return', f_ident), + (2, 'call', f_ident), + (2, 'return', f_ident), + # once more to hit the raise: + (2, 'call', f_ident), + (2, 'return', f_ident), + (1, 'return', g_ident), + ]) + + +class ProfileSimulatorTestCase(TestCaseBase): + def new_watcher(self): + return ProfileSimulator(self) + + def test_simple(self): + def f(p): + pass + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_basic_exception(self): + def f(p): + 1./0 + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_caught_exception(self): + def f(p): + try: 1./0 + except: pass + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident), + ]) + + def test_distant_exception(self): + def f(): + 1./0 + def g(): + f() + def h(): + g() + def i(): + h() + def j(p): + i() + f_ident = ident(f) + g_ident = ident(g) + h_ident = ident(h) + i_ident = ident(i) + j_ident = ident(j) + self.check_events(j, [(1, 'call', j_ident), + (2, 'call', i_ident), + (3, 'call', h_ident), + (4, 'call', g_ident), + (5, 'call', f_ident), + (5, 'return', f_ident), + (4, 'return', g_ident), + (3, 'return', h_ident), + (2, 'return', i_ident), + (1, 'return', j_ident), + ]) + + +def ident(function): + if hasattr(function, "f_code"): + code = function.f_code + else: + code = function.func_code + return code.co_firstlineno, code.co_name + + +def protect(f, p): + try: f(p) + except: pass + +protect_ident = ident(protect) + + +def capture_events(callable, p=None): + try: + sys.setprofile() + except TypeError: + pass + else: + raise test_support.TestFailed( + 'sys.setprofile() did not raise TypeError') + + if p is None: + p = HookWatcher() + sys.setprofile(p.callback) + protect(callable, p) + sys.setprofile(None) + return p.get_events()[1:-1] + + +def show_events(callable): + import pprint + pprint.pprint(capture_events(callable)) + + +def test_main(): + test_support.run_unittest( + TestGetProfile, + ProfileHookTestCase, + ProfileSimulatorTestCase + ) + + +if __name__ == "__main__": + test_main() diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py new file mode 100644 index 0000000..c04be50 --- /dev/null +++ b/Lib/test/test_sys_settrace.py @@ -0,0 +1,214 @@ +import imp +import os +import sys +from test import test_support +import unittest + +import trace +from trace import CoverageResults, Trace + + +#------------------------------- Utilities -----------------------------------# + +def make_fake_module(): + """Creates a fake module named 'fakemodule'. + + The new module has a single function named 'foo', and it's placed in + sys.modules + The file this fake module "comes from" is fakefile.py + + """ + + # Prepare the function to import from the fake module + # + _fake_foo_src = r''' +def foo(a_): + b = a_ + 1 + return b + 2 +'''.lstrip() + + _fake_foo = compile(_fake_foo_src, 'fakefile.py', 'exec') + + # Create a new module, place the function into it and add it to sys.modules + # + fakemodule = imp.new_module('fakemodule') + exec _fake_foo in fakemodule.__dict__ + fakemodule.__file__ = 'fakefile.py' + sys.modules['fakemodule'] = fakemodule + + +def modname(filename): + """Infer a module name from a containing file name""" + base = os.path.basename(filename) + mod, ext = os.path.splitext(base) + return mod + + +def my_file_and_modname(): + """The file and module name of this file (__file__)""" + return __file__, modname(__file__) + + +#-------------------- Target functions for tracing ---------------------------# + +def _traced_func_linear(a_, b_): + a = a_ + b = b_ + c = a + b + return c + +def _traced_func_loop(a_, b_): + c = a_ + for i in range(5): + c += b_ + return c + +# Expects the 'fakemodule' module to exist and have a 'foo' function in it +# +def _traced_func_importing(a_, b_): + from fakemodule import foo + return a_ + b_ + foo(1) + +def _traced_func_simple_caller(a_): + c = _traced_func_linear(a_, a_) + return c + a_ + +def _traced_func_importing_caller(a_): + k = _traced_func_simple_caller(a_) + k += _traced_func_importing(k, a_) + return k + + +#------------------------------ Test cases -----------------------------------# + + +class TestLineCounts(unittest.TestCase): + """White-box testing of line-counting, via runfunc""" + def setUp(self): + self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) + + def test_traced_func_linear(self): + result = self.tr.runfunc(_traced_func_linear, 2, 5) + self.assertEqual(result, 7) + + # all lines are executed once + expected = {} + firstlineno = _traced_func_linear.__code__.co_firstlineno + for i in range(1, 5): + expected[(__file__, firstlineno + i)] = 1 + + self.assertEqual(self.tr.results().counts, expected) + + def test_traced_func_loop(self): + self.tr.runfunc(_traced_func_loop, 2, 3) + + firstlineno = _traced_func_loop.__code__.co_firstlineno + expected = { + (__file__, firstlineno + 1): 1, + (__file__, firstlineno + 2): 6, + (__file__, firstlineno + 3): 5, + (__file__, firstlineno + 4): 1, + } + self.assertEqual(self.tr.results().counts, expected) + + def test_traced_func_importing(self): + make_fake_module() + self.tr.runfunc(_traced_func_importing, 2, 5) + + firstlineno = _traced_func_importing.__code__.co_firstlineno + expected = { + (__file__, firstlineno + 1): 1, + (__file__, firstlineno + 2): 1, + ('fakefile.py', 2): 1, + ('fakefile.py', 3): 1, + } + self.assertEqual(self.tr.results().counts, expected) + + +class TestRunExecCounts(unittest.TestCase): + """A simple sanity test of line-counting, via run (exec)""" + def test_tt(self): + self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) + code = r'''_traced_func_loop(2, 5)''' + code = compile(code, __file__, 'exec') + self.tr.run(code) + + firstlineno = _traced_func_loop.__code__.co_firstlineno + expected = { + (__file__, firstlineno + 1): 1, + (__file__, firstlineno + 2): 6, + (__file__, firstlineno + 3): 5, + (__file__, firstlineno + 4): 1, + } + + # When used through 'run', some other spurios counts are produced, like + # the settrace of threading, which we ignore, just making sure that the + # counts fo _traced_func_loop were right. + # + for k in expected.keys(): + self.assertEqual(self.tr.results().counts[k], expected[k]) + + +class TestFuncs(unittest.TestCase): + """White-box testing of funcs tracing""" + def setUp(self): + self.tr = Trace(count=0, trace=0, countfuncs=1) + self.filemod = my_file_and_modname() + + def test_simple_caller(self): + self.tr.runfunc(_traced_func_simple_caller, 1) + + expected = { + self.filemod + ('_traced_func_simple_caller',): 1, + self.filemod + ('_traced_func_linear',): 1, + } + self.assertEqual(self.tr.results().calledfuncs, expected) + + def test_loop_caller_importing(self): + make_fake_module() + self.tr.runfunc(_traced_func_importing_caller, 1) + + expected = { + self.filemod + ('_traced_func_simple_caller',): 1, + self.filemod + ('_traced_func_linear',): 1, + self.filemod + ('_traced_func_importing_caller',): 1, + self.filemod + ('_traced_func_importing',): 1, + ('fakefile.py', 'fakefile', 'foo'): 1, + } + self.assertEqual(self.tr.results().calledfuncs, expected) + + +class TestCallers(unittest.TestCase): + """White-box testing of callers tracing""" + def setUp(self): + self.tr = Trace(count=0, trace=0, countcallers=1) + self.filemod = my_file_and_modname() + + def test_loop_caller_importing(self): + make_fake_module() + self.tr.runfunc(_traced_func_importing_caller, 1) + + expected = { + ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'), + (self.filemod + ('_traced_func_importing_caller',))): 1, + ((self.filemod + ('_traced_func_simple_caller',)), + (self.filemod + ('_traced_func_linear',))): 1, + ((self.filemod + ('_traced_func_importing_caller',)), + (self.filemod + ('_traced_func_simple_caller',))): 1, + ((self.filemod + ('_traced_func_importing_caller',)), + (self.filemod + ('_traced_func_importing',))): 1, + ((self.filemod + ('_traced_func_importing',)), + ('fakefile.py', 'fakefile', 'foo')): 1, + } + self.assertEqual(self.tr.results().callers, expected) + + +#------------------------------ Driver ---------------------------------------# + +def test_main(): + print(__name__, type(__name__)) + test_support.run_unittest(__name__) + + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py deleted file mode 100644 index c04be50..0000000 --- a/Lib/test/test_trace.py +++ /dev/null @@ -1,214 +0,0 @@ -import imp -import os -import sys -from test import test_support -import unittest - -import trace -from trace import CoverageResults, Trace - - -#------------------------------- Utilities -----------------------------------# - -def make_fake_module(): - """Creates a fake module named 'fakemodule'. - - The new module has a single function named 'foo', and it's placed in - sys.modules - The file this fake module "comes from" is fakefile.py - - """ - - # Prepare the function to import from the fake module - # - _fake_foo_src = r''' -def foo(a_): - b = a_ + 1 - return b + 2 -'''.lstrip() - - _fake_foo = compile(_fake_foo_src, 'fakefile.py', 'exec') - - # Create a new module, place the function into it and add it to sys.modules - # - fakemodule = imp.new_module('fakemodule') - exec _fake_foo in fakemodule.__dict__ - fakemodule.__file__ = 'fakefile.py' - sys.modules['fakemodule'] = fakemodule - - -def modname(filename): - """Infer a module name from a containing file name""" - base = os.path.basename(filename) - mod, ext = os.path.splitext(base) - return mod - - -def my_file_and_modname(): - """The file and module name of this file (__file__)""" - return __file__, modname(__file__) - - -#-------------------- Target functions for tracing ---------------------------# - -def _traced_func_linear(a_, b_): - a = a_ - b = b_ - c = a + b - return c - -def _traced_func_loop(a_, b_): - c = a_ - for i in range(5): - c += b_ - return c - -# Expects the 'fakemodule' module to exist and have a 'foo' function in it -# -def _traced_func_importing(a_, b_): - from fakemodule import foo - return a_ + b_ + foo(1) - -def _traced_func_simple_caller(a_): - c = _traced_func_linear(a_, a_) - return c + a_ - -def _traced_func_importing_caller(a_): - k = _traced_func_simple_caller(a_) - k += _traced_func_importing(k, a_) - return k - - -#------------------------------ Test cases -----------------------------------# - - -class TestLineCounts(unittest.TestCase): - """White-box testing of line-counting, via runfunc""" - def setUp(self): - self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) - - def test_traced_func_linear(self): - result = self.tr.runfunc(_traced_func_linear, 2, 5) - self.assertEqual(result, 7) - - # all lines are executed once - expected = {} - firstlineno = _traced_func_linear.__code__.co_firstlineno - for i in range(1, 5): - expected[(__file__, firstlineno + i)] = 1 - - self.assertEqual(self.tr.results().counts, expected) - - def test_traced_func_loop(self): - self.tr.runfunc(_traced_func_loop, 2, 3) - - firstlineno = _traced_func_loop.__code__.co_firstlineno - expected = { - (__file__, firstlineno + 1): 1, - (__file__, firstlineno + 2): 6, - (__file__, firstlineno + 3): 5, - (__file__, firstlineno + 4): 1, - } - self.assertEqual(self.tr.results().counts, expected) - - def test_traced_func_importing(self): - make_fake_module() - self.tr.runfunc(_traced_func_importing, 2, 5) - - firstlineno = _traced_func_importing.__code__.co_firstlineno - expected = { - (__file__, firstlineno + 1): 1, - (__file__, firstlineno + 2): 1, - ('fakefile.py', 2): 1, - ('fakefile.py', 3): 1, - } - self.assertEqual(self.tr.results().counts, expected) - - -class TestRunExecCounts(unittest.TestCase): - """A simple sanity test of line-counting, via run (exec)""" - def test_tt(self): - self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) - code = r'''_traced_func_loop(2, 5)''' - code = compile(code, __file__, 'exec') - self.tr.run(code) - - firstlineno = _traced_func_loop.__code__.co_firstlineno - expected = { - (__file__, firstlineno + 1): 1, - (__file__, firstlineno + 2): 6, - (__file__, firstlineno + 3): 5, - (__file__, firstlineno + 4): 1, - } - - # When used through 'run', some other spurios counts are produced, like - # the settrace of threading, which we ignore, just making sure that the - # counts fo _traced_func_loop were right. - # - for k in expected.keys(): - self.assertEqual(self.tr.results().counts[k], expected[k]) - - -class TestFuncs(unittest.TestCase): - """White-box testing of funcs tracing""" - def setUp(self): - self.tr = Trace(count=0, trace=0, countfuncs=1) - self.filemod = my_file_and_modname() - - def test_simple_caller(self): - self.tr.runfunc(_traced_func_simple_caller, 1) - - expected = { - self.filemod + ('_traced_func_simple_caller',): 1, - self.filemod + ('_traced_func_linear',): 1, - } - self.assertEqual(self.tr.results().calledfuncs, expected) - - def test_loop_caller_importing(self): - make_fake_module() - self.tr.runfunc(_traced_func_importing_caller, 1) - - expected = { - self.filemod + ('_traced_func_simple_caller',): 1, - self.filemod + ('_traced_func_linear',): 1, - self.filemod + ('_traced_func_importing_caller',): 1, - self.filemod + ('_traced_func_importing',): 1, - ('fakefile.py', 'fakefile', 'foo'): 1, - } - self.assertEqual(self.tr.results().calledfuncs, expected) - - -class TestCallers(unittest.TestCase): - """White-box testing of callers tracing""" - def setUp(self): - self.tr = Trace(count=0, trace=0, countcallers=1) - self.filemod = my_file_and_modname() - - def test_loop_caller_importing(self): - make_fake_module() - self.tr.runfunc(_traced_func_importing_caller, 1) - - expected = { - ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'), - (self.filemod + ('_traced_func_importing_caller',))): 1, - ((self.filemod + ('_traced_func_simple_caller',)), - (self.filemod + ('_traced_func_linear',))): 1, - ((self.filemod + ('_traced_func_importing_caller',)), - (self.filemod + ('_traced_func_simple_caller',))): 1, - ((self.filemod + ('_traced_func_importing_caller',)), - (self.filemod + ('_traced_func_importing',))): 1, - ((self.filemod + ('_traced_func_importing',)), - ('fakefile.py', 'fakefile', 'foo')): 1, - } - self.assertEqual(self.tr.results().callers, expected) - - -#------------------------------ Driver ---------------------------------------# - -def test_main(): - print(__name__, type(__name__)) - test_support.run_unittest(__name__) - - -if __name__ == '__main__': - test_main() -- cgit v0.12