Removes usage of httplib2 in unit tests.

The only remaining unit test module utilizing httplib2
is test_transport since it utilizes httplib2 directly
at the moment.
This commit is contained in:
Danny Hermes
2016-08-02 15:51:12 -07:00
parent cd825cc561
commit 256d48dab8
7 changed files with 218 additions and 234 deletions

View File

@@ -31,7 +31,6 @@ from google.appengine.api.memcache import memcache_stub
from google.appengine.ext import db from google.appengine.ext import db
from google.appengine.ext import ndb from google.appengine.ext import ndb
from google.appengine.ext import testbed from google.appengine.ext import testbed
import httplib2
import mock import mock
from six.moves import urllib from six.moves import urllib
import unittest2 import unittest2
@@ -42,11 +41,19 @@ import oauth2client
from oauth2client import client from oauth2client import client
from oauth2client import clientsecrets from oauth2client import clientsecrets
from oauth2client.contrib import appengine from oauth2client.contrib import appengine
from ..http_mock import CacheMock from .. import http_mock
__author__ = 'jcgregorio@google.com (Joe Gregorio)' __author__ = 'jcgregorio@google.com (Joe Gregorio)'
DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data') DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data')
DEFAULT_RESP = """\
{
"access_token": "foo_access_token",
"expires_in": 3600,
"extra": "value",
"refresh_token": "foo_refresh_token"
}
"""
def datafile(filename): def datafile(filename):
@@ -75,22 +82,6 @@ class UserNotLoggedInMock(object):
return None return None
class Http2Mock(object):
"""Mock httplib2.Http"""
status = 200
content = {
'access_token': 'foo_access_token',
'refresh_token': 'foo_refresh_token',
'expires_in': 3600,
'extra': 'value',
}
def request(self, token_uri, method, body, headers, *args, **kwargs):
self.body = body
self.headers = headers
return self, json.dumps(self.content)
class TestAppAssertionCredentials(unittest2.TestCase): class TestAppAssertionCredentials(unittest2.TestCase):
account_name = "service_account_name@appspot.com" account_name = "service_account_name@appspot.com"
signature = "signature" signature = "signature"
@@ -139,7 +130,7 @@ class TestAppAssertionCredentials(unittest2.TestCase):
scope = 'http://www.googleapis.com/scope' scope = 'http://www.googleapis.com/scope'
credentials = appengine.AppAssertionCredentials(scope) credentials = appengine.AppAssertionCredentials(scope)
http = httplib2.Http() http = http_mock.HttpMock(data=DEFAULT_RESP)
with self.assertRaises(client.AccessTokenRefreshError): with self.assertRaises(client.AccessTokenRefreshError):
credentials.refresh(http) credentials.refresh(http)
@@ -155,7 +146,7 @@ class TestAppAssertionCredentials(unittest2.TestCase):
"http://www.googleapis.com/scope", "http://www.googleapis.com/scope",
"http://www.googleapis.com/scope2"] "http://www.googleapis.com/scope2"]
credentials = appengine.AppAssertionCredentials(scope) credentials = appengine.AppAssertionCredentials(scope)
http = httplib2.Http() http = http_mock.HttpMock(data=DEFAULT_RESP)
credentials.refresh(http) credentials.refresh(http)
self.assertEqual('a_token_123', credentials.access_token) self.assertEqual('a_token_123', credentials.access_token)
@@ -168,7 +159,7 @@ class TestAppAssertionCredentials(unittest2.TestCase):
scope = ('http://www.googleapis.com/scope ' scope = ('http://www.googleapis.com/scope '
'http://www.googleapis.com/scope2') 'http://www.googleapis.com/scope2')
credentials = appengine.AppAssertionCredentials(scope) credentials = appengine.AppAssertionCredentials(scope)
http = httplib2.Http() http = http_mock.HttpMock(data=DEFAULT_RESP)
credentials.refresh(http) credentials.refresh(http)
self.assertEqual('a_token_123', credentials.access_token) self.assertEqual('a_token_123', credentials.access_token)
self.assertEqual( self.assertEqual(
@@ -184,7 +175,7 @@ class TestAppAssertionCredentials(unittest2.TestCase):
autospec=True) as get_access_token: autospec=True) as get_access_token:
credentials = appengine.AppAssertionCredentials( credentials = appengine.AppAssertionCredentials(
scope, service_account_id=account_id) scope, service_account_id=account_id)
http = httplib2.Http() http = http_mock.HttpMock(data=DEFAULT_RESP)
credentials.refresh(http) credentials.refresh(http)
self.assertEqual('a_token_456', credentials.access_token) self.assertEqual('a_token_456', credentials.access_token)
@@ -370,7 +361,7 @@ class CredentialsPropertyTest(unittest2.TestCase):
def _http_request(*args, **kwargs): def _http_request(*args, **kwargs):
resp = httplib2.Response({'status': '200'}) resp = http_mock.ResponseMock()
content = json.dumps({'access_token': 'bar'}) content = json.dumps({'access_token': 'bar'})
return resp, content return resp, content
@@ -630,12 +621,9 @@ class DecoratorTests(unittest2.TestCase):
}) })
self.current_user = user_mock() self.current_user = user_mock()
users.get_current_user = self.current_user users.get_current_user = self.current_user
self.httplib2_orig = httplib2.Http
httplib2.Http = Http2Mock
def tearDown(self): def tearDown(self):
self.testbed.deactivate() self.testbed.deactivate()
httplib2.Http = self.httplib2_orig
def test_in_error(self): def test_in_error(self):
# NOTE: This branch is never reached. _in_error is not set by any code # NOTE: This branch is never reached. _in_error is not set by any code
@@ -655,7 +643,9 @@ class DecoratorTests(unittest2.TestCase):
app.router.match_routes[0].handler.__name__, app.router.match_routes[0].handler.__name__,
'OAuth2Handler') 'OAuth2Handler')
def test_required(self): @mock.patch('oauth2client.transport.get_http_object')
def test_required(self, new_http):
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# An initial request to an oauth_required decorated path should be a # An initial request to an oauth_required decorated path should be a
# redirect to start the OAuth dance. # redirect to start the OAuth dance.
self.assertEqual(self.decorator.flow, None) self.assertEqual(self.decorator.flow, None)
@@ -688,7 +678,7 @@ class DecoratorTests(unittest2.TestCase):
response_query = urllib.parse.parse_qs(parts[1]) response_query = urllib.parse.parse_qs(parts[1])
response = response_query[ response = response_query[
self.decorator._token_response_param][0] self.decorator._token_response_param][0]
self.assertEqual(Http2Mock.content, self.assertEqual(json.loads(DEFAULT_RESP),
json.loads(urllib.parse.unquote(response))) json.loads(urllib.parse.unquote(response)))
self.assertEqual(self.decorator.flow, self.decorator._tls.flow) self.assertEqual(self.decorator.flow, self.decorator._tls.flow)
self.assertEqual(self.decorator.credentials, self.assertEqual(self.decorator.credentials,
@@ -736,7 +726,12 @@ class DecoratorTests(unittest2.TestCase):
self.assertEqual('http://localhost/oauth2callback', self.assertEqual('http://localhost/oauth2callback',
query_params['redirect_uri'][0]) query_params['redirect_uri'][0])
def test_storage_delete(self): # Check the mocks were called.
new_http.assert_called_once_with()
@mock.patch('oauth2client.transport.get_http_object')
def test_storage_delete(self, new_http):
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# An initial request to an oauth_required decorated path should be a # An initial request to an oauth_required decorated path should be a
# redirect to start the OAuth dance. # redirect to start the OAuth dance.
response = self.app.get('/foo_path') response = self.app.get('/foo_path')
@@ -772,7 +767,12 @@ class DecoratorTests(unittest2.TestCase):
parse_state_value.assert_called_once_with( parse_state_value.assert_called_once_with(
'foo_path:xsrfkey123', self.current_user) 'foo_path:xsrfkey123', self.current_user)
def test_aware(self): # Check the mocks were called.
new_http.assert_called_once_with()
@mock.patch('oauth2client.transport.get_http_object')
def test_aware(self, new_http):
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# An initial request to an oauth_aware decorated path should # An initial request to an oauth_aware decorated path should
# not redirect. # not redirect.
response = self.app.get('http://localhost/bar_path/2012/01') response = self.app.get('http://localhost/bar_path/2012/01')
@@ -825,6 +825,9 @@ class DecoratorTests(unittest2.TestCase):
self.should_raise = False self.should_raise = False
self.assertEqual(None, self.decorator.credentials) self.assertEqual(None, self.decorator.credentials)
# Check the mocks were called.
new_http.assert_called_once_with()
def test_error_in_step2(self): def test_error_in_step2(self):
# An initial request to an oauth_aware decorated path should # An initial request to an oauth_aware decorated path should
# not redirect. # not redirect.
@@ -855,10 +858,14 @@ class DecoratorTests(unittest2.TestCase):
self.assertEqual(decorator.flow, decorator._tls.flow) self.assertEqual(decorator.flow, decorator._tls.flow)
def test_token_response_param(self): def test_token_response_param(self):
# No need to set-up a mock since test_required() does.
self.decorator._token_response_param = 'foobar' self.decorator._token_response_param = 'foobar'
self.test_required() self.test_required()
def test_decorator_from_client_secrets(self): @mock.patch('oauth2client.transport.get_http_object')
def test_decorator_from_client_secrets(self, new_http):
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# Execute test after setting up mock.
decorator = appengine.OAuth2DecoratorFromClientSecrets( decorator = appengine.OAuth2DecoratorFromClientSecrets(
datafile('client_secrets.json'), datafile('client_secrets.json'),
scope=['foo_scope', 'bar_scope']) scope=['foo_scope', 'bar_scope'])
@@ -877,6 +884,9 @@ class DecoratorTests(unittest2.TestCase):
self.assertEqual(self.decorator._revoke_uri, self.assertEqual(self.decorator._revoke_uri,
self.decorator.credentials.revoke_uri) self.decorator.credentials.revoke_uri)
# Check the mocks were called.
new_http.assert_called_once_with()
def test_decorator_from_client_secrets_toplevel(self): def test_decorator_from_client_secrets_toplevel(self):
decorator_patch = mock.patch( decorator_patch = mock.patch(
'oauth2client.contrib.appengine.OAuth2DecoratorFromClientSecrets') 'oauth2client.contrib.appengine.OAuth2DecoratorFromClientSecrets')
@@ -915,7 +925,7 @@ class DecoratorTests(unittest2.TestCase):
self.assertIn('prompt', decorator._kwargs) self.assertIn('prompt', decorator._kwargs)
def test_decorator_from_cached_client_secrets(self): def test_decorator_from_cached_client_secrets(self):
cache_mock = CacheMock() cache_mock = http_mock.CacheMock()
load_and_cache('client_secrets.json', 'secret', cache_mock) load_and_cache('client_secrets.json', 'secret', cache_mock)
decorator = appengine.OAuth2DecoratorFromClientSecrets( decorator = appengine.OAuth2DecoratorFromClientSecrets(
# filename, scope, message=None, cache=None # filename, scope, message=None, cache=None
@@ -991,7 +1001,10 @@ class DecoratorTests(unittest2.TestCase):
# This is never set, but it's consistent with other tests. # This is never set, but it's consistent with other tests.
self.assertFalse(decorator._in_error) self.assertFalse(decorator._in_error)
def test_invalid_state(self): @mock.patch('oauth2client.transport.get_http_object')
def test_invalid_state(self, new_http):
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# Execute test after setting up mock.
with mock.patch.object(appengine, '_parse_state_value', with mock.patch.object(appengine, '_parse_state_value',
return_value=None, autospec=True): return_value=None, autospec=True):
# Now simulate the callback to /oauth2callback. # Now simulate the callback to /oauth2callback.
@@ -1002,6 +1015,9 @@ class DecoratorTests(unittest2.TestCase):
self.assertEqual('200 OK', response.status) self.assertEqual('200 OK', response.status)
self.assertEqual('The authorization request failed', response.body) self.assertEqual('The authorization request failed', response.body)
# Check the mocks were called.
new_http.assert_called_once_with()
class DecoratorXsrfSecretTests(unittest2.TestCase): class DecoratorXsrfSecretTests(unittest2.TestCase):
"""Test xsrf_secret_key.""" """Test xsrf_secret_key."""

View File

@@ -19,7 +19,6 @@ import json
import logging import logging
import flask import flask
import httplib2
import mock import mock
import six.moves.http_client as httplib import six.moves.http_client as httplib
import six.moves.urllib.parse as urlparse import six.moves.urllib.parse as urlparse
@@ -29,39 +28,20 @@ import oauth2client
from oauth2client import client from oauth2client import client
from oauth2client import clientsecrets from oauth2client import clientsecrets
from oauth2client.contrib import flask_util from oauth2client.contrib import flask_util
from .. import http_mock
__author__ = 'jonwayne@google.com (Jon Wayne Parrott)' __author__ = 'jonwayne@google.com (Jon Wayne Parrott)'
class Http2Mock(object): DEFAULT_RESP = """\
"""Mock httplib2.Http for code exchange / refresh""" {
"access_token": "foo_access_token",
def __init__(self, status=httplib.OK, **kwargs): "expires_in": 3600,
self.status = status "extra": "value",
self.content = { "refresh_token": "foo_refresh_token"
'access_token': 'foo_access_token', }
'refresh_token': 'foo_refresh_token', """
'expires_in': 3600,
'extra': 'value',
}
self.content.update(kwargs)
def request(self, token_uri, method, body, headers, *args, **kwargs):
self.body = body
self.headers = headers
return (self, json.dumps(self.content).encode('utf-8'))
def __enter__(self):
self.httplib2_orig = httplib2.Http
httplib2.Http = self
return self
def __exit__(self, exc_type, exc_value, traceback):
httplib2.Http = self.httplib2_orig
def __call__(self, *args, **kwargs):
return self
class FlaskOAuth2Tests(unittest2.TestCase): class FlaskOAuth2Tests(unittest2.TestCase):
@@ -246,7 +226,12 @@ class FlaskOAuth2Tests(unittest2.TestCase):
def test_callback_view(self): def test_callback_view(self):
self.oauth2.storage = mock.Mock() self.oauth2.storage = mock.Mock()
with self.app.test_client() as client: with self.app.test_client() as client:
with Http2Mock() as http: with mock.patch(
'oauth2client.transport.get_http_object') as new_http:
# Set-up mock.
new_http.return_value = http = http_mock.HttpMock(
data=DEFAULT_RESP)
# Run tests.
state = self._setup_callback_state(client) state = self._setup_callback_state(client)
response = client.get( response = client.get(
@@ -258,6 +243,9 @@ class FlaskOAuth2Tests(unittest2.TestCase):
self.assertIn('codez', http.body) self.assertIn('codez', http.body)
self.assertTrue(self.oauth2.storage.put.called) self.assertTrue(self.oauth2.storage.put.called)
# Check the mocks were called.
new_http.assert_called_once_with()
def test_authorize_callback(self): def test_authorize_callback(self):
self.oauth2.authorize_callback = mock.Mock() self.oauth2.authorize_callback = mock.Mock()
self.test_callback_view() self.test_callback_view()
@@ -296,11 +284,20 @@ class FlaskOAuth2Tests(unittest2.TestCase):
with self.app.test_client() as client: with self.app.test_client() as client:
state = self._setup_callback_state(client) state = self._setup_callback_state(client)
with Http2Mock(status=httplib.INTERNAL_SERVER_ERROR): with mock.patch(
'oauth2client.transport.get_http_object') as new_http:
# Set-up mock.
new_http.return_value = http_mock.HttpMock(
headers={'status': httplib.INTERNAL_SERVER_ERROR},
data=DEFAULT_RESP)
# Run tests.
response = client.get( response = client.get(
'/oauth2callback?state={0}&code=codez'.format(state)) '/oauth2callback?state={0}&code=codez'.format(state))
self.assertEqual(response.status_code, httplib.BAD_REQUEST) self.assertEqual(response.status_code, httplib.BAD_REQUEST)
# Check the mocks were called.
new_http.assert_called_once_with()
# Invalid state json # Invalid state json
with self.app.test_client() as client: with self.app.test_client() as client:
with client.session_transaction() as session: with client.session_transaction() as session:
@@ -495,7 +492,10 @@ class FlaskOAuth2Tests(unittest2.TestCase):
def test_incremental_auth_exchange(self): def test_incremental_auth_exchange(self):
self._create_incremental_auth_app() self._create_incremental_auth_app()
with Http2Mock(): with mock.patch('oauth2client.transport.get_http_object') as new_http:
# Set-up mock.
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP)
# Run tests.
with self.app.test_client() as client: with self.app.test_client() as client:
state = self._setup_callback_state( state = self._setup_callback_state(
client, client,
@@ -511,16 +511,21 @@ class FlaskOAuth2Tests(unittest2.TestCase):
self.assertTrue( self.assertTrue(
credentials.has_scopes(['email', 'one', 'two'])) credentials.has_scopes(['email', 'one', 'two']))
# Check the mocks were called.
new_http.assert_called_once_with()
def test_refresh(self): def test_refresh(self):
token_val = 'new_token'
json_resp = '{"access_token": "%s"}' % (token_val,)
http = http_mock.HttpMock(data=json_resp)
with self.app.test_request_context(): with self.app.test_request_context():
with mock.patch('flask.session'): with mock.patch('flask.session'):
self.oauth2.storage.put(self._generate_credentials()) self.oauth2.storage.put(self._generate_credentials())
self.oauth2.credentials.refresh( self.oauth2.credentials.refresh(http)
Http2Mock(access_token='new_token'))
self.assertEqual( self.assertEqual(
self.oauth2.storage.get().access_token, 'new_token') self.oauth2.storage.get().access_token, token_val)
def test_delete(self): def test_delete(self):
with self.app.test_request_context(): with self.app.test_request_context():

View File

@@ -17,7 +17,6 @@
import datetime import datetime
import json import json
import httplib2
import mock import mock
from six.moves import http_client from six.moves import http_client
from tests.contrib.test_metadata import request_mock from tests.contrib.test_metadata import request_mock
@@ -129,12 +128,12 @@ class AppAssertionCredentialsTests(unittest2.TestCase):
service_account='default') service_account='default')
@mock.patch('oauth2client.contrib._metadata.get_service_account_info', @mock.patch('oauth2client.contrib._metadata.get_service_account_info',
side_effect=httplib2.HttpLib2Error('No Such Email')) side_effect=http_client.HTTPException('No Such Email'))
def test_retrieve_scopes_bad_email(self, metadata): def test_retrieve_scopes_bad_email(self, metadata):
http_request = mock.MagicMock() http_request = mock.MagicMock()
http_mock = mock.MagicMock(request=http_request) http_mock = mock.MagicMock(request=http_request)
credentials = gce.AppAssertionCredentials(email='b@example.com') credentials = gce.AppAssertionCredentials(email='b@example.com')
with self.assertRaises(httplib2.HttpLib2Error): with self.assertRaises(http_client.HTTPException):
credentials.retrieve_scopes(http_mock) credentials.retrieve_scopes(http_mock)
metadata.assert_called_once_with(http_request, metadata.assert_called_once_with(http_request,

View File

@@ -15,12 +15,13 @@
import datetime import datetime
import json import json
import httplib2
import mock import mock
from six.moves import http_client from six.moves import http_client
import unittest2 import unittest2
from oauth2client.contrib import _metadata from oauth2client.contrib import _metadata
from .. import http_mock
PATH = 'instance/service-accounts/default' PATH = 'instance/service-accounts/default'
DATA = {'foo': 'bar'} DATA = {'foo': 'bar'}
@@ -31,12 +32,9 @@ EXPECTED_KWARGS = dict(headers=_metadata.METADATA_HEADERS)
def request_mock(status, content_type, content): def request_mock(status, content_type, content):
return mock.MagicMock(return_value=( resp = http_mock.ResponseMock(
httplib2.Response( {'status': status, 'content-type': content_type})
{'status': status, 'content-type': content_type} return mock.Mock(return_value=(resp, content.encode('utf-8')))
),
content.encode('utf-8')
))
class TestMetadata(unittest2.TestCase): class TestMetadata(unittest2.TestCase):

View File

@@ -12,17 +12,23 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
"""Copy of googleapiclient.http's mock functionality.""" """HTTP helpers mock functionality."""
import httplib2
# TODO(craigcitro): Find a cleaner way to share this code with googleapiclient. class ResponseMock(dict):
"""Mock HTTP response"""
def __init__(self, vals=None):
if vals is None:
vals = {}
self.update(vals)
self.status = int(self.get('status', 200))
class HttpMock(object): class HttpMock(object):
"""Mock of httplib2.Http""" """Mock of HTTP object."""
def __init__(self, headers=None): def __init__(self, headers=None, data=None):
"""HttpMock constructor. """HttpMock constructor.
Args: Args:
@@ -30,7 +36,7 @@ class HttpMock(object):
""" """
if headers is None: if headers is None:
headers = {'status': '200'} headers = {'status': '200'}
self.data = None self.data = data
self.response_headers = headers self.response_headers = headers
self.headers = None self.headers = None
self.uri = None self.uri = None
@@ -48,15 +54,15 @@ class HttpMock(object):
self.method = method self.method = method
self.body = body self.body = body
self.headers = headers self.headers = headers
return httplib2.Response(self.response_headers), self.data return ResponseMock(self.response_headers), self.data
class HttpMockSequence(object): class HttpMockSequence(object):
"""Mock of httplib2.Http """Mock of HTTP object with multiple return values.
Mocks a sequence of calls to request returning different responses for each Mocks a sequence of calls to request returning different responses for each
call. Create an instance initialized with the desired response headers call. Create an instance initialized with the desired response headers
and content and then use as if an httplib2.Http instance:: and content and then use as if an HttpMock instance::
http = HttpMockSequence([ http = HttpMockSequence([
({'status': '401'}, b''), ({'status': '401'}, b''),
@@ -99,7 +105,7 @@ class HttpMockSequence(object):
elif content == 'echo_request_body': elif content == 'echo_request_body':
content = (body content = (body
if body_stream_content is None else body_stream_content) if body_stream_content is None else body_stream_content)
return httplib2.Response(resp), content return ResponseMock(resp), content
class CacheMock(object): class CacheMock(object):

View File

@@ -27,7 +27,6 @@ import socket
import sys import sys
import tempfile import tempfile
import httplib2
import mock import mock
import six import six
from six.moves import http_client from six.moves import http_client
@@ -40,9 +39,7 @@ from oauth2client import client
from oauth2client import clientsecrets from oauth2client import clientsecrets
from oauth2client import service_account from oauth2client import service_account
from oauth2client import util from oauth2client import util
from .http_mock import CacheMock from . import http_mock
from .http_mock import HttpMock
from .http_mock import HttpMockSequence
__author__ = 'jcgregorio@google.com (Joe Gregorio)' __author__ = 'jcgregorio@google.com (Joe Gregorio)'
@@ -855,7 +852,7 @@ def _token_revoke_test_helper(testcase, status, revoke_raise,
return actual_do_revoke(http_request, token) return actual_do_revoke(http_request, token)
testcase.credentials._do_revoke = do_revoke_stub testcase.credentials._do_revoke = do_revoke_stub
http = HttpMock(headers={'status': status}) http = http_mock.HttpMock(headers={'status': status})
if revoke_raise: if revoke_raise:
testcase.assertRaises(client.TokenRevokeError, testcase.assertRaises(client.TokenRevokeError,
testcase.credentials.revoke, http) testcase.credentials.revoke, http)
@@ -898,11 +895,11 @@ class BasicCredentialsTests(unittest2.TestCase):
def test_token_refresh_success(self): def test_token_refresh_success(self):
for status_code in client.REFRESH_STATUS_CODES: for status_code in client.REFRESH_STATUS_CODES:
token_response = {'access_token': '1/3w', 'expires_in': 3600} token_response = {'access_token': '1/3w', 'expires_in': 3600}
http = HttpMockSequence([ json_resp = json.dumps(token_response).encode('utf-8')
http = http_mock.HttpMockSequence([
({'status': status_code}, b''), ({'status': status_code}, b''),
({'status': '200'}, json.dumps(token_response).encode( ({'status': http_client.OK}, json_resp),
'utf-8')), ({'status': http_client.OK}, 'echo_request_headers'),
({'status': '200'}, 'echo_request_headers'),
]) ])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
resp, content = http.request('http://example.com') resp, content = http.request('http://example.com')
@@ -911,28 +908,24 @@ class BasicCredentialsTests(unittest2.TestCase):
self.assertEqual(token_response, self.credentials.token_response) self.assertEqual(token_response, self.credentials.token_response)
def test_recursive_authorize(self): def test_recursive_authorize(self):
"""Tests that OAuth2Credentials doesn't intro. new method constraints. # Tests that OAuth2Credentials doesn't intro. new method constraints.
# Formerly, OAuth2Credentials.authorize monkeypatched the request method
Formerly, OAuth2Credentials.authorize monkeypatched the request method # of the passed in HTTP object with a wrapper annotated with
of its httplib2.Http argument with a wrapper annotated with # @util.positional(1). Since the original method has no such annotation,
@util.positional(1). Since the original method has no such annotation, # that meant that the wrapper was violating the contract of the original
that meant that the wrapper was violating the contract of the original # method by adding a new requirement to it. And in fact the wrapper
method by adding a new requirement to it. And in fact the wrapper # itself doesn't even respect that requirement. So before the removal of
itself doesn't even respect that requirement. So before the removal of # the annotation, this test would fail.
the annotation, this test would fail.
"""
token_response = {'access_token': '1/3w', 'expires_in': 3600} token_response = {'access_token': '1/3w', 'expires_in': 3600}
encoded_response = json.dumps(token_response).encode('utf-8') encoded_response = json.dumps(token_response).encode('utf-8')
http = HttpMockSequence([ http = http_mock.HttpMock(data=encoded_response)
({'status': '200'}, encoded_response),
])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
http.request('http://example.com') http.request('http://example.com')
def test_token_refresh_failure(self): def test_token_refresh_failure(self):
for status_code in client.REFRESH_STATUS_CODES: for status_code in client.REFRESH_STATUS_CODES:
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': status_code}, b''), ({'status': status_code}, b''),
({'status': http_client.BAD_REQUEST}, ({'status': http_client.BAD_REQUEST},
b'{"error":"access_denied"}'), b'{"error":"access_denied"}'),
@@ -965,9 +958,7 @@ class BasicCredentialsTests(unittest2.TestCase):
self.credentials = self.credentials.from_json(original_credentials) self.credentials = self.credentials.from_json(original_credentials)
def test_non_401_error_response(self): def test_non_401_error_response(self):
http = HttpMockSequence([ http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST})
({'status': '400'}, b''),
])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
resp, content = http.request('http://example.com') resp, content = http.request('http://example.com')
self.assertEqual(http_client.BAD_REQUEST, resp.status) self.assertEqual(http_client.BAD_REQUEST, resp.status)
@@ -1010,7 +1001,7 @@ class BasicCredentialsTests(unittest2.TestCase):
# First, test that we correctly encode basic objects, making sure # First, test that we correctly encode basic objects, making sure
# to include a bytes object. Note that oauth2client will normalize # to include a bytes object. Note that oauth2client will normalize
# everything to bytes, no matter what python version we're in. # everything to bytes, no matter what python version we're in.
http = credentials.authorize(HttpMock()) http = credentials.authorize(http_mock.HttpMock())
headers = {u'foo': 3, b'bar': True, 'baz': b'abc'} headers = {u'foo': 3, b'bar': True, 'baz': b'abc'}
cleaned_headers = {b'foo': b'3', b'bar': b'True', b'baz': b'abc'} cleaned_headers = {b'foo': b'3', b'bar': b'True', b'baz': b'abc'}
http.request(u'http://example.com', method=u'GET', headers=headers) http.request(u'http://example.com', method=u'GET', headers=headers)
@@ -1037,7 +1028,7 @@ class BasicCredentialsTests(unittest2.TestCase):
access_token, client_id, client_secret, refresh_token, access_token, client_id, client_secret, refresh_token,
token_expiry, token_uri, user_agent, revoke_uri=revoke_uri) token_expiry, token_uri, user_agent, revoke_uri=revoke_uri)
http = HttpMock() http = http_mock.HttpMock()
http = credentials.authorize(http) http = credentials.authorize(http)
http.request(u'http://example.com', method=u'GET', http.request(u'http://example.com', method=u'GET',
headers={u'foo': u'bar'}) headers={u'foo': u'bar'})
@@ -1107,7 +1098,7 @@ class BasicCredentialsTests(unittest2.TestCase):
'access_token': token2, 'access_token': token2,
'expires_in': lifetime, 'expires_in': lifetime,
} }
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': '200'}, json.dumps(token_response_first).encode( ({'status': '200'}, json.dumps(token_response_first).encode(
'utf-8')), 'utf-8')),
({'status': '200'}, json.dumps(token_response_second).encode( ({'status': '200'}, json.dumps(token_response_second).encode(
@@ -1181,11 +1172,12 @@ class BasicCredentialsTests(unittest2.TestCase):
# Specify a token so we can use it in the response. # Specify a token so we can use it in the response.
credentials.access_token = 'ya29-s3kr3t' credentials.access_token = 'ya29-s3kr3t'
with mock.patch('httplib2.Http', with mock.patch('oauth2client.transport.get_http_object',
return_value=object) as http_kls: return_value=object()) as new_http:
token_info = credentials.get_access_token() token_info = credentials.get_access_token()
expires_in.assert_called_once_with() expires_in.assert_called_once_with()
refresh_mock.assert_called_once_with(http_kls.return_value) refresh_mock.assert_called_once_with(new_http.return_value)
new_http.assert_called_once_with()
self.assertIsInstance(token_info, client.AccessTokenInfo) self.assertIsInstance(token_info, client.AccessTokenInfo)
self.assertEqual(token_info.access_token, self.assertEqual(token_info.access_token,
@@ -1249,33 +1241,26 @@ class BasicCredentialsTests(unittest2.TestCase):
store.locked_put.assert_called_once_with(credentials) store.locked_put.assert_called_once_with(credentials)
def test__do_refresh_request_non_json_failure(self): def test__do_refresh_request_non_json_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_REQUEST})
'status': int(http_client.BAD_REQUEST),
})
content = u'Bad request' content = u'Bad request'
error_msg = 'Invalid response {0}.'.format(int(response.status)) error_msg = 'Invalid response {0}.'.format(int(response.status))
self._do_refresh_request_test_helper(response, content, error_msg) self._do_refresh_request_test_helper(response, content, error_msg)
def test__do_refresh_request_basic_failure(self): def test__do_refresh_request_basic_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock(
'status': int(http_client.INTERNAL_SERVER_ERROR), {'status': http_client.INTERNAL_SERVER_ERROR})
})
content = u'{}' content = u'{}'
error_msg = 'Invalid response {0}.'.format(int(response.status)) error_msg = 'Invalid response {0}.'.format(int(response.status))
self._do_refresh_request_test_helper(response, content, error_msg) self._do_refresh_request_test_helper(response, content, error_msg)
def test__do_refresh_request_failure_w_json_error(self): def test__do_refresh_request_failure_w_json_error(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_GATEWAY})
'status': http_client.BAD_GATEWAY,
})
error_msg = 'Hi I am an error not a bearer' error_msg = 'Hi I am an error not a bearer'
content = json.dumps({'error': error_msg}) content = json.dumps({'error': error_msg})
self._do_refresh_request_test_helper(response, content, error_msg) self._do_refresh_request_test_helper(response, content, error_msg)
def test__do_refresh_request_failure_w_json_error_and_store(self): def test__do_refresh_request_failure_w_json_error_and_store(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_GATEWAY})
'status': http_client.BAD_GATEWAY,
})
error_msg = 'Where are we going wearer?' error_msg = 'Where are we going wearer?'
content = json.dumps({'error': error_msg}) content = json.dumps({'error': error_msg})
store = mock.MagicMock() store = mock.MagicMock()
@@ -1283,9 +1268,8 @@ class BasicCredentialsTests(unittest2.TestCase):
store=store) store=store)
def test__do_refresh_request_failure_w_json_error_and_desc(self): def test__do_refresh_request_failure_w_json_error_and_desc(self):
response = httplib2.Response({ response = http_mock.ResponseMock(
'status': http_client.SERVICE_UNAVAILABLE, {'status': http_client.SERVICE_UNAVAILABLE})
})
base_error = 'Ruckus' base_error = 'Ruckus'
error_desc = 'Can you describe the ruckus' error_desc = 'Can you describe the ruckus'
content = json.dumps({ content = json.dumps({
@@ -1328,46 +1312,35 @@ class BasicCredentialsTests(unittest2.TestCase):
logger.info.assert_called_once_with('Revoking token') logger.info.assert_called_once_with('Revoking token')
def test__do_revoke_success(self): def test__do_revoke_success(self):
response = httplib2.Response({ response = http_mock.ResponseMock()
'status': http_client.OK,
})
self._do_revoke_test_helper(response, b'', None) self._do_revoke_test_helper(response, b'', None)
def test__do_revoke_success_with_store(self): def test__do_revoke_success_with_store(self):
response = httplib2.Response({ response = http_mock.ResponseMock()
'status': http_client.OK,
})
store = mock.MagicMock() store = mock.MagicMock()
self._do_revoke_test_helper(response, b'', None, store=store) self._do_revoke_test_helper(response, b'', None, store=store)
def test__do_revoke_non_json_failure(self): def test__do_revoke_non_json_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_REQUEST})
'status': http_client.BAD_REQUEST,
})
content = u'Bad request' content = u'Bad request'
error_msg = 'Invalid response {0}.'.format(response.status) error_msg = 'Invalid response {0}.'.format(response.status)
self._do_revoke_test_helper(response, content, error_msg) self._do_revoke_test_helper(response, content, error_msg)
def test__do_revoke_basic_failure(self): def test__do_revoke_basic_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock(
'status': http_client.INTERNAL_SERVER_ERROR, {'status': http_client.INTERNAL_SERVER_ERROR})
})
content = u'{}' content = u'{}'
error_msg = 'Invalid response {0}.'.format(response.status) error_msg = 'Invalid response {0}.'.format(response.status)
self._do_revoke_test_helper(response, content, error_msg) self._do_revoke_test_helper(response, content, error_msg)
def test__do_revoke_failure_w_json_error(self): def test__do_revoke_failure_w_json_error(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_GATEWAY})
'status': http_client.BAD_GATEWAY,
})
error_msg = 'Hi I am an error not a bearer' error_msg = 'Hi I am an error not a bearer'
content = json.dumps({'error': error_msg}) content = json.dumps({'error': error_msg})
self._do_revoke_test_helper(response, content, error_msg) self._do_revoke_test_helper(response, content, error_msg)
def test__do_revoke_failure_w_json_error_and_store(self): def test__do_revoke_failure_w_json_error_and_store(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_GATEWAY})
'status': http_client.BAD_GATEWAY,
})
error_msg = 'Where are we going wearer?' error_msg = 'Where are we going wearer?'
content = json.dumps({'error': error_msg}) content = json.dumps({'error': error_msg})
store = mock.MagicMock() store = mock.MagicMock()
@@ -1409,41 +1382,32 @@ class BasicCredentialsTests(unittest2.TestCase):
logger.info.assert_called_once_with('Refreshing scopes') logger.info.assert_called_once_with('Refreshing scopes')
def test__do_retrieve_scopes_success_bad_json(self): def test__do_retrieve_scopes_success_bad_json(self):
response = httplib2.Response({ response = http_mock.ResponseMock()
'status': http_client.OK,
})
invalid_json = b'{' invalid_json = b'{'
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self._do_retrieve_scopes_test_helper(response, invalid_json, None) self._do_retrieve_scopes_test_helper(response, invalid_json, None)
def test__do_retrieve_scopes_success(self): def test__do_retrieve_scopes_success(self):
response = httplib2.Response({ response = http_mock.ResponseMock()
'status': http_client.OK,
})
content = b'{"scope": "foo bar"}' content = b'{"scope": "foo bar"}'
self._do_retrieve_scopes_test_helper(response, content, None, self._do_retrieve_scopes_test_helper(response, content, None,
scopes=set(['foo', 'bar'])) scopes=set(['foo', 'bar']))
def test__do_retrieve_scopes_non_json_failure(self): def test__do_retrieve_scopes_non_json_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_REQUEST})
'status': http_client.BAD_REQUEST,
})
content = u'Bad request' content = u'Bad request'
error_msg = 'Invalid response {0}.'.format(response.status) error_msg = 'Invalid response {0}.'.format(response.status)
self._do_retrieve_scopes_test_helper(response, content, error_msg) self._do_retrieve_scopes_test_helper(response, content, error_msg)
def test__do_retrieve_scopes_basic_failure(self): def test__do_retrieve_scopes_basic_failure(self):
response = httplib2.Response({ response = http_mock.ResponseMock(
'status': http_client.INTERNAL_SERVER_ERROR, {'status': http_client.INTERNAL_SERVER_ERROR})
})
content = u'{}' content = u'{}'
error_msg = 'Invalid response {0}.'.format(response.status) error_msg = 'Invalid response {0}.'.format(response.status)
self._do_retrieve_scopes_test_helper(response, content, error_msg) self._do_retrieve_scopes_test_helper(response, content, error_msg)
def test__do_retrieve_scopes_failure_w_json_error(self): def test__do_retrieve_scopes_failure_w_json_error(self):
response = httplib2.Response({ response = http_mock.ResponseMock({'status': http_client.BAD_GATEWAY})
'status': http_client.BAD_GATEWAY,
})
error_msg = 'Error desc I sit at a desk' error_msg = 'Error desc I sit at a desk'
content = json.dumps({'error_description': error_msg}) content = json.dumps({'error_description': error_msg})
self._do_retrieve_scopes_test_helper(response, content, error_msg) self._do_retrieve_scopes_test_helper(response, content, error_msg)
@@ -1467,7 +1431,7 @@ class BasicCredentialsTests(unittest2.TestCase):
def test_retrieve_scopes(self): def test_retrieve_scopes(self):
info_response_first = {'scope': 'foo bar'} info_response_first = {'scope': 'foo bar'}
info_response_second = {'error_description': 'abcdef'} info_response_second = {'error_description': 'abcdef'}
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': '200'}, json.dumps(info_response_first).encode( ({'status': '200'}, json.dumps(info_response_first).encode(
'utf-8')), 'utf-8')),
({'status': '400'}, json.dumps(info_response_second).encode( ({'status': '400'}, json.dumps(info_response_second).encode(
@@ -1496,7 +1460,7 @@ class BasicCredentialsTests(unittest2.TestCase):
b' "expires_in":3600,' b' "expires_in":3600,'
b' "id_token": "' + jwt + b'"' b' "id_token": "' + jwt + b'"'
b'}') b'}')
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': status_code}, b''), ({'status': status_code}, b''),
({'status': '200'}, token_response), ({'status': '200'}, token_response),
({'status': '200'}, 'echo_request_headers'), ({'status': '200'}, 'echo_request_headers'),
@@ -1517,9 +1481,8 @@ class AccessTokenCredentialsTests(unittest2.TestCase):
def test_token_refresh_success(self): def test_token_refresh_success(self):
for status_code in client.REFRESH_STATUS_CODES: for status_code in client.REFRESH_STATUS_CODES:
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': status_code}, b''), headers={'status': status_code}, data=b'')
])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
with self.assertRaises(client.AccessTokenCredentialsError): with self.assertRaises(client.AccessTokenCredentialsError):
resp, content = http.request('http://example.com') resp, content = http.request('http://example.com')
@@ -1535,15 +1498,13 @@ class AccessTokenCredentialsTests(unittest2.TestCase):
valid_bool_value=False, token_attr='access_token') valid_bool_value=False, token_attr='access_token')
def test_non_401_error_response(self): def test_non_401_error_response(self):
http = HttpMockSequence([ http = http_mock.HttpMock(headers={'status': http_client.BAD_REQUEST})
({'status': '400'}, b''),
])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
resp, content = http.request('http://example.com') resp, content = http.request('http://example.com')
self.assertEqual(http_client.BAD_REQUEST, resp.status) self.assertEqual(http_client.BAD_REQUEST, resp.status)
def test_auth_header_sent(self): def test_auth_header_sent(self):
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': '200'}, 'echo_request_headers'), ({'status': '200'}, 'echo_request_headers'),
]) ])
http = self.credentials.authorize(http) http = self.credentials.authorize(http)
@@ -1578,7 +1539,7 @@ class TestAssertionCredentials(unittest2.TestCase):
body['grant_type'][0]) body['grant_type'][0])
def test_assertion_refresh(self): def test_assertion_refresh(self):
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': '200'}, b'{"access_token":"1/3w"}'), ({'status': '200'}, b'{"access_token":"1/3w"}'),
({'status': '200'}, 'echo_request_headers'), ({'status': '200'}, 'echo_request_headers'),
]) ])
@@ -1758,12 +1719,15 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
'user_code': user_code, 'user_code': user_code,
'verification_url': ver_url, 'verification_url': ver_url,
}) })
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': http_client.OK}, content), ({'status': http_client.OK}, content),
]) ])
if default_http: if default_http:
with mock.patch('httplib2.Http', return_value=http): with mock.patch('oauth2client.transport.get_http_object',
return_value=http) as new_http:
result = flow.step1_get_device_and_user_codes() result = flow.step1_get_device_and_user_codes()
# Check the mock was called.
new_http.assert_called_once_with()
else: else:
result = flow.step1_get_device_and_user_codes(http=http) result = flow.step1_get_device_and_user_codes(http=http)
@@ -1803,9 +1767,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
def _step1_get_device_and_user_codes_fail_helper(self, status, def _step1_get_device_and_user_codes_fail_helper(self, status,
content, error_msg): content, error_msg):
flow = client.OAuth2WebServerFlow('CID', scope='foo') flow = client.OAuth2WebServerFlow('CID', scope='foo')
http = HttpMockSequence([ http = http_mock.HttpMock(headers={'status': status}, data=content)
({'status': status}, content),
])
with self.assertRaises(client.OAuth2DeviceCodeError) as exc_manager: with self.assertRaises(client.OAuth2DeviceCodeError) as exc_manager:
flow.step1_get_device_and_user_codes(http=http) flow.step1_get_device_and_user_codes(http=http)
@@ -1849,17 +1811,19 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
client.OAuth2WebServerFlow('client_id+1') client.OAuth2WebServerFlow('client_id+1')
def test_exchange_failure(self): def test_exchange_failure(self):
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': '400'}, b'{"error":"invalid_request"}'), headers={'status': http_client.BAD_REQUEST},
]) data=b'{"error":"invalid_request"}',
)
with self.assertRaises(client.FlowExchangeError): with self.assertRaises(client.FlowExchangeError):
self.flow.step2_exchange(code='some random code', http=http) self.flow.step2_exchange(code='some random code', http=http)
def test_urlencoded_exchange_failure(self): def test_urlencoded_exchange_failure(self):
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': '400'}, b'error=invalid_request'), headers={'status': http_client.BAD_REQUEST},
]) data=b'error=invalid_request',
)
with self.assertRaisesRegexp(client.FlowExchangeError, with self.assertRaisesRegexp(client.FlowExchangeError,
'invalid_request'): 'invalid_request'):
@@ -1876,7 +1840,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "type": "OAuthException"' b' "type": "OAuthException"'
b' }' b' }'
b'}') b'}')
http = HttpMockSequence([({'status': '400'}, payload)]) http = http_mock.HttpMock(data=payload)
with self.assertRaises(client.FlowExchangeError): with self.assertRaises(client.FlowExchangeError):
self.flow.step2_exchange(code='some random code', http=http) self.flow.step2_exchange(code='some random code', http=http)
@@ -1887,7 +1851,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "expires_in":3600,' b' "expires_in":3600,'
b' "refresh_token":"8xLOxBtZp8"' b' "refresh_token":"8xLOxBtZp8"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
credentials = self.flow.step2_exchange( credentials = self.flow.step2_exchange(
code=code, device_flow_info=device_flow_info, http=http) code=code, device_flow_info=device_flow_info, http=http)
self.assertEqual('SlAV32hkKG', credentials.access_token) self.assertEqual('SlAV32hkKG', credentials.access_token)
@@ -1916,8 +1880,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
' "expires_in":' + expires_in + ',' ' "expires_in":' + expires_in + ','
' "refresh_token":"' + refresh_token + '"' ' "refresh_token":"' + refresh_token + '"'
'}') '}')
http = HttpMockSequence( http = http_mock.HttpMock(data=_helpers._to_bytes(payload))
[({'status': '200'}, _helpers._to_bytes(payload))])
credentials = self.flow.step2_exchange(code=binary_code, http=http) credentials = self.flow.step2_exchange(code=binary_code, http=http)
self.assertEqual(access_token, credentials.access_token) self.assertEqual(access_token, credentials.access_token)
self.assertIsNotNone(credentials.token_expiry) self.assertIsNotNone(credentials.token_expiry)
@@ -1943,7 +1906,9 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "expires_in":3600,' b' "expires_in":3600,'
b' "refresh_token":"8xLOxBtZp8"' b' "refresh_token":"8xLOxBtZp8"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMockSequence([
({'status': http_client.OK}, payload),
])
credentials = self.flow.step2_exchange(code=not_a_dict, http=http) credentials = self.flow.step2_exchange(code=not_a_dict, http=http)
self.assertEqual('SlAV32hkKG', credentials.access_token) self.assertEqual('SlAV32hkKG', credentials.access_token)
@@ -1951,6 +1916,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
self.assertEqual('8xLOxBtZp8', credentials.refresh_token) self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri) self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
self.assertEqual(set(['foo']), credentials.scopes) self.assertEqual(set(['foo']), credentials.scopes)
self.assertEqual(len(http.requests), 1)
request_code = urllib.parse.parse_qs( request_code = urllib.parse.parse_qs(
http.requests[0]['body'])['code'][0] http.requests[0]['body'])['code'][0]
self.assertEqual(code, request_code) self.assertEqual(code, request_code)
@@ -1965,13 +1931,14 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
user_agent='unittest-sample/1.0', user_agent='unittest-sample/1.0',
revoke_uri='dummy_revoke_uri', revoke_uri='dummy_revoke_uri',
) )
http = HttpMockSequence([ http = http_mock.HttpMockSequence([
({'status': '200'}, b'access_token=SlAV32hkKG'), ({'status': http_client.OK}, b'access_token=SlAV32hkKG'),
]) ])
credentials = flow.step2_exchange(code='some random code', http=http) credentials = flow.step2_exchange(code='some random code', http=http)
self.assertEqual('SlAV32hkKG', credentials.access_token) self.assertEqual('SlAV32hkKG', credentials.access_token)
self.assertEqual(len(http.requests), 1)
test_request = http.requests[0] test_request = http.requests[0]
# Did we pass the Authorization header? # Did we pass the Authorization header?
self.assertEqual(test_request['headers']['Authorization'], auth_header) self.assertEqual(test_request['headers']['Authorization'], auth_header)
@@ -1979,9 +1946,8 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
self.assertTrue('client_secret' not in test_request['body']) self.assertTrue('client_secret' not in test_request['body'])
def test_urlencoded_exchange_success(self): def test_urlencoded_exchange_success(self):
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': '200'}, b'access_token=SlAV32hkKG&expires_in=3600'), data=b'access_token=SlAV32hkKG&expires_in=3600')
])
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
@@ -1989,12 +1955,9 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
self.assertNotEqual(None, credentials.token_expiry) self.assertNotEqual(None, credentials.token_expiry)
def test_urlencoded_expires_param(self): def test_urlencoded_expires_param(self):
http = HttpMockSequence([ # Note the 'expires=3600' where you'd normally
# Note the 'expires=3600' where you'd normally # have if named 'expires_in'
# have if named 'expires_in' http = http_mock.HttpMock(data=b'access_token=SlAV32hkKG&expires=3600')
({'status': '200'}, b'access_token=SlAV32hkKG&expires=3600'),
])
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
self.assertNotEqual(None, credentials.token_expiry) self.assertNotEqual(None, credentials.token_expiry)
@@ -2004,18 +1967,16 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "access_token":"SlAV32hkKG",' b' "access_token":"SlAV32hkKG",'
b' "refresh_token":"8xLOxBtZp8"' b' "refresh_token":"8xLOxBtZp8"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
self.assertEqual(None, credentials.token_expiry) self.assertEqual(None, credentials.token_expiry)
def test_urlencoded_exchange_no_expires_in(self): def test_urlencoded_exchange_no_expires_in(self):
http = HttpMockSequence([ # This might be redundant but just to make sure
# This might be redundant but just to make sure # urlencoded access_token gets parsed correctly
# urlencoded access_token gets parsed correctly http = http_mock.HttpMock(data=b'access_token=SlAV32hkKG')
({'status': '200'}, b'access_token=SlAV32hkKG'),
])
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
@@ -2026,7 +1987,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "access_token":"SlAV32hkKG",' b' "access_token":"SlAV32hkKG",'
b' "refresh_token":"8xLOxBtZp8"' b' "refresh_token":"8xLOxBtZp8"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
code = {'error': 'thou shall not pass'} code = {'error': 'thou shall not pass'}
with self.assertRaisesRegexp( with self.assertRaisesRegexp(
@@ -2039,7 +2000,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "refresh_token":"8xLOxBtZp8",' b' "refresh_token":"8xLOxBtZp8",'
b' "id_token": "stuff.payload"' b' "id_token": "stuff.payload"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
with self.assertRaises(client.VerifyJwtTokenError): with self.assertRaises(client.VerifyJwtTokenError):
self.flow.step2_exchange(code='some random code', http=http) self.flow.step2_exchange(code='some random code', http=http)
@@ -2056,7 +2017,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
b' "refresh_token":"8xLOxBtZp8",' b' "refresh_token":"8xLOxBtZp8",'
b' "id_token": "' + jwt + b'"' b' "id_token": "' + jwt + b'"'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
credentials = self.flow.step2_exchange(code='some random code', credentials = self.flow.step2_exchange(code='some random code',
http=http) http=http)
self.assertEqual(credentials.id_token, body) self.assertEqual(credentials.id_token, body)
@@ -2065,7 +2026,7 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
class FlowFromCachedClientsecrets(unittest2.TestCase): class FlowFromCachedClientsecrets(unittest2.TestCase):
def test_flow_from_clientsecrets_cached(self): def test_flow_from_clientsecrets_cached(self):
cache_mock = CacheMock() cache_mock = http_mock.CacheMock()
load_and_cache('client_secrets.json', 'some_secrets', cache_mock) load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
flow = client.flow_from_clientsecrets( flow = client.flow_from_clientsecrets(
@@ -2180,9 +2141,7 @@ class CredentialsFromCodeTests(unittest2.TestCase):
def test_exchange_code_for_token(self): def test_exchange_code_for_token(self):
token = 'asdfghjkl' token = 'asdfghjkl'
payload = json.dumps({'access_token': token, 'expires_in': 3600}) payload = json.dumps({'access_token': token, 'expires_in': 3600})
http = HttpMockSequence([ http = http_mock.HttpMock(data=payload.encode('utf-8'))
({'status': '200'}, payload.encode('utf-8')),
])
credentials = client.credentials_from_code( credentials = client.credentials_from_code(
self.client_id, self.client_secret, self.scope, self.client_id, self.client_secret, self.scope,
self.code, http=http, redirect_uri=self.redirect_uri) self.code, http=http, redirect_uri=self.redirect_uri)
@@ -2191,9 +2150,10 @@ class CredentialsFromCodeTests(unittest2.TestCase):
self.assertEqual(set(['foo']), credentials.scopes) self.assertEqual(set(['foo']), credentials.scopes)
def test_exchange_code_for_token_fail(self): def test_exchange_code_for_token_fail(self):
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': '400'}, b'{"error":"invalid_request"}'), headers={'status': http_client.BAD_REQUEST},
]) data=b'{"error":"invalid_request"}',
)
with self.assertRaises(client.FlowExchangeError): with self.assertRaises(client.FlowExchangeError):
client.credentials_from_code( client.credentials_from_code(
@@ -2205,7 +2165,7 @@ class CredentialsFromCodeTests(unittest2.TestCase):
b' "access_token":"asdfghjkl",' b' "access_token":"asdfghjkl",'
b' "expires_in":3600' b' "expires_in":3600'
b'}') b'}')
http = HttpMockSequence([({'status': '200'}, payload)]) http = http_mock.HttpMock(data=payload)
credentials = client.credentials_from_clientsecrets_and_code( credentials = client.credentials_from_clientsecrets_and_code(
datafile('client_secrets.json'), self.scope, datafile('client_secrets.json'), self.scope,
self.code, http=http) self.code, http=http)
@@ -2214,10 +2174,8 @@ class CredentialsFromCodeTests(unittest2.TestCase):
self.assertEqual(set(['foo']), credentials.scopes) self.assertEqual(set(['foo']), credentials.scopes)
def test_exchange_code_and_cached_file_for_token(self): def test_exchange_code_and_cached_file_for_token(self):
http = HttpMockSequence([ http = http_mock.HttpMock(data=b'{ "access_token":"asdfghjkl"}')
({'status': '200'}, b'{ "access_token":"asdfghjkl"}'), cache_mock = http_mock.CacheMock()
])
cache_mock = CacheMock()
load_and_cache('client_secrets.json', 'some_secrets', cache_mock) load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
credentials = client.credentials_from_clientsecrets_and_code( credentials = client.credentials_from_clientsecrets_and_code(
@@ -2227,9 +2185,10 @@ class CredentialsFromCodeTests(unittest2.TestCase):
self.assertEqual(set(['foo']), credentials.scopes) self.assertEqual(set(['foo']), credentials.scopes)
def test_exchange_code_and_file_for_token_fail(self): def test_exchange_code_and_file_for_token_fail(self):
http = HttpMockSequence([ http = http_mock.HttpMock(
({'status': '400'}, b'{"error":"invalid_request"}'), headers={'status': http_client.BAD_REQUEST},
]) data=b'{"error":"invalid_request"}',
)
with self.assertRaises(client.FlowExchangeError): with self.assertRaises(client.FlowExchangeError):
client.credentials_from_clientsecrets_and_code( client.credentials_from_clientsecrets_and_code(

View File

@@ -22,7 +22,6 @@ import json
import os import os
import tempfile import tempfile
import httplib2
import mock import mock
import rsa import rsa
from six import BytesIO from six import BytesIO
@@ -488,9 +487,10 @@ class JWTAccessCredentialsTests(unittest2.TestCase):
self.assertEqual(payload['exp'], T1_EXPIRY) self.assertEqual(payload['exp'], T1_EXPIRY)
self.assertEqual(uri, self.url) self.assertEqual(uri, self.url)
self.assertEqual(bearer, b'Bearer') self.assertEqual(bearer, b'Bearer')
return (httplib2.Response({'status': '200'}), b'') response = mock.Mock(status=200)
return response, b''
h = httplib2.Http() h = mock.Mock()
h.request = mock_request h.request = mock_request
self.jwt.authorize(h) self.jwt.authorize(h)
h.request(self.url) h.request(self.url)
@@ -523,9 +523,10 @@ class JWTAccessCredentialsTests(unittest2.TestCase):
self.assertEqual(payload['exp'], T1_EXPIRY) self.assertEqual(payload['exp'], T1_EXPIRY)
self.assertEqual(uri, self.url) self.assertEqual(uri, self.url)
self.assertEqual(bearer, b'Bearer') self.assertEqual(bearer, b'Bearer')
return httplib2.Response({'status': '200'}), b'' response = mock.Mock(status=200)
return response, b''
h = httplib2.Http() h = mock.Mock()
h.request = mock_request h.request = mock_request
jwt.authorize(h) jwt.authorize(h)
h.request(self.url) h.request(self.url)