summaryrefslogtreecommitdiffstats
path: root/Lib/test/support/hashlib_helper.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/support/hashlib_helper.py')
-rw-r--r--Lib/test/support/hashlib_helper.py92
1 files changed, 65 insertions, 27 deletions
diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py
index 477e0f1..bed3d69 100644
--- a/Lib/test/support/hashlib_helper.py
+++ b/Lib/test/support/hashlib_helper.py
@@ -1,6 +1,7 @@
import functools
import hashlib
import unittest
+from test.support.import_helper import import_module
try:
import _hashlib
@@ -12,44 +13,81 @@ def requires_hashlib():
return unittest.skipIf(_hashlib is None, "requires _hashlib")
+def _decorate_func_or_class(func_or_class, decorator_func):
+ if not isinstance(func_or_class, type):
+ return decorator_func(func_or_class)
+
+ decorated_class = func_or_class
+ setUpClass = decorated_class.__dict__.get('setUpClass')
+ if setUpClass is None:
+ def setUpClass(cls):
+ super(decorated_class, cls).setUpClass()
+ setUpClass.__qualname__ = decorated_class.__qualname__ + '.setUpClass'
+ setUpClass.__module__ = decorated_class.__module__
+ else:
+ setUpClass = setUpClass.__func__
+ setUpClass = classmethod(decorator_func(setUpClass))
+ decorated_class.setUpClass = setUpClass
+ return decorated_class
+
+
def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
- """Decorator raising SkipTest if a hashing algorithm is not available
+ """Decorator raising SkipTest if a hashing algorithm is not available.
- The hashing algorithm could be missing or blocked by a strict crypto
- policy.
+ The hashing algorithm may be missing, blocked by a strict crypto policy,
+ or Python may be configured with `--with-builtin-hashlib-hashes=no`.
If 'openssl' is True, then the decorator checks that OpenSSL provides
- the algorithm. Otherwise the check falls back to built-in
- implementations. The usedforsecurity flag is passed to the constructor.
+ the algorithm. Otherwise the check falls back to (optional) built-in
+ HACL* implementations.
+
+ The usedforsecurity flag is passed to the constructor but has no effect
+ on HACL* implementations.
+ Examples of exceptions being suppressed:
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
ValueError: unsupported hash type md4
"""
+ if openssl and _hashlib is not None:
+ def test_availability():
+ _hashlib.new(digestname, usedforsecurity=usedforsecurity)
+ else:
+ def test_availability():
+ hashlib.new(digestname, usedforsecurity=usedforsecurity)
+
+ def decorator_func(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ test_availability()
+ except ValueError as exc:
+ msg = f"missing hash algorithm: {digestname!r}"
+ raise unittest.SkipTest(msg) from exc
+ return func(*args, **kwargs)
+ return wrapper
+
def decorator(func_or_class):
- if isinstance(func_or_class, type):
- setUpClass = func_or_class.__dict__.get('setUpClass')
- if setUpClass is None:
- def setUpClass(cls):
- super(func_or_class, cls).setUpClass()
- setUpClass.__qualname__ = func_or_class.__qualname__ + '.setUpClass'
- setUpClass.__module__ = func_or_class.__module__
- else:
- setUpClass = setUpClass.__func__
- setUpClass = classmethod(decorator(setUpClass))
- func_or_class.setUpClass = setUpClass
- return func_or_class
-
- @functools.wraps(func_or_class)
+ return _decorate_func_or_class(func_or_class, decorator_func)
+ return decorator
+
+
+def requires_openssl_hashdigest(digestname, *, usedforsecurity=True):
+ """Decorator raising SkipTest if an OpenSSL hashing algorithm is missing.
+
+ The hashing algorithm may be missing or blocked by a strict crypto policy.
+ """
+ def decorator_func(func):
+ @requires_hashlib()
+ @functools.wraps(func)
def wrapper(*args, **kwargs):
try:
- if openssl and _hashlib is not None:
- _hashlib.new(digestname, usedforsecurity=usedforsecurity)
- else:
- hashlib.new(digestname, usedforsecurity=usedforsecurity)
+ _hashlib.new(digestname, usedforsecurity=usedforsecurity)
except ValueError:
- raise unittest.SkipTest(
- f"hash digest {digestname!r} is not available."
- )
- return func_or_class(*args, **kwargs)
+ msg = f"missing OpenSSL hash algorithm: {digestname!r}"
+ raise unittest.SkipTest(msg)
+ return func(*args, **kwargs)
return wrapper
+
+ def decorator(func_or_class):
+ return _decorate_func_or_class(func_or_class, decorator_func)
return decorator