Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 19 additions & 24 deletions Lib/test/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import unittest
from test import support
from test.support import cpython_only, import_helper, isolation
from test.support import cpython_only, import_helper

testmeths = [

Expand Down Expand Up @@ -1014,7 +1014,6 @@ class C:
C.a = X()

@support.nomemtest
@isolation.runInSubprocess()
def test_detach_materialized_dict_no_memory(self):
import _testcapi

Expand All @@ -1026,31 +1025,27 @@ def __init__(self):
# The failing allocation should be the one which detaches the
# dictionary from the object, but other allocations can happen
# first, so try to fail every one of the first allocations.
raised = False
# Drop the last reference from C, so that nothing else (such as
# GC) runs between arming the failure and the deallocation.
seen = []
for n in range(20):
a = A()
d = a.__dict__
try:
with support.catch_unraisable_exception() as ex:
_testcapi.set_nomemory(n, n + 1)
try:
del a
finally:
_testcapi.remove_mem_hooks()
exc_type = ex.unraisable and ex.unraisable.exc_type
except MemoryError:
# The failing allocation was not in the deallocation code.
continue
if exc_type is not MemoryError:
continue
raised = True
if "a" not in d:
# The dictionary was cleared, as expected.
lst = [A()]
d = lst[0].__dict__
with support.catch_unraisable_exception() as ex:
_testcapi.call_with_nomemory(n, n + 1, lst.clear)
if ex.unraisable is None:
continue
exc_type = ex.unraisable.exc_type
err_msg = ex.unraisable.err_msg
seen.append((n, exc_type, err_msg))
if (exc_type is MemoryError and err_msg ==
'Exception ignored while clearing an object managed dict'):
# The dictionary should have been cleared.
self.assertNotIn("a", d)
break
else:
if not raised:
self.fail("MemoryError was not raised during deallocation")
self.fail("the dictionary was not cleared")
self.fail("MemoryError was not raised while detaching "
f"the dictionary: {seen}")

class DefinitionOrderTests(unittest.TestCase):
# PEP 520: Preserving Class Attribute Definition Order
Expand Down
35 changes: 35 additions & 0 deletions Modules/_testcapi/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,39 @@ remove_mem_hooks(PyObject *self, PyObject *Py_UNUSED(ignored))
Py_RETURN_NONE;
}

static PyObject *
call_with_nomemory(PyObject *self, PyObject *args)
{
/* Call func(*args) with memory allocation failing as in set_nomemory().
* No bytecode is executed between arming the failure and the call. */
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
if (nargs < 3) {
PyErr_SetString(PyExc_TypeError,
"call_with_nomemory() requires at least 3 arguments");
return NULL;
}
int start = PyLong_AsInt(PyTuple_GET_ITEM(args, 0));
if (start == -1 && PyErr_Occurred()) {
return NULL;
}
int stop = PyLong_AsInt(PyTuple_GET_ITEM(args, 1));
if (stop == -1 && PyErr_Occurred()) {
return NULL;
}
PyObject *func = PyTuple_GET_ITEM(args, 2);
/* PyObject_Call() with a prebuilt tuple does not allocate,
* unlike PyObject_Vectorcall() for a callee without vectorcall. */
PyObject *callargs = PyTuple_GetSlice(args, 3, nargs);
if (callargs == NULL) {
return NULL;
}
fm_set_nomemory(start, stop);
PyObject *res = PyObject_Call(func, callargs, NULL);
fm_remove_hooks();
Py_DECREF(callargs);
return res;
}

static PyObject *
test_setallocators(PyMemAllocatorDomain domain)
{
Expand Down Expand Up @@ -964,6 +997,8 @@ static PyMethodDef test_methods[] = {
PyDoc_STR("Remove memory hooks.")},
{"set_nomemory", set_nomemory, METH_VARARGS,
PyDoc_STR("set_nomemory(start:int, stop:int = 0)")},
{"call_with_nomemory", call_with_nomemory, METH_VARARGS,
PyDoc_STR("call_with_nomemory(start:int, stop:int, func, /, *args)")},
{"test_pymem_alloc0", test_pymem_alloc0, METH_NOARGS},
{"test_pymem_setallocators", test_pymem_setallocators, METH_NOARGS},
{"test_pymem_setrawallocators", test_pymem_setrawallocators, METH_NOARGS},
Expand Down
Loading