Fix bug in StorageByKeyName.

Reviewed in http://codereview.appspot.com/5782058/.
diff --git a/apiclient/discovery.py b/apiclient/discovery.py
index 0c374ae..0c44516 100644
--- a/apiclient/discovery.py
+++ b/apiclient/discovery.py
@@ -55,6 +55,7 @@
 from email.mime.nonmultipart import MIMENonMultipart
 from oauth2client.anyjson import simplejson
 
+logger = logging.getLogger(__name__)
 
 URITEMPLATE = re.compile('{[^}]*}')
 VARNAME = re.compile('[a-zA-Z0-9_-]+')
@@ -175,7 +176,7 @@
   if 'REMOTE_ADDR' in os.environ:
     requested_url = _add_query_parameter(requested_url, 'userIp',
                                          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)
 
@@ -188,7 +189,7 @@
   try:
     service = simplejson.loads(content)
   except ValueError, e:
-    logging.error('Failed to parse as JSON: ' + content)
+    logger.error('Failed to parse as JSON: ' + content)
     raise InvalidJsonError()
 
   filename = os.path.join(os.path.dirname(__file__), 'contrib',
@@ -536,7 +537,7 @@
                                        'boundary="%s"') % multipart_boundary
             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,
                                   model.response,
                                   url,
@@ -616,7 +617,7 @@
       headers = {}
       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)
 
       return self._requestBuilder(self._http,
@@ -663,7 +664,7 @@
 
       request.uri = uri
 
-      logging.info('URL being requested: %s' % uri)
+      logger.info('URL being requested: %s' % uri)
 
       return request
 
diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py
index 73c48d4..1420279 100644
--- a/oauth2client/appengine.py
+++ b/oauth2client/appengine.py
@@ -224,7 +224,7 @@
       if credential and hasattr(credential, 'set_store'):
         credential.set_store(self)
         if self._cache:
-          self._cache.set(self._key_name, credentials.to_json())
+          self._cache.set(self._key_name, credential.to_json())
 
     return credential
 
diff --git a/runtests.py b/runtests.py
index 8ec0f54..cf97afc 100644
--- a/runtests.py
+++ b/runtests.py
@@ -7,6 +7,8 @@
 import unittest
 from trace import fullmodname
 
+logging.basicConfig(level=logging.CRITICAL)
+
 APP_ENGINE_PATH='../google_appengine'
 
 # Conditional import of cleanup function
diff --git a/tests/test_oauth2client_appengine.py b/tests/test_oauth2client_appengine.py
index 1520ae1..680cea2 100644
--- a/tests/test_oauth2client_appengine.py
+++ b/tests/test_oauth2client_appengine.py
@@ -23,6 +23,7 @@
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
 
 import base64
+import datetime
 import httplib2
 import time
 import unittest
@@ -42,15 +43,20 @@
 from google.appengine.api import apiproxy_stub_map
 from google.appengine.api import app_identity
 from google.appengine.api import users
+from google.appengine.api import memcache
 from google.appengine.api.memcache import memcache_stub
+from google.appengine.ext import db
 from google.appengine.ext import testbed
 from google.appengine.runtime import apiproxy_errors
 from oauth2client.anyjson import simplejson
 from oauth2client.appengine import AppAssertionCredentials
+from oauth2client.appengine import CredentialsModel
 from oauth2client.appengine import OAuth2Decorator
 from oauth2client.appengine import OAuth2Handler
+from oauth2client.appengine import StorageByKeyName
 from oauth2client.client import AccessTokenRefreshError
 from oauth2client.client import FlowExchangeError
+from oauth2client.client import OAuth2Credentials
 from webtest import TestApp
 
 class UserMock(object):
@@ -132,6 +138,75 @@
     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):
 
   def setUp(self):