]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-116303: Skip tests if C recursion limit is unavailable (GH-117368)
authorErlend E. Aasland <erlend@python.org>
Mon, 8 Apr 2024 12:45:25 +0000 (14:45 +0200)
committerGitHub <noreply@github.com>
Mon, 8 Apr 2024 12:45:25 +0000 (14:45 +0200)
The test suite fetches the C recursion limit from the _testcapi
extension module. Test extension modules can be disabled using the
--disable-test-modules configure option.

14 files changed:
Lib/test/list_tests.py
Lib/test/mapping_tests.py
Lib/test/support/__init__.py
Lib/test/test_ast.py
Lib/test/test_collections.py
Lib/test/test_compile.py
Lib/test/test_dict.py
Lib/test/test_dictviews.py
Lib/test/test_exception_group.py
Lib/test/test_exceptions.py
Lib/test/test_functools.py
Lib/test/test_isinstance.py
Lib/test/test_marshal.py
Lib/test/test_sys_settrace.py

index 26118e14bb97e08d66fd331fa6115c9be53c94dc..89cd10f76a318ee235caccb2c7897f4b5b30d40c 100644 (file)
@@ -6,7 +6,7 @@ import sys
 from functools import cmp_to_key
 
 from test import seq_tests
-from test.support import ALWAYS_EQ, NEVER_EQ, Py_C_RECURSION_LIMIT
+from test.support import ALWAYS_EQ, NEVER_EQ, get_c_recursion_limit
 
 
 class CommonTest(seq_tests.CommonTest):
@@ -61,7 +61,7 @@ class CommonTest(seq_tests.CommonTest):
 
     def test_repr_deep(self):
         a = self.type2test([])
-        for i in range(Py_C_RECURSION_LIMIT + 1):
+        for i in range(get_c_recursion_limit() + 1):
             a = self.type2test([a])
         self.assertRaises(RecursionError, repr, a)
 
index b4cfce19a7174e6be309e152bbc29a8116962e5f..ed89a81a6ea685df63aa219b8646036ae7775c83 100644 (file)
@@ -1,7 +1,7 @@
 # tests common to dict and UserDict
 import unittest
 import collections
-from test.support import Py_C_RECURSION_LIMIT
+from test.support import get_c_recursion_limit
 
 
 class BasicTestMappingProtocol(unittest.TestCase):
@@ -624,7 +624,7 @@ class TestHashMappingProtocol(TestMappingProtocol):
 
     def test_repr_deep(self):
         d = self._empty_mapping()
-        for i in range(Py_C_RECURSION_LIMIT + 1):
+        for i in range(get_c_recursion_limit() + 1):
             d0 = d
             d = self._empty_mapping()
             d[1] = d0
index 2be9cd099a68d621ae26495ff3eecd22da67aa10..4bf2d7b5142da9642732ea73a66383f42dee7249 100644 (file)
@@ -56,7 +56,7 @@ __all__ = [
     "run_with_tz", "PGO", "missing_compiler_executable",
     "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
     "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
-    "Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "Py_C_RECURSION_LIMIT",
+    "Py_DEBUG", "exceeds_recursion_limit", "get_c_recursion_limit",
     "skip_on_s390x",
     "without_optimizer",
     ]
@@ -2490,22 +2490,18 @@ def adjust_int_max_str_digits(max_digits):
         sys.set_int_max_str_digits(current)
 
 
-def _get_c_recursion_limit():
+def get_c_recursion_limit():
     try:
         import _testcapi
         return _testcapi.Py_C_RECURSION_LIMIT
-    except (ImportError, AttributeError):
-        # Originally taken from Include/cpython/pystate.h .
-        if sys.platform == 'win32':
-            return 4000
-        else:
-            return 10000
+    except ImportError:
+        raise unittest.SkipTest('requires _testcapi')
+
 
-# The default C recursion limit.
-Py_C_RECURSION_LIMIT = _get_c_recursion_limit()
+def exceeds_recursion_limit():
+    """For recursion tests, easily exceeds default recursion limit."""
+    return get_c_recursion_limit() * 3
 
-#For recursion tests, easily exceeds default recursion limit
-EXCEEDS_RECURSION_LIMIT = Py_C_RECURSION_LIMIT * 3
 
 #Windows doesn't have os.uname() but it doesn't support s390x.
 skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
index 3929e4e00d59c221c12403787613b97f0ea5e09a..5b47cdaafb092e4de92f7aaa6437a1438be03d44 100644 (file)
@@ -1153,9 +1153,9 @@ class AST_Tests(unittest.TestCase):
 
     @support.cpython_only
     def test_ast_recursion_limit(self):
-        fail_depth = support.EXCEEDS_RECURSION_LIMIT
+        fail_depth = support.exceeds_recursion_limit()
         crash_depth = 100_000
-        success_depth = int(support.Py_C_RECURSION_LIMIT * 0.8)
+        success_depth = int(support.get_c_recursion_limit() * 0.8)
         if _testinternalcapi is not None:
             remaining = _testinternalcapi.get_c_recursion_remaining()
             success_depth = min(success_depth, remaining)
index 1fb492ecebd668757a17c1797da610821826cabe..955323cae88f922a49985af6b0b611a43c8b5d0a 100644 (file)
@@ -542,7 +542,7 @@ class TestNamedTuple(unittest.TestCase):
         self.assertEqual(Dot(1)._replace(d=999), (999,))
         self.assertEqual(Dot(1)._fields, ('d',))
 
-        n = support.EXCEEDS_RECURSION_LIMIT
+        n = support.exceeds_recursion_limit()
         names = list(set(''.join([choice(string.ascii_letters)
                                   for j in range(10)]) for i in range(n)))
         n = len(names)
index 9d5f721806a884a32808c59e500e9ed59d025017..638b6e96b5025bf641ea7d0949e72e15921bf7f3 100644 (file)
@@ -13,7 +13,7 @@ import textwrap
 import warnings
 from test import support
 from test.support import (script_helper, requires_debug_ranges,
-                          requires_specialization, Py_C_RECURSION_LIMIT)
+                          requires_specialization, get_c_recursion_limit)
 from test.support.bytecode_helper import instructions_with_positions
 from test.support.os_helper import FakePath
 
@@ -114,7 +114,7 @@ class TestSpecifics(unittest.TestCase):
 
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
     def test_extended_arg(self):
-        repeat = int(Py_C_RECURSION_LIMIT * 0.9)
+        repeat = int(get_c_recursion_limit() * 0.9)
         longexpr = 'x = x or ' + '-x' * repeat
         g = {}
         code = textwrap.dedent('''
@@ -634,9 +634,10 @@ class TestSpecifics(unittest.TestCase):
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
     def test_compiler_recursion_limit(self):
         # Expected limit is Py_C_RECURSION_LIMIT
-        fail_depth = Py_C_RECURSION_LIMIT + 1
-        crash_depth = Py_C_RECURSION_LIMIT * 100
-        success_depth = int(Py_C_RECURSION_LIMIT * 0.8)
+        limit = get_c_recursion_limit()
+        fail_depth = limit + 1
+        crash_depth = limit * 100
+        success_depth = int(limit * 0.8)
 
         def check_limit(prefix, repeated, mode="single"):
             expect_ok = prefix + repeated * success_depth
index 620d0ca4f4c2dae65de4a96584198d3d2b6b35bd..e5dba7cdc570a85ada8664e3f922554ae72f34e8 100644 (file)
@@ -8,7 +8,7 @@ import sys
 import unittest
 import weakref
 from test import support
-from test.support import import_helper, Py_C_RECURSION_LIMIT
+from test.support import import_helper, get_c_recursion_limit
 
 
 class DictTest(unittest.TestCase):
@@ -596,7 +596,7 @@ class DictTest(unittest.TestCase):
 
     def test_repr_deep(self):
         d = {}
-        for i in range(Py_C_RECURSION_LIMIT + 1):
+        for i in range(get_c_recursion_limit() + 1):
             d = {1: d}
         self.assertRaises(RecursionError, repr, d)
 
index cad568b6ac4c2d8acf7a270532504d93fa2e5808..d9881611c19c437868647f2e6309f6aca79a2344 100644 (file)
@@ -2,7 +2,7 @@ import collections.abc
 import copy
 import pickle
 import unittest
-from test.support import Py_C_RECURSION_LIMIT
+from test.support import get_c_recursion_limit
 
 class DictSetTest(unittest.TestCase):
 
@@ -279,7 +279,7 @@ class DictSetTest(unittest.TestCase):
 
     def test_deeply_nested_repr(self):
         d = {}
-        for i in range(Py_C_RECURSION_LIMIT//2 + 100):
+        for i in range(get_c_recursion_limit()//2 + 100):
             d = {42: d.values()}
         self.assertRaises(RecursionError, repr, d)
 
index 20122679223843151252b18998619f8394f71433..b4fc290b1f32b61f1508c8beef8ab11ff10ffceb 100644 (file)
@@ -1,7 +1,7 @@
 import collections.abc
 import types
 import unittest
-from test.support import Py_C_RECURSION_LIMIT
+from test.support import get_c_recursion_limit
 
 class TestExceptionGroupTypeHierarchy(unittest.TestCase):
     def test_exception_group_types(self):
@@ -460,7 +460,7 @@ class ExceptionGroupSplitTests(ExceptionGroupTestBase):
 class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
     def make_deep_eg(self):
         e = TypeError(1)
-        for i in range(Py_C_RECURSION_LIMIT + 1):
+        for i in range(get_c_recursion_limit() + 1):
             e = ExceptionGroup('eg', [e])
         return e
 
index 6ad6acc61563e529ac690f1bc0095d8ebc28c869..36fd89dbb8896cc7c308ab17347211271e08819f 100644 (file)
@@ -1424,7 +1424,7 @@ class ExceptionTests(unittest.TestCase):
             next(generator)
             recursionlimit = sys.getrecursionlimit()
             try:
-                recurse(support.EXCEEDS_RECURSION_LIMIT)
+                recurse(support.exceeds_recursion_limit())
             finally:
                 sys.setrecursionlimit(recursionlimit)
                 print('Done.')
index 3ba4929dd1b13309b1e21290c21c674a2ce253d3..c48c399a10c853ab07067037a3a5538f3460a8af 100644 (file)
@@ -1867,7 +1867,7 @@ class TestLRU:
             return fib(n-1) + fib(n-2)
 
         if not support.Py_DEBUG:
-            depth = support.Py_C_RECURSION_LIMIT*2//7
+            depth = support.get_c_recursion_limit()*2//7
             with support.infinite_recursion():
                 fib(depth)
         if self.module == c_functools:
index 7f759fb3317146eb62c78f234bfcc3e7a0895742..95a119ba683e09e184e7419ed544075e01fcf05e 100644 (file)
@@ -352,7 +352,7 @@ def blowstack(fxn, arg, compare_to):
     # Make sure that calling isinstance with a deeply nested tuple for its
     # argument will raise RecursionError eventually.
     tuple_arg = (compare_to,)
-    for cnt in range(support.EXCEEDS_RECURSION_LIMIT):
+    for cnt in range(support.exceeds_recursion_limit()):
         tuple_arg = (tuple_arg,)
         fxn(arg, tuple_arg)
 
index 615568e6af21028240a7d3004188844cdb6a168e..64ee1ba867d592b69d7a166748b50d6506b404f5 100644 (file)
@@ -118,7 +118,7 @@ class CodeTestCase(unittest.TestCase):
     def test_many_codeobjects(self):
         # Issue2957: bad recursion count on code objects
         # more than MAX_MARSHAL_STACK_DEPTH
-        count = support.EXCEEDS_RECURSION_LIMIT
+        count = support.exceeds_recursion_limit()
         codes = (ExceptionTestCase.test_exceptions.__code__,) * count
         marshal.loads(marshal.dumps(codes))
 
index 125f40227118f6366795f5c7443cbe5494d5222d..ded1d9224d82d916f0060368f5ad28169f8a857d 100644 (file)
@@ -3039,7 +3039,7 @@ class TestExtendedArgs(unittest.TestCase):
 
     def test_trace_lots_of_globals(self):
 
-        count = min(1000, int(support.Py_C_RECURSION_LIMIT * 0.8))
+        count = min(1000, int(support.get_c_recursion_limit() * 0.8))
 
         code = """if 1:
             def f():