https://github.com/python/cpython/commit/43634fc1fcc88b35171aa79258f767ba6477f764
commit: 43634fc1fcc88b35171aa79258f767ba6477f764
branch: main
author: Hood Chatham <[email protected]>
committer: freakboy3742 <[email protected]>
date: 2024-12-05T08:26:25+08:00
summary:

gh-127146: Emscripten: Skip segfaults in test suite (#127151)

Added skips for tests known to cause problems when running on Emscripten. 
These mostly relate to the limited stack depth on Emscripten.

files:
M Lib/test/list_tests.py
M Lib/test/mapping_tests.py
M Lib/test/support/__init__.py
M Lib/test/test_ast/test_ast.py
M Lib/test/test_call.py
M Lib/test/test_capi/test_misc.py
M Lib/test/test_class.py
M Lib/test/test_compile.py
M Lib/test/test_copy.py
M Lib/test/test_descr.py
M Lib/test/test_dict.py
M Lib/test/test_dictviews.py
M Lib/test/test_exception_group.py
M Lib/test/test_functools.py
M Lib/test/test_isinstance.py
M Lib/test/test_json/test_recursion.py
M Lib/test/test_pathlib/test_pathlib_abc.py
M Lib/test/test_traceback.py
M Lib/test/test_xml_etree_c.py
M configure
M configure.ac

diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py
index dbc5ef4f9f2cd5..dbd9f27872962d 100644
--- a/Lib/test/list_tests.py
+++ b/Lib/test/list_tests.py
@@ -6,7 +6,7 @@
 from functools import cmp_to_key
 
 from test import seq_tests
-from test.support import ALWAYS_EQ, NEVER_EQ, get_c_recursion_limit
+from test.support import ALWAYS_EQ, NEVER_EQ, get_c_recursion_limit, 
skip_emscripten_stack_overflow
 
 
 class CommonTest(seq_tests.CommonTest):
@@ -59,6 +59,7 @@ def test_repr(self):
         self.assertEqual(str(a2), "[0, 1, 2, [...], 3]")
         self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]")
 
+    @skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         a = self.type2test([])
         for i in range(get_c_recursion_limit() + 1):
diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py
index ed89a81a6ea685..f249f0021e9c1c 100644
--- a/Lib/test/mapping_tests.py
+++ b/Lib/test/mapping_tests.py
@@ -1,7 +1,7 @@
 # tests common to dict and UserDict
 import unittest
 import collections
-from test.support import get_c_recursion_limit
+from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
 
 
 class BasicTestMappingProtocol(unittest.TestCase):
@@ -622,6 +622,7 @@ def __repr__(self):
         d = self._full_mapping({1: BadRepr()})
         self.assertRaises(Exc, repr, d)
 
+    @skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         d = self._empty_mapping()
         for i in range(get_c_recursion_limit() + 1):
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 2ad267e3e08f0f..5c738ffaa27713 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -535,6 +535,9 @@ def skip_android_selinux(name):
 is_emscripten = sys.platform == "emscripten"
 is_wasi = sys.platform == "wasi"
 
+def skip_emscripten_stack_overflow():
+    return unittest.skipIf(is_emscripten, "Exhausts limited stack on 
Emscripten")
+
 is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"}
 is_apple = is_apple_mobile or sys.platform == "darwin"
 
diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py
index 67ab8cf6baf657..c268a1f00f938e 100644
--- a/Lib/test/test_ast/test_ast.py
+++ b/Lib/test/test_ast/test_ast.py
@@ -18,7 +18,7 @@
     _testinternalcapi = None
 
 from test import support
-from test.support import os_helper, script_helper
+from test.support import os_helper, script_helper, 
skip_emscripten_stack_overflow
 from test.support.ast_helper import ASTTestMixin
 from test.test_ast.utils import to_tuple
 from test.test_ast.snippets import (
@@ -745,6 +745,7 @@ def next(self):
         enum._test_simple_enum(_Precedence, ast._Precedence)
 
     @support.cpython_only
+    @skip_emscripten_stack_overflow()
     def test_ast_recursion_limit(self):
         fail_depth = support.exceeds_recursion_limit()
         crash_depth = 100_000
@@ -1661,6 +1662,7 @@ def test_level_as_none(self):
         exec(code, ns)
         self.assertIn('sleep', ns)
 
+    @skip_emscripten_stack_overflow()
     def test_recursion_direct(self):
         e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, 
operand=ast.Constant(1))
         e.operand = e
@@ -1668,6 +1670,7 @@ def test_recursion_direct(self):
             with support.infinite_recursion():
                 compile(ast.Expression(e), "<test>", "eval")
 
+    @skip_emscripten_stack_overflow()
     def test_recursion_indirect(self):
         e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, 
operand=ast.Constant(1))
         f = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, 
operand=ast.Constant(1))
diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index 9d5256b566b8af..78a706436aea0e 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -1,6 +1,6 @@
 import unittest
 from test.support import (cpython_only, is_wasi, requires_limited_api, 
Py_DEBUG,
-                          set_recursion_limit, skip_on_s390x)
+                          set_recursion_limit, skip_on_s390x, 
skip_emscripten_stack_overflow)
 try:
     import _testcapi
 except ImportError:
@@ -1038,6 +1038,7 @@ class TestRecursion(unittest.TestCase):
     @skip_on_s390x
     @unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack")
     @unittest.skipIf(_testcapi is None, "requires _testcapi")
+    @skip_emscripten_stack_overflow()
     def test_super_deep(self):
 
         def recurse(n):
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 80e705a37c4c5e..8e0271919cc8a5 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -2137,6 +2137,7 @@ def test_py_config_isoloated_per_interpreter(self):
         # test fails, assume that the environment in this process may
         # be altered and suspect.
 
+    @requires_subinterpreters
     @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
     def test_configured_settings(self):
         """
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 7720cf157fa9ae..e20e59944e9ce9 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -1,7 +1,7 @@
 "Test the functionality of Python classes implementing operators."
 
 import unittest
-from test.support import cpython_only, import_helper, script_helper
+from test.support import cpython_only, import_helper, script_helper, 
skip_emscripten_stack_overflow
 
 testmeths = [
 
@@ -554,6 +554,7 @@ class Custom:
         self.assertFalse(hasattr(o, "__call__"))
         self.assertFalse(hasattr(c, "__call__"))
 
+    @skip_emscripten_stack_overflow()
     def testSFBug532646(self):
         # Test for SF bug 532646
 
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index f7ea923ef17672..b5cf2ad18fe60b 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -121,6 +121,7 @@ def __getitem__(self, key):
         self.assertEqual(d['z'], 12)
 
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
+    @support.skip_emscripten_stack_overflow()
     def test_extended_arg(self):
         repeat = int(get_c_recursion_limit() * 0.9)
         longexpr = 'x = x or ' + '-x' * repeat
@@ -709,6 +710,7 @@ def test_yet_more_evil_still_undecodable(self):
 
     @support.cpython_only
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
+    @support.skip_emscripten_stack_overflow()
     def test_compiler_recursion_limit(self):
         # Expected limit is Py_C_RECURSION_LIMIT
         limit = get_c_recursion_limit()
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index 3dec64cc9a2414..d76341417e9bef 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -371,6 +371,7 @@ def test_deepcopy_list(self):
         self.assertIsNot(x, y)
         self.assertIsNot(x[0], y[0])
 
+    @support.skip_emscripten_stack_overflow()
     def test_deepcopy_reflexive_list(self):
         x = []
         x.append(x)
@@ -398,6 +399,7 @@ def test_deepcopy_tuple_of_immutables(self):
         y = copy.deepcopy(x)
         self.assertIs(x, y)
 
+    @support.skip_emscripten_stack_overflow()
     def test_deepcopy_reflexive_tuple(self):
         x = ([],)
         x[0].append(x)
@@ -415,6 +417,7 @@ def test_deepcopy_dict(self):
         self.assertIsNot(x, y)
         self.assertIsNot(x["foo"], y["foo"])
 
+    @support.skip_emscripten_stack_overflow()
     def test_deepcopy_reflexive_dict(self):
         x = {}
         x['foo'] = x
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index aa801b9c4f7ad9..168b78a477ee9c 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -3663,6 +3663,7 @@ def f(a): return a
                            encoding='latin1', errors='replace')
         self.assertEqual(ba, b'abc\xbd?')
 
+    @support.skip_emscripten_stack_overflow()
     def test_recursive_call(self):
         # Testing recursive __call__() by setting to instance of class...
         class A(object):
@@ -3942,6 +3943,7 @@ def __del__(self):
         # it as a leak.
         del C.__del__
 
+    @unittest.skipIf(support.is_emscripten, "Seems to works in Pyodide?")
     def test_slots_trash(self):
         # Testing slot trash...
         # Deallocating deeply nested slotted trash caused stack overflows
@@ -4864,6 +4866,7 @@ class Thing:
                 # CALL_METHOD_DESCRIPTOR_O
                 deque.append(thing, thing)
 
+    @support.skip_emscripten_stack_overflow()
     def test_repr_as_str(self):
         # Issue #11603: crash or infinite loop when rebinding __str__ as
         # __repr__.
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index c94dc2df4f0a7f..86b2f22dee5347 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -594,6 +594,7 @@ def __repr__(self):
         d = {1: BadRepr()}
         self.assertRaises(Exc, repr, d)
 
+    @support.skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         d = {}
         for i in range(get_c_recursion_limit() + 1):
diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py
index d9881611c19c43..d6bf00eeeb0013 100644
--- a/Lib/test/test_dictviews.py
+++ b/Lib/test/test_dictviews.py
@@ -2,7 +2,7 @@
 import copy
 import pickle
 import unittest
-from test.support import get_c_recursion_limit
+from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
 
 class DictSetTest(unittest.TestCase):
 
@@ -277,6 +277,7 @@ def test_recursive_repr(self):
         # Again.
         self.assertIsInstance(r, str)
 
+    @skip_emscripten_stack_overflow()
     def test_deeply_nested_repr(self):
         d = {}
         for i in range(get_c_recursion_limit()//2 + 100):
diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py
index b4fc290b1f32b6..53212529c27e28 100644
--- a/Lib/test/test_exception_group.py
+++ b/Lib/test/test_exception_group.py
@@ -1,7 +1,7 @@
 import collections.abc
 import types
 import unittest
-from test.support import get_c_recursion_limit
+from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
 
 class TestExceptionGroupTypeHierarchy(unittest.TestCase):
     def test_exception_group_types(self):
@@ -464,11 +464,13 @@ def make_deep_eg(self):
             e = ExceptionGroup('eg', [e])
         return e
 
+    @skip_emscripten_stack_overflow()
     def test_deep_split(self):
         e = self.make_deep_eg()
         with self.assertRaises(RecursionError):
             e.split(TypeError)
 
+    @skip_emscripten_stack_overflow()
     def test_deep_subgroup(self):
         e = self.make_deep_eg()
         with self.assertRaises(RecursionError):
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index 6d60f6941c4c5d..ffd2adb8665b45 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -404,6 +404,7 @@ def test_setstate_subclasses(self):
         self.assertEqual(r, ((1, 2), {}))
         self.assertIs(type(r[0]), tuple)
 
+    @support.skip_emscripten_stack_overflow()
     def test_recursive_pickle(self):
         with replaced_module('functools', self.module):
             f = self.partial(capture)
@@ -2054,6 +2055,7 @@ def orig(a, /, b, c=True): ...
 
     @support.skip_on_s390x
     @unittest.skipIf(support.is_wasi, "WASI has limited C stack")
+    @support.skip_emscripten_stack_overflow()
     def test_lru_recursion(self):
 
         @self.module.lru_cache
diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py
index 95a119ba683e09..abc75c82375d98 100644
--- a/Lib/test/test_isinstance.py
+++ b/Lib/test/test_isinstance.py
@@ -263,12 +263,14 @@ def test_subclass_tuple(self):
         self.assertEqual(True, issubclass(int, (int, (float, int))))
         self.assertEqual(True, issubclass(str, (str, (Child, str))))
 
+    @support.skip_emscripten_stack_overflow()
     def test_subclass_recursion_limit(self):
         # make sure that issubclass raises RecursionError before the C stack is
         # blown
         with support.infinite_recursion():
             self.assertRaises(RecursionError, blowstack, issubclass, str, str)
 
+    @support.skip_emscripten_stack_overflow()
     def test_isinstance_recursion_limit(self):
         # make sure that issubclass raises RecursionError before the C stack is
         # blown
@@ -315,6 +317,7 @@ def __bases__(self):
             self.assertRaises(RecursionError, issubclass, int, X())
             self.assertRaises(RecursionError, isinstance, 1, X())
 
+    @support.skip_emscripten_stack_overflow()
     def test_infinite_recursion_via_bases_tuple(self):
         """Regression test for bpo-30570."""
         class Failure(object):
diff --git a/Lib/test/test_json/test_recursion.py 
b/Lib/test/test_json/test_recursion.py
index 290207e9c15b88..663c0643579ac8 100644
--- a/Lib/test/test_json/test_recursion.py
+++ b/Lib/test/test_json/test_recursion.py
@@ -68,6 +68,7 @@ def default(self, o):
             self.fail("didn't raise ValueError on default recursion")
 
 
+    @support.skip_emscripten_stack_overflow()
     def test_highly_nested_objects_decoding(self):
         # test that loading highly-nested objects doesn't segfault when C
         # accelerations are used. See #12017
@@ -81,6 +82,7 @@ def test_highly_nested_objects_decoding(self):
             with support.infinite_recursion():
                 self.loads('[' * 100000 + '1' + ']' * 100000)
 
+    @support.skip_emscripten_stack_overflow()
     def test_highly_nested_objects_encoding(self):
         # See #12051
         l, d = [], {}
@@ -93,6 +95,7 @@ def test_highly_nested_objects_encoding(self):
             with support.infinite_recursion(5000):
                 self.dumps(d)
 
+    @support.skip_emscripten_stack_overflow()
     def test_endless_recursion(self):
         # See #12051
         class EndlessJSONEncoder(self.json.JSONEncoder):
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py 
b/Lib/test/test_pathlib/test_pathlib_abc.py
index af94ac039808f0..5fa2f550cefcf4 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -9,7 +9,7 @@
 from pathlib._abc import UnsupportedOperation, ParserBase, PurePathBase, 
PathBase
 import posixpath
 
-from test.support import is_wasi
+from test.support import is_wasi, is_emscripten
 from test.support.os_helper import TESTFN
 
 
@@ -2298,6 +2298,7 @@ def _check(path, pattern, case_sensitive, expected):
         _check(path, "dirb/file*", False, ["dirB/fileB"])
 
     @needs_symlinks
+    @unittest.skipIf(is_emscripten, "Hangs")
     def test_glob_recurse_symlinks_common(self):
         def _check(path, glob, expected):
             actual = {path for path in path.glob(glob, recurse_symlinks=True)
@@ -2393,6 +2394,7 @@ def test_rglob_windows(self):
         self.assertEqual(set(p.rglob("*\\")), { P(self.base, "dirC/dirD/") })
 
     @needs_symlinks
+    @unittest.skipIf(is_emscripten, "Hangs")
     def test_rglob_recurse_symlinks_common(self):
         def _check(path, glob, expected):
             actual = {path for path in path.rglob(glob, recurse_symlinks=True)
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index ea8d9f2137aca5..31f0a61d6a9d59 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -2097,6 +2097,7 @@ def deep_eg(self):
         return e
 
     @cpython_only
+    @support.skip_emscripten_stack_overflow()
     def test_exception_group_deep_recursion_capi(self):
         from _testcapi import exception_print
         LIMIT = 75
@@ -2108,6 +2109,7 @@ def test_exception_group_deep_recursion_capi(self):
         self.assertIn('ExceptionGroup', output)
         self.assertLessEqual(output.count('ExceptionGroup'), LIMIT)
 
+    @support.skip_emscripten_stack_overflow()
     def test_exception_group_deep_recursion_traceback(self):
         LIMIT = 75
         eg = self.deep_eg()
diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index 3a0fc572f457ff..db19af419bdeab 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -57,6 +57,7 @@ def test_del_attribute(self):
             del element.attrib
         self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
 
+    @unittest.skipIf(support.is_emscripten, "segfaults")
     def test_trashcan(self):
         # If this test fails, it will most likely die via segfault.
         e = root = cET.Element('root')
diff --git a/configure b/configure
index 7efda041ae69d4..c6790777793566 100755
--- a/configure
+++ b/configure
@@ -9436,6 +9436,7 @@ fi
         as_fn_append LDFLAGS_NODIST " -sFORCE_FILESYSTEM -lidbfs.js 
-lnodefs.js -lproxyfs.js -lworkerfs.js"
     as_fn_append LDFLAGS_NODIST " -sEXPORTED_RUNTIME_METHODS=FS,callMain"
     as_fn_append LDFLAGS_NODIST " -sEXPORTED_FUNCTIONS=_main,_Py_Version"
+    as_fn_append LDFLAGS_NODIST " -sSTACK_SIZE=5MB"
 
     if test "x$enable_wasm_dynamic_linking" = xyes
 then :
diff --git a/configure.ac b/configure.ac
index 15f7d07f22473b..9648e438cc7424 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2334,6 +2334,7 @@ AS_CASE([$ac_sys_system],
     AS_VAR_APPEND([LDFLAGS_NODIST], [" -sFORCE_FILESYSTEM -lidbfs.js 
-lnodefs.js -lproxyfs.js -lworkerfs.js"])
     AS_VAR_APPEND([LDFLAGS_NODIST], [" 
-sEXPORTED_RUNTIME_METHODS=FS,callMain"])
     AS_VAR_APPEND([LDFLAGS_NODIST], [" 
-sEXPORTED_FUNCTIONS=_main,_Py_Version"])
+    AS_VAR_APPEND([LDFLAGS_NODIST], [" -sSTACK_SIZE=5MB"])
 
     AS_VAR_IF([enable_wasm_dynamic_linking], [yes], [
       AS_VAR_APPEND([LINKFORSHARED], [" -sMAIN_MODULE"])

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to