Debugger: Disable optimization for test cases manually as they don't use distutils...
authorMark Florisson <markflorisson88@gmail.com>
Sat, 8 Jan 2011 22:05:16 +0000 (23:05 +0100)
committerMark Florisson <markflorisson88@gmail.com>
Sat, 8 Jan 2011 22:05:16 +0000 (23:05 +0100)
Cython/Debugger/Tests/TestLibCython.py
Cython/Debugger/Tests/test_libcython_in_gdb.py

index ba0b772e92372f3d31112e1008b2d1d87ea560f2..8bc123a0559ee7be44b2136bac462059f12974b8 100644 (file)
@@ -16,6 +16,7 @@ from distutils import ccompiler
 
 import runtests
 import Cython.Distutils.extension
+import Cython.Distutils.build_ext
 from Cython.Debugger import Cygdb as cygdb
 
 root = os.path.dirname(os.path.abspath(__file__))
@@ -24,6 +25,10 @@ cfuncs_file = os.path.join(root, 'cfuncs.c')
 with open(codefile) as f:
     source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f))
 
+# Cython.Distutils.__init__ imports build_ext from build_ext which means we
+# can't access the module anymore. Get it from sys.modules instead.
+build_ext = sys.modules['Cython.Distutils.build_ext']
+
 class DebuggerTestCase(unittest.TestCase):
 
     def setUp(self):
@@ -52,6 +57,9 @@ class DebuggerTestCase(unittest.TestCase):
             module='codefile',
         )
 
+        optimization_disabler = build_ext.Optimization()
+        optimization_disabler.disable_optimization()
+
         cython_compile_testcase = runtests.CythonCompileTestCase(
             workdir=self.tempdir,
             # we clean up everything (not only compiled files)
@@ -77,6 +85,8 @@ class DebuggerTestCase(unittest.TestCase):
             **opts
         )
 
+        optimization_disabler.restore_state()
+
         # ext = Cython.Distutils.extension.Extension(
             # 'codefile',
             # ['codefile.pyx'],
@@ -95,6 +105,7 @@ class DebuggerTestCase(unittest.TestCase):
 
 
 class GdbDebuggerTestCase(DebuggerTestCase):
+
     def setUp(self):
         super(GdbDebuggerTestCase, self).setUp()
 
index 8fe1cb6e37b13e840f281dcdc9f5c8bb4883198a..5775969af2b69f0426685eafa7d7233a2219edbe 100644 (file)
@@ -14,6 +14,7 @@ import warnings
 import unittest
 import textwrap
 import tempfile
+import functools
 import traceback
 import itertools
 from test import test_support
@@ -28,12 +29,35 @@ from Cython.Debugger.Tests import TestLibCython as test_libcython
 sys.argv = ['gdb']
 
 
+def print_on_call_decorator(func):
+    @functools.wraps(func)
+    def wrapper(self, *args, **kwargs):
+        _debug(type(self).__name__, func.__name__)
+
+        try:
+            return func(self, *args, **kwargs)
+        except Exception, e:
+            _debug("An exception occurred:", traceback.format_exc(e))
+            raise
+
+    return wrapper
+
+class TraceMethodCallMeta(type):
+
+    def __init__(self, name, bases, dict):
+        for func_name, func in dict.iteritems():
+            if inspect.isfunction(func):
+                setattr(self, func_name, print_on_call_decorator(func))
+
+
 class DebugTestCase(unittest.TestCase):
     """
-    Base class for test cases. On teardown it kills the inferior and unsets 
+    Base class for test cases. On teardown it kills the inferior and unsets
     all breakpoints.
     """
-    
+
+    __metaclass__ = TraceMethodCallMeta
+
     def __init__(self, name):
         super(DebugTestCase, self).__init__(name)
         self.cy = libcython.cy
@@ -43,17 +67,17 @@ class DebugTestCase(unittest.TestCase):
             'codefile.ham']
         self.eggs_func = libcython.cy.functions_by_qualified_name[
             'codefile.eggs']
-    
+
     def read_var(self, varname, cast_to=None):
         result = gdb.parse_and_eval('$cy_cvalue("%s")' % varname)
         if cast_to:
             result = cast_to(result)
-        
+
         return result
-    
+
     def local_info(self):
         return gdb.execute('info locals', to_string=True)
-    
+
     def lineno_equals(self, source_line=None, lineno=None):
         if source_line is not None:
             lineno = test_libcython.source_to_lineno[source_line]
@@ -71,19 +95,19 @@ class DebugTestCase(unittest.TestCase):
             gdb.execute('kill inferior 1', to_string=True)
         except RuntimeError:
             pass
-        
+
         gdb.execute('set args -c "import codefile"')
-        
+
 
 class TestDebugInformationClasses(DebugTestCase):
-    
+
     def test_CythonModule(self):
         "test that debug information was parsed properly into data structures"
         self.assertEqual(self.module.name, 'codefile')
-        global_vars = ('c_var', 'python_var', '__name__', 
+        global_vars = ('c_var', 'python_var', '__name__',
                        '__builtins__', '__doc__', '__file__')
         assert set(global_vars).issubset(self.module.globals)
-        
+
     def test_CythonVariable(self):
         module_globals = self.module.globals
         c_var = module_globals['c_var']
@@ -91,32 +115,32 @@ class TestDebugInformationClasses(DebugTestCase):
         self.assertEqual(c_var.type, libcython.CObject)
         self.assertEqual(python_var.type, libcython.PythonObject)
         self.assertEqual(c_var.qualified_name, 'codefile.c_var')
-    
+
     def test_CythonFunction(self):
         self.assertEqual(self.spam_func.qualified_name, 'codefile.spam')
-        self.assertEqual(self.spam_meth.qualified_name, 
+        self.assertEqual(self.spam_meth.qualified_name,
                          'codefile.SomeClass.spam')
         self.assertEqual(self.spam_func.module, self.module)
-        
+
         assert self.eggs_func.pf_cname, (self.eggs_func, self.eggs_func.pf_cname)
         assert not self.ham_func.pf_cname
         assert not self.spam_func.pf_cname
         assert not self.spam_meth.pf_cname
-        
+
         self.assertEqual(self.spam_func.type, libcython.CObject)
         self.assertEqual(self.ham_func.type, libcython.CObject)
-        
+
         self.assertEqual(self.spam_func.arguments, ['a'])
-        self.assertEqual(self.spam_func.step_into_functions, 
+        self.assertEqual(self.spam_func.step_into_functions,
                          set(['puts', 'some_c_function']))
-        
+
         expected_lineno = test_libcython.source_to_lineno['def spam(a=0):']
         self.assertEqual(self.spam_func.lineno, expected_lineno)
         self.assertEqual(sorted(self.spam_func.locals), list('abcd'))
 
 
 class TestParameters(unittest.TestCase):
-    
+
     def test_parameters(self):
         gdb.execute('set cy_colorize_code on')
         assert libcython.parameters.colorize_code
@@ -129,7 +153,7 @@ class TestBreak(DebugTestCase):
     def test_break(self):
         breakpoint_amount = len(gdb.breakpoints() or ())
         gdb.execute('cy break codefile.spam')
-        
+
         self.assertEqual(len(gdb.breakpoints()), breakpoint_amount + 1)
         bp = gdb.breakpoints()[-1]
         self.assertEqual(bp.type, gdb.BP_BREAKPOINT)
@@ -152,67 +176,67 @@ class TestBreak(DebugTestCase):
 
 
 class TestKilled(DebugTestCase):
-    
+
     def test_abort(self):
         gdb.execute("set args -c 'import os; os.abort()'")
         output = gdb.execute('cy run', to_string=True)
         assert 'abort' in output.lower()
 
 class DebugStepperTestCase(DebugTestCase):
-    
+
     def step(self, varnames_and_values, source_line=None, lineno=None):
         gdb.execute(self.command)
         for varname, value in varnames_and_values:
             self.assertEqual(self.read_var(varname), value, self.local_info())
-        
+
         self.lineno_equals(source_line, lineno)
 
 
 class TestStep(DebugStepperTestCase):
     """
-    Test stepping. Stepping happens in the code found in 
+    Test stepping. Stepping happens in the code found in
     Cython/Debugger/Tests/codefile.
     """
-    
+
     def test_cython_step(self):
         gdb.execute('cy break codefile.spam')
-        
+
         gdb.execute('run', to_string=True)
         self.lineno_equals('def spam(a=0):')
-        
+
         gdb.execute('cy step', to_string=True)
         self.lineno_equals('b = c = d = 0')
-        
+
         self.command = 'cy step'
         self.step([('b', 0)], source_line='b = 1')
         self.step([('b', 1), ('c', 0)], source_line='c = 2')
         self.step([('c', 2)], source_line='int(10)')
         self.step([], source_line='puts("spam")')
-        
+
         gdb.execute('cont', to_string=True)
         self.assertEqual(len(gdb.inferiors()), 1)
         self.assertEqual(gdb.inferiors()[0].pid, 0)
-    
+
     def test_c_step(self):
         self.break_and_run('some_c_function()')
         gdb.execute('cy step', to_string=True)
         self.assertEqual(gdb.selected_frame().name(), 'some_c_function')
-    
+
     def test_python_step(self):
         self.break_and_run('os.path.join("foo", "bar")')
-        
+
         result = gdb.execute('cy step', to_string=True)
-        
+
         curframe = gdb.selected_frame()
         self.assertEqual(curframe.name(), 'PyEval_EvalFrameEx')
-        
+
         pyframe = libpython.Frame(curframe).get_pyop()
         self.assertEqual(str(pyframe.co_name), 'join')
         assert re.match(r'\d+    def join\(', result), result
 
 
 class TestNext(DebugStepperTestCase):
-    
+
     def test_cython_next(self):
         self.break_and_run('c = 2')
 
@@ -229,18 +253,18 @@ class TestNext(DebugStepperTestCase):
 
 
 class TestLocalsGlobals(DebugTestCase):
-    
+
     def test_locals(self):
         self.break_and_run('int(10)')
-        
+
         result = gdb.execute('cy locals', to_string=True)
         assert 'a = 0', repr(result)
         assert 'b = (int) 1', result
         assert 'c = (int) 2' in result, repr(result)
-    
+
     def test_globals(self):
         self.break_and_run('int(10)')
-        
+
         result = gdb.execute('cy globals', to_string=True)
         assert '__name__ ' in result, repr(result)
         assert '__doc__ ' in result, repr(result)
@@ -250,45 +274,45 @@ class TestLocalsGlobals(DebugTestCase):
 
 
 class TestBacktrace(DebugTestCase):
-    
+
     def test_backtrace(self):
         libcython.parameters.colorize_code.value = False
-        
+
         self.break_and_run('os.path.join("foo", "bar")')
         result = gdb.execute('cy bt', to_string=True)
-        
+
         _debug(libpython.execute, libpython._execute, gdb.execute)
         _debug(gdb.execute('cy list', to_string=True))
         _debug(repr(result))
-        
-        assert re.search(r'\#\d+ *0x.* in spam\(\) at .*codefile\.pyx:22', 
+
+        assert re.search(r'\#\d+ *0x.* in spam\(\) at .*codefile\.pyx:22',
                          result), result
         assert 'os.path.join("foo", "bar")' in result, result
-        
+
         gdb.execute("cy step")
-        
+
         gdb.execute('cy bt')
         result = gdb.execute('cy bt -a', to_string=True)
         assert re.search(r'\#0 *0x.* in main\(\)', result), result
 
 
 class TestFunctions(DebugTestCase):
-    
+
     def test_functions(self):
         self.break_and_run('c = 2')
         result = gdb.execute('print $cy_cname("b")', to_string=True)
         assert re.search('__pyx_.*b', result), result
-        
+
         result = gdb.execute('print $cy_lineno()', to_string=True)
         supposed_lineno = test_libcython.source_to_lineno['c = 2']
         assert str(supposed_lineno) in result, (supposed_lineno, result)
-        
+
         result = gdb.execute('print $cy_cvalue("b")', to_string=True)
         assert '= 1' in result
-        
+
 
 class TestPrint(DebugTestCase):
-    
+
     def test_print(self):
         self.break_and_run('c = 2')
         result = gdb.execute('cy print b', to_string=True)
@@ -301,68 +325,68 @@ class TestUpDown(DebugTestCase):
         self.break_and_run('os.path.join("foo", "bar")')
         gdb.execute('cy step')
         self.assertRaises(RuntimeError, gdb.execute, 'cy down')
-        
+
         result = gdb.execute('cy up', to_string=True)
         assert 'spam()' in result
         assert 'os.path.join("foo", "bar")' in result
 
 
 class TestExec(DebugTestCase):
-    
+
     def setUp(self):
         super(TestExec, self).setUp()
         self.fd, self.tmpfilename = tempfile.mkstemp()
         self.tmpfile = os.fdopen(self.fd, 'r+')
-        
+
     def tearDown(self):
         super(TestExec, self).tearDown()
-        
+
         try:
             self.tmpfile.close()
         finally:
             os.remove(self.tmpfilename)
-    
+
     def eval_command(self, command):
-        gdb.execute('cy exec open(%r, "w").write(str(%s))' % 
+        gdb.execute('cy exec open(%r, "w").write(str(%s))' %
                                                 (self.tmpfilename, command))
         return self.tmpfile.read().strip()
-    
+
     def test_cython_exec(self):
         self.break_and_run('os.path.join("foo", "bar")')
-        
+
         # test normal behaviour
         self.assertEqual("[0]", self.eval_command('[a]'))
-        
+
         # test multiline code
         result = gdb.execute(textwrap.dedent('''\
             cy exec
             pass
-            
+
             "nothing"
             end
             '''))
         result = self.tmpfile.read().rstrip()
         self.assertEqual('', result)
-    
+
     def test_python_exec(self):
         self.break_and_run('os.path.join("foo", "bar")')
         gdb.execute('cy step')
-        
+
         gdb.execute('cy exec some_random_var = 14')
         self.assertEqual('14', self.eval_command('some_random_var'))
 
 class TestClosure(DebugTestCase):
-    
+
     def test_cython_closure(self):
         self.break_and_run('def inner():')
-        
+
         # Allow the Cython-generated code to initialize the scope variable
         gdb.execute('cy step')
-        
+
         self.assertEqual(str(self.read_var('a')), '1')
         print_result = gdb.execute('cy print a', to_string=True).strip()
         self.assertEqual(print_result, 'a = 1')
-    
+
     def test_cython_closure_no_closing_variables(self):
         self.break_and_run('def inner2():')
         self.assertEqual(gdb.execute('cy locals', to_string=True), '')
@@ -374,7 +398,7 @@ if _do_debug:
 
 def _debug(*messages):
     if _do_debug:
-        messages = itertools.chain([sys._getframe(1).f_code.co_name, ':'], 
+        messages = itertools.chain([sys._getframe(1).f_code.co_name, ':'],
                                    messages)
         _debug_file.write(' '.join(str(msg) for msg in messages) + '\n')
 
@@ -391,13 +415,13 @@ def run_unittest_in_module(modulename):
     else:
         m = __import__(modulename, fromlist=[''])
         tests = inspect.getmembers(m, inspect.isclass)
-        
+
         # test_support.run_unittest(tests)
-        
+
         test_loader = unittest.TestLoader()
         suite = unittest.TestSuite(
             [test_loader.loadTestsFromTestCase(cls) for name, cls in tests])
-        
+
         result = unittest.TextTestRunner(verbosity=1).run(suite)
         return result.wasSuccessful()
 
@@ -410,15 +434,15 @@ def runtests():
 
     success_libcython = run_unittest_in_module(__name__)
     success_libpython = run_unittest_in_module(test_libpython_in_gdb.__name__)
-    
+
     if not success_libcython or not success_libpython:
         sys.exit(1)
-    
+
 def main(version, trace_code=False):
-    global inferior_python_version 
-    
+    global inferior_python_version
+
     inferior_python_version = version
-    
+
     if trace_code:
         tracer = trace.Trace(count=False, trace=True, outfile=sys.stderr,
                             ignoredirs=[sys.prefix, sys.exec_prefix])