Fix bug in StorageByKeyName.

Reviewed in http://codereview.appspot.com/5782058/.
This commit is contained in:
Joe Gregorio
2012-03-12 08:45:57 -04:00
parent e78621a3c0
commit e84c94409f
4 changed files with 84 additions and 6 deletions

View File

@@ -55,6 +55,7 @@ from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart from email.mime.nonmultipart import MIMENonMultipart
from oauth2client.anyjson import simplejson from oauth2client.anyjson import simplejson
logger = logging.getLogger(__name__)
URITEMPLATE = re.compile('{[^}]*}') URITEMPLATE = re.compile('{[^}]*}')
VARNAME = re.compile('[a-zA-Z0-9_-]+') VARNAME = re.compile('[a-zA-Z0-9_-]+')
@@ -175,7 +176,7 @@ def build(serviceName,
if 'REMOTE_ADDR' in os.environ: if 'REMOTE_ADDR' in os.environ:
requested_url = _add_query_parameter(requested_url, 'userIp', requested_url = _add_query_parameter(requested_url, 'userIp',
os.environ['REMOTE_ADDR']) os.environ['REMOTE_ADDR'])
logging.info('URL being requested: %s' % requested_url) logger.info('URL being requested: %s' % requested_url)
resp, content = http.request(requested_url) resp, content = http.request(requested_url)
@@ -188,7 +189,7 @@ def build(serviceName,
try: try:
service = simplejson.loads(content) service = simplejson.loads(content)
except ValueError, e: except ValueError, e:
logging.error('Failed to parse as JSON: ' + content) logger.error('Failed to parse as JSON: ' + content)
raise InvalidJsonError() raise InvalidJsonError()
filename = os.path.join(os.path.dirname(__file__), 'contrib', filename = os.path.join(os.path.dirname(__file__), 'contrib',
@@ -536,7 +537,7 @@ def createResource(http, baseUrl, model, requestBuilder,
'boundary="%s"') % multipart_boundary 'boundary="%s"') % multipart_boundary
url = _add_query_parameter(url, 'uploadType', 'multipart') url = _add_query_parameter(url, 'uploadType', 'multipart')
logging.info('URL being requested: %s' % url) logger.info('URL being requested: %s' % url)
return self._requestBuilder(self._http, return self._requestBuilder(self._http,
model.response, model.response,
url, url,
@@ -616,7 +617,7 @@ def createResource(http, baseUrl, model, requestBuilder,
headers = {} headers = {}
headers, params, query, body = self._model.request(headers, {}, {}, None) headers, params, query, body = self._model.request(headers, {}, {}, None)
logging.info('URL being requested: %s' % url) logger.info('URL being requested: %s' % url)
resp, content = self._http.request(url, method='GET', headers=headers) resp, content = self._http.request(url, method='GET', headers=headers)
return self._requestBuilder(self._http, return self._requestBuilder(self._http,
@@ -663,7 +664,7 @@ def createResource(http, baseUrl, model, requestBuilder,
request.uri = uri request.uri = uri
logging.info('URL being requested: %s' % uri) logger.info('URL being requested: %s' % uri)
return request return request

View File

@@ -224,7 +224,7 @@ class StorageByKeyName(Storage):
if credential and hasattr(credential, 'set_store'): if credential and hasattr(credential, 'set_store'):
credential.set_store(self) credential.set_store(self)
if self._cache: if self._cache:
self._cache.set(self._key_name, credentials.to_json()) self._cache.set(self._key_name, credential.to_json())
return credential return credential

View File

@@ -7,6 +7,8 @@ import sys
import unittest import unittest
from trace import fullmodname from trace import fullmodname
logging.basicConfig(level=logging.CRITICAL)
APP_ENGINE_PATH='../google_appengine' APP_ENGINE_PATH='../google_appengine'
# Conditional import of cleanup function # Conditional import of cleanup function

View File

@@ -23,6 +23,7 @@ Unit tests for objects created from discovery documents.
__author__ = 'jcgregorio@google.com (Joe Gregorio)' __author__ = 'jcgregorio@google.com (Joe Gregorio)'
import base64 import base64
import datetime
import httplib2 import httplib2
import time import time
import unittest import unittest
@@ -42,15 +43,20 @@ from google.appengine.api import apiproxy_stub
from google.appengine.api import apiproxy_stub_map from google.appengine.api import apiproxy_stub_map
from google.appengine.api import app_identity from google.appengine.api import app_identity
from google.appengine.api import users from google.appengine.api import users
from google.appengine.api import memcache
from google.appengine.api.memcache import memcache_stub from google.appengine.api.memcache import memcache_stub
from google.appengine.ext import db
from google.appengine.ext import testbed from google.appengine.ext import testbed
from google.appengine.runtime import apiproxy_errors from google.appengine.runtime import apiproxy_errors
from oauth2client.anyjson import simplejson from oauth2client.anyjson import simplejson
from oauth2client.appengine import AppAssertionCredentials from oauth2client.appengine import AppAssertionCredentials
from oauth2client.appengine import CredentialsModel
from oauth2client.appengine import OAuth2Decorator from oauth2client.appengine import OAuth2Decorator
from oauth2client.appengine import OAuth2Handler from oauth2client.appengine import OAuth2Handler
from oauth2client.appengine import StorageByKeyName
from oauth2client.client import AccessTokenRefreshError from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import FlowExchangeError from oauth2client.client import FlowExchangeError
from oauth2client.client import OAuth2Credentials
from webtest import TestApp from webtest import TestApp
class UserMock(object): class UserMock(object):
@@ -132,6 +138,75 @@ class TestAppAssertionCredentials(unittest.TestCase):
self.assertEqual('a_token_123', credentials.access_token) self.assertEqual('a_token_123', credentials.access_token)
def _http_request(*args, **kwargs):
resp = httplib2.Response({'status': '200'})
content = simplejson.dumps({'access_token': 'bar'})
return resp, content
class StorageByKeyNameTest(unittest.TestCase):
def setUp(self):
self.testbed = testbed.Testbed()
self.testbed.activate()
self.testbed.init_datastore_v3_stub()
self.testbed.init_memcache_stub()
self.testbed.init_user_stub()
access_token = "foo"
client_id = "some_client_id"
client_secret = "cOuDdkfjxxnv+"
refresh_token = "1/0/a.df219fjls0"
token_expiry = datetime.datetime.utcnow()
token_uri = "https://www.google.com/accounts/o8/oauth2/token"
user_agent = "refresh_checker/1.0"
self.credentials = OAuth2Credentials(
access_token, client_id, client_secret,
refresh_token, token_expiry, token_uri,
user_agent)
def tearDown(self):
self.testbed.deactivate()
def test_get_and_put_simple(self):
storage = StorageByKeyName(
CredentialsModel, 'foo', 'credentials')
self.assertEqual(None, storage.get())
self.credentials.set_store(storage)
self.credentials._refresh(_http_request)
credmodel = CredentialsModel.get_by_key_name('foo')
self.assertEqual('bar', credmodel.credentials.access_token)
def test_get_and_put_cached(self):
storage = StorageByKeyName(
CredentialsModel, 'foo', 'credentials', cache=memcache)
self.assertEqual(None, storage.get())
self.credentials.set_store(storage)
self.credentials._refresh(_http_request)
credmodel = CredentialsModel.get_by_key_name('foo')
self.assertEqual('bar', credmodel.credentials.access_token)
# Now remove the item from the cache.
memcache.delete('foo')
# Check that getting refreshes the cache.
credentials = storage.get()
self.assertEqual('bar', credentials.access_token)
self.assertNotEqual(None, memcache.get('foo'))
# Deleting should clear the cache.
storage.delete()
credentials = storage.get()
self.assertEqual(None, credentials)
self.assertEqual(None, memcache.get('foo'))
class DecoratorTests(unittest.TestCase): class DecoratorTests(unittest.TestCase):
def setUp(self): def setUp(self):