with self.assertRaises(TypeError):
self.dumps(c)
+ @support.skip_if_unlimited_stack_size
@no_tracing
def test_bad_getattr(self):
# Issue #3514: crash when there is an infinite loop in __getattr__
"check__all__", "skip_if_buggy_ucrt_strfptime",
"check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer",
"requires_limited_api", "requires_specialization", "thread_unsafe",
+ "skip_if_unlimited_stack_size",
# sys
"MS_WINDOWS", "is_jython", "is_android", "is_emscripten", "is_wasi",
"is_apple_mobile", "check_impl_detail", "unix_shell", "setswitchinterval",
return test if ok else unittest.skip(msg)(test)
+def skip_if_unlimited_stack_size(test):
+ """Skip decorator for tests not run when an unlimited stack size is configured.
+
+ Tests using support.infinite_recursion([...]) may otherwise run into
+ an infinite loop, running until the memory on the system is filled and
+ crashing due to OOM.
+
+ See https://github.com/python/cpython/issues/143460.
+ """
+ if is_wasi or os.name == "nt":
+ return test
+
+ import resource
+ curlim, maxlim = resource.getrlimit(resource.RLIMIT_STACK)
+ unlimited_stack_size_cond = curlim == maxlim and curlim in (-1, 0xFFFF_FFFF_FFFF_FFFF)
+ reason = "Not run due to unlimited stack size"
+ return unittest.skipIf(unlimited_stack_size_cond, reason)(test)
+
+
def detect_api_mismatch(ref_api, other_api, *, ignore=()):
"""Returns the set of items in ref_api not in other_api, except for a
defined list of items to be ignored in this check.
from test import support
from test.support import os_helper
-from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow
+from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow, skip_if_unlimited_stack_size
from test.support.ast_helper import ASTTestMixin
from test.support.import_helper import ensure_lazy_imports
from test.test_ast.utils import to_tuple
enum._test_simple_enum(_Precedence, _ast_unparse._Precedence)
@support.cpython_only
+ @skip_if_unlimited_stack_size
@skip_wasi_stack_overflow()
@skip_emscripten_stack_overflow()
def test_ast_recursion_limit(self):
ast2 = pickle.loads(pickle.dumps(tree, protocol))
self.assertEqual(to_tuple(ast2), to_tuple(tree))
+ @skip_if_unlimited_stack_size
def test_copy_with_parents(self):
# gh-120108
code = """
exec(code, ns)
self.assertIn('sleep', ns)
+ @skip_if_unlimited_stack_size
@skip_emscripten_stack_overflow()
def test_recursion_direct(self):
e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, operand=ast.Constant(1))
with support.infinite_recursion():
compile(ast.Expression(e), "<test>", "eval")
+ @skip_if_unlimited_stack_size
@skip_emscripten_stack_overflow()
def test_recursion_indirect(self):
e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, operand=ast.Constant(1))
self.assertIs(type(r[0]), tuple)
@support.skip_if_sanitizer("thread sanitizer crashes in __tsan::FuncEntry", thread=True)
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
def test_recursive_pickle(self):
with replaced_module('functools', self.module):
@support.skip_on_s390x
@unittest.skipIf(support.is_wasi, "WASI has limited C stack")
@support.skip_if_sanitizer("requires deep stack", ub=True, thread=True)
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
def test_lru_recursion(self):
self.assertRaises(RecursionError, issubclass, int, X())
self.assertRaises(RecursionError, isinstance, 1, X())
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_infinite_recursion_via_bases_tuple(self):
with self.assertRaises(RecursionError):
issubclass(Failure(), int)
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_infinite_cycle_in_bases(self):
self.fail("didn't raise ValueError on default recursion")
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_highly_nested_objects_decoding(self):
with support.infinite_recursion():
self.loads('[' * very_deep + '1' + ']' * very_deep)
+ @support.skip_if_unlimited_stack_size
@support.skip_wasi_stack_overflow()
@support.skip_emscripten_stack_overflow()
@support.requires_resource('cpu')
with support.infinite_recursion(5000):
self.dumps(d)
+ @support.skip_if_unlimited_stack_size
@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_endless_recursion(self):
""")
script_helper.assert_python_ok("-c", code)
+ @support.skip_if_unlimited_stack_size
def test_recursion(self):
# Test infinite_recursion() and get_recursion_available() functions.
def recursive_function(depth):
}
self.assertEqual(obj_copy, expected_obj)
+ @support.skip_if_unlimited_stack_size
def test_inline_array_recursion_limit(self):
with support.infinite_recursion(max_depth=100):
available = support.get_recursion_available()
recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]"
tomllib.loads(recursive_array_toml)
+ @support.skip_if_unlimited_stack_size
def test_inline_table_recursion_limit(self):
with support.infinite_recursion(max_depth=100):
available = support.get_recursion_available()
--- /dev/null
+Skip tests relying on infinite recusion if stack size is unlimited.