From 37e6b45b0ca3fea0c6fea11c320af2a948383cd8 Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Wed, 22 Nov 2017 17:57:31 +0100 Subject: [PATCH 1/5] bpo-28684: asyncio tests now handle PermissionError raised when binding a unix socket --- Lib/asyncio/test_utils.py | 9 ++++-- Lib/test/test_asyncio/test_events.py | 5 +++- Lib/test/test_asyncio/test_streams.py | 7 +++-- Lib/test/test_asyncio/test_unix_events.py | 29 ++++++++++++++----- .../2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst | 2 ++ 5 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index c3ddfe37563a6a4..383dd134aa9490e 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -220,9 +220,12 @@ def unix_socket_path(): @contextlib.contextmanager def run_test_unix_server(*, use_ssl=False): with unix_socket_path() as path: - yield from _run_test_server(address=path, use_ssl=use_ssl, - server_cls=SilentUnixWSGIServer, - server_ssl_cls=UnixSSLWSGIServer) + try: + yield from _run_test_server(address=path, use_ssl=use_ssl, + server_cls=SilentUnixWSGIServer, + server_ssl_cls=UnixSSLWSGIServer) + except PermissionError as e: + raise unittest.SkipTest('_run_test_server(): %s' % e) @contextlib.contextmanager diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 1a8bc13429648f4..bda958d6be26e8a 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -957,7 +957,10 @@ def _make_unix_server(self, factory, **kwargs): self.addCleanup(lambda: os.path.exists(path) and os.unlink(path)) f = self.loop.create_unix_server(factory, path, **kwargs) - server = self.loop.run_until_complete(f) + try: + server = self.loop.run_until_complete(f) + except PermissionError as e: + self.skipTest('run_until_complete(): %s' % e) return server, path diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 6d16d2007967d31..30758b068d020f1 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -652,10 +652,13 @@ def handle_client(self, client_reader, client_writer): client_writer.close() def start(self): - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client, + try: + self.server = self.loop.run_until_complete( + asyncio.start_unix_server(self.handle_client, path=self.path, loop=self.loop)) + except PermissionError as e: + raise unittest.SkipTest('run_until_complete(): %s' % e) def handle_client_callback(self, client_reader, client_writer): self.loop.create_task(self.handle_client(client_reader, diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index d558842a1f83d24..85a930c86d92176 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -17,6 +17,13 @@ if sys.platform == 'win32': raise unittest.SkipTest('UNIX only') +try: + from test.support import unlink +except ImportError: + def unlink(fn): + if os.path.exists(fn): + os.unlink(fn) + import asyncio from asyncio import log @@ -241,10 +248,12 @@ def setUp(self): def test_create_unix_server_existing_path_sock(self): with test_utils.unix_socket_path() as path: - sock = socket.socket(socket.AF_UNIX) - sock.bind(path) - sock.listen(1) - sock.close() + with socket.socket(socket.AF_UNIX) as sock: + try: + sock.bind(path) + except PermissionError as e: + self.skipTest('bind(): %s' % e) + sock.listen(1) coro = self.loop.create_unix_server(lambda: None, path) srv = self.loop.run_until_complete(coro) @@ -256,7 +265,10 @@ def test_create_unix_server_pathlib(self): with test_utils.unix_socket_path() as path: path = pathlib.Path(path) srv_coro = self.loop.create_unix_server(lambda: None, path) - srv = self.loop.run_until_complete(srv_coro) + try: + srv = self.loop.run_until_complete(srv_coro) + except PermissionError as e: + self.skipTest('run_until_complete(): %s' % e) srv.close() self.loop.run_until_complete(srv.wait_closed()) @@ -307,14 +319,17 @@ def test_create_unix_server_path_stream_bittype(self): fn = file.name try: with sock: - sock.bind(fn) + try: + sock.bind(fn) + except PermissionError as e: + self.skipTest('bind(): %s' % e) coro = self.loop.create_unix_server(lambda: None, path=None, sock=sock) srv = self.loop.run_until_complete(coro) srv.close() self.loop.run_until_complete(srv.wait_closed()) finally: - os.unlink(fn) + unlink(fn) def test_create_unix_connection_path_inetsock(self): sock = socket.socket() diff --git a/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst b/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst new file mode 100644 index 000000000000000..952d1897c557698 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst @@ -0,0 +1,2 @@ +The asyncio tests now handle PermissionError raised when binding a unix +socket. From b5073f5bc0e23ce36d208a5316b4c43c1d226a9d Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Fri, 24 Nov 2017 14:05:38 +0100 Subject: [PATCH 2/5] Use instead a new skip_unless_bind_unix_socket() decorator 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). --- Lib/asyncio/test_utils.py | 9 ++--- Lib/test/support/__init__.py | 21 ++++++++++++ Lib/test/test_asyncio/test_events.py | 13 +++++--- Lib/test/test_asyncio/test_streams.py | 12 ++++--- Lib/test/test_asyncio/test_unix_events.py | 33 +++++++------------ .../2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst | 7 ++-- 6 files changed, 56 insertions(+), 39 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index 383dd134aa9490e..c3ddfe37563a6a4 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -220,12 +220,9 @@ def unix_socket_path(): @contextlib.contextmanager def run_test_unix_server(*, use_ssl=False): with unix_socket_path() as path: - try: - yield from _run_test_server(address=path, use_ssl=use_ssl, - server_cls=SilentUnixWSGIServer, - server_ssl_cls=UnixSSLWSGIServer) - except PermissionError as e: - raise unittest.SkipTest('_run_test_server(): %s' % e) + yield from _run_test_server(address=path, use_ssl=use_ssl, + server_cls=SilentUnixWSGIServer, + server_ssl_cls=UnixSSLWSGIServer) @contextlib.contextmanager diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 527cf7fbf95328c..8c49e6d37e1cdbc 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -88,6 +88,7 @@ "requires_IEEE_754", "skip_unless_xattr", "requires_zlib", "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "requires_android_level", "requires_multiprocessing_queue", + "skip_unless_bind_unix_socket", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", "setswitchinterval", @@ -2387,6 +2388,26 @@ def skip_unless_xattr(test): msg = "no non-broken extended attribute support" 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.""" + 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 = '' + 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): """Detects if the file system for the specified directory is case-insensitive.""" diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index bda958d6be26e8a..6dd8563c95c4d3c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -22,6 +22,7 @@ import unittest from unittest import mock import weakref +from test import support if sys.platform != 'win32': import tty @@ -471,6 +472,7 @@ def test_sock_client_ops(self): 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): with test_utils.run_test_unix_server() as httpd: sock = socket.socket(socket.AF_UNIX) @@ -607,6 +609,7 @@ def test_create_connection(self): 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): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -738,6 +741,7 @@ def test_create_ssl_connection(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_create_ssl_unix_connection(self): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -957,14 +961,12 @@ def _make_unix_server(self, factory, **kwargs): self.addCleanup(lambda: os.path.exists(path) and os.unlink(path)) f = self.loop.create_unix_server(factory, path, **kwargs) - try: - server = self.loop.run_until_complete(f) - except PermissionError as e: - self.skipTest('run_until_complete(): %s' % e) + server = self.loop.run_until_complete(f) return server, path @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_create_unix_server(self): proto = MyProto(loop=self.loop) server, path = self._make_unix_server(lambda: proto) @@ -1058,6 +1060,7 @@ def test_create_server_ssl(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1118,6 +1121,7 @@ def test_create_server_ssl_verify_failed(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl_verify_failed(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1176,6 +1180,7 @@ def test_create_server_ssl_match_failed(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl_verified(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 30758b068d020f1..b8851237bb87470 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -9,6 +9,7 @@ import threading import unittest from unittest import mock +from test import support try: import ssl except ImportError: @@ -58,6 +59,7 @@ def test_open_connection(self): 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): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -88,6 +90,7 @@ def test_open_connection_no_loop_ssl(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + @support.skip_unless_bind_unix_socket def test_open_unix_connection_no_loop_ssl(self): with test_utils.run_test_unix_server(use_ssl=True) as httpd: conn_fut = asyncio.open_unix_connection( @@ -114,6 +117,7 @@ def test_open_connection_error(self): 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): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -635,6 +639,7 @@ def client(addr): 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): class MyServer: @@ -652,13 +657,10 @@ def handle_client(self, client_reader, client_writer): client_writer.close() def start(self): - try: - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client, + self.server = self.loop.run_until_complete( + asyncio.start_unix_server(self.handle_client, path=self.path, loop=self.loop)) - except PermissionError as e: - raise unittest.SkipTest('run_until_complete(): %s' % e) def handle_client_callback(self, client_reader, client_writer): self.loop.create_task(self.handle_client(client_reader, diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 85a930c86d92176..37ac198a44ab859 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,17 +13,11 @@ import threading import unittest from unittest import mock +from test import support if sys.platform == 'win32': raise unittest.SkipTest('UNIX only') -try: - from test.support import unlink -except ImportError: - def unlink(fn): - if os.path.exists(fn): - os.unlink(fn) - import asyncio from asyncio import log @@ -246,14 +240,13 @@ def setUp(self): self.loop = asyncio.SelectorEventLoop() self.set_event_loop(self.loop) + @support.skip_unless_bind_unix_socket def test_create_unix_server_existing_path_sock(self): with test_utils.unix_socket_path() as path: - with socket.socket(socket.AF_UNIX) as sock: - try: - sock.bind(path) - except PermissionError as e: - self.skipTest('bind(): %s' % e) - sock.listen(1) + sock = socket.socket(socket.AF_UNIX) + sock.bind(path) + sock.listen(1) + sock.close() coro = self.loop.create_unix_server(lambda: None, path) srv = self.loop.run_until_complete(coro) @@ -261,14 +254,12 @@ def test_create_unix_server_existing_path_sock(self): self.loop.run_until_complete(srv.wait_closed()) @unittest.skipUnless(hasattr(os, 'fspath'), 'no os.fspath') + @support.skip_unless_bind_unix_socket def test_create_unix_server_pathlib(self): with test_utils.unix_socket_path() as path: path = pathlib.Path(path) srv_coro = self.loop.create_unix_server(lambda: None, path) - try: - srv = self.loop.run_until_complete(srv_coro) - except PermissionError as e: - self.skipTest('run_until_complete(): %s' % e) + srv = self.loop.run_until_complete(srv_coro) srv.close() self.loop.run_until_complete(srv.wait_closed()) @@ -312,6 +303,7 @@ def test_create_unix_server_path_dgram(self): @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), 'no socket.SOCK_NONBLOCK (linux only)') + @support.skip_unless_bind_unix_socket def test_create_unix_server_path_stream_bittype(self): sock = socket.socket( socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_NONBLOCK) @@ -319,17 +311,14 @@ def test_create_unix_server_path_stream_bittype(self): fn = file.name try: with sock: - try: - sock.bind(fn) - except PermissionError as e: - self.skipTest('bind(): %s' % e) + sock.bind(fn) coro = self.loop.create_unix_server(lambda: None, path=None, sock=sock) srv = self.loop.run_until_complete(coro) srv.close() self.loop.run_until_complete(srv.wait_closed()) finally: - unlink(fn) + os.unlink(fn) def test_create_unix_connection_path_inetsock(self): sock = socket.socket() diff --git a/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst b/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst index 952d1897c557698..9d8e4da822f3773 100644 --- a/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst +++ b/Misc/NEWS.d/next/Library/2017-11-22-12-54-46.bpo-28684.NLiDKZ.rst @@ -1,2 +1,5 @@ -The asyncio tests now handle PermissionError raised when binding a unix -socket. +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). + From 62e26d412fca46e4b11a1b84cea5cf1be03f0a0c Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Fri, 24 Nov 2017 15:19:53 +0100 Subject: [PATCH 3/5] The decorator must be applied last --- Lib/test/test_asyncio/test_events.py | 14 +++++++------- Lib/test/test_asyncio/test_streams.py | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 6dd8563c95c4d3c..2a1a416a8cee894 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -471,8 +471,8 @@ def test_sock_client_ops(self): sock = socket.socket() self._basetest_sock_recv_into(httpd, sock) - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_unix_sock_client_ops(self): with test_utils.run_test_unix_server() as httpd: sock = socket.socket(socket.AF_UNIX) @@ -608,8 +608,8 @@ def test_create_connection(self): lambda: MyProto(loop=self.loop), *httpd.address) self._basetest_create_connection(conn_fut) - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_connection(self): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -739,9 +739,9 @@ def test_create_ssl_connection(self): self._test_create_ssl_connection(httpd, create_connection, peername=httpd.address) + @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - @support.skip_unless_bind_unix_socket def test_create_ssl_unix_connection(self): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -965,8 +965,8 @@ def _make_unix_server(self, factory, **kwargs): return server, path - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_server(self): proto = MyProto(loop=self.loop) server, path = self._make_unix_server(lambda: proto) @@ -1058,9 +1058,9 @@ def test_create_server_ssl(self): # stop serving server.close() + @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1119,9 +1119,9 @@ def test_create_server_ssl_verify_failed(self): self.assertIsNone(proto.transport) server.close() + @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl_verify_failed(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1178,9 +1178,9 @@ def test_create_server_ssl_match_failed(self): proto.transport.close() server.close() + @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - @support.skip_unless_bind_unix_socket def test_create_unix_server_ssl_verified(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index b8851237bb87470..4d21638cf1ac59d 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -58,8 +58,8 @@ def test_open_connection(self): loop=self.loop) self._basetest_open_connection(conn_fut) - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_open_unix_connection(self): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -88,9 +88,9 @@ def test_open_connection_no_loop_ssl(self): self._basetest_open_connection_no_loop_ssl(conn_fut) + @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - @support.skip_unless_bind_unix_socket def test_open_unix_connection_no_loop_ssl(self): with test_utils.run_test_unix_server(use_ssl=True) as httpd: conn_fut = asyncio.open_unix_connection( @@ -116,8 +116,8 @@ def test_open_connection_error(self): loop=self.loop) self._basetest_open_connection_error(conn_fut) - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_open_unix_connection_error(self): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -638,8 +638,8 @@ def client(addr): server.stop() self.assertEqual(msg, b"hello world!\n") - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') @support.skip_unless_bind_unix_socket + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_start_unix_server(self): class MyServer: From b58c5abee3693a657ce2e9612989c40b26b0c63e Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Fri, 24 Nov 2017 16:08:30 +0100 Subject: [PATCH 4/5] Only one decorator is needed --- Lib/test/support/__init__.py | 2 ++ Lib/test/test_asyncio/test_events.py | 7 ------- Lib/test/test_asyncio/test_streams.py | 4 ---- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 9d458b931f410a9..9580e7b925805b6 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2436,6 +2436,8 @@ def skip_unless_xattr(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" diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 2a1a416a8cee894..78b30b9b6c32249 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -472,7 +472,6 @@ def test_sock_client_ops(self): self._basetest_sock_recv_into(httpd, sock) @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_unix_sock_client_ops(self): with test_utils.run_test_unix_server() as httpd: sock = socket.socket(socket.AF_UNIX) @@ -609,7 +608,6 @@ def test_create_connection(self): self._basetest_create_connection(conn_fut) @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_connection(self): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -741,7 +739,6 @@ def test_create_ssl_connection(self): @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_ssl_unix_connection(self): # Issue #20682: On Mac OS X Tiger, getsockname() returns a # zero-length address for UNIX socket. @@ -966,7 +963,6 @@ def _make_unix_server(self, factory, **kwargs): return server, path @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_server(self): proto = MyProto(loop=self.loop) server, path = self._make_unix_server(lambda: proto) @@ -1060,7 +1056,6 @@ def test_create_server_ssl(self): @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_server_ssl(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1121,7 +1116,6 @@ def test_create_server_ssl_verify_failed(self): @support.skip_unless_bind_unix_socket @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): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1180,7 +1174,6 @@ def test_create_server_ssl_match_failed(self): @support.skip_unless_bind_unix_socket @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): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 4d21638cf1ac59d..a1e5bd7fab6c8e1 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -59,7 +59,6 @@ def test_open_connection(self): self._basetest_open_connection(conn_fut) @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_open_unix_connection(self): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -90,7 +89,6 @@ def test_open_connection_no_loop_ssl(self): @support.skip_unless_bind_unix_socket @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): with test_utils.run_test_unix_server(use_ssl=True) as httpd: conn_fut = asyncio.open_unix_connection( @@ -117,7 +115,6 @@ def test_open_connection_error(self): self._basetest_open_connection_error(conn_fut) @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_open_unix_connection_error(self): with test_utils.run_test_unix_server() as httpd: conn_fut = asyncio.open_unix_connection(httpd.address, @@ -639,7 +636,6 @@ def client(addr): self.assertEqual(msg, b"hello world!\n") @support.skip_unless_bind_unix_socket - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_start_unix_server(self): class MyServer: From 4c3a2246073394edfb31b47e79339bbe0769392a Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Fri, 24 Nov 2017 16:36:06 +0100 Subject: [PATCH 5/5] Set _bind_nix_socket_error to False when no error --- Lib/test/support/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 9580e7b925805b6..e8648964d1e29e1 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2444,7 +2444,7 @@ def skip_unless_bind_unix_socket(test): with socket.socket(socket.AF_UNIX) as sock: try: sock.bind(path) - _bind_nix_socket_error = '' + _bind_nix_socket_error = False except OSError as e: _bind_nix_socket_error = e finally: