Commit 0f86cd38 authored by xdegaye's avatar xdegaye Committed by GitHub

bpo-28684: asyncio tests handle PermissionError raised on binding unix sockets (GH-4503)

The test.support.skip_unless_bind_unix_socket() decorator is used to skip
asyncio tests that fail because the platform lacks a functional bind()
function for unix domain sockets (as it is the case for non root users on the
recent Android versions that run now SELinux in enforcing mode).
parent 19fb1341
...@@ -88,6 +88,7 @@ __all__ = [ ...@@ -88,6 +88,7 @@ __all__ = [
"requires_IEEE_754", "skip_unless_xattr", "requires_zlib", "requires_IEEE_754", "skip_unless_xattr", "requires_zlib",
"anticipate_failure", "load_package_tests", "detect_api_mismatch", "anticipate_failure", "load_package_tests", "detect_api_mismatch",
"check__all__", "requires_android_level", "requires_multiprocessing_queue", "check__all__", "requires_android_level", "requires_multiprocessing_queue",
"skip_unless_bind_unix_socket",
# sys # sys
"is_jython", "is_android", "check_impl_detail", "unix_shell", "is_jython", "is_android", "check_impl_detail", "unix_shell",
"setswitchinterval", "setswitchinterval",
...@@ -2432,6 +2433,28 @@ def skip_unless_xattr(test): ...@@ -2432,6 +2433,28 @@ def skip_unless_xattr(test):
msg = "no non-broken extended attribute support" msg = "no non-broken extended attribute support"
return test if ok else unittest.skip(msg)(test) return test if ok else unittest.skip(msg)(test)
_bind_nix_socket_error = None
def skip_unless_bind_unix_socket(test):
"""Decorator for tests requiring a functional bind() for unix sockets."""
if not hasattr(socket, 'AF_UNIX'):
return unittest.skip('No UNIX Sockets')(test)
global _bind_nix_socket_error
if _bind_nix_socket_error is None:
path = TESTFN + "can_bind_unix_socket"
with socket.socket(socket.AF_UNIX) as sock:
try:
sock.bind(path)
_bind_nix_socket_error = False
except OSError as e:
_bind_nix_socket_error = e
finally:
unlink(path)
if _bind_nix_socket_error:
msg = 'Requires a functional unix bind(): %s' % _bind_nix_socket_error
return unittest.skip(msg)(test)
else:
return test
def fs_is_case_insensitive(directory): def fs_is_case_insensitive(directory):
"""Detects if the file system for the specified directory is case-insensitive.""" """Detects if the file system for the specified directory is case-insensitive."""
......
...@@ -22,6 +22,7 @@ import errno ...@@ -22,6 +22,7 @@ import errno
import unittest import unittest
from unittest import mock from unittest import mock
import weakref import weakref
from test import support
if sys.platform != 'win32': if sys.platform != 'win32':
import tty import tty
...@@ -470,7 +471,7 @@ class EventLoopTestsMixin: ...@@ -470,7 +471,7 @@ class EventLoopTestsMixin:
sock = socket.socket() sock = socket.socket()
self._basetest_sock_recv_into(httpd, sock) self._basetest_sock_recv_into(httpd, sock)
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_unix_sock_client_ops(self): def test_unix_sock_client_ops(self):
with test_utils.run_test_unix_server() as httpd: with test_utils.run_test_unix_server() as httpd:
sock = socket.socket(socket.AF_UNIX) sock = socket.socket(socket.AF_UNIX)
...@@ -606,7 +607,7 @@ class EventLoopTestsMixin: ...@@ -606,7 +607,7 @@ class EventLoopTestsMixin:
lambda: MyProto(loop=self.loop), *httpd.address) lambda: MyProto(loop=self.loop), *httpd.address)
self._basetest_create_connection(conn_fut) self._basetest_create_connection(conn_fut)
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_create_unix_connection(self): def test_create_unix_connection(self):
# Issue #20682: On Mac OS X Tiger, getsockname() returns a # Issue #20682: On Mac OS X Tiger, getsockname() returns a
# zero-length address for UNIX socket. # zero-length address for UNIX socket.
...@@ -736,8 +737,8 @@ class EventLoopTestsMixin: ...@@ -736,8 +737,8 @@ class EventLoopTestsMixin:
self._test_create_ssl_connection(httpd, create_connection, self._test_create_ssl_connection(httpd, create_connection,
peername=httpd.address) peername=httpd.address)
@support.skip_unless_bind_unix_socket
@unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_ssl_unix_connection(self): def test_create_ssl_unix_connection(self):
# Issue #20682: On Mac OS X Tiger, getsockname() returns a # Issue #20682: On Mac OS X Tiger, getsockname() returns a
# zero-length address for UNIX socket. # zero-length address for UNIX socket.
...@@ -961,7 +962,7 @@ class EventLoopTestsMixin: ...@@ -961,7 +962,7 @@ class EventLoopTestsMixin:
return server, path return server, path
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_create_unix_server(self): def test_create_unix_server(self):
proto = MyProto(loop=self.loop) proto = MyProto(loop=self.loop)
server, path = self._make_unix_server(lambda: proto) server, path = self._make_unix_server(lambda: proto)
...@@ -1053,8 +1054,8 @@ class EventLoopTestsMixin: ...@@ -1053,8 +1054,8 @@ class EventLoopTestsMixin:
# stop serving # stop serving
server.close() server.close()
@support.skip_unless_bind_unix_socket
@unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl(self): def test_create_unix_server_ssl(self):
proto = MyProto(loop=self.loop) proto = MyProto(loop=self.loop)
server, path = self._make_ssl_unix_server( server, path = self._make_ssl_unix_server(
...@@ -1113,8 +1114,8 @@ class EventLoopTestsMixin: ...@@ -1113,8 +1114,8 @@ class EventLoopTestsMixin:
self.assertIsNone(proto.transport) self.assertIsNone(proto.transport)
server.close() server.close()
@support.skip_unless_bind_unix_socket
@unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl_verify_failed(self): def test_create_unix_server_ssl_verify_failed(self):
proto = MyProto(loop=self.loop) proto = MyProto(loop=self.loop)
server, path = self._make_ssl_unix_server( server, path = self._make_ssl_unix_server(
...@@ -1171,8 +1172,8 @@ class EventLoopTestsMixin: ...@@ -1171,8 +1172,8 @@ class EventLoopTestsMixin:
proto.transport.close() proto.transport.close()
server.close() server.close()
@support.skip_unless_bind_unix_socket
@unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl_verified(self): def test_create_unix_server_ssl_verified(self):
proto = MyProto(loop=self.loop) proto = MyProto(loop=self.loop)
server, path = self._make_ssl_unix_server( server, path = self._make_ssl_unix_server(
......
...@@ -9,6 +9,7 @@ import sys ...@@ -9,6 +9,7 @@ import sys
import threading import threading
import unittest import unittest
from unittest import mock from unittest import mock
from test import support
try: try:
import ssl import ssl
except ImportError: except ImportError:
...@@ -57,7 +58,7 @@ class StreamReaderTests(test_utils.TestCase): ...@@ -57,7 +58,7 @@ class StreamReaderTests(test_utils.TestCase):
loop=self.loop) loop=self.loop)
self._basetest_open_connection(conn_fut) self._basetest_open_connection(conn_fut)
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_open_unix_connection(self): def test_open_unix_connection(self):
with test_utils.run_test_unix_server() as httpd: with test_utils.run_test_unix_server() as httpd:
conn_fut = asyncio.open_unix_connection(httpd.address, conn_fut = asyncio.open_unix_connection(httpd.address,
...@@ -86,8 +87,8 @@ class StreamReaderTests(test_utils.TestCase): ...@@ -86,8 +87,8 @@ class StreamReaderTests(test_utils.TestCase):
self._basetest_open_connection_no_loop_ssl(conn_fut) self._basetest_open_connection_no_loop_ssl(conn_fut)
@support.skip_unless_bind_unix_socket
@unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_open_unix_connection_no_loop_ssl(self): def test_open_unix_connection_no_loop_ssl(self):
with test_utils.run_test_unix_server(use_ssl=True) as httpd: with test_utils.run_test_unix_server(use_ssl=True) as httpd:
conn_fut = asyncio.open_unix_connection( conn_fut = asyncio.open_unix_connection(
...@@ -113,7 +114,7 @@ class StreamReaderTests(test_utils.TestCase): ...@@ -113,7 +114,7 @@ class StreamReaderTests(test_utils.TestCase):
loop=self.loop) loop=self.loop)
self._basetest_open_connection_error(conn_fut) self._basetest_open_connection_error(conn_fut)
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_open_unix_connection_error(self): def test_open_unix_connection_error(self):
with test_utils.run_test_unix_server() as httpd: with test_utils.run_test_unix_server() as httpd:
conn_fut = asyncio.open_unix_connection(httpd.address, conn_fut = asyncio.open_unix_connection(httpd.address,
...@@ -634,7 +635,7 @@ class StreamReaderTests(test_utils.TestCase): ...@@ -634,7 +635,7 @@ class StreamReaderTests(test_utils.TestCase):
server.stop() server.stop()
self.assertEqual(msg, b"hello world!\n") self.assertEqual(msg, b"hello world!\n")
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket
def test_start_unix_server(self): def test_start_unix_server(self):
class MyServer: class MyServer:
......
...@@ -13,6 +13,7 @@ import tempfile ...@@ -13,6 +13,7 @@ import tempfile
import threading import threading
import unittest import unittest
from unittest import mock from unittest import mock
from test import support
if sys.platform == 'win32': if sys.platform == 'win32':
raise unittest.SkipTest('UNIX only') raise unittest.SkipTest('UNIX only')
...@@ -239,6 +240,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -239,6 +240,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
self.loop = asyncio.SelectorEventLoop() self.loop = asyncio.SelectorEventLoop()
self.set_event_loop(self.loop) self.set_event_loop(self.loop)
@support.skip_unless_bind_unix_socket
def test_create_unix_server_existing_path_sock(self): def test_create_unix_server_existing_path_sock(self):
with test_utils.unix_socket_path() as path: with test_utils.unix_socket_path() as path:
sock = socket.socket(socket.AF_UNIX) sock = socket.socket(socket.AF_UNIX)
...@@ -251,6 +253,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -251,6 +253,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
srv.close() srv.close()
self.loop.run_until_complete(srv.wait_closed()) self.loop.run_until_complete(srv.wait_closed())
@support.skip_unless_bind_unix_socket
def test_create_unix_server_pathlib(self): def test_create_unix_server_pathlib(self):
with test_utils.unix_socket_path() as path: with test_utils.unix_socket_path() as path:
path = pathlib.Path(path) path = pathlib.Path(path)
...@@ -308,6 +311,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -308,6 +311,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
@unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'),
'no socket.SOCK_NONBLOCK (linux only)') 'no socket.SOCK_NONBLOCK (linux only)')
@support.skip_unless_bind_unix_socket
def test_create_unix_server_path_stream_bittype(self): def test_create_unix_server_path_stream_bittype(self):
sock = socket.socket( sock = socket.socket(
socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_NONBLOCK) socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_NONBLOCK)
......
The new test.support.skip_unless_bind_unix_socket() decorator is used here to
skip asyncio tests that fail because the platform lacks a functional bind()
function for unix domain sockets (as it is the case for non root users on the
recent Android versions that run now SELinux in enforcing mode).
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment