# # Copyright 2015 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for http_wrapper.""" import socket import unittest import httplib2 from six.moves import http_client from mock import patch from apitools.base.py import exceptions from apitools.base.py import http_wrapper # pylint: disable=ungrouped-imports try: from oauth2client.client import HttpAccessTokenRefreshError from oauth2client.client import AccessTokenRefreshError _TOKEN_REFRESH_STATUS_AVAILABLE = True except ImportError: from oauth2client.client import AccessTokenRefreshError _TOKEN_REFRESH_STATUS_AVAILABLE = False class _MockHttpRequest(object): url = None class _MockHttpResponse(object): def __init__(self, status_code): self.response = {'status': status_code} class RaisesExceptionOnLen(object): """Supports length property but raises if __len__ is used.""" def __len__(self): raise Exception('len() called unnecessarily') def length(self): return 1 class HttpWrapperTest(unittest.TestCase): def testRequestBodyUsesLengthProperty(self): http_wrapper.Request(body=RaisesExceptionOnLen()) def testRequestBodyWithLen(self): http_wrapper.Request(body='burrito') @unittest.skipIf(not _TOKEN_REFRESH_STATUS_AVAILABLE, 'oauth2client<1.5 lacks HttpAccessTokenRefreshError.') def testExceptionHandlerHttpAccessTokenError(self): exception_arg = HttpAccessTokenRefreshError(status=503) retry_args = http_wrapper.ExceptionRetryArgs( http={'connections': {}}, http_request=_MockHttpRequest(), exc=exception_arg, num_retries=0, max_retry_wait=0, total_wait_sec=0) # Disable time.sleep for this handler as it is called with # a minimum value of 1 second. with patch('time.sleep', return_value=None): http_wrapper.HandleExceptionsAndRebuildHttpConnections( retry_args) @unittest.skipIf(not _TOKEN_REFRESH_STATUS_AVAILABLE, 'oauth2client<1.5 lacks HttpAccessTokenRefreshError.') def testExceptionHandlerHttpAccessTokenErrorRaises(self): exception_arg = HttpAccessTokenRefreshError(status=200) retry_args = http_wrapper.ExceptionRetryArgs( http={'connections': {}}, http_request=_MockHttpRequest(), exc=exception_arg, num_retries=0, max_retry_wait=0, total_wait_sec=0) # Disable time.sleep for this handler as it is called with # a minimum value of 1 second. with self.assertRaises(HttpAccessTokenRefreshError): with patch('time.sleep', return_value=None): http_wrapper.HandleExceptionsAndRebuildHttpConnections( retry_args) def testExceptionHandlerAccessTokenErrorRaises(self): exception_arg = AccessTokenRefreshError() retry_args = http_wrapper.ExceptionRetryArgs( http={'connections': {}}, http_request=_MockHttpRequest(), exc=exception_arg, num_retries=0, max_retry_wait=0, total_wait_sec=0) # Disable time.sleep for this handler as it is called with # a minimum value of 1 second. with self.assertRaises(AccessTokenRefreshError): with patch('time.sleep', return_value=None): http_wrapper.HandleExceptionsAndRebuildHttpConnections( retry_args) def testDefaultExceptionHandler(self): """Ensures exception handles swallows (retries)""" mock_http_content = 'content'.encode('utf8') for exception_arg in ( http_client.BadStatusLine('line'), http_client.IncompleteRead('partial'), http_client.ResponseNotReady(), socket.error(), socket.gaierror(), httplib2.ServerNotFoundError(), ValueError(), exceptions.RequestError(), exceptions.BadStatusCodeError( {'status': 503}, mock_http_content, 'url'), exceptions.RetryAfterError( {'status': 429}, mock_http_content, 'url', 0)): retry_args = http_wrapper.ExceptionRetryArgs( http={'connections': {}}, http_request=_MockHttpRequest(), exc=exception_arg, num_retries=0, max_retry_wait=0, total_wait_sec=0) # Disable time.sleep for this handler as it is called with # a minimum value of 1 second. with patch('time.sleep', return_value=None): http_wrapper.HandleExceptionsAndRebuildHttpConnections( retry_args)