def test_renew_session(): OLD_SESSION_TOKEN = "old_session_token" OLD_MASTER_TOKEN = "old_master_token" NEW_SESSION_TOKEN = "new_session_token" NEW_MASTER_TOKEN = "new_master_token" connection = MagicMock() connection.errorhandler = Mock(return_value=None) type(connection)._probe_connection = PropertyMock(return_value=False) rest = SnowflakeRestful(host='testaccount.snowflakecomputing.com', port=443, connection=connection) rest._token = OLD_SESSION_TOKEN rest._master_token = OLD_MASTER_TOKEN # inject a fake method (success) def fake_request_exec(**_): return { u'success': True, u'data': { u"sessionToken": NEW_SESSION_TOKEN, u"masterToken": NEW_MASTER_TOKEN } } rest._request_exec = fake_request_exec rest._renew_session() assert not rest._connection.errorhandler.called # no error assert rest.master_token == NEW_MASTER_TOKEN assert rest.token == NEW_SESSION_TOKEN # inject a fake method (failure) def fake_request_exec(**_): return { u'success': False, u'message': "failed to renew session", u'code': 987654 } rest._request_exec = fake_request_exec rest._renew_session() assert rest._connection.errorhandler.called # error # no master token del rest._master_token rest._renew_session() assert rest._connection.errorhandler.called # error
def test_request_exec(): rest = SnowflakeRestful(host="testaccount.snowflakecomputing.com", port=443) default_parameters = { "method": "POST", "full_url": "https://testaccount.snowflakecomputing.com/", "headers": {}, "data": '{"code": 12345}', "token": None, } # request mock output_data = {"success": True, "code": 12345} request_mock = MagicMock() type(request_mock).status_code = PropertyMock(return_value=OK) request_mock.json.return_value = output_data # session mock session = MagicMock() session.request.return_value = request_mock # success ret = rest._request_exec(session=session, **default_parameters) assert ret == output_data, "output data" # retryable exceptions for errcode in [ BAD_REQUEST, # 400 FORBIDDEN, # 403 INTERNAL_SERVER_ERROR, # 500 BAD_GATEWAY, # 502 SERVICE_UNAVAILABLE, # 503 GATEWAY_TIMEOUT, # 504 555, # random 5xx error ]: type(request_mock).status_code = PropertyMock(return_value=errcode) try: rest._request_exec(session=session, **default_parameters) pytest.fail("should fail") except RetryRequest as e: cls = STATUS_TO_EXCEPTION.get(errcode, OtherHTTPRetryableError) assert isinstance(e.args[0], cls), "must be internal error exception" # unauthorized type(request_mock).status_code = PropertyMock(return_value=UNAUTHORIZED) with pytest.raises(InterfaceError): rest._request_exec(session=session, **default_parameters) # unauthorized with catch okta unauthorized error # TODO: what is the difference to InterfaceError? type(request_mock).status_code = PropertyMock(return_value=UNAUTHORIZED) with pytest.raises(DatabaseError): rest._request_exec(session=session, catch_okta_unauthorized_error=True, **default_parameters) class IncompleteReadMock(IncompleteRead): def __init__(self): IncompleteRead.__init__(self, "") # handle retryable exception for exc in [ requests.exceptions.ConnectTimeout, requests.exceptions.ReadTimeout, IncompleteReadMock, urllib3.exceptions.ProtocolError, requests.exceptions.ConnectionError, AttributeError, ]: session = MagicMock() session.request = Mock(side_effect=exc) try: rest._request_exec(session=session, **default_parameters) pytest.fail("should fail") except RetryRequest as e: cause = e.args[0] assert isinstance(cause, exc), "same error class" # handle OpenSSL errors and BadStateLine for exc in [ OpenSSL.SSL.SysCallError(errno.ECONNRESET), OpenSSL.SSL.SysCallError(errno.ETIMEDOUT), OpenSSL.SSL.SysCallError(errno.EPIPE), OpenSSL.SSL.SysCallError(-1), # unknown # TODO: should we keep this? # urllib3.exceptions.ReadTimeoutError(None, None, None), BadStatusLine("fake"), ]: session = MagicMock() session.request = Mock(side_effect=exc) try: rest._request_exec(session=session, **default_parameters) pytest.fail("should fail") except RetryRequest as e: assert e.args[0] == exc, "same error instance"
def test_fetch(): connection = MagicMock() connection.errorhandler = Mock(return_value=None) rest = SnowflakeRestful(host="testaccount.snowflakecomputing.com", port=443, connection=connection) class Cnt: def __init__(self): self.c = 0 def set(self, cnt): self.c = cnt def reset(self): self.set(0) cnt = Cnt() default_parameters = { "method": "POST", "full_url": "https://testaccount.snowflakecomputing.com/", "headers": { "cnt": cnt }, "data": '{"code": 12345}', } NOT_RETRYABLE = 1000 class NotRetryableException(Exception): pass def fake_request_exec(**kwargs): headers = kwargs.get("headers") cnt = headers["cnt"] time.sleep(3) if cnt.c <= 1: # the first two raises failure cnt.c += 1 raise RetryRequest(Exception("can retry")) elif cnt.c == NOT_RETRYABLE: # not retryable exception raise NotRetryableException("cannot retry") else: # return success in the third attempt return {"success": True, "data": "valid data"} # inject a fake method rest._request_exec = fake_request_exec # first two attempts will fail but third will success cnt.reset() ret = rest.fetch(timeout=10, **default_parameters) assert ret == {"success": True, "data": "valid data"} assert not rest._connection.errorhandler.called # no error # first attempt to reach timeout even if the exception is retryable cnt.reset() ret = rest.fetch(timeout=1, **default_parameters) assert ret == {} assert rest._connection.errorhandler.called # error # not retryable excpetion cnt.set(NOT_RETRYABLE) with pytest.raises(NotRetryableException): rest.fetch(timeout=7, **default_parameters) # first attempt fails and will not retry cnt.reset() default_parameters["no_retry"] = True ret = rest.fetch(timeout=10, **default_parameters) assert ret == {} assert cnt.c == 1 # failed on first call - did not retry assert rest._connection.errorhandler.called # error
def test_request_exec(): rest = SnowflakeRestful( host='testaccount.snowflakecomputing.com', port=443) default_parameters = { 'method': "POST", 'full_url': "https://testaccount.snowflakecomputing.com/", 'headers': {}, 'data': '{"code": 12345}', 'proxies': None, 'token': None } # request mock output_data = {'success': True, 'code': 12345} request_mock = MagicMock() type(request_mock).status_code = PropertyMock(return_value=OK) request_mock.json.return_value = output_data # session mock session = MagicMock() session.request.return_value = request_mock # success ret = rest._request_exec(session=session, **default_parameters) assert ret == output_data, 'output data' # retryable exceptions for errcode in [ BAD_REQUEST, # 400 FORBIDDEN, # 403 INTERNAL_SERVER_ERROR, # 500 BAD_GATEWAY, # 502 SERVICE_UNAVAILABLE, # 503 GATEWAY_TIMEOUT, # 504 555, # random 5xx error ]: type(request_mock).status_code = PropertyMock(return_value=errcode) try: rest._request_exec( session=session, **default_parameters) pytest.fail('should fail') except RetryRequest as e: cls = STATUS_TO_EXCEPTION.get( errcode, OtherHTTPRetryableError) assert isinstance( e.args[0], cls), "must be internal error exception" # unauthorized type(request_mock).status_code = PropertyMock(return_value=UNAUTHORIZED) with pytest.raises(InterfaceError): rest._request_exec( session=session, **default_parameters) # unauthorized with catch okta unauthorized error # TODO: what is the difference to InterfaceError? type(request_mock).status_code = PropertyMock(return_value=UNAUTHORIZED) with pytest.raises(DatabaseError): rest._request_exec( session=session, catch_okta_unauthorized_error=True, **default_parameters) # handle retryable exception for exc in [ ConnectTimeout, ReadTimeout, SSLError, ProtocolError, ConnectionError, AttributeError, PyAsn1Error ]: session = MagicMock() session.request = Mock(side_effect=exc) try: rest._request_exec( session=session, **default_parameters) pytest.fail('should fail') except RetryRequest as e: cause = e.args[0] assert isinstance(cause, exc), "same error class" # handle OpenSSL errors and BadStateLine for exc in [ OpenSSL.SSL.SysCallError(errno.ECONNRESET), OpenSSL.SSL.SysCallError(errno.ETIMEDOUT), OpenSSL.SSL.SysCallError(errno.EPIPE), OpenSSL.SSL.SysCallError(-1), # unknown ReadTimeoutError(None, None, None), BadStatusLine('fake') ]: session = MagicMock() session.request = Mock(side_effect=exc) try: rest._request_exec( session=session, **default_parameters) pytest.fail('should fail') except RetryRequest as e: assert e.args[0] == exc, "same error instance"
def test_fetch(): connection = MagicMock() connection.errorhandler = Mock(return_value=None) rest = SnowflakeRestful( host='testaccount.snowflakecomputing.com', port=443, connection=connection) class Cnt(object): def __init__(self): self.c = 0 def set(self, cnt): self.c = cnt def reset(self): self.set(0) cnt = Cnt() default_parameters = { 'method': "POST", 'full_url': "https://testaccount.snowflakecomputing.com/", 'headers': {'cnt': cnt}, 'data': '{"code": 12345}', } NOT_RETRYABLE = 1000 class NotRetryableException(Exception): pass def fake_request_exec(**kwargs): headers = kwargs.get('headers') cnt = headers['cnt'] time.sleep(3) if cnt.c <= 1: # the first two raises failure cnt.c += 1 raise RetryRequest(Exception('can retry')) elif cnt.c == NOT_RETRYABLE: # not retryable exception raise NotRetryableException('cannot retry') else: # return success in the third attempt return {'success': True, 'data': "valid data"} # inject a fake method rest._request_exec = fake_request_exec # first two attempts will fail but third will success cnt.reset() ret = rest.fetch(timeout=10, **default_parameters) assert ret == {'success': True, 'data': "valid data"} assert not rest._connection.errorhandler.called # no error # first attempt to reach timeout even if the exception is retryable cnt.reset() ret = rest.fetch(timeout=1, **default_parameters) assert ret == {} assert rest._connection.errorhandler.called # error # not retryable excpetion cnt.set(NOT_RETRYABLE) with pytest.raises(NotRetryableException): rest.fetch(timeout=7, **default_parameters)