]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-71052: Add test exclusions to support running the test suite on Android (#115918)
authorMalcolm Smith <smith@chaquo.com>
Thu, 29 Feb 2024 21:32:50 +0000 (21:32 +0000)
committerGitHub <noreply@github.com>
Thu, 29 Feb 2024 21:32:50 +0000 (22:32 +0100)
12 files changed:
Lib/test/support/__init__.py
Lib/test/support/os_helper.py
Lib/test/test_asyncio/test_subprocess.py
Lib/test/test_compileall.py
Lib/test/test_fcntl.py
Lib/test/test_interpreters/test_lifecycle.py
Lib/test/test_os.py
Lib/test/test_pathlib/test_pathlib.py
Lib/test/test_posix.py
Lib/test/test_pty.py
Lib/test/test_venv.py
Misc/NEWS.d/next/Tests/2024-02-25-16-28-26.gh-issue-71052.lSb9EC.rst [new file with mode: 0644]

index 401b2ce1fe213cb380f5989ea2f9fa7884f67dad..14e3766a34377b808e1ae9b8ea9623cd6d9a9ce8 100644 (file)
@@ -532,24 +532,33 @@ else:
 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():
index 22787e32b5f3abe39e6a0c36cc3e947633a2d9b2..ffa5fc52e9b2bd94647033dfd50d0ae6a8cf3565 100644 (file)
@@ -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
 
 
index f50a9ebc031ba8ade59bbad3ba1c7ae3a30583d2..890c0acc1720dc9f68bb3257956f5a06e4220400 100644 (file)
@@ -13,6 +13,8 @@ from test.test_asyncio import utils as test_utils
 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
@@ -47,7 +49,6 @@ class TestSubprocessTransport(base_subprocess.BaseSubprocessTransport):
         self._proc.pid = -1
 
 
-@support.requires_subprocess()
 class SubprocessTransportTests(test_utils.TestCase):
     def setUp(self):
         super().setUp()
@@ -111,7 +112,6 @@ class SubprocessTransportTests(test_utils.TestCase):
         transport.close()
 
 
-@support.requires_subprocess()
 class SubprocessMixin:
 
     def test_stdin_stdout(self):
index 0ec6013dc11e3e6b86f0cd3015f4294cf7458ab7..14c2af19e3eb28b8c187edea2314d158ed1f7a77 100644 (file)
@@ -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()
 
index 6d734d052454d3442d82f98c8b708a06155cc101..8b4ed4a9e3a4febd036ec53f4ff178693df0b4d9 100644 (file)
@@ -129,7 +129,8 @@ class TestFcntl(unittest.TestCase):
             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
index 67b6f439c3191fc0954b5ed211081031578655bd..becf003e2e5f2076e4aa80f830b59cbd45c9ca64 100644 (file)
@@ -164,6 +164,7 @@ class StartupTests(TestBase):
 
 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.
index 2372ac4c21efd9fd1a939991023b141130a46346..3b2d5fccc30f3c1024e30a3f512903a24ba9bec5 100644 (file)
@@ -1592,6 +1592,9 @@ class FwalkTests(WalkTests):
     @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
@@ -2492,8 +2495,10 @@ class Pep383Tests(unittest.TestCase):
         # 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)
 
@@ -4838,7 +4843,7 @@ class TestScandir(unittest.TestCase):
                                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")
index c0dcf314da4bfc3ed882243cb19f585acd829af3..7e44ae61a5eba7ac41bd906f62df7f252532eb65 100644 (file)
@@ -796,7 +796,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
         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'
index a45f620e18dc1d0c1b122b69a946bc36d3122bae..2706d5eb6d98305ac0ab022e17a5762f7dccf426 100644 (file)
@@ -1270,9 +1270,10 @@ class PosixTester(unittest.TestCase):
         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)
@@ -1287,9 +1288,8 @@ class PosixTester(unittest.TestCase):
             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)
index 3f2bac0155fd9e8490a0836e025402d9df26c778..dee94533c7454910bf2d414389654886ebcd1d01 100644 (file)
@@ -1,7 +1,6 @@
-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
@@ -9,9 +8,8 @@ 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
index ba31beb81e80b0911f116bca19dffb49c05b5d10..f60c662d322e382ef3cb7103a614ccca1a1f9a38 100644 (file)
@@ -19,8 +19,9 @@ import sysconfig
 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
@@ -39,10 +40,8 @@ requireVenvCreate = unittest.skipUnless(
     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):
diff --git a/Misc/NEWS.d/next/Tests/2024-02-25-16-28-26.gh-issue-71052.lSb9EC.rst b/Misc/NEWS.d/next/Tests/2024-02-25-16-28-26.gh-issue-71052.lSb9EC.rst
new file mode 100644 (file)
index 0000000..9d3467c
--- /dev/null
@@ -0,0 +1 @@
+Add test exclusions to support running the test suite on Android.