Commit 90b53708 authored by Stefan Behnel's avatar Stefan Behnel

extend line tracing test to include trace function failures in nogil functions

parent fc794431
# cython: linetrace=True # cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE_NOGIL=1
# mode: run # mode: run
# tag: trace # tag: trace
...@@ -39,24 +40,29 @@ cdef int _failing_call_trace_func(PyObject* _traceobj, PyFrameObject* _frame, in ...@@ -39,24 +40,29 @@ cdef int _failing_call_trace_func(PyObject* _traceobj, PyFrameObject* _frame, in
cdef int _failing_line_trace_func(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* arg) except -1: cdef int _failing_line_trace_func(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* arg) except -1:
if what == PyTrace_LINE and _traceobj: if what == PyTrace_LINE and _traceobj:
trace = <object>_traceobj frame, traceobj = <object>_frame, <object>_traceobj
if len(trace) == 1: if traceobj and traceobj[0] == frame.f_code.co_name:
# right after call with empty trace list => fail! # first line in the right function => fail!
raise ValueError("failing line trace!") raise ValueError("failing line trace!")
return _trace_func(_traceobj, _frame, what, arg) return _trace_func(_traceobj, _frame, what, arg)
def cy_add(a,b): def cy_add(a,b):
x = a + b x = a + b # 1
return x return x # 2
def cy_add_with_nogil(a,b):
cdef int z, x=a, y=b # 1
with nogil: # 2
z = 0 # 3
z += cy_add_nogil(x, y) # 4
return z # 5
def cy_add_nogil(a,b): cdef int cy_add_nogil(int a, int b) nogil except -1:
cdef int z, x=a, y=b x = a + b # 1
with nogil: # no traces in this block ! return x # 2
z = 0
z += x + y
return z
def run_trace(func, *args): def run_trace(func, *args):
...@@ -68,8 +74,13 @@ def run_trace(func, *args): ...@@ -68,8 +74,13 @@ def run_trace(func, *args):
[('call', 0), ('line', 1), ('line', 2), ('return', 2)] [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> run_trace(cy_add, 1, 2) >>> run_trace(cy_add, 1, 2)
[('call', 0), ('line', 1), ('line', 2), ('return', 2)] [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> run_trace(cy_add_nogil, 1, 2) >>> result = run_trace(cy_add_with_nogil, 1, 2)
[('call', 0), ('line', 1), ('line', 2), ('line', 5), ('return', 5)] >>> result[:5]
[('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
>>> result[5:9]
[('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> result[9:]
[('line', 2), ('line', 5), ('return', 5)]
""" """
trace = [] trace = []
PyEval_SetTrace(<Py_tracefunc>_trace_func, trace) PyEval_SetTrace(<Py_tracefunc>_trace_func, trace)
...@@ -98,27 +109,51 @@ def fail_on_call_trace(func, *args): ...@@ -98,27 +109,51 @@ def fail_on_call_trace(func, *args):
assert not trace assert not trace
def fail_on_line_trace(bint fail): def fail_on_line_trace(fail_func):
""" """
>>> fail_on_line_trace(False) >>> result = fail_on_line_trace(None)
['STARTING', ('call', 0), ('line', 1), ('line', 2), ('return', 2), ('call', 0), ('line', 1), ('line', 2), ('return', 2)] >>> len(result)
>>> fail_on_line_trace(True) 17
Traceback (most recent call last): >>> result[:5]
ValueError: failing line trace! ['NO ERROR', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> result[5:10]
[('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
>>> result[10:14]
[('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> result[14:]
[('line', 2), ('line', 5), ('return', 5)]
>>> result = fail_on_line_trace('cy_add_with_nogil')
failing line trace!
>>> result
['cy_add_with_nogil', ('call', 0), ('line', 1), ('line', 2), ('return', 2), ('call', 0), ('return', 1)]
>>> result = fail_on_line_trace('cy_add_nogil')
failing line trace!
>>> result[:5]
['cy_add_nogil', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
>>> result[5:]
[('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4), ('call', 0), ('return', 1), ('return', 4)]
""" """
cdef int x = 1 cdef int x = 1
trace = ['STARTING'] trace = ['NO ERROR']
exception = None
PyEval_SetTrace(<Py_tracefunc>_failing_line_trace_func, trace) PyEval_SetTrace(<Py_tracefunc>_failing_line_trace_func, trace)
try: try:
x += 1 x += 1
cy_add(1, 2) cy_add(1, 2)
x += 1 x += 1
if fail: if fail_func:
del trace[:] # trigger error trace[0] = fail_func # trigger error on first line
x += 1 x += 1
cy_add(3, 4) cy_add_with_nogil(3, 4)
x += 1 x += 1
except Exception as exc:
exception = str(exc)
finally: finally:
PyEval_SetTrace(NULL, None) PyEval_SetTrace(NULL, None)
if exception:
print(exception)
else:
assert x == 5 assert x == 5
return trace return trace
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