mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-40275: Move requires_hashdigest() to test.support.hashlib_helper (GH-19716)
Add a new test.support.hashlib_helper submodule.
This commit is contained in:
parent
2208134918
commit
66abe98a81
9 changed files with 71 additions and 68 deletions
|
@ -11,7 +11,6 @@ import fnmatch
|
||||||
import functools
|
import functools
|
||||||
import gc
|
import gc
|
||||||
import glob
|
import glob
|
||||||
import hashlib
|
|
||||||
import importlib
|
import importlib
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import locale
|
import locale
|
||||||
|
@ -59,11 +58,6 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
resource = None
|
resource = None
|
||||||
|
|
||||||
try:
|
|
||||||
import _hashlib
|
|
||||||
except ImportError:
|
|
||||||
_hashlib = None
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# globals
|
# globals
|
||||||
"PIPE_MAX_SIZE", "verbose", "max_memuse", "use_resources", "failfast",
|
"PIPE_MAX_SIZE", "verbose", "max_memuse", "use_resources", "failfast",
|
||||||
|
@ -81,7 +75,7 @@ __all__ = [
|
||||||
"create_empty_file", "can_symlink", "fs_is_case_insensitive",
|
"create_empty_file", "can_symlink", "fs_is_case_insensitive",
|
||||||
# unittest
|
# unittest
|
||||||
"is_resource_enabled", "requires", "requires_freebsd_version",
|
"is_resource_enabled", "requires", "requires_freebsd_version",
|
||||||
"requires_linux_version", "requires_mac_ver", "requires_hashdigest",
|
"requires_linux_version", "requires_mac_ver",
|
||||||
"check_syntax_error", "check_syntax_warning",
|
"check_syntax_error", "check_syntax_warning",
|
||||||
"TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset",
|
"TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset",
|
||||||
"transient_internet", "BasicTestRunner", "run_unittest", "run_doctest",
|
"transient_internet", "BasicTestRunner", "run_unittest", "run_doctest",
|
||||||
|
@ -685,36 +679,6 @@ def requires_mac_ver(*min_version):
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
|
|
||||||
"""Decorator raising SkipTest if a hashing algorithm is not available
|
|
||||||
|
|
||||||
The hashing algorithm could be missing or blocked by a strict crypto
|
|
||||||
policy.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
|
||||||
ValueError: unsupported hash type md4
|
|
||||||
"""
|
|
||||||
def decorator(func):
|
|
||||||
@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)
|
|
||||||
except ValueError:
|
|
||||||
raise unittest.SkipTest(
|
|
||||||
f"hash digest '{digestname}' is not available."
|
|
||||||
)
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
return wrapper
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
|
|
||||||
def system_must_validate_cert(f):
|
def system_must_validate_cert(f):
|
||||||
"""Skip the test on TLS certificate validation failures."""
|
"""Skip the test on TLS certificate validation failures."""
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
|
|
38
Lib/test/support/hashlib_helper.py
Normal file
38
Lib/test/support/hashlib_helper.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import functools
|
||||||
|
import hashlib
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _hashlib
|
||||||
|
except ImportError:
|
||||||
|
_hashlib = None
|
||||||
|
|
||||||
|
|
||||||
|
def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
|
||||||
|
"""Decorator raising SkipTest if a hashing algorithm is not available
|
||||||
|
|
||||||
|
The hashing algorithm could be missing or blocked by a strict crypto
|
||||||
|
policy.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
||||||
|
ValueError: unsupported hash type md4
|
||||||
|
"""
|
||||||
|
def decorator(func):
|
||||||
|
@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)
|
||||||
|
except ValueError:
|
||||||
|
raise unittest.SkipTest(
|
||||||
|
f"hash digest '{digestname}' is not available."
|
||||||
|
)
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
|
@ -19,7 +19,6 @@ import unittest
|
||||||
import warnings
|
import warnings
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import _4G, bigmemtest, import_fresh_module
|
from test.support import _4G, bigmemtest, import_fresh_module
|
||||||
from test.support import requires_hashdigest
|
|
||||||
from http.client import HTTPException
|
from http.client import HTTPException
|
||||||
|
|
||||||
# Were we compiled --with-pydebug or with #define Py_DEBUG?
|
# Were we compiled --with-pydebug or with #define Py_DEBUG?
|
||||||
|
|
|
@ -6,7 +6,7 @@ import unittest
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from test.support import requires_hashdigest
|
from test.support import hashlib_helper
|
||||||
|
|
||||||
|
|
||||||
def ignore_warning(func):
|
def ignore_warning(func):
|
||||||
|
@ -21,7 +21,7 @@ def ignore_warning(func):
|
||||||
|
|
||||||
class TestVectorsTestCase(unittest.TestCase):
|
class TestVectorsTestCase(unittest.TestCase):
|
||||||
|
|
||||||
@requires_hashdigest('md5', openssl=True)
|
@hashlib_helper.requires_hashdigest('md5', openssl=True)
|
||||||
def test_md5_vectors(self):
|
def test_md5_vectors(self):
|
||||||
# Test the HMAC module against test vectors from the RFC.
|
# Test the HMAC module against test vectors from the RFC.
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||||
b"and Larger Than One Block-Size Data"),
|
b"and Larger Than One Block-Size Data"),
|
||||||
"6f630fad67cda0ee1fb1f562db3aa53e")
|
"6f630fad67cda0ee1fb1f562db3aa53e")
|
||||||
|
|
||||||
@requires_hashdigest('sha1', openssl=True)
|
@hashlib_helper.requires_hashdigest('sha1', openssl=True)
|
||||||
def test_sha_vectors(self):
|
def test_sha_vectors(self):
|
||||||
def shatest(key, data, digest):
|
def shatest(key, data, digest):
|
||||||
h = hmac.HMAC(key, data, digestmod=hashlib.sha1)
|
h = hmac.HMAC(key, data, digestmod=hashlib.sha1)
|
||||||
|
@ -272,23 +272,23 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||||
'134676fb6de0446065c97440fa8c6a58',
|
'134676fb6de0446065c97440fa8c6a58',
|
||||||
})
|
})
|
||||||
|
|
||||||
@requires_hashdigest('sha224', openssl=True)
|
@hashlib_helper.requires_hashdigest('sha224', openssl=True)
|
||||||
def test_sha224_rfc4231(self):
|
def test_sha224_rfc4231(self):
|
||||||
self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64)
|
self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64)
|
||||||
|
|
||||||
@requires_hashdigest('sha256', openssl=True)
|
@hashlib_helper.requires_hashdigest('sha256', openssl=True)
|
||||||
def test_sha256_rfc4231(self):
|
def test_sha256_rfc4231(self):
|
||||||
self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64)
|
self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64)
|
||||||
|
|
||||||
@requires_hashdigest('sha384', openssl=True)
|
@hashlib_helper.requires_hashdigest('sha384', openssl=True)
|
||||||
def test_sha384_rfc4231(self):
|
def test_sha384_rfc4231(self):
|
||||||
self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128)
|
self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128)
|
||||||
|
|
||||||
@requires_hashdigest('sha512', openssl=True)
|
@hashlib_helper.requires_hashdigest('sha512', openssl=True)
|
||||||
def test_sha512_rfc4231(self):
|
def test_sha512_rfc4231(self):
|
||||||
self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
|
self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_legacy_block_size_warnings(self):
|
def test_legacy_block_size_warnings(self):
|
||||||
class MockCrazyHash(object):
|
class MockCrazyHash(object):
|
||||||
"""Ain't no block_size attribute here."""
|
"""Ain't no block_size attribute here."""
|
||||||
|
@ -329,7 +329,7 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
"6c845b47f52b3b47f6590c502db7825aad757bf4fadc8fa972f7cd2e76a5bdeb"
|
"6c845b47f52b3b47f6590c502db7825aad757bf4fadc8fa972f7cd2e76a5bdeb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_normal(self):
|
def test_normal(self):
|
||||||
# Standard constructor call.
|
# Standard constructor call.
|
||||||
try:
|
try:
|
||||||
|
@ -337,21 +337,21 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
except Exception:
|
except Exception:
|
||||||
self.fail("Standard constructor call raised exception.")
|
self.fail("Standard constructor call raised exception.")
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_with_str_key(self):
|
def test_with_str_key(self):
|
||||||
# Pass a key of type str, which is an error, because it expects a key
|
# Pass a key of type str, which is an error, because it expects a key
|
||||||
# of type bytes
|
# of type bytes
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
h = hmac.HMAC("key", digestmod='sha256')
|
h = hmac.HMAC("key", digestmod='sha256')
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_dot_new_with_str_key(self):
|
def test_dot_new_with_str_key(self):
|
||||||
# Pass a key of type str, which is an error, because it expects a key
|
# Pass a key of type str, which is an error, because it expects a key
|
||||||
# of type bytes
|
# of type bytes
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
h = hmac.new("key", digestmod='sha256')
|
h = hmac.new("key", digestmod='sha256')
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_withtext(self):
|
def test_withtext(self):
|
||||||
# Constructor call with text.
|
# Constructor call with text.
|
||||||
try:
|
try:
|
||||||
|
@ -360,7 +360,7 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
self.fail("Constructor call with text argument raised exception.")
|
self.fail("Constructor call with text argument raised exception.")
|
||||||
self.assertEqual(h.hexdigest(), self.expected)
|
self.assertEqual(h.hexdigest(), self.expected)
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_with_bytearray(self):
|
def test_with_bytearray(self):
|
||||||
try:
|
try:
|
||||||
h = hmac.HMAC(bytearray(b"key"), bytearray(b"hash this!"),
|
h = hmac.HMAC(bytearray(b"key"), bytearray(b"hash this!"),
|
||||||
|
@ -369,7 +369,7 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
self.fail("Constructor call with bytearray arguments raised exception.")
|
self.fail("Constructor call with bytearray arguments raised exception.")
|
||||||
self.assertEqual(h.hexdigest(), self.expected)
|
self.assertEqual(h.hexdigest(), self.expected)
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_with_memoryview_msg(self):
|
def test_with_memoryview_msg(self):
|
||||||
try:
|
try:
|
||||||
h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256")
|
h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256")
|
||||||
|
@ -377,7 +377,7 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
self.fail("Constructor call with memoryview msg raised exception.")
|
self.fail("Constructor call with memoryview msg raised exception.")
|
||||||
self.assertEqual(h.hexdigest(), self.expected)
|
self.assertEqual(h.hexdigest(), self.expected)
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_withmodule(self):
|
def test_withmodule(self):
|
||||||
# Constructor call with text and digest module.
|
# Constructor call with text and digest module.
|
||||||
try:
|
try:
|
||||||
|
@ -388,7 +388,7 @@ class ConstructorTestCase(unittest.TestCase):
|
||||||
|
|
||||||
class SanityTestCase(unittest.TestCase):
|
class SanityTestCase(unittest.TestCase):
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_exercise_all_methods(self):
|
def test_exercise_all_methods(self):
|
||||||
# Exercising all methods once.
|
# Exercising all methods once.
|
||||||
# This must not raise any exceptions
|
# This must not raise any exceptions
|
||||||
|
@ -404,7 +404,7 @@ class SanityTestCase(unittest.TestCase):
|
||||||
|
|
||||||
class CopyTestCase(unittest.TestCase):
|
class CopyTestCase(unittest.TestCase):
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_attributes(self):
|
def test_attributes(self):
|
||||||
# Testing if attributes are of same type.
|
# Testing if attributes are of same type.
|
||||||
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
||||||
|
@ -416,7 +416,7 @@ class CopyTestCase(unittest.TestCase):
|
||||||
self.assertEqual(type(h1.outer), type(h2.outer),
|
self.assertEqual(type(h1.outer), type(h2.outer),
|
||||||
"Types of outer don't match.")
|
"Types of outer don't match.")
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_realcopy(self):
|
def test_realcopy(self):
|
||||||
# Testing if the copy method created a real copy.
|
# Testing if the copy method created a real copy.
|
||||||
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
||||||
|
@ -428,7 +428,7 @@ class CopyTestCase(unittest.TestCase):
|
||||||
self.assertTrue(id(h1.outer) != id(h2.outer),
|
self.assertTrue(id(h1.outer) != id(h2.outer),
|
||||||
"No real copy of the attribute 'outer'.")
|
"No real copy of the attribute 'outer'.")
|
||||||
|
|
||||||
@requires_hashdigest('sha256')
|
@hashlib_helper.requires_hashdigest('sha256')
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
# Testing if the copy has the same digests.
|
# Testing if the copy has the same digests.
|
||||||
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
h1 = hmac.HMAC(b"key", digestmod="sha256")
|
||||||
|
|
|
@ -11,8 +11,8 @@ import threading
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from test.support import (reap_threads, verbose, transient_internet,
|
from test.support import (reap_threads, verbose, transient_internet,
|
||||||
run_with_tz, run_with_locale, cpython_only,
|
run_with_tz, run_with_locale, cpython_only)
|
||||||
requires_hashdigest)
|
from test.support import hashlib_helper
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from datetime import datetime, timezone, timedelta
|
from datetime import datetime, timezone, timedelta
|
||||||
|
@ -385,7 +385,7 @@ class NewIMAPTestsMixin():
|
||||||
self.assertEqual(code, 'OK')
|
self.assertEqual(code, 'OK')
|
||||||
self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
||||||
|
|
||||||
@requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_login_cram_md5_bytes(self):
|
def test_login_cram_md5_bytes(self):
|
||||||
class AuthHandler(SimpleIMAPHandler):
|
class AuthHandler(SimpleIMAPHandler):
|
||||||
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
||||||
|
@ -403,7 +403,7 @@ class NewIMAPTestsMixin():
|
||||||
ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf")
|
ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf")
|
||||||
self.assertEqual(ret, "OK")
|
self.assertEqual(ret, "OK")
|
||||||
|
|
||||||
@requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_login_cram_md5_plain_text(self):
|
def test_login_cram_md5_plain_text(self):
|
||||||
class AuthHandler(SimpleIMAPHandler):
|
class AuthHandler(SimpleIMAPHandler):
|
||||||
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
capabilities = 'LOGINDISABLED AUTH=CRAM-MD5'
|
||||||
|
@ -849,7 +849,7 @@ class ThreadedNetworkedTests(unittest.TestCase):
|
||||||
b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
b'ZmFrZQ==\r\n') # b64 encoded 'fake'
|
||||||
|
|
||||||
@reap_threads
|
@reap_threads
|
||||||
@requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_login_cram_md5(self):
|
def test_login_cram_md5(self):
|
||||||
|
|
||||||
class AuthHandler(SimpleIMAPHandler):
|
class AuthHandler(SimpleIMAPHandler):
|
||||||
|
|
|
@ -13,6 +13,7 @@ import threading
|
||||||
|
|
||||||
from unittest import TestCase, skipUnless
|
from unittest import TestCase, skipUnless
|
||||||
from test import support as test_support
|
from test import support as test_support
|
||||||
|
from test.support import hashlib_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
|
|
||||||
HOST = socket_helper.HOST
|
HOST = socket_helper.HOST
|
||||||
|
@ -311,11 +312,11 @@ class TestPOP3Class(TestCase):
|
||||||
def test_rpop(self):
|
def test_rpop(self):
|
||||||
self.assertOK(self.client.rpop('foo'))
|
self.assertOK(self.client.rpop('foo'))
|
||||||
|
|
||||||
@test_support.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_apop_normal(self):
|
def test_apop_normal(self):
|
||||||
self.assertOK(self.client.apop('foo', 'dummypassword'))
|
self.assertOK(self.client.apop('foo', 'dummypassword'))
|
||||||
|
|
||||||
@test_support.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_apop_REDOS(self):
|
def test_apop_REDOS(self):
|
||||||
# Replace welcome with very long evil welcome.
|
# Replace welcome with very long evil welcome.
|
||||||
# NB The upper bound on welcome length is currently 2048.
|
# NB The upper bound on welcome length is currently 2048.
|
||||||
|
|
|
@ -20,9 +20,9 @@ import threading
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from test import support, mock_socket
|
from test import support, mock_socket
|
||||||
|
from test.support import hashlib_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
from test.support import threading_setup, threading_cleanup, join_thread
|
from test.support import threading_setup, threading_cleanup, join_thread
|
||||||
from test.support import requires_hashdigest
|
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
HOST = socket_helper.HOST
|
HOST = socket_helper.HOST
|
||||||
|
@ -1058,7 +1058,7 @@ class SMTPSimTests(unittest.TestCase):
|
||||||
self.assertEqual(resp, (235, b'Authentication Succeeded'))
|
self.assertEqual(resp, (235, b'Authentication Succeeded'))
|
||||||
smtp.close()
|
smtp.close()
|
||||||
|
|
||||||
@requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def testAUTH_CRAM_MD5(self):
|
def testAUTH_CRAM_MD5(self):
|
||||||
self.serv.add_feature("AUTH CRAM-MD5")
|
self.serv.add_feature("AUTH CRAM-MD5")
|
||||||
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost',
|
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost',
|
||||||
|
|
|
@ -11,7 +11,7 @@ import unittest.mock
|
||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import script_helper, requires_hashdigest
|
from test.support import script_helper
|
||||||
|
|
||||||
# Check for our compression modules.
|
# Check for our compression modules.
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -9,6 +9,7 @@ import unittest
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import hashlib_helper
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ssl
|
import ssl
|
||||||
|
@ -322,7 +323,7 @@ class ProxyAuthTests(unittest.TestCase):
|
||||||
PASSWD = "test123"
|
PASSWD = "test123"
|
||||||
REALM = "TestRealm"
|
REALM = "TestRealm"
|
||||||
|
|
||||||
@support.requires_hashdigest("md5")
|
@hashlib_helper.requires_hashdigest("md5")
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ProxyAuthTests, self).setUp()
|
super(ProxyAuthTests, self).setUp()
|
||||||
# Ignore proxy bypass settings in the environment.
|
# Ignore proxy bypass settings in the environment.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue