Skip to content

Commit 41d5391

Browse files
authored
gh-71052: Add test exclusions to support running the test suite on Android (#115918)
1 parent 83c5ecd commit 41d5391

File tree

12 files changed

+58
-27
lines changed

12 files changed

+58
-27
lines changed

Lib/test/support/__init__.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -532,24 +532,33 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
532532
is_emscripten = sys.platform == "emscripten"
533533
is_wasi = sys.platform == "wasi"
534534

535-
# Apple mobile platforms (iOS/tvOS/watchOS) are POSIX-like but do not
536-
# have subprocess or fork support.
537535
is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"}
538536
is_apple = is_apple_mobile or sys.platform == "darwin"
539537

540538
has_fork_support = hasattr(os, "fork") and not (
539+
# WASM and Apple mobile platforms do not support subprocesses.
541540
is_emscripten
542541
or is_wasi
543542
or is_apple_mobile
543+
544+
# Although Android supports fork, it's unsafe to call it from Python because
545+
# all Android apps are multi-threaded.
546+
or is_android
544547
)
545548

546549
def requires_fork():
547550
return unittest.skipUnless(has_fork_support, "requires working os.fork()")
548551

549552
has_subprocess_support = not (
553+
# WASM and Apple mobile platforms do not support subprocesses.
550554
is_emscripten
551555
or is_wasi
552556
or is_apple_mobile
557+
558+
# Although Android supports subproceses, they're almost never useful in
559+
# practice (see PEP 738). And most of the tests that use them are calling
560+
# sys.executable, which won't work when Python is embedded in an Android app.
561+
or is_android
553562
)
554563

555564
def requires_subprocess():

Lib/test/support/os_helper.py

+17
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,23 @@ def skip_unless_symlink(test):
198198
return test if ok else unittest.skip(msg)(test)
199199

200200

201+
_can_hardlink = None
202+
203+
def can_hardlink():
204+
global _can_hardlink
205+
if _can_hardlink is None:
206+
# Android blocks hard links using SELinux
207+
# (https://stackoverflow.com/q/32365690).
208+
_can_hardlink = hasattr(os, "link") and not support.is_android
209+
return _can_hardlink
210+
211+
212+
def skip_unless_hardlink(test):
213+
ok = can_hardlink()
214+
msg = "requires hardlink support"
215+
return test if ok else unittest.skip(msg)(test)
216+
217+
201218
_can_xattr = None
202219

203220

Lib/test/test_asyncio/test_subprocess.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from test import support
1414
from test.support import os_helper
1515

16+
if not support.has_subprocess_support:
17+
raise unittest.SkipTest("test module requires subprocess")
1618

1719
if support.MS_WINDOWS:
1820
import msvcrt
@@ -47,7 +49,6 @@ def _start(self, *args, **kwargs):
4749
self._proc.pid = -1
4850

4951

50-
@support.requires_subprocess()
5152
class SubprocessTransportTests(test_utils.TestCase):
5253
def setUp(self):
5354
super().setUp()
@@ -111,7 +112,6 @@ def test_subprocess_repr(self):
111112
transport.close()
112113

113114

114-
@support.requires_subprocess()
115115
class SubprocessMixin:
116116

117117
def test_stdin_stdout(self):

Lib/test/test_compileall.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ class CommandLineTestsNoSourceEpoch(CommandLineTestsBase,
977977

978978

979979

980-
@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
980+
@os_helper.skip_unless_hardlink
981981
class HardlinkDedupTestsBase:
982982
# Test hardlink_dupes parameter of compileall.compile_dir()
983983

Lib/test/test_fcntl.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ def test_fcntl_bad_file_overflow(self):
129129
fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK)
130130

131131
@unittest.skipIf(
132-
platform.machine().startswith('arm') and platform.system() == 'Linux',
132+
any(platform.machine().startswith(name) for name in {"arm", "aarch"})
133+
and platform.system() in {"Linux", "Android"},
133134
"ARM Linux returns EINVAL for F_NOTIFY DN_MULTISHOT")
134135
def test_fcntl_64_bit(self):
135136
# Issue #1309352: fcntl shouldn't fail when the third arg fits in a

Lib/test/test_interpreters/test_lifecycle.py

+1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ def test_sys_path_0(self):
164164

165165
class FinalizationTests(TestBase):
166166

167+
@support.requires_subprocess()
167168
def test_gh_109793(self):
168169
# Make sure finalization finishes and the correct error code
169170
# is reported, even when subinterpreters get cleaned up at the end.

Lib/test/test_os.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,9 @@ def test_yields_correct_dir_fd(self):
15921592
@unittest.skipIf(
15931593
support.is_emscripten, "Cannot dup stdout on Emscripten"
15941594
)
1595+
@unittest.skipIf(
1596+
support.is_android, "dup return value is unpredictable on Android"
1597+
)
15951598
def test_fd_leak(self):
15961599
# Since we're opening a lot of FDs, we must be careful to avoid leaks:
15971600
# we both check that calling fwalk() a large number of times doesn't
@@ -2492,8 +2495,10 @@ def test_listdir(self):
24922495
# test listdir without arguments
24932496
current_directory = os.getcwd()
24942497
try:
2495-
os.chdir(os.sep)
2496-
self.assertEqual(set(os.listdir()), set(os.listdir(os.sep)))
2498+
# The root directory is not readable on Android, so use a directory
2499+
# we created ourselves.
2500+
os.chdir(self.dir)
2501+
self.assertEqual(set(os.listdir()), expected)
24972502
finally:
24982503
os.chdir(current_directory)
24992504

@@ -4838,7 +4843,7 @@ def check_entry(self, entry, name, is_dir, is_file, is_symlink):
48384843
os.name == 'nt')
48394844

48404845
def test_attributes(self):
4841-
link = hasattr(os, 'link')
4846+
link = os_helper.can_hardlink()
48424847
symlink = os_helper.can_symlink()
48434848

48444849
dirname = os.path.join(self.path, "dir")

Lib/test/test_pathlib/test_pathlib.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ def test_rmdir(self):
796796
self.assertFileNotFound(p.stat)
797797
self.assertFileNotFound(p.unlink)
798798

799-
@unittest.skipUnless(hasattr(os, "link"), "os.link() is not present")
799+
@os_helper.skip_unless_hardlink
800800
def test_hardlink_to(self):
801801
P = self.cls(self.base)
802802
target = P / 'fileA'

Lib/test/test_posix.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1270,9 +1270,10 @@ def test_get_and_set_scheduler_and_param(self):
12701270
self.assertIn(mine, possible_schedulers)
12711271
try:
12721272
parent = posix.sched_getscheduler(os.getppid())
1273-
except OSError as e:
1274-
if e.errno != errno.EPERM:
1275-
raise
1273+
except PermissionError:
1274+
# POSIX specifies EPERM, but Android returns EACCES. Both errno
1275+
# values are mapped to PermissionError.
1276+
pass
12761277
else:
12771278
self.assertIn(parent, possible_schedulers)
12781279
self.assertRaises(OSError, posix.sched_getscheduler, -1)
@@ -1287,9 +1288,8 @@ def test_get_and_set_scheduler_and_param(self):
12871288
try:
12881289
posix.sched_setscheduler(0, mine, param)
12891290
posix.sched_setparam(0, param)
1290-
except OSError as e:
1291-
if e.errno != errno.EPERM:
1292-
raise
1291+
except PermissionError:
1292+
pass
12931293
self.assertRaises(OSError, posix.sched_setparam, -1, param)
12941294

12951295
self.assertRaises(OSError, posix.sched_setscheduler, -1, mine, param)

Lib/test/test_pty.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
import sys
21
import unittest
32
from test.support import (
4-
is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
3+
is_android, is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
54
)
65
from test.support.import_helper import import_module
76
from test.support.os_helper import TESTFN, unlink
87

98
# Skip these tests if termios is not available
109
import_module('termios')
1110

12-
# Skip tests on WASM platforms, plus iOS/tvOS/watchOS
13-
if is_apple_mobile or is_emscripten or is_wasi:
14-
raise unittest.SkipTest(f"pty tests not required on {sys.platform}")
11+
if is_android or is_apple_mobile or is_emscripten or is_wasi:
12+
raise unittest.SkipTest("pty is not available on this platform")
1513

1614
import errno
1715
import os

Lib/test/test_venv.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
import tempfile
2020
from test.support import (captured_stdout, captured_stderr,
2121
skip_if_broken_multiprocessing_synchronize, verbose,
22-
requires_subprocess, is_apple_mobile, is_emscripten,
23-
is_wasi, requires_venv_with_pip, TEST_HOME_DIR,
22+
requires_subprocess, is_android, is_apple_mobile,
23+
is_emscripten, is_wasi,
24+
requires_venv_with_pip, TEST_HOME_DIR,
2425
requires_resource, copy_python_src_ignore)
2526
from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
2627
import unittest
@@ -39,10 +40,8 @@
3940
or sys._base_executable != sys.executable,
4041
'cannot run venv.create from within a venv on this platform')
4142

42-
# Skip tests on WASM platforms, plus iOS/tvOS/watchOS
43-
if is_apple_mobile or is_emscripten or is_wasi:
44-
raise unittest.SkipTest(f"venv tests not required on {sys.platform}")
45-
43+
if is_android or is_apple_mobile or is_emscripten or is_wasi:
44+
raise unittest.SkipTest("venv is not available on this platform")
4645

4746
@requires_subprocess()
4847
def check_output(cmd, encoding=None):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add test exclusions to support running the test suite on Android.

0 commit comments

Comments
 (0)