diff --git a/tests/run/call_py_cy.pyx b/tests/run/call_py_cy.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..cf830527cf74b92563dab4f7a7a5c4764e3f33f8
--- /dev/null
+++ b/tests/run/call_py_cy.pyx
@@ -0,0 +1,165 @@
+# mode: run
+# tag: cyfunction,call,python
+# cython: binding=True
+
+#######
+# Test that Cython and Python functions can call each other in various signature combinations.
+#######
+
+py_call_noargs = eval("lambda: 'noargs'")
+py_call_onearg = eval("lambda arg: arg")
+py_call_twoargs = eval("lambda arg, arg2: (arg, arg2)")
+py_call_starargs = eval("lambda *args: args")
+py_call_pos_and_starargs = eval("lambda arg, *args: (arg, args)")
+py_call_starstarargs = eval("lambda **kw: sorted(kw.items())")
+
+
+def cy_call_noargs():
+    """
+    >>> cy_call_noargs()
+    'noargs'
+    """
+    return py_call_noargs()
+
+
+def cy_call_onearg(f):
+    """
+    >>> cy_call_onearg(py_call_onearg)
+    'onearg'
+    >>> try: cy_call_onearg(py_call_noargs)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    >>> try: cy_call_onearg(py_call_twoargs)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    return f('onearg')
+
+
+def cy_call_twoargs(f, arg):
+    """
+    >>> cy_call_twoargs(py_call_twoargs, 132)
+    (132, 'twoargs')
+    """
+    return f(arg, 'twoargs')
+
+
+def cy_call_two_kwargs(f, arg):
+    """
+    >>> cy_call_twoargs(py_call_twoargs, arg=132)
+    (132, 'twoargs')
+    >>> cy_call_twoargs(f=py_call_twoargs, arg=132)
+    (132, 'twoargs')
+    >>> cy_call_twoargs(arg=132, f=py_call_twoargs)
+    (132, 'twoargs')
+    """
+    return f(arg2='twoargs', arg1=arg)
+
+
+def cy_call_starargs(*args):
+    """
+    >>> cy_call_starargs()
+    ()
+    >>> cy_call_starargs(1)
+    (1,)
+    >>> cy_call_starargs(1, 2)
+    (1, 2)
+    >>> cy_call_starargs(1, 2, 3)
+    (1, 2, 3)
+    """
+    return py_call_starargs(*args)
+
+
+def cy_call_pos_and_starargs(f, *args):
+    """
+    >>> cy_call_pos_and_starargs(py_call_onearg)
+    'no-arg'
+    >>> cy_call_pos_and_starargs(py_call_onearg, 123)
+    123
+    >>> cy_call_pos_and_starargs(py_call_twoargs, 123, 321)
+    (123, 321)
+    >>> cy_call_pos_and_starargs(py_call_starargs)
+    ('no-arg',)
+    >>> cy_call_pos_and_starargs(py_call_starargs, 123)
+    (123,)
+    >>> cy_call_pos_and_starargs(py_call_starargs, 123, 321)
+    (123, 321)
+    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs)
+    ('no-arg', ())
+    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123)
+    (123, ())
+    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321)
+    (123, (321,))
+    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321, 234)
+    (123, (321, 234))
+    """
+    return f(args[0] if args else 'no-arg', *args[1:])
+
+
+def cy_call_starstarargs(**kw):
+    """
+    >>> kw = {}
+    >>> cy_call_starstarargs(**kw)
+    []
+    >>> kw = {'a': 123}
+    >>> cy_call_starstarargs(**kw)
+    [('a', 123)]
+    >>> kw = {'a': 123, 'b': 321}
+    >>> cy_call_starstarargs(**kw)
+    [('a', 123), ('b', 321)]
+    """
+    return py_call_starstarargs(**kw)
+
+
+def cy_call_kw_and_starstarargs(f=None, arg1=None, **kw):
+    """
+    >>> kw = {}
+    >>> cy_call_kw_and_starstarargs(**kw)
+    [('arg', None)]
+    >>> try: cy_call_kw_and_starstarargs(py_call_noargs, **kw)
+    ... except TypeError: pass
+    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw)
+    >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw)
+    >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw)
+    (None, ())
+
+    >>> kw = {'arg1': 123}
+    >>> cy_call_kw_and_starstarargs(**kw)
+    [('arg', 123)]
+    >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw)
+    123
+    >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw)
+    123
+    >>> cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, **kw)
+    (123, 321)
+    >>> cy_call_kw_and_starstarargs(f=py_call_twoargs, arg2=321, **kw)
+    (123, 321)
+    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, other=234, **kw)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw)
+    (123, ())
+
+    >>> try: cy_call_kw_and_starstarargs(arg=321, **kw)   # duplicate kw in Python call
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+
+    >>> kw = {'a': 123}
+    >>> cy_call_kw_and_starstarargs(**kw)
+    [('a', 123), ('arg', None)]
+    >>> cy_call_kw_and_starstarargs(arg1=321, **kw)
+    [('a', 123), ('arg', 321)]
+
+    >>> kw = {'a': 123, 'b': 321}
+    >>> cy_call_kw_and_starstarargs(**kw)
+    [('a', 123), ('arg', None), ('b', 321)]
+    >>> cy_call_kw_and_starstarargs(arg1=234, **kw)
+    [('a', 123), ('arg', 234), ('b', 321)]
+    """
+    return (f or py_call_starstarargs)(arg=arg1, **kw)