|
18 | 18 | import aiohttp |
19 | 19 | import OpenSSL.SSL |
20 | 20 | import pytest |
| 21 | +from aiohttp import ClientSSLError |
21 | 22 |
|
22 | 23 | import snowflake.connector.aio |
23 | 24 | from snowflake.connector.aio._network import SnowflakeRestful |
|
41 | 42 | ServiceUnavailableError, |
42 | 43 | ) |
43 | 44 | from snowflake.connector.network import STATUS_TO_EXCEPTION, RetryRequest |
| 45 | +from snowflake.connector.vendored.requests.exceptions import SSLError |
44 | 46 |
|
45 | 47 | pytestmark = pytest.mark.skipolddriver |
46 | 48 |
|
@@ -454,3 +456,60 @@ async def test_retry_request_timeout(mockSessionRequest, next_action_result): |
454 | 456 | # 13 seconds should be enough for authenticator to attempt thrice |
455 | 457 | # however, loosen restrictions to avoid thread scheduling causing failure |
456 | 458 | assert 1 < mockSessionRequest.call_count < 5 |
| 459 | + |
| 460 | + |
| 461 | +async def test_sslerror_with_econnreset_retries(): |
| 462 | + """Test that SSLError with ECONNRESET raises RetryRequest.""" |
| 463 | + connection = mock_connection() |
| 464 | + connection.errorhandler = Error.default_errorhandler |
| 465 | + rest = SnowflakeRestful( |
| 466 | + host="testaccount.snowflakecomputing.com", |
| 467 | + port=443, |
| 468 | + connection=connection, |
| 469 | + ) |
| 470 | + |
| 471 | + default_parameters = { |
| 472 | + "method": "POST", |
| 473 | + "full_url": "https://testaccount.snowflakecomputing.com/", |
| 474 | + "headers": {}, |
| 475 | + "data": '{"code": 12345}', |
| 476 | + "token": None, |
| 477 | + } |
| 478 | + |
| 479 | + # Test SSLError with ECONNRESET in the message |
| 480 | + econnreset_ssl_error = ClientSSLError( |
| 481 | + MagicMock(), SSLError("Connection broken: ECONNRESET") |
| 482 | + ) |
| 483 | + session = MagicMock() |
| 484 | + session.request = Mock(side_effect=econnreset_ssl_error) |
| 485 | + |
| 486 | + with pytest.raises(RetryRequest, match="Connection broken: ECONNRESET"): |
| 487 | + await rest._request_exec(session=session, **default_parameters) |
| 488 | + |
| 489 | + |
| 490 | +async def test_sslerror_without_econnreset_does_not_retry(): |
| 491 | + """Test that SSLError without ECONNRESET does not retry but raises OperationalError.""" |
| 492 | + connection = mock_connection() |
| 493 | + connection.errorhandler = Error.default_errorhandler |
| 494 | + rest = SnowflakeRestful( |
| 495 | + host="testaccount.snowflakecomputing.com", |
| 496 | + port=443, |
| 497 | + connection=connection, |
| 498 | + ) |
| 499 | + |
| 500 | + default_parameters = { |
| 501 | + "method": "POST", |
| 502 | + "full_url": "https://testaccount.snowflakecomputing.com/", |
| 503 | + "headers": {}, |
| 504 | + "data": '{"code": 12345}', |
| 505 | + "token": None, |
| 506 | + } |
| 507 | + |
| 508 | + # Test SSLError without ECONNRESET in the message |
| 509 | + regular_ssl_error = SSLError("SSL handshake failed") |
| 510 | + session = MagicMock() |
| 511 | + session.request = Mock(side_effect=regular_ssl_error) |
| 512 | + |
| 513 | + # This should raise OperationalError, not RetryRequest |
| 514 | + with pytest.raises(OperationalError): |
| 515 | + await rest._request_exec(session=session, **default_parameters) |
0 commit comments