Skip to content

Commit 12ac1ed

Browse files
miss-islingtonserhiy-storchakaclaude
authored
[3.14] gh-155146: Do not depend on the exact number of allocations in test_class (GH-155150) (GH-155156)
Try to fail every one of the first allocations and accept the first one which fails in the code detaching the instance dictionary from the object, instead of assuming that this is the first allocation after set_nomemory(). Run the test with the test.support.isolation.runInSubprocess() decorator instead of executing it as a source string in a subprocess. (cherry picked from commit 416c346) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent bddc018 commit 12ac1ed

1 file changed

Lines changed: 34 additions & 23 deletions

File tree

Lib/test/test_class.py

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import unittest
44
from test import support
5-
from test.support import cpython_only, import_helper, script_helper
5+
from test.support import cpython_only, import_helper, isolation
66

77
testmeths = [
88

@@ -1013,32 +1013,43 @@ class C:
10131013
C.a = X()
10141014

10151015
@support.nomemtest
1016+
@isolation.runInSubprocess()
10161017
def test_detach_materialized_dict_no_memory(self):
1017-
code = """if 1:
1018-
import test.support
1019-
import _testcapi
1020-
1021-
class A:
1022-
def __init__(self):
1023-
self.a = 1
1024-
self.b = 2
1018+
import _testcapi
1019+
1020+
class A:
1021+
def __init__(self):
1022+
self.a = 1
1023+
self.b = 2
1024+
1025+
# The failing allocation should be the one which detaches the
1026+
# dictionary from the object, but other allocations can happen
1027+
# first, so try to fail every one of the first allocations.
1028+
raised = False
1029+
for n in range(20):
10251030
a = A()
10261031
d = a.__dict__
1027-
with test.support.catch_unraisable_exception() as ex:
1028-
_testcapi.set_nomemory(0, 1)
1029-
del a
1030-
assert ex.unraisable.exc_type is MemoryError
10311032
try:
1032-
d["a"]
1033-
except KeyError:
1034-
pass
1035-
else:
1036-
assert False, "KeyError not raised"
1037-
"""
1038-
rc, out, err = script_helper.assert_python_ok("-c", code)
1039-
self.assertEqual(rc, 0)
1040-
self.assertFalse(out, msg=out.decode('utf-8'))
1041-
self.assertFalse(err, msg=err.decode('utf-8'))
1033+
with support.catch_unraisable_exception() as ex:
1034+
_testcapi.set_nomemory(n, n + 1)
1035+
try:
1036+
del a
1037+
finally:
1038+
_testcapi.remove_mem_hooks()
1039+
exc_type = ex.unraisable and ex.unraisable.exc_type
1040+
except MemoryError:
1041+
# The failing allocation was not in the deallocation code.
1042+
continue
1043+
if exc_type is not MemoryError:
1044+
continue
1045+
raised = True
1046+
if "a" not in d:
1047+
# The dictionary was cleared, as expected.
1048+
break
1049+
else:
1050+
if not raised:
1051+
self.fail("MemoryError was not raised during deallocation")
1052+
self.fail("the dictionary was not cleared")
10421053

10431054
if __name__ == '__main__':
10441055
unittest.main()

0 commit comments

Comments
 (0)