diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2012-06-22 19:11:52 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2012-06-22 19:11:52 (GMT) |
commit | 3b36fb1f537a771829c9c7c9720dc040d3c87885 (patch) | |
tree | aaec4c06b55dfb3681c56be22fe1112a79d3c433 /Lib/test/test_ssl.py | |
parent | 31227ca5148436ee3e48430814c59fc31876821d (diff) | |
download | cpython-3b36fb1f537a771829c9c7c9720dc040d3c87885.zip cpython-3b36fb1f537a771829c9c7c9720dc040d3c87885.tar.gz cpython-3b36fb1f537a771829c9c7c9720dc040d3c87885.tar.bz2 |
Issue #14837: SSL errors now have `library` and `reason` attributes describing precisely what happened and in which OpenSSL submodule.
The str() of a SSLError is also enhanced accordingly.
NOTE: this commit creates a reference leak. The leak seems tied to the
use of PyType_FromSpec() to create the SSLError type. The leak is on the
type object when it is instantiated:
>>> e = ssl.SSLError()
>>> sys.getrefcount(ssl.SSLError)
35
>>> e = ssl.SSLError()
>>> sys.getrefcount(ssl.SSLError)
36
>>> e = ssl.SSLError()
>>> sys.getrefcount(ssl.SSLError)
37
Diffstat (limited to 'Lib/test/test_ssl.py')
-rw-r--r-- | Lib/test/test_ssl.py | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index d2839dd..51762cf 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -552,7 +552,7 @@ class ContextTests(unittest.TestCase): with self.assertRaises(FileNotFoundError) as cm: ctx.load_dh_params(WRONGCERT) self.assertEqual(cm.exception.errno, errno.ENOENT) - with self.assertRaisesRegex(ssl.SSLError, "PEM routines"): + with self.assertRaises(ssl.SSLError) as cm: ctx.load_dh_params(CERTFILE) @skip_if_broken_ubuntu_ssl @@ -590,6 +590,47 @@ class ContextTests(unittest.TestCase): self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo") +class SSLErrorTests(unittest.TestCase): + + def test_str(self): + # The str() of a SSLError doesn't include the errno + e = ssl.SSLError(1, "foo") + self.assertEqual(str(e), "foo") + self.assertEqual(e.errno, 1) + # Same for a subclass + e = ssl.SSLZeroReturnError(1, "foo") + self.assertEqual(str(e), "foo") + self.assertEqual(e.errno, 1) + + def test_lib_reason(self): + # Test the library and reason attributes + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + with self.assertRaises(ssl.SSLError) as cm: + ctx.load_dh_params(CERTFILE) + self.assertEqual(cm.exception.library, 'PEM') + self.assertEqual(cm.exception.reason, 'NO_START_LINE') + s = str(cm.exception) + self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s) + + def test_subclass(self): + # Check that the appropriate SSLError subclass is raised + # (this only tests one of them) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + with socket.socket() as s: + s.bind(("127.0.0.1", 0)) + s.listen(5) + with socket.socket() as c: + c.connect(s.getsockname()) + c.setblocking(False) + c = ctx.wrap_socket(c, False, do_handshake_on_connect=False) + with self.assertRaises(ssl.SSLWantReadError) as cm: + c.do_handshake() + s = str(cm.exception) + self.assertTrue(s.startswith("The operation did not complete (read)"), s) + # For compatibility + self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ) + + class NetworkedTests(unittest.TestCase): def test_connect(self): @@ -1931,7 +1972,7 @@ def test_main(verbose=False): if not os.path.exists(filename): raise support.TestFailed("Can't read certificate file %r" % filename) - tests = [ContextTests, BasicSocketTests] + tests = [ContextTests, BasicSocketTests, SSLErrorTests] if support.is_resource_enabled('network'): tests.append(NetworkedTests) |