From 17ed58daa9573458157b02f822f5dc471d954298 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Tue, 21 Jan 2014 20:19:17 +0000 Subject: Python implementation of OpenSSL locking callback --- tests/hazmat/bindings/test_openssl.py | 106 ++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'tests') diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index d1e85058..b2264fb5 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -11,6 +11,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import threading +import time + +import pytest + from cryptography.hazmat.bindings.openssl.binding import Binding @@ -23,3 +28,104 @@ class TestOpenSSL(object): def test_is_available(self): assert Binding.is_available() is True + + def test_crypto_lock_init(self): + b = Binding() + b.init_static_locks() + lock_cb = b.lib.CRYPTO_get_locking_callback() + assert lock_cb != b.ffi.NULL + + def test_our_crypto_lock(self, capfd): + b = Binding() + b.init_static_locks() + + # only run this test if we are using our locking cb + original_cb = b.lib.CRYPTO_get_locking_callback() + if original_cb != b._lock_cb_handle: + pytest.skip("Not using Python locking callback implementation") + + # check that the lock state changes appropriately + lock = b._locks[b.lib.CRYPTO_LOCK_SSL] + + assert lock.acquire(False) + + lock.release() + + b.lib.CRYPTO_lock( + b.lib.CRYPTO_LOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, + b.ffi.NULL, + 0 + ) + + assert not lock.acquire(False) + + b.lib.CRYPTO_lock( + b.lib.CRYPTO_UNLOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, + b.ffi.NULL, + 0 + ) + + assert lock.acquire(False) + lock.release() + + # force the error path to run. + + b.lib.CRYPTO_lock( + 0, + b.lib.CRYPTO_LOCK_SSL, + b.ffi.NULL, + 0 + ) + + lock.acquire(False) + lock.release() + + out, err = capfd.readouterr() + assert "RuntimeError: Unknown lock mode" in err + + def test_crypto_lock_mutex(self): + b = Binding() + b.init_static_locks() + + # make sure whatever locking system we end up with actually acts + # like a mutex. + + self._shared_value = 0 + + def critical_loop(): + for i in range(10): + b.lib.CRYPTO_lock( + b.lib.CRYPTO_LOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, + b.ffi.NULL, + 0 + ) + + assert self._shared_value == 0 + self._shared_value += 1 + time.sleep(0.01) + assert self._shared_value == 1 + self._shared_value = 0 + + b.lib.CRYPTO_lock( + b.lib.CRYPTO_UNLOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, + b.ffi.NULL, + 0 + ) + + threads = [] + for x in range(10): + t = threading.Thread(target=critical_loop) + t.daemon = True + t.start() + + threads.append(t) + + while threads: + for t in threads: + t.join(0.1) + if not t.is_alive(): + threads.remove(t) -- cgit v1.2.3 From 06649cf8bcd764c51c9ee819f43a5a0a29290a38 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Wed, 22 Jan 2014 15:07:38 +0000 Subject: Also test the locking cb directly --- tests/hazmat/bindings/test_openssl.py | 39 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'tests') diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index b2264fb5..e5094133 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -47,43 +47,46 @@ class TestOpenSSL(object): # check that the lock state changes appropriately lock = b._locks[b.lib.CRYPTO_LOCK_SSL] + # starts out unlocked assert lock.acquire(False) - lock.release() b.lib.CRYPTO_lock( b.lib.CRYPTO_LOCK | b.lib.CRYPTO_READ, - b.lib.CRYPTO_LOCK_SSL, - b.ffi.NULL, - 0 + b.lib.CRYPTO_LOCK_SSL, b.ffi.NULL, 0 ) + # becomes locked assert not lock.acquire(False) b.lib.CRYPTO_lock( b.lib.CRYPTO_UNLOCK | b.lib.CRYPTO_READ, - b.lib.CRYPTO_LOCK_SSL, - b.ffi.NULL, - 0 + b.lib.CRYPTO_LOCK_SSL, b.ffi.NULL, 0 ) + # then unlocked assert lock.acquire(False) lock.release() - # force the error path to run. + # then test directly - b.lib.CRYPTO_lock( - 0, - b.lib.CRYPTO_LOCK_SSL, - b.ffi.NULL, - 0 - ) + with pytest.raises(RuntimeError): + b._lock_cb(0, b.lib.CRYPTO_LOCK_SSL, "", 1) - lock.acquire(False) + # errors shouldnt cause locking + assert lock.acquire(False) lock.release() - out, err = capfd.readouterr() - assert "RuntimeError: Unknown lock mode" in err + b._lock_cb(b.lib.CRYPTO_LOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, "", 1) + # locked + assert not lock.acquire(False) + + b._lock_cb(b.lib.CRYPTO_UNLOCK | b.lib.CRYPTO_READ, + b.lib.CRYPTO_LOCK_SSL, "", 1) + # unlocked + assert lock.acquire(False) + lock.release() def test_crypto_lock_mutex(self): b = Binding() @@ -119,9 +122,7 @@ class TestOpenSSL(object): threads = [] for x in range(10): t = threading.Thread(target=critical_loop) - t.daemon = True t.start() - threads.append(t) while threads: -- cgit v1.2.3 From 7ce51f26bb10dc56483a5f0e9639092ccb2f9d5c Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Thu, 23 Jan 2014 20:43:49 +0000 Subject: Split a test in half --- tests/hazmat/bindings/test_openssl.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index e5094133..43a07760 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -35,14 +35,20 @@ class TestOpenSSL(object): lock_cb = b.lib.CRYPTO_get_locking_callback() assert lock_cb != b.ffi.NULL - def test_our_crypto_lock(self, capfd): - b = Binding() - b.init_static_locks() - + def _skip_if_not_fallback_lock(self, b): # only run this test if we are using our locking cb original_cb = b.lib.CRYPTO_get_locking_callback() if original_cb != b._lock_cb_handle: - pytest.skip("Not using Python locking callback implementation") + pytest.skip( + "Not using the fallback Python locking callback " + "implementation. Probably because import _ssl set one" + ) + + def test_fallback_crypto_lock_via_openssl_api(self): + b = Binding() + b.init_static_locks() + + self._skip_if_not_fallback_lock(b) # check that the lock state changes appropriately lock = b._locks[b.lib.CRYPTO_LOCK_SSL] @@ -68,7 +74,13 @@ class TestOpenSSL(object): assert lock.acquire(False) lock.release() - # then test directly + def test_fallback_crypto_lock_via_binding_api(self): + b = Binding() + b.init_static_locks() + + self._skip_if_not_fallback_lock(b) + + lock = b._locks[b.lib.CRYPTO_LOCK_SSL] with pytest.raises(RuntimeError): b._lock_cb(0, b.lib.CRYPTO_LOCK_SSL, "", 1) -- cgit v1.2.3 From 29446cd8315985680fd2af0d0137c3d1c4c2a4a1 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Fri, 24 Jan 2014 19:04:01 +0000 Subject: Remove the contenious test of contention --- tests/hazmat/bindings/test_openssl.py | 46 ----------------------------------- 1 file changed, 46 deletions(-) (limited to 'tests') diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 43a07760..35eb7e8d 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -11,9 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import threading -import time - import pytest from cryptography.hazmat.bindings.openssl.binding import Binding @@ -99,46 +96,3 @@ class TestOpenSSL(object): # unlocked assert lock.acquire(False) lock.release() - - def test_crypto_lock_mutex(self): - b = Binding() - b.init_static_locks() - - # make sure whatever locking system we end up with actually acts - # like a mutex. - - self._shared_value = 0 - - def critical_loop(): - for i in range(10): - b.lib.CRYPTO_lock( - b.lib.CRYPTO_LOCK | b.lib.CRYPTO_READ, - b.lib.CRYPTO_LOCK_SSL, - b.ffi.NULL, - 0 - ) - - assert self._shared_value == 0 - self._shared_value += 1 - time.sleep(0.01) - assert self._shared_value == 1 - self._shared_value = 0 - - b.lib.CRYPTO_lock( - b.lib.CRYPTO_UNLOCK | b.lib.CRYPTO_READ, - b.lib.CRYPTO_LOCK_SSL, - b.ffi.NULL, - 0 - ) - - threads = [] - for x in range(10): - t = threading.Thread(target=critical_loop) - t.start() - threads.append(t) - - while threads: - for t in threads: - t.join(0.1) - if not t.is_alive(): - threads.remove(t) -- cgit v1.2.3