Skip to content

Commit 5081e78

Browse files
authored
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.
1 parent 36dd739 commit 5081e78

8 files changed

+37
-10
lines changed

Lib/distutils/tests/test_file_util.py

+2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def test_move_file_exception_unpacking_unlink(self):
7979
fobj.write('spam eggs')
8080
move_file(self.source, self.target, verbose=0)
8181

82+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
8283
def test_copy_file_hard_link(self):
8384
with open(self.source, 'w') as f:
8485
f.write('some content')
@@ -99,6 +100,7 @@ def test_copy_file_hard_link(self):
99100
with open(self.source, 'r') as f:
100101
self.assertEqual(f.read(), 'some content')
101102

103+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
102104
def test_copy_file_hard_link_failure(self):
103105
# If hard linking fails, copy_file() falls back on copying file
104106
# (some special filesystems don't support hard linking even under

Lib/test/support/os_helper.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
'encoding (%s). Unicode filename tests may not be effective'
5050
% (TESTFN_UNENCODABLE, sys.getfilesystemencoding()))
5151
TESTFN_UNENCODABLE = None
52-
# Mac OS X denies unencodable filenames (invalid utf-8)
53-
elif sys.platform != 'darwin':
52+
# macOS and Emscripten deny unencodable filenames (invalid utf-8)
53+
elif sys.platform not in {'darwin', 'emscripten'}:
5454
try:
5555
# ascii and utf-8 cannot encode the byte 0xff
5656
b'\xff'.decode(sys.getfilesystemencoding())

Lib/test/test_compileall.py

+4
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ def test_compile_one_worker(self, compile_file_mock, pool_mock):
244244
self.assertFalse(pool_mock.called)
245245
self.assertTrue(compile_file_mock.called)
246246

247+
@skipUnless(_have_multiprocessing, "requires multiprocessing")
247248
@mock.patch('concurrent.futures.ProcessPoolExecutor', new=None)
248249
@mock.patch('compileall.compile_file')
249250
def test_compile_missing_multiprocessing(self, compile_file_mock):
@@ -296,6 +297,7 @@ def test_ddir_only_one_worker(self):
296297
"""Recursive compile_dir ddir= contains package paths; bpo39769."""
297298
return self._test_ddir_only(ddir="<a prefix>", parallel=False)
298299

300+
@skipUnless(_have_multiprocessing, "requires multiprocessing")
299301
def test_ddir_multiple_workers(self):
300302
"""Recursive compile_dir ddir= contains package paths; bpo39769."""
301303
return self._test_ddir_only(ddir="<a prefix>", parallel=True)
@@ -304,6 +306,7 @@ def test_ddir_empty_only_one_worker(self):
304306
"""Recursive compile_dir ddir='' contains package paths; bpo39769."""
305307
return self._test_ddir_only(ddir="", parallel=False)
306308

309+
@skipUnless(_have_multiprocessing, "requires multiprocessing")
307310
def test_ddir_empty_multiple_workers(self):
308311
"""Recursive compile_dir ddir='' contains package paths; bpo39769."""
309312
return self._test_ddir_only(ddir="", parallel=True)
@@ -924,6 +927,7 @@ class CommandLineTestsNoSourceEpoch(CommandLineTestsBase,
924927

925928

926929

930+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
927931
class HardlinkDedupTestsBase:
928932
# Test hardlink_dupes parameter of compileall.compile_dir()
929933

Lib/test/test_genericpath.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import unittest
99
import warnings
10+
from test.support import is_emscripten
1011
from test.support import os_helper
1112
from test.support import warnings_helper
1213
from test.support.script_helper import assert_python_ok
@@ -154,6 +155,7 @@ def test_exists(self):
154155
self.assertIs(self.pathmodule.lexists(bfilename + b'\x00'), False)
155156

156157
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
158+
@unittest.skipIf(is_emscripten, "Emscripten pipe fds have no stat")
157159
def test_exists_fd(self):
158160
r, w = os.pipe()
159161
try:
@@ -246,6 +248,7 @@ def _test_samefile_on_link_func(self, func):
246248
def test_samefile_on_symlink(self):
247249
self._test_samefile_on_link_func(os.symlink)
248250

251+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
249252
def test_samefile_on_link(self):
250253
try:
251254
self._test_samefile_on_link_func(os.link)
@@ -288,6 +291,7 @@ def _test_samestat_on_link_func(self, func):
288291
def test_samestat_on_symlink(self):
289292
self._test_samestat_on_link_func(os.symlink)
290293

294+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
291295
def test_samestat_on_link(self):
292296
try:
293297
self._test_samestat_on_link_func(os.link)
@@ -476,11 +480,11 @@ def test_abspath_issue3426(self):
476480

477481
def test_nonascii_abspath(self):
478482
if (os_helper.TESTFN_UNDECODABLE
479-
# Mac OS X denies the creation of a directory with an invalid
480-
# UTF-8 name. Windows allows creating a directory with an
483+
# macOS and Emscripten deny the creation of a directory with an
484+
# invalid UTF-8 name. Windows allows creating a directory with an
481485
# arbitrary bytes name, but fails to enter this directory
482486
# (when the bytes name is used).
483-
and sys.platform not in ('win32', 'darwin')):
487+
and sys.platform not in ('win32', 'darwin', 'emscripten')):
484488
name = os_helper.TESTFN_UNDECODABLE
485489
elif os_helper.TESTFN_NONASCII:
486490
name = os_helper.TESTFN_NONASCII

Lib/test/test_os.py

+1
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,7 @@ def test_blocking(self):
22032203
self.check(os.set_blocking, True)
22042204

22052205

2206+
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
22062207
class LinkTests(unittest.TestCase):
22072208
def setUp(self):
22082209
self.file1 = os_helper.TESTFN

Lib/test/test_posix.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ def testNoArgFunctions(self):
7575
for name in NO_ARG_FUNCTIONS:
7676
posix_func = getattr(posix, name, None)
7777
if posix_func is not None:
78-
posix_func()
79-
self.assertRaises(TypeError, posix_func, 1)
78+
with self.subTest(name):
79+
posix_func()
80+
self.assertRaises(TypeError, posix_func, 1)
8081

8182
@unittest.skipUnless(hasattr(posix, 'getresuid'),
8283
'test needs posix.getresuid()')
@@ -1399,7 +1400,10 @@ def test_utime_dir_fd(self):
13991400
# whoops! using both together not supported on this platform.
14001401
pass
14011402

1402-
@unittest.skipUnless(os.link in os.supports_dir_fd, "test needs dir_fd support in os.link()")
1403+
@unittest.skipUnless(
1404+
hasattr(os, "link") and os.link in os.supports_dir_fd,
1405+
"test needs dir_fd support in os.link()"
1406+
)
14031407
def test_link_dir_fd(self):
14041408
with self.prepare_file() as (dir_fd, name, fullname), \
14051409
self.prepare() as (dir_fd2, linkname, fulllinkname):

Lib/test/test_script_helper.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import subprocess
44
import sys
55
import os
6-
from test.support import script_helper
6+
from test.support import script_helper, requires_subprocess
77
import unittest
88
from unittest import mock
99

@@ -69,6 +69,7 @@ def test_assert_python_not_isolated_when_env_is_required(self, mock_popen):
6969
self.assertNotIn('-E', popen_command)
7070

7171

72+
@requires_subprocess()
7273
class TestScriptHelperEnvironment(unittest.TestCase):
7374
"""Code coverage for interpreter_requires_environment()."""
7475

Tools/wasm/config.site-wasm32-emscripten

+12-1
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,22 @@ ac_cv_func_mkfifoat=no
8686
ac_cv_func_mknod=no
8787
ac_cv_func_mknodat=no
8888

89-
# always fails with permission error
89+
# always fails with permission or not implemented error
90+
ac_cv_func_getgroups=no
9091
ac_cv_func_setgroups=no
9192
ac_cv_func_setresuid=no
9293
ac_cv_func_setresgid=no
9394

95+
# Emscripten geteuid() / getegid() always return 0 (root), which breaks
96+
# assumption in tarfile module and some tests.
97+
ac_cv_func_getegid=no
98+
ac_cv_func_geteuid=no
99+
100+
# Emscripten does not support hard links, always fails with errno 34
101+
# "Too many links". See emscripten_syscall_stubs.c
102+
ac_cv_func_link=no
103+
ac_cv_func_linkat=no
104+
94105
# alarm signal is not delivered, may need a callback into the event loop?
95106
ac_cv_func_alarm=no
96107

0 commit comments

Comments
 (0)