[Python-checkins] bpo-40280: Block more non-working syscalls in Emscripten (GH-31757)
tiran
webhook-mailer at python.org
Tue Mar 8 06:18:22 EST 2022
https://github.com/python/cpython/commit/5081e78efde901556398615eb477c63c836686e5
commit: 5081e78efde901556398615eb477c63c836686e5
branch: main
author: Christian Heimes <christian at python.org>
committer: tiran <christian at python.org>
date: 2022-03-08T12:17:30+01:00
summary:
bpo-40280: Block more non-working syscalls in Emscripten (GH-31757)
- getgroups always fails.
- geteuid and getegid always return 0 (root), which confuse tarfile and
tests.
- hardlinks (link, linkat) always fails.
- non-encodable file names are not supported by NODERAWFS layer.
- mark more tests with dependency on subprocess and multiprocessing.
Mocking does not work if the module fails to import.
files:
M Lib/distutils/tests/test_file_util.py
M Lib/test/support/os_helper.py
M Lib/test/test_compileall.py
M Lib/test/test_genericpath.py
M Lib/test/test_os.py
M Lib/test/test_posix.py
M Lib/test/test_script_helper.py
M Tools/wasm/config.site-wasm32-emscripten
diff --git a/Lib/distutils/tests/test_file_util.py b/Lib/distutils/tests/test_file_util.py
index a614219a10b1d..551151b014366 100644
--- a/Lib/distutils/tests/test_file_util.py
+++ b/Lib/distutils/tests/test_file_util.py
@@ -79,6 +79,7 @@ def test_move_file_exception_unpacking_unlink(self):
fobj.write('spam eggs')
move_file(self.source, self.target, verbose=0)
+ @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
def test_copy_file_hard_link(self):
with open(self.source, 'w') as f:
f.write('some content')
@@ -99,6 +100,7 @@ def test_copy_file_hard_link(self):
with open(self.source, 'r') as f:
self.assertEqual(f.read(), 'some content')
+ @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
def test_copy_file_hard_link_failure(self):
# If hard linking fails, copy_file() falls back on copying file
# (some special filesystems don't support hard linking even under
diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py
index c761d7bd3d2b6..eee37ef0d5a71 100644
--- a/Lib/test/support/os_helper.py
+++ b/Lib/test/support/os_helper.py
@@ -49,8 +49,8 @@
'encoding (%s). Unicode filename tests may not be effective'
% (TESTFN_UNENCODABLE, sys.getfilesystemencoding()))
TESTFN_UNENCODABLE = None
-# Mac OS X denies unencodable filenames (invalid utf-8)
-elif sys.platform != 'darwin':
+# macOS and Emscripten deny unencodable filenames (invalid utf-8)
+elif sys.platform not in {'darwin', 'emscripten'}:
try:
# ascii and utf-8 cannot encode the byte 0xff
b'\xff'.decode(sys.getfilesystemencoding())
diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py
index e207cf8f1793b..98dab339caa1c 100644
--- a/Lib/test/test_compileall.py
+++ b/Lib/test/test_compileall.py
@@ -244,6 +244,7 @@ def test_compile_one_worker(self, compile_file_mock, pool_mock):
self.assertFalse(pool_mock.called)
self.assertTrue(compile_file_mock.called)
+ @skipUnless(_have_multiprocessing, "requires multiprocessing")
@mock.patch('concurrent.futures.ProcessPoolExecutor', new=None)
@mock.patch('compileall.compile_file')
def test_compile_missing_multiprocessing(self, compile_file_mock):
@@ -296,6 +297,7 @@ def test_ddir_only_one_worker(self):
"""Recursive compile_dir ddir= contains package paths; bpo39769."""
return self._test_ddir_only(ddir="<a prefix>", parallel=False)
+ @skipUnless(_have_multiprocessing, "requires multiprocessing")
def test_ddir_multiple_workers(self):
"""Recursive compile_dir ddir= contains package paths; bpo39769."""
return self._test_ddir_only(ddir="<a prefix>", parallel=True)
@@ -304,6 +306,7 @@ def test_ddir_empty_only_one_worker(self):
"""Recursive compile_dir ddir='' contains package paths; bpo39769."""
return self._test_ddir_only(ddir="", parallel=False)
+ @skipUnless(_have_multiprocessing, "requires multiprocessing")
def test_ddir_empty_multiple_workers(self):
"""Recursive compile_dir ddir='' contains package paths; bpo39769."""
return self._test_ddir_only(ddir="", parallel=True)
@@ -924,6 +927,7 @@ class CommandLineTestsNoSourceEpoch(CommandLineTestsBase,
+ at unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
class HardlinkDedupTestsBase:
# Test hardlink_dupes parameter of compileall.compile_dir()
diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py
index 1ff7f75ad3e61..2741adc139bcf 100644
--- a/Lib/test/test_genericpath.py
+++ b/Lib/test/test_genericpath.py
@@ -7,6 +7,7 @@
import sys
import unittest
import warnings
+from test.support import is_emscripten
from test.support import os_helper
from test.support import warnings_helper
from test.support.script_helper import assert_python_ok
@@ -154,6 +155,7 @@ def test_exists(self):
self.assertIs(self.pathmodule.lexists(bfilename + b'\x00'), False)
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
+ @unittest.skipIf(is_emscripten, "Emscripten pipe fds have no stat")
def test_exists_fd(self):
r, w = os.pipe()
try:
@@ -246,6 +248,7 @@ def _test_samefile_on_link_func(self, func):
def test_samefile_on_symlink(self):
self._test_samefile_on_link_func(os.symlink)
+ @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
def test_samefile_on_link(self):
try:
self._test_samefile_on_link_func(os.link)
@@ -288,6 +291,7 @@ def _test_samestat_on_link_func(self, func):
def test_samestat_on_symlink(self):
self._test_samestat_on_link_func(os.symlink)
+ @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
def test_samestat_on_link(self):
try:
self._test_samestat_on_link_func(os.link)
@@ -476,11 +480,11 @@ def test_abspath_issue3426(self):
def test_nonascii_abspath(self):
if (os_helper.TESTFN_UNDECODABLE
- # Mac OS X denies the creation of a directory with an invalid
- # UTF-8 name. Windows allows creating a directory with an
+ # macOS and Emscripten deny the creation of a directory with an
+ # invalid UTF-8 name. Windows allows creating a directory with an
# arbitrary bytes name, but fails to enter this directory
# (when the bytes name is used).
- and sys.platform not in ('win32', 'darwin')):
+ and sys.platform not in ('win32', 'darwin', 'emscripten')):
name = os_helper.TESTFN_UNDECODABLE
elif os_helper.TESTFN_NONASCII:
name = os_helper.TESTFN_NONASCII
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 660691579c163..4800291023233 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2203,6 +2203,7 @@ def test_blocking(self):
self.check(os.set_blocking, True)
+ at unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
class LinkTests(unittest.TestCase):
def setUp(self):
self.file1 = os_helper.TESTFN
diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
index eecddfed8c5c5..395f065234519 100644
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -75,8 +75,9 @@ def testNoArgFunctions(self):
for name in NO_ARG_FUNCTIONS:
posix_func = getattr(posix, name, None)
if posix_func is not None:
- posix_func()
- self.assertRaises(TypeError, posix_func, 1)
+ with self.subTest(name):
+ posix_func()
+ self.assertRaises(TypeError, posix_func, 1)
@unittest.skipUnless(hasattr(posix, 'getresuid'),
'test needs posix.getresuid()')
@@ -1399,7 +1400,10 @@ def test_utime_dir_fd(self):
# whoops! using both together not supported on this platform.
pass
- @unittest.skipUnless(os.link in os.supports_dir_fd, "test needs dir_fd support in os.link()")
+ @unittest.skipUnless(
+ hasattr(os, "link") and os.link in os.supports_dir_fd,
+ "test needs dir_fd support in os.link()"
+ )
def test_link_dir_fd(self):
with self.prepare_file() as (dir_fd, name, fullname), \
self.prepare() as (dir_fd2, linkname, fulllinkname):
diff --git a/Lib/test/test_script_helper.py b/Lib/test/test_script_helper.py
index 4ade2cbc0d4b1..f7871fd3b77c0 100644
--- a/Lib/test/test_script_helper.py
+++ b/Lib/test/test_script_helper.py
@@ -3,7 +3,7 @@
import subprocess
import sys
import os
-from test.support import script_helper
+from test.support import script_helper, requires_subprocess
import unittest
from unittest import mock
@@ -69,6 +69,7 @@ def test_assert_python_not_isolated_when_env_is_required(self, mock_popen):
self.assertNotIn('-E', popen_command)
+ at requires_subprocess()
class TestScriptHelperEnvironment(unittest.TestCase):
"""Code coverage for interpreter_requires_environment()."""
diff --git a/Tools/wasm/config.site-wasm32-emscripten b/Tools/wasm/config.site-wasm32-emscripten
index 98991b462446f..f85024e21720f 100644
--- a/Tools/wasm/config.site-wasm32-emscripten
+++ b/Tools/wasm/config.site-wasm32-emscripten
@@ -86,11 +86,22 @@ ac_cv_func_mkfifoat=no
ac_cv_func_mknod=no
ac_cv_func_mknodat=no
-# always fails with permission error
+# always fails with permission or not implemented error
+ac_cv_func_getgroups=no
ac_cv_func_setgroups=no
ac_cv_func_setresuid=no
ac_cv_func_setresgid=no
+# Emscripten geteuid() / getegid() always return 0 (root), which breaks
+# assumption in tarfile module and some tests.
+ac_cv_func_getegid=no
+ac_cv_func_geteuid=no
+
+# Emscripten does not support hard links, always fails with errno 34
+# "Too many links". See emscripten_syscall_stubs.c
+ac_cv_func_link=no
+ac_cv_func_linkat=no
+
# alarm signal is not delivered, may need a callback into the event loop?
ac_cv_func_alarm=no
More information about the Python-checkins
mailing list