From ef1327e3b622e0cafdf8bfc1f480fed0dd386be6 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Thu, 17 Mar 2022 13:09:57 +0200 Subject: [PATCH] bpo-40280: Skip more tests on Emscripten (GH-31947) - lchmod, lchown are not fully implemented - skip umask tests - cannot fstat unlinked or renamed files yet - ignore musl libc issues that affect Emscripten --- Lib/distutils/tests/test_dir_util.py | 3 ++- Lib/test/test__locale.py | 8 ++++++++ Lib/test/test__xxsubinterpreters.py | 2 +- Lib/test/test_coroutines.py | 3 +++ Lib/test/test_interpreters.py | 3 ++- Lib/test/test_locale.py | 4 +++- Lib/test/test_logging.py | 3 ++- Lib/test/test_ntpath.py | 3 ++- Lib/test/test_os.py | 10 +++++++++- Lib/test/test_re.py | 4 +++- Lib/test/test_select.py | 3 +++ Lib/test/test_strptime.py | 6 ++++++ Lib/test/test_support.py | 3 +++ Lib/test/test_tempfile.py | 7 +++++++ Lib/test/test_time.py | 6 ++++++ Tools/wasm/config.site-wasm32-emscripten | 3 +++ 16 files changed, 63 insertions(+), 8 deletions(-) diff --git a/Lib/distutils/tests/test_dir_util.py b/Lib/distutils/tests/test_dir_util.py index 1b1f3bbb02e..f3ba0ee33b4 100644 --- a/Lib/distutils/tests/test_dir_util.py +++ b/Lib/distutils/tests/test_dir_util.py @@ -11,7 +11,7 @@ from distutils.dir_util import (mkpath, remove_tree, create_tree, copy_tree, from distutils import log from distutils.tests import support -from test.support import run_unittest +from test.support import run_unittest, is_emscripten class DirUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -55,6 +55,7 @@ class DirUtilTestCase(support.TempdirManager, unittest.TestCase): @unittest.skipIf(sys.platform.startswith('win'), "This test is only appropriate for POSIX-like systems.") + @unittest.skipIf(is_emscripten, "Emscripten's umask is a stub.") def test_mkpath_with_custom_mode(self): # Get and set the current umask value for testing mode bits. umask = os.umask(0o002) diff --git a/Lib/test/test__locale.py b/Lib/test/test__locale.py index 59a00bad7d9..e25c92c2c82 100644 --- a/Lib/test/test__locale.py +++ b/Lib/test/test__locale.py @@ -9,6 +9,8 @@ import sys import unittest from platform import uname +from test import support + if uname().system == "Darwin": maj, min, mic = [int(part) for part in uname().release.split(".")] if (maj, min, mic) < (8, 0, 0): @@ -106,6 +108,9 @@ class _LocaleTests(unittest.TestCase): return True @unittest.skipUnless(nl_langinfo, "nl_langinfo is not available") + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_lc_numeric_nl_langinfo(self): # Test nl_langinfo against known values tested = False @@ -122,6 +127,9 @@ class _LocaleTests(unittest.TestCase): if not tested: self.skipTest('no suitable locales') + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_lc_numeric_localeconv(self): # Test localeconv against known values tested = False diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 177a8a64a43..5d0ed9ea14a 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -818,7 +818,7 @@ class RunStringTests(TestBase): self.assertEqual(out, 'it worked!') - @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + @support.requires_fork() def test_fork(self): import tempfile with tempfile.NamedTemporaryFile('w+', encoding="utf-8") as file: diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 3081853303b..77944e678c7 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2208,6 +2208,9 @@ class CoroutineTest(unittest.TestCase): gen.cr_frame.clear() +@unittest.skipIf( + support.is_emscripten, "asyncio does not work under Emscripten yet." +) class CoroAsyncIOCompatTest(unittest.TestCase): def test_asyncio_1(self): diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py index 48c7119fff1..b969ddf33d8 100644 --- a/Lib/test/test_interpreters.py +++ b/Lib/test/test_interpreters.py @@ -5,6 +5,7 @@ from textwrap import dedent import unittest import time +from test import support from test.support import import_helper _interpreters = import_helper.import_module('_xxsubinterpreters') from test.support import interpreters @@ -408,7 +409,7 @@ class TestInterpreterRun(TestBase): self.assertEqual(out, 'it worked!') - @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + @support.requires_fork() def test_fork(self): interp = interpreters.create() import tempfile diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 2a3b0acc6bd..774b0fcd333 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -1,5 +1,5 @@ from decimal import Decimal -from test.support import verbose, is_android +from test.support import verbose, is_android, is_emscripten from test.support.warnings_helper import check_warnings import unittest import locale @@ -373,11 +373,13 @@ class TestEnUSCollation(BaseLocalizedTest, TestCollation): @unittest.skipIf(sys.platform.startswith('aix'), 'bpo-29972: broken test on AIX') + @unittest.skipIf(is_emscripten, "musl libc issue on Emscripten, bpo-46390") def test_strcoll_with_diacritic(self): self.assertLess(locale.strcoll('à', 'b'), 0) @unittest.skipIf(sys.platform.startswith('aix'), 'bpo-29972: broken test on AIX') + @unittest.skipIf(is_emscripten, "musl libc issue on Emscripten, bpo-46390") def test_strxfrm_with_diacritic(self): self.assertLess(locale.strxfrm('à'), locale.strxfrm('b')) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 4f3315161cf..be193dcdacf 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -674,7 +674,7 @@ class HandlerTest(BaseTest): # based on os.fork existing because that is what users and this test use. # This helps ensure that when fork exists (the important concept) that the # register_at_fork mechanism is also present and used. - @unittest.skipIf(not hasattr(os, 'fork'), 'Test requires os.fork().') + @support.requires_fork() def test_post_fork_child_no_deadlock(self): """Ensure child logging locks are not held; bpo-6721 & bpo-36533.""" class _OurHandler(logging.Handler): @@ -4493,6 +4493,7 @@ class LogRecordTest(BaseTest): return results def test_multiprocessing(self): + support.skip_if_broken_multiprocessing_synchronize() multiprocessing_imported = 'multiprocessing' in sys.modules try: # logMultiprocessing is True by default diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 99a77e3fb43..7211ed86176 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -4,7 +4,7 @@ import sys import unittest import warnings from test.support import os_helper -from test.support import TestFailed +from test.support import TestFailed, is_emscripten from test.support.os_helper import FakePath from test import test_genericpath from tempfile import TemporaryFile @@ -747,6 +747,7 @@ class TestNtpath(NtpathTestCase): self.assertRaises(TypeError, ntpath.commonpath, ['Program Files', b'C:\\Program Files\\Foo']) + @unittest.skipIf(is_emscripten, "Emscripten cannot fstat unnamed files.") def test_sameopenfile(self): with TemporaryFile() as tf1, TemporaryFile() as tf2: # Make sure the same file is really the same diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index ae8d930a952..426d2ae9373 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -181,6 +181,9 @@ class FileTests(unittest.TestCase): os.close(f) self.assertTrue(os.access(os_helper.TESTFN, os.W_OK)) + @unittest.skipIf( + support.is_emscripten, "Test is unstable under Emscripten." + ) def test_closerange(self): first = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR) # We must allocate two consecutive file descriptors, otherwise @@ -1578,6 +1581,7 @@ class MakedirTests(unittest.TestCase): 'dir5', 'dir6') os.makedirs(path) + @unittest.skipIf(support.is_emscripten, "Emscripten's umask is a stub.") def test_mode(self): with os_helper.temp_umask(0o002): base = os_helper.TESTFN @@ -2158,6 +2162,9 @@ class TestInvalidFD(unittest.TestCase): self.check(os.fchown, -1, -1) @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()') + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_fpathconf(self): self.check(os.pathconf, "PC_NAME_MAX") self.check(os.fpathconf, "PC_NAME_MAX") @@ -4058,6 +4065,7 @@ class PathTConverterTests(unittest.TestCase): @unittest.skipUnless(hasattr(os, 'get_blocking'), 'needs os.get_blocking() and os.set_blocking()') +@unittest.skipIf(support.is_emscripten, "Cannot unset blocking flag") class BlockingTests(unittest.TestCase): def test_blocking(self): fd = os.open(__file__, os.O_RDONLY) @@ -4513,7 +4521,7 @@ class TimesTests(unittest.TestCase): self.assertEqual(times.elapsed, 0) -@requires_os_func('fork') +@support.requires_fork() class ForkTests(unittest.TestCase): def test_fork(self): # bpo-42540: ensure os.fork() with non-default memory allocator does diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 18fa24a99ce..59575962eb4 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,6 +1,6 @@ from test.support import (gc_collect, bigmemtest, _2G, cpython_only, captured_stdout, - check_disallow_instantiation) + check_disallow_instantiation, is_emscripten) import locale import re import sre_compile @@ -1892,6 +1892,7 @@ ELSE # with ignore case. self.assertEqual(re.fullmatch('[a-c]+', 'ABC', re.I).span(), (0, 3)) + @unittest.skipIf(is_emscripten, "musl libc issue on Emscripten, bpo-46390") def test_locale_caching(self): # Issue #22410 oldlocale = locale.setlocale(locale.LC_CTYPE) @@ -1928,6 +1929,7 @@ ELSE self.assertIsNone(re.match(b'(?Li)\xc5', b'\xe5')) self.assertIsNone(re.match(b'(?Li)\xe5', b'\xc5')) + @unittest.skipIf(is_emscripten, "musl libc issue on Emscripten, bpo-46390") def test_locale_compiled(self): oldlocale = locale.setlocale(locale.LC_CTYPE) self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py index 69421fd7755..8b59321121e 100644 --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -78,6 +78,9 @@ class SelectTestCase(unittest.TestCase): rfd, wfd, xfd) # Issue 16230: Crash on select resized list + @unittest.skipIf( + support.is_emscripten, "Emscripten cannot select a fd multiple times." + ) def test_select_mutated(self): a = [] class F: diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index e5f75b7aab9..e3fcabef946 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -70,6 +70,9 @@ class LocaleTime_Tests(unittest.TestCase): self.assertEqual(self.LT_ins.am_pm[position], strftime_output, "AM/PM representation in the wrong position within the tuple") + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_timezone(self): # Make sure timezone is correct timezone = time.strftime("%Z", self.time_tuple).lower() @@ -368,6 +371,9 @@ class StrptimeTests(unittest.TestCase): self.assertEqual("Inconsistent use of : in -01:3030", str(err.exception)) @skip_if_buggy_ucrt_strfptime + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_timezone(self): # Test timezone directives. # When gmtime() is used with %Z, entire result of strftime() is empty. diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 59e9f3a6c1c..2cff377cf62 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -658,10 +658,13 @@ class TestSupport(unittest.TestCase): self.assertFalse(support.match_test(test_access)) self.assertTrue(support.match_test(test_chdir)) + @unittest.skipIf(support.is_emscripten, "Unstable in Emscripten") def test_fd_count(self): # We cannot test the absolute value of fd_count(): on old Linux # kernel or glibc versions, os.urandom() keeps a FD open on # /dev/urandom device and Python has 4 FD opens instead of 3. + # Test is unstable on Emscripten. The platform starts and stops + # background threads that use pipes and epoll fds. start = os_helper.fd_count() fd = os.open(__file__, os.O_RDONLY) try: diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 25fddaec6d3..a6847189dca 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -341,6 +341,9 @@ def _mock_candidate_names(*names): class TestBadTempdir: + @unittest.skipIf( + support.is_emscripten, "Emscripten cannot remove write bits." + ) def test_read_only_directory(self): with _inside_empty_temp_dir(): oldmode = mode = os.stat(tempfile.tempdir).st_mode @@ -465,6 +468,7 @@ class TestMkstempInner(TestBadTempdir, BaseTestCase): self.assertEqual(mode, expected) @unittest.skipUnless(has_spawnl, 'os.spawnl not available') + @support.requires_subprocess() def test_noinherit(self): # _mkstemp_inner file handles are not inherited by child processes @@ -1282,6 +1286,9 @@ class TestSpooledTemporaryFile(BaseTestCase): pass self.assertRaises(ValueError, use_closed) + @unittest.skipIf( + support.is_emscripten, "Emscripten cannot fstat renamed files." + ) def test_truncate_with_size_parameter(self): # A SpooledTemporaryFile can be truncated to zero size f = tempfile.SpooledTemporaryFile(max_size=10) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index faac639613a..dc0bbb0ee29 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -313,6 +313,9 @@ class TimeTestCase(unittest.TestCase): def test_asctime_bounding_check(self): self._bounds_checking(time.asctime) + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_ctime(self): t = time.mktime((1973, 9, 16, 1, 3, 52, 0, 0, -1)) self.assertEqual(time.ctime(t), 'Sun Sep 16 01:03:52 1973') @@ -699,6 +702,9 @@ class TestStrftime4dyear(_TestStrftimeYear, _Test4dYear, unittest.TestCase): class TestPytime(unittest.TestCase): @skip_if_buggy_ucrt_strfptime @unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support") + @unittest.skipIf( + support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + ) def test_localtime_timezone(self): # Get the localtime and examine it for the offset and zone. diff --git a/Tools/wasm/config.site-wasm32-emscripten b/Tools/wasm/config.site-wasm32-emscripten index 2a601987cce..7f2df3a4772 100644 --- a/Tools/wasm/config.site-wasm32-emscripten +++ b/Tools/wasm/config.site-wasm32-emscripten @@ -53,6 +53,9 @@ ac_cv_func_symlinkat=no ac_cv_func_readlinkat=no ac_cv_func_fchmodat=no ac_cv_func_dup3=no +# lchmod/lchown are implemented, but fail with ENOTSUP. +ac_cv_func_lchmod=no +ac_cv_func_lchown=no # Syscalls not implemented in emscripten # [Errno 52] Function not implemented