Skip to content

Commit b7202b5

Browse files
committed
Add a test for capsule destructor
1 parent f2048f0 commit b7202b5

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import os
4343
import shutil
4444
import sys
45+
import time
4546
import unittest
4647
from copy import deepcopy
4748
from io import StringIO
@@ -54,6 +55,13 @@
5455

5556
IS_MANAGED_LAUNCHER = not GRAALPYTHON or __graalpython__.is_managed_launcher()
5657

58+
59+
def run_gc():
60+
for i in range(3):
61+
gc.collect()
62+
time.sleep(0.01)
63+
64+
5765
def assert_raises(err, fn, *args, **kwargs):
5866
raised = False
5967
try:

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_capsule.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40-
from . import CPyExtTestCase, CPyExtFunction, unhandled_error_compare
40+
from . import CPyExtTestCase, CPyExtFunction, unhandled_error_compare, CPyExtType, run_gc
4141

4242
__dir__ = __file__.rpartition("/")[0]
4343

4444

4545
class TestPyCapsule(CPyExtTestCase):
46-
4746
test_PyCapsule_CheckExact = CPyExtFunction(
4847
lambda args: True,
4948
lambda: (
@@ -112,3 +111,29 @@ class TestPyCapsule(CPyExtTestCase):
112111
callfunction="wrap_PyCapsule_SetContext",
113112
cmpfunc=unhandled_error_compare
114113
)
114+
115+
def test_capsule_destructor(self):
116+
Tester = CPyExtType(
117+
"CapsuleDestructorTester",
118+
code="""
119+
static void capsule_destructor(PyObject* capsule) {
120+
PyObject* contents = (PyObject*) PyCapsule_GetPointer(capsule, "capsule");
121+
assert(PyDict_Check(contents));
122+
PyDict_SetItemString(contents, "destructor_was_here", Py_NewRef(Py_True));
123+
Py_DECREF(contents);
124+
}
125+
126+
static PyObject* create_capsule(PyObject* unused, PyObject* contents) {
127+
return PyCapsule_New(Py_NewRef(contents), "capsule", capsule_destructor);
128+
}
129+
""",
130+
tp_methods='{"create_capsule", (PyCFunction)create_capsule, METH_O | METH_STATIC, NULL}',
131+
)
132+
d = {}
133+
capsule = Tester.create_capsule(d)
134+
run_gc()
135+
assert capsule
136+
assert not d
137+
del capsule
138+
run_gc()
139+
assert "destructor_was_here" in d

0 commit comments

Comments
 (0)