Commit d07e7567 authored by Mark Florisson's avatar Mark Florisson

lots of tests

parent 1327c85b
......@@ -197,10 +197,12 @@ class TestDebugTransform(TestLibCython.DebuggerTestCase):
self.assertEqual(1, len(list(spam_arguments)))
# test step-into functions
spam_stepinto = list(spam.find('StepIntoFunctions'))
step_into = spam.find('StepIntoFunctions')
spam_stepinto = [x.attrib['name'] for x in step_into]
assert spam_stepinto
self.assertEqual(1, len(list(spam_stepinto)))
self.assertEqual('puts', list(spam_stepinto)[0].attrib['name'])
self.assertEqual(2, len(spam_stepinto))
assert 'puts' in spam_stepinto
assert 'some_c_function' in spam_stepinto
except:
print open(self.debug_dest).read()
raise
......
......@@ -9,10 +9,16 @@ import tempfile
import subprocess
import distutils.core
from distutils import sysconfig
from distutils import ccompiler
import Cython.Distutils.extension
from Cython.Debugger import Cygdb as cygdb
root = os.path.dirname(os.path.abspath(__file__))
codefile = os.path.join(root, 'codefile')
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))
class DebuggerTestCase(unittest.TestCase):
......@@ -26,48 +32,22 @@ class DebuggerTestCase(unittest.TestCase):
self.debug_dest = os.path.join(self.tempdir,
'cython_debug',
'cython_debug_info_codefile')
code = textwrap.dedent("""
cdef extern from "stdio.h":
int puts(char *s)
cdef int c_var = 0
python_var = 0
def spam(a=0):
cdef:
int b, c, d
b = c = d = 0
b = 1
c = 2
d = 3
int(10)
puts("spam")
cdef ham():
pass
cpdef eggs():
pass
cdef class SomeClass(object):
def spam(self):
pass
spam()
""")
self.cfuncs_destfile = os.path.join(self.tempdir, 'cfuncs')
self.cwd = os.getcwd()
os.chdir(self.tempdir)
open(self.destfile, 'w').write(code)
shutil.copy(codefile, self.destfile)
shutil.copy(cfuncs_file, self.cfuncs_destfile + '.c')
compiler = ccompiler.new_compiler()
compiler.compile(['cfuncs.c'], debug=True)
ext = Cython.Distutils.extension.Extension(
'codefile',
['codefile.pyx'],
pyrex_debug=True)
pyrex_debug=True,
extra_objects=['cfuncs.o'])
distutils.core.setup(
script_args=['build_ext', '--inplace'],
......@@ -84,11 +64,38 @@ class GdbDebuggerTestCase(DebuggerTestCase):
def setUp(self):
super(GdbDebuggerTestCase, self).setUp()
self.gdb_command_file = cygdb.make_command_file(self.tempdir)
with open(self.gdb_command_file, 'a') as f:
f.write('python '
'from Cython.Debugger.Tests import test_libcython_in_gdb;'
'test_libcython_in_gdb.main()\n')
prefix_code = textwrap.dedent('''\
python
import os
import sys
import traceback
def excepthook(type, value, tb):
traceback.print_exception(type, value, tb)
os._exit(1)
sys.excepthook = excepthook
# Have tracebacks end up on sys.stderr (gdb replaces sys.stderr
# with an object that calls gdb.write())
sys.stderr = sys.__stderr__
end
''')
code = textwrap.dedent('''\
python
from Cython.Debugger.Tests import test_libcython_in_gdb
test_libcython_in_gdb.main()
end
''')
self.gdb_command_file = cygdb.make_command_file(self.tempdir,
prefix_code)
open(self.gdb_command_file, 'a').write(code)
args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args',
sys.executable, '-c', 'import codefile']
......@@ -100,6 +107,7 @@ class GdbDebuggerTestCase(DebuggerTestCase):
paths.append(os.path.dirname(os.path.dirname(
os.path.abspath(Cython.__file__))))
env = dict(os.environ, PYTHONPATH=os.pathsep.join(paths))
self.p = subprocess.Popen(
args,
stdout=open(os.devnull, 'w'),
......
void
some_c_function(void)
{
int a, b, c;
a = 1;
b = 2;
}
\ No newline at end of file
cdef extern from "stdio.h":
int puts(char *s)
cdef extern:
void some_c_function()
import os
cdef int c_var = 0
python_var = 0
def spam(a=0):
cdef:
int b, c
b = c = d = 0
b = 1
c = 2
int(10)
puts("spam")
os.path.join("foo", "bar")
some_c_function()
cdef ham():
pass
cpdef eggs():
pass
cdef class SomeClass(object):
def spam(self):
pass
spam()
print "bye!"
......@@ -5,19 +5,9 @@ Note: debug information is already imported by the file generated by
Cython.Debugger.Cygdb.make_command_file()
"""
import sys
# First, fix gdb's python. Make sure to do this before importing modules
# that bind output streams as default parameters
# for some reason sys.argv is missing in gdb
sys.argv = ['gdb']
# Allow gdb to capture output, but have errors end up on stderr
# sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
import os
import sys
import trace
import warnings
import unittest
import traceback
......@@ -26,6 +16,12 @@ from test import test_support
import gdb
from Cython.Debugger import libcython
from Cython.Debugger import libpython
from Cython.Debugger.Tests import TestLibCython as test_libcython
# for some reason sys.argv is missing in gdb
sys.argv = ['gdb']
class DebugTestCase(unittest.TestCase):
......@@ -39,14 +35,35 @@ class DebugTestCase(unittest.TestCase):
self.eggs_func = libcython.cy.functions_by_qualified_name[
'codefile.eggs']
def read_var(self, varname):
return gdb.parse_and_eval('$cy_cname("%s")' % varname)
def read_var(self, varname, cast_to=None):
result = gdb.parse_and_eval('$cy_cname("%s")' % varname)
if cast_to:
result = cast_to(result)
return result
def local_info(self):
return gdb.execute('info locals', to_string=True)
class TestDebugInformationClasses(DebugTestCase):
def lineno_equals(self, source_line=None, lineno=None):
if source_line is not None:
lineno = test_libcython.source_to_lineno[source_line]
frame = gdb.selected_frame()
self.assertEqual(libcython.cy.step.lineno(frame), lineno)
def tearDown(self):
gdb.execute('delete breakpoints', to_string=True)
try:
gdb.execute('kill inferior 1', to_string=True)
except RuntimeError:
pass
def break_and_run(self, source_line):
break_lineno = test_libcython.source_to_lineno[source_line]
gdb.execute('cy break codefile:%d' % break_lineno, to_string=True)
gdb.execute('run', to_string=True)
class TestDebugInformationClasses(DebugTestCase):
def test_CythonModule(self):
"test that debug information was parsed properly into data structures"
......@@ -78,9 +95,11 @@ class TestDebugInformationClasses(DebugTestCase):
self.assertEqual(self.ham_func.type, libcython.CObject)
self.assertEqual(self.spam_func.arguments, ['a'])
self.assertEqual(self.spam_func.step_into_functions, set(['puts']))
self.assertEqual(self.spam_func.step_into_functions,
set(['puts', 'some_c_function']))
self.assertEqual(self.spam_func.lineno, 8)
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'))
......@@ -95,7 +114,8 @@ class TestParameters(unittest.TestCase):
class TestBreak(DebugTestCase):
def test_break(self):
result = gdb.execute('cy break codefile.spam', to_string=True)
result = libpython._execute('cy break codefile.spam', to_string=True)
print >>sys.stderr, repr(result)
assert self.spam_func.cname in result
self.assertEqual(len(gdb.breakpoints()), 1)
......@@ -105,26 +125,79 @@ class TestBreak(DebugTestCase):
assert bp.enabled
class TestStep(DebugTestCase):
class DebugStepperTestCase(DebugTestCase):
def test_step(self):
# Note: breakpoint for spam is still set
gdb.execute('run')
def step(self, varnames_and_values, source_line=None, lineno=None):
gdb.execute(self.command, to_string=True)
for varname, value in varnames_and_values:
self.assertEqual(self.read_var(varname), value, self.local_info())
gdb.execute('cy step', to_string=True) # b = c = d = 0
gdb.execute('cy step', to_string=True) # b = 1
self.assertEqual(self.read_var('b'), 1, self.local_info())
self.assertRaises(RuntimeError, self.read_var('b'))
gdb.execute('cont')
self.lineno_equals(source_line, lineno)
class TestNext(DebugTestCase):
class TestStep(DebugStepperTestCase):
"""
Test stepping. Stepping happens in the code found in
Cython/Debugger/Tests/codefile.
"""
def test_cython_step(self):
gdb.execute('cy break codefile.spam')
libcython.parameters.step_into_c_code.value = False
def test_next(self):
pass
gdb.execute('run', to_string=True)
self.lineno_equals('def spam(a=0):')
def main():
try:
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")')
self.step([], source_line='os.path.join("foo", "bar")')
gdb.execute('cont', to_string=True)
self.assertEqual(len(gdb.inferiors()), 1)
self.assertEqual(gdb.inferiors()[0].pid, 0)
def test_c_step(self):
libcython.parameters.step_into_c_code.value = True
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")')
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')
class TestNext(DebugStepperTestCase):
def test_cython_next(self):
libcython.parameters.step_into_c_code.value = True
self.break_and_run('c = 2')
lines = (
'int(10)',
'puts("spam")',
'os.path.join("foo", "bar")',
'some_c_function()',
)
for line in lines:
gdb.execute('cy next')
self.lineno_equals(line)
def _main():
# unittest.main(module=__import__(__name__, fromlist=['']))
try:
gdb.lookup_type('PyModuleObject')
......@@ -138,14 +211,22 @@ def main():
TestDebugInformationClasses,
TestParameters,
TestBreak,
TestStep
TestStep,
TestNext,
)
# test_support.run_unittest(tests)
test_loader = unittest.TestLoader()
suite = unittest.TestSuite(
[test_loader.loadTestsFromTestCase(cls) for cls in tests])
unittest.TextTestRunner(verbosity=1).run(suite)
except Exception:
traceback.print_exc()
result = unittest.TextTestRunner(verbosity=1).run(suite)
if not result.wasSuccessful():
os._exit(1)
def main(trace_code=False):
if trace_code:
tracer = trace.Trace(count=False, trace=True, outfile=sys.stderr,
ignoredirs=[sys.prefix, sys.exec_prefix])
tracer.runfunc(_main)
else:
_main()
\ No newline at end of file
import unittest
from Cython import StringIOTree as stringtree
code = """
cdef int spam # line 1
cdef ham():
a = 1
b = 2
c = 3
d = 4
def eggs():
pass
cpdef bacon():
print spam
print 'scotch'
print 'tea?'
print 'or coffee?' # line 16
"""
linemap = dict(enumerate(code.splitlines()))
class TestStringIOTree(unittest.TestCase):
def setUp(self):
self.tree = stringtree.StringIOTree()
def test_markers(self):
assert not self.tree.allmarkers()
def test_insertion(self):
self.write_lines((1, 2, 3))
line_4_to_6_insertion_point = self.tree.insertion_point()
self.write_lines((7, 8))
line_9_to_13_insertion_point = self.tree.insertion_point()
self.write_lines((14, 15, 16))
line_4_insertion_point = line_4_to_6_insertion_point.insertion_point()
self.write_lines((5, 6), tree=line_4_to_6_insertion_point)
line_9_to_12_insertion_point = (
line_9_to_13_insertion_point.insertion_point())
self.write_line(13, tree=line_9_to_13_insertion_point)
self.write_line(4, tree=line_4_insertion_point)
self.write_line(9, tree=line_9_to_12_insertion_point)
line_10_insertion_point = line_9_to_12_insertion_point.insertion_point()
self.write_line(11, tree=line_9_to_12_insertion_point)
self.write_line(10, tree=line_10_insertion_point)
self.write_line(12, tree=line_9_to_12_insertion_point)
self.assertEqual(self.tree.allmarkers(), range(1, 17))
self.assertEqual(code.strip(), self.tree.getvalue().strip())
def write_lines(self, linenos, tree=None):
for lineno in linenos:
self.write_line(lineno, tree=tree)
def write_line(self, lineno, tree=None):
if tree is None:
tree = self.tree
tree.markers.append(lineno)
tree.write(linemap[lineno] + '\n')
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment