Skip to content

Commit

Permalink
pythongh-71052: Add test exclusions to support running the test suite…
Browse files Browse the repository at this point in the history
… on Android (python#115918)
  • Loading branch information
mhsmith authored and adorilson committed Mar 25, 2024
1 parent 00384fc commit 096832f
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 27 deletions.
13 changes: 11 additions & 2 deletions Lib/test/support/__init__.py
Expand Up @@ -532,24 +532,33 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
is_emscripten = sys.platform == "emscripten"
is_wasi = sys.platform == "wasi"

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

has_fork_support = hasattr(os, "fork") and not (
# WASM and Apple mobile platforms do not support subprocesses.
is_emscripten
or is_wasi
or is_apple_mobile

# Although Android supports fork, it's unsafe to call it from Python because
# all Android apps are multi-threaded.
or is_android
)

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

has_subprocess_support = not (
# WASM and Apple mobile platforms do not support subprocesses.
is_emscripten
or is_wasi
or is_apple_mobile

# Although Android supports subproceses, they're almost never useful in
# practice (see PEP 738). And most of the tests that use them are calling
# sys.executable, which won't work when Python is embedded in an Android app.
or is_android
)

def requires_subprocess():
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/support/os_helper.py
Expand Up @@ -198,6 +198,23 @@ def skip_unless_symlink(test):
return test if ok else unittest.skip(msg)(test)


_can_hardlink = None

def can_hardlink():
global _can_hardlink
if _can_hardlink is None:
# Android blocks hard links using SELinux
# (https://stackoverflow.com/q/32365690).
_can_hardlink = hasattr(os, "link") and not support.is_android
return _can_hardlink


def skip_unless_hardlink(test):
ok = can_hardlink()
msg = "requires hardlink support"
return test if ok else unittest.skip(msg)(test)


_can_xattr = None


Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_asyncio/test_subprocess.py
Expand Up @@ -13,6 +13,8 @@
from test import support
from test.support import os_helper

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

if support.MS_WINDOWS:
import msvcrt
Expand Down Expand Up @@ -47,7 +49,6 @@ def _start(self, *args, **kwargs):
self._proc.pid = -1


@support.requires_subprocess()
class SubprocessTransportTests(test_utils.TestCase):
def setUp(self):
super().setUp()
Expand Down Expand Up @@ -111,7 +112,6 @@ def test_subprocess_repr(self):
transport.close()


@support.requires_subprocess()
class SubprocessMixin:

def test_stdin_stdout(self):
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_compileall.py
Expand Up @@ -977,7 +977,7 @@ class CommandLineTestsNoSourceEpoch(CommandLineTestsBase,



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

Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_fcntl.py
Expand Up @@ -129,7 +129,8 @@ def test_fcntl_bad_file_overflow(self):
fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK)

@unittest.skipIf(
platform.machine().startswith('arm') and platform.system() == 'Linux',
any(platform.machine().startswith(name) for name in {"arm", "aarch"})
and platform.system() in {"Linux", "Android"},
"ARM Linux returns EINVAL for F_NOTIFY DN_MULTISHOT")
def test_fcntl_64_bit(self):
# Issue #1309352: fcntl shouldn't fail when the third arg fits in a
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_interpreters/test_lifecycle.py
Expand Up @@ -164,6 +164,7 @@ def test_sys_path_0(self):

class FinalizationTests(TestBase):

@support.requires_subprocess()
def test_gh_109793(self):
# Make sure finalization finishes and the correct error code
# is reported, even when subinterpreters get cleaned up at the end.
Expand Down
11 changes: 8 additions & 3 deletions Lib/test/test_os.py
Expand Up @@ -1592,6 +1592,9 @@ def test_yields_correct_dir_fd(self):
@unittest.skipIf(
support.is_emscripten, "Cannot dup stdout on Emscripten"
)
@unittest.skipIf(
support.is_android, "dup return value is unpredictable on Android"
)
def test_fd_leak(self):
# Since we're opening a lot of FDs, we must be careful to avoid leaks:
# we both check that calling fwalk() a large number of times doesn't
Expand Down Expand Up @@ -2492,8 +2495,10 @@ def test_listdir(self):
# test listdir without arguments
current_directory = os.getcwd()
try:
os.chdir(os.sep)
self.assertEqual(set(os.listdir()), set(os.listdir(os.sep)))
# The root directory is not readable on Android, so use a directory
# we created ourselves.
os.chdir(self.dir)
self.assertEqual(set(os.listdir()), expected)
finally:
os.chdir(current_directory)

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

def test_attributes(self):
link = hasattr(os, 'link')
link = os_helper.can_hardlink()
symlink = os_helper.can_symlink()

dirname = os.path.join(self.path, "dir")
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_pathlib/test_pathlib.py
Expand Up @@ -796,7 +796,7 @@ def test_rmdir(self):
self.assertFileNotFound(p.stat)
self.assertFileNotFound(p.unlink)

@unittest.skipUnless(hasattr(os, "link"), "os.link() is not present")
@os_helper.skip_unless_hardlink
def test_hardlink_to(self):
P = self.cls(self.base)
target = P / 'fileA'
Expand Down
12 changes: 6 additions & 6 deletions Lib/test/test_posix.py
Expand Up @@ -1270,9 +1270,10 @@ def test_get_and_set_scheduler_and_param(self):
self.assertIn(mine, possible_schedulers)
try:
parent = posix.sched_getscheduler(os.getppid())
except OSError as e:
if e.errno != errno.EPERM:
raise
except PermissionError:
# POSIX specifies EPERM, but Android returns EACCES. Both errno
# values are mapped to PermissionError.
pass
else:
self.assertIn(parent, possible_schedulers)
self.assertRaises(OSError, posix.sched_getscheduler, -1)
Expand All @@ -1287,9 +1288,8 @@ def test_get_and_set_scheduler_and_param(self):
try:
posix.sched_setscheduler(0, mine, param)
posix.sched_setparam(0, param)
except OSError as e:
if e.errno != errno.EPERM:
raise
except PermissionError:
pass
self.assertRaises(OSError, posix.sched_setparam, -1, param)

self.assertRaises(OSError, posix.sched_setscheduler, -1, mine, param)
Expand Down
8 changes: 3 additions & 5 deletions Lib/test/test_pty.py
@@ -1,17 +1,15 @@
import sys
import unittest
from test.support import (
is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
is_android, is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
)
from test.support.import_helper import import_module
from test.support.os_helper import TESTFN, unlink

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

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

import errno
import os
Expand Down
11 changes: 5 additions & 6 deletions Lib/test/test_venv.py
Expand Up @@ -19,8 +19,9 @@
import tempfile
from test.support import (captured_stdout, captured_stderr,
skip_if_broken_multiprocessing_synchronize, verbose,
requires_subprocess, is_apple_mobile, is_emscripten,
is_wasi, requires_venv_with_pip, TEST_HOME_DIR,
requires_subprocess, is_android, is_apple_mobile,
is_emscripten, is_wasi,
requires_venv_with_pip, TEST_HOME_DIR,
requires_resource, copy_python_src_ignore)
from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
import unittest
Expand All @@ -39,10 +40,8 @@
or sys._base_executable != sys.executable,
'cannot run venv.create from within a venv on this platform')

# Skip tests on WASM platforms, plus iOS/tvOS/watchOS
if is_apple_mobile or is_emscripten or is_wasi:
raise unittest.SkipTest(f"venv tests not required on {sys.platform}")

if is_android or is_apple_mobile or is_emscripten or is_wasi:
raise unittest.SkipTest("venv is not available on this platform")

@requires_subprocess()
def check_output(cmd, encoding=None):
Expand Down
@@ -0,0 +1 @@
Add test exclusions to support running the test suite on Android.

0 comments on commit 096832f

Please sign in to comment.