From cac747892be07a06d0315917fc72cfd06d10e471 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 13 Feb 2023 17:06:56 +0100 Subject: [PATCH] Fix tests on Windows, add Windows CI (#1186) * fix tests on Windows, add Windows CI * remove test safeguards from coverage --- .github/workflows/ci.yml | 3 +- setup.py | 7 +++-- tests/test_crypto.py | 6 ++-- tests/test_ssl.py | 67 +++++++++++++++++++++++----------------- 4 files changed, 48 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4407e178f..a16af9036 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311"} - {VERSION: "pypy-3.7", TOXENV: "pypy3"} - {VERSION: "pypy-3.8", TOXENV: "pypy3"} + - {VERSION: "3.11", TOXENV: "py311-useWheel", OS: "windows-2022" } # -cryptographyMain - {VERSION: "3.6", TOXENV: "py36-cryptographyMain", OS: "ubuntu-20.04"} - {VERSION: "3.7", TOXENV: "py37-cryptographyMain"} @@ -47,7 +48,7 @@ jobs: - {VERSION: "3.9", TOXENV: "flake8"} - {VERSION: "3.6", TOXENV: "py36-mypy", OS: "ubuntu-20.04"} - {VERSION: "3.9", TOXENV: "docs"} - name: "${{ matrix.PYTHON.TOXENV }}" + name: "${{ matrix.PYTHON.TOXENV }}${{ matrix.PYTHON.OS && format(' on {0}', matrix.PYTHON.OS) || '' }}" steps: - uses: actions/checkout@v3 - name: Setup python diff --git a/setup.py b/setup.py index 3b01f4388..0ccbbbdf0 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,6 @@ Installation script for the OpenSSL package. """ -import codecs import os import re @@ -21,10 +20,12 @@ def read_file(*parts): """ - Build an absolute path from *parts* and and return the contents of the + Build an absolute path from *parts* and return the contents of the resulting file. Assume UTF-8 encoding. """ - with codecs.open(os.path.join(HERE, *parts), "rb", "ascii") as f: + with open( + os.path.join(HERE, *parts), "r", encoding="utf-8", newline=None + ) as f: return f.read() diff --git a/tests/test_crypto.py b/tests/test_crypto.py index 44bbd0f2a..4b63fa2c0 100644 --- a/tests/test_crypto.py +++ b/tests/test_crypto.py @@ -2524,7 +2524,7 @@ def check_recovery( b"-passin", b"pass:" + passwd, *extra, - ) + ).replace(b"\r\n", b"\n") assert recovered_key[-len(key) :] == key if cert: recovered_cert = _runopenssl( @@ -2536,7 +2536,7 @@ def check_recovery( b"pass:" + passwd, b"-nokeys", *extra, - ) + ).replace(b"\r\n", b"\n") assert recovered_cert[-len(cert) :] == cert if ca: recovered_cert = _runopenssl( @@ -2548,7 +2548,7 @@ def check_recovery( b"pass:" + passwd, b"-nokeys", *extra, - ) + ).replace(b"\r\n", b"\n") assert recovered_cert[-len(ca) :] == ca def verify_pkcs12_container(self, p12): diff --git a/tests/test_ssl.py b/tests/test_ssl.py index e6c0cdca6..024436f06 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -1140,23 +1140,30 @@ def _load_verify_directory_locations_capath(self, capath): self._load_verify_locations_test(None, capath) - def test_load_verify_directory_bytes_capath(self, tmpfile): + @pytest.mark.parametrize( + "pathtype", + [ + "ascii_path", + pytest.param( + "unicode_path", + marks=pytest.mark.skipif( + platform == "win32", + reason="Unicode paths not supported on Windows", + ), + ), + ], + ) + @pytest.mark.parametrize("argtype", ["bytes_arg", "unicode_arg"]) + def test_load_verify_directory_capath(self, pathtype, argtype, tmpfile): """ `Context.load_verify_locations` accepts a directory name as a `bytes` instance and uses the certificates within for verification purposes. """ - self._load_verify_directory_locations_capath( - tmpfile + NON_ASCII.encode(getfilesystemencoding()) - ) - - def test_load_verify_directory_unicode_capath(self, tmpfile): - """ - `Context.load_verify_locations` accepts a directory name as a `unicode` - instance and uses the certificates within for verification purposes. - """ - self._load_verify_directory_locations_capath( - tmpfile.decode(getfilesystemencoding()) + NON_ASCII - ) + if pathtype == "unicode_path": + tmpfile += NON_ASCII.encode(getfilesystemencoding()) + if argtype == "unicode_arg": + tmpfile = tmpfile.decode(getfilesystemencoding()) + self._load_verify_directory_locations_capath(tmpfile) def test_load_verify_locations_wrong_args(self): """ @@ -2838,23 +2845,24 @@ def test_wantWriteError(self): """ client_socket, server_socket = socket_pair() # Fill up the client's send buffer so Connection won't be able to write - # anything. Only write a single byte at a time so we can be sure we + # anything. Start by sending larger chunks (Windows Socket I/O is slow) + # and continue by writing a single byte at a time so we can be sure we # completely fill the buffer. Even though the socket API is allowed to # signal a short write via its return value it seems this doesn't # always happen on all platforms (FreeBSD and OS X particular) for the # very last bit of available buffer space. - msg = b"x" - for i in range(1024 * 1024 * 64): - try: - client_socket.send(msg) - except error as e: - if e.errno == EWOULDBLOCK: - break - raise - else: - pytest.fail( - "Failed to fill socket buffer, cannot test BIO want write" - ) + for msg in [b"x" * 65536, b"x"]: + for i in range(1024 * 1024 * 64): + try: + client_socket.send(msg) + except error as e: + if e.errno == EWOULDBLOCK: + break + raise # pragma: no cover + else: # pragma: no cover + pytest.fail( + "Failed to fill socket buffer, cannot test BIO want write" + ) ctx = Context(SSLv23_METHOD) conn = Connection(ctx, client_socket) @@ -3753,13 +3761,16 @@ def test_unexpected_EOF(self): """ If the connection is lost before an orderly SSL shutdown occurs, `OpenSSL.SSL.SysCallError` is raised with a message of - "Unexpected EOF". + "Unexpected EOF" (or WSAECONNRESET on Windows). """ server_conn, client_conn = loopback() client_conn.sock_shutdown(SHUT_RDWR) with pytest.raises(SysCallError) as err: server_conn.recv(1024) - assert err.value.args == (-1, "Unexpected EOF") + if platform == "win32": + assert err.value.args == (10054, "WSAECONNRESET") + else: + assert err.value.args == (-1, "Unexpected EOF") def _check_client_ca_list(self, func): """