blob: 8f855d4f40e78dbe4030beed78ad48fa791e4bd4 [file] [log] [blame]
Joe Gregorioccc79542011-02-19 00:05:26 -05001#!/usr/bin/python2.4
2#
3# Copyright 2010 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17
Joe Gregorio0bc70912011-05-24 15:30:49 -040018"""Oauth2client tests
Joe Gregorioccc79542011-02-19 00:05:26 -050019
Joe Gregorio0bc70912011-05-24 15:30:49 -040020Unit tests for oauth2client.
Joe Gregorioccc79542011-02-19 00:05:26 -050021"""
22
23__author__ = 'jcgregorio@google.com (Joe Gregorio)'
24
Joe Gregorio8b4c1732011-12-06 11:28:29 -050025import base64
Joe Gregorio562b7312011-09-15 09:06:38 -040026import datetime
Joe Gregorioe1de4162011-02-23 11:30:29 -050027import httplib2
Joe Gregorio32d852d2012-06-14 09:08:18 -040028import os
Joe Gregorioccc79542011-02-19 00:05:26 -050029import unittest
30import urlparse
Joe Gregorioe1de4162011-02-23 11:30:29 -050031
Joe Gregorioccc79542011-02-19 00:05:26 -050032try:
33 from urlparse import parse_qs
34except ImportError:
35 from cgi import parse_qs
36
37from apiclient.http import HttpMockSequence
Joe Gregorio549230c2012-01-11 10:38:05 -050038from oauth2client.anyjson import simplejson
Joe Gregorioc29aaa92012-07-16 16:16:31 -040039from oauth2client.clientsecrets import _loadfile
Joe Gregorioccc79542011-02-19 00:05:26 -050040from oauth2client.client import AccessTokenCredentials
41from oauth2client.client import AccessTokenCredentialsError
42from oauth2client.client import AccessTokenRefreshError
JacobMoshenko8e905102011-06-20 09:53:10 -040043from oauth2client.client import AssertionCredentials
Joe Gregorio08cdcb82012-03-14 00:09:33 -040044from oauth2client.client import Credentials
Joe Gregorioccc79542011-02-19 00:05:26 -050045from oauth2client.client import FlowExchangeError
Joe Gregorio08cdcb82012-03-14 00:09:33 -040046from oauth2client.client import MemoryCache
Joe Gregorioccc79542011-02-19 00:05:26 -050047from oauth2client.client import OAuth2Credentials
48from oauth2client.client import OAuth2WebServerFlow
Joe Gregoriof2326c02012-02-09 12:18:44 -050049from oauth2client.client import OOB_CALLBACK_URN
Joe Gregorio8b4c1732011-12-06 11:28:29 -050050from oauth2client.client import VerifyJwtTokenError
51from oauth2client.client import _extract_id_token
Joe Gregorio32d852d2012-06-14 09:08:18 -040052from oauth2client.client import credentials_from_code
53from oauth2client.client import credentials_from_clientsecrets_and_code
Joe Gregorioc29aaa92012-07-16 16:16:31 -040054from oauth2client.client import flow_from_clientsecrets
Joe Gregorio32d852d2012-06-14 09:08:18 -040055
56DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
57
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040058
Joe Gregorio32d852d2012-06-14 09:08:18 -040059def datafile(filename):
60 return os.path.join(DATA_DIR, filename)
Joe Gregorioccc79542011-02-19 00:05:26 -050061
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040062
Joe Gregorioc29aaa92012-07-16 16:16:31 -040063def load_and_cache(existing_file, fakename, cache_mock):
64 client_type, client_info = _loadfile(datafile(existing_file))
65 cache_mock.cache[fakename] = {client_type: client_info}
66
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040067
Joe Gregorioc29aaa92012-07-16 16:16:31 -040068class CacheMock(object):
69 def __init__(self):
70 self.cache = {}
71
72 def get(self, key, namespace=''):
73 # ignoring namespace for easier testing
74 return self.cache.get(key, None)
75
76 def set(self, key, value, namespace=''):
77 # ignoring namespace for easier testing
78 self.cache[key] = value
79
Joe Gregorioccc79542011-02-19 00:05:26 -050080
Joe Gregorio08cdcb82012-03-14 00:09:33 -040081class CredentialsTests(unittest.TestCase):
82
83 def test_to_from_json(self):
84 credentials = Credentials()
85 json = credentials.to_json()
86 restored = Credentials.new_from_json(json)
87
88
Joe Gregorioccc79542011-02-19 00:05:26 -050089class OAuth2CredentialsTests(unittest.TestCase):
90
91 def setUp(self):
92 access_token = "foo"
93 client_id = "some_client_id"
94 client_secret = "cOuDdkfjxxnv+"
95 refresh_token = "1/0/a.df219fjls0"
Joe Gregorio562b7312011-09-15 09:06:38 -040096 token_expiry = datetime.datetime.utcnow()
Joe Gregorioccc79542011-02-19 00:05:26 -050097 token_uri = "https://www.google.com/accounts/o8/oauth2/token"
98 user_agent = "refresh_checker/1.0"
99 self.credentials = OAuth2Credentials(
100 access_token, client_id, client_secret,
101 refresh_token, token_expiry, token_uri,
102 user_agent)
103
104 def test_token_refresh_success(self):
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400105 # Older API (GData) respond with 403
106 for status_code in ['401', '403']:
107 http = HttpMockSequence([
108 ({'status': status_code}, ''),
109 ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'),
110 ({'status': '200'}, 'echo_request_headers'),
111 ])
112 http = self.credentials.authorize(http)
113 resp, content = http.request("http://example.com")
114 self.assertEqual('Bearer 1/3w', content['Authorization'])
115 self.assertFalse(self.credentials.access_token_expired)
Joe Gregorioccc79542011-02-19 00:05:26 -0500116
117 def test_token_refresh_failure(self):
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400118 # Older API (GData) respond with 403
119 for status_code in ['401', '403']:
120 http = HttpMockSequence([
121 ({'status': status_code}, ''),
122 ({'status': '400'}, '{"error":"access_denied"}'),
123 ])
124 http = self.credentials.authorize(http)
125 try:
126 http.request("http://example.com")
127 self.fail("should raise AccessTokenRefreshError exception")
128 except AccessTokenRefreshError:
129 pass
130 self.assertTrue(self.credentials.access_token_expired)
Joe Gregorioccc79542011-02-19 00:05:26 -0500131
132 def test_non_401_error_response(self):
133 http = HttpMockSequence([
134 ({'status': '400'}, ''),
135 ])
136 http = self.credentials.authorize(http)
137 resp, content = http.request("http://example.com")
138 self.assertEqual(400, resp.status)
139
Joe Gregorio562b7312011-09-15 09:06:38 -0400140 def test_to_from_json(self):
141 json = self.credentials.to_json()
142 instance = OAuth2Credentials.from_json(json)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500143 self.assertEqual(OAuth2Credentials, type(instance))
Joe Gregorio1daa71b2011-09-15 18:12:14 -0400144 instance.token_expiry = None
145 self.credentials.token_expiry = None
146
Joe Gregorio654f4a22012-02-09 14:15:44 -0500147 self.assertEqual(instance.__dict__, self.credentials.__dict__)
Joe Gregorio562b7312011-09-15 09:06:38 -0400148
Joe Gregorioccc79542011-02-19 00:05:26 -0500149
150class AccessTokenCredentialsTests(unittest.TestCase):
151
152 def setUp(self):
153 access_token = "foo"
154 user_agent = "refresh_checker/1.0"
155 self.credentials = AccessTokenCredentials(access_token, user_agent)
156
157 def test_token_refresh_success(self):
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400158 # Older API (GData) respond with 403
159 for status_code in ['401', '403']:
160 http = HttpMockSequence([
161 ({'status': status_code}, ''),
162 ])
163 http = self.credentials.authorize(http)
164 try:
165 resp, content = http.request("http://example.com")
166 self.fail("should throw exception if token expires")
167 except AccessTokenCredentialsError:
168 pass
169 except Exception:
170 self.fail("should only throw AccessTokenCredentialsError")
Joe Gregorioccc79542011-02-19 00:05:26 -0500171
172 def test_non_401_error_response(self):
173 http = HttpMockSequence([
174 ({'status': '400'}, ''),
175 ])
176 http = self.credentials.authorize(http)
Joe Gregorio83cd4392011-06-20 10:11:35 -0400177 resp, content = http.request('http://example.com')
Joe Gregorioccc79542011-02-19 00:05:26 -0500178 self.assertEqual(400, resp.status)
179
Joe Gregorio83cd4392011-06-20 10:11:35 -0400180 def test_auth_header_sent(self):
181 http = HttpMockSequence([
182 ({'status': '200'}, 'echo_request_headers'),
183 ])
184 http = self.credentials.authorize(http)
185 resp, content = http.request('http://example.com')
Joe Gregorio654f4a22012-02-09 14:15:44 -0500186 self.assertEqual('Bearer foo', content['Authorization'])
Joe Gregorioccc79542011-02-19 00:05:26 -0500187
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500188
JacobMoshenko8e905102011-06-20 09:53:10 -0400189class TestAssertionCredentials(unittest.TestCase):
190 assertion_text = "This is the assertion"
191 assertion_type = "http://www.google.com/assertionType"
192
193 class AssertionCredentialsTestImpl(AssertionCredentials):
194
195 def _generate_assertion(self):
196 return TestAssertionCredentials.assertion_text
197
198 def setUp(self):
199 user_agent = "fun/2.0"
200 self.credentials = self.AssertionCredentialsTestImpl(self.assertion_type,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400201 user_agent=user_agent)
JacobMoshenko8e905102011-06-20 09:53:10 -0400202
203 def test_assertion_body(self):
204 body = urlparse.parse_qs(self.credentials._generate_refresh_request_body())
Joe Gregorio654f4a22012-02-09 14:15:44 -0500205 self.assertEqual(self.assertion_text, body['assertion'][0])
206 self.assertEqual(self.assertion_type, body['assertion_type'][0])
JacobMoshenko8e905102011-06-20 09:53:10 -0400207
208 def test_assertion_refresh(self):
209 http = HttpMockSequence([
210 ({'status': '200'}, '{"access_token":"1/3w"}'),
211 ({'status': '200'}, 'echo_request_headers'),
212 ])
213 http = self.credentials.authorize(http)
214 resp, content = http.request("http://example.com")
Joe Gregorio654f4a22012-02-09 14:15:44 -0500215 self.assertEqual('Bearer 1/3w', content['Authorization'])
JacobMoshenko8e905102011-06-20 09:53:10 -0400216
217
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500218class ExtractIdTokenText(unittest.TestCase):
219 """Tests _extract_id_token()."""
220
221 def test_extract_success(self):
222 body = {'foo': 'bar'}
223 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
224 jwt = 'stuff.' + payload + '.signature'
225
226 extracted = _extract_id_token(jwt)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500227 self.assertEqual(extracted, body)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500228
229 def test_extract_failure(self):
230 body = {'foo': 'bar'}
231 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
232 jwt = 'stuff.' + payload
233
234 self.assertRaises(VerifyJwtTokenError, _extract_id_token, jwt)
235
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400236
Joe Gregorioccc79542011-02-19 00:05:26 -0500237class OAuth2WebServerFlowTest(unittest.TestCase):
238
239 def setUp(self):
240 self.flow = OAuth2WebServerFlow(
241 client_id='client_id+1',
242 client_secret='secret+1',
243 scope='foo',
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400244 redirect_uri=OOB_CALLBACK_URN,
Joe Gregorioccc79542011-02-19 00:05:26 -0500245 user_agent='unittest-sample/1.0',
246 )
247
248 def test_construct_authorize_url(self):
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400249 authorize_url = self.flow.step1_get_authorize_url()
Joe Gregorioccc79542011-02-19 00:05:26 -0500250
251 parsed = urlparse.urlparse(authorize_url)
252 q = parse_qs(parsed[4])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500253 self.assertEqual('client_id+1', q['client_id'][0])
254 self.assertEqual('code', q['response_type'][0])
255 self.assertEqual('foo', q['scope'][0])
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400256 self.assertEqual(OOB_CALLBACK_URN, q['redirect_uri'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500257 self.assertEqual('offline', q['access_type'][0])
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400258
Joe Gregorio32f73192012-10-23 16:13:44 -0400259 def test_override_flow_via_kwargs(self):
260 """Passing kwargs to override defaults."""
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400261 flow = OAuth2WebServerFlow(
262 client_id='client_id+1',
263 client_secret='secret+1',
264 scope='foo',
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400265 redirect_uri=OOB_CALLBACK_URN,
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400266 user_agent='unittest-sample/1.0',
Joe Gregorio32f73192012-10-23 16:13:44 -0400267 access_type='online',
268 response_type='token'
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400269 )
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400270 authorize_url = flow.step1_get_authorize_url()
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400271
272 parsed = urlparse.urlparse(authorize_url)
273 q = parse_qs(parsed[4])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500274 self.assertEqual('client_id+1', q['client_id'][0])
Joe Gregorio32f73192012-10-23 16:13:44 -0400275 self.assertEqual('token', q['response_type'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500276 self.assertEqual('foo', q['scope'][0])
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400277 self.assertEqual(OOB_CALLBACK_URN, q['redirect_uri'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500278 self.assertEqual('online', q['access_type'][0])
Joe Gregorioccc79542011-02-19 00:05:26 -0500279
280 def test_exchange_failure(self):
281 http = HttpMockSequence([
JacobMoshenko8e905102011-06-20 09:53:10 -0400282 ({'status': '400'}, '{"error":"invalid_request"}'),
Joe Gregorioccc79542011-02-19 00:05:26 -0500283 ])
284
285 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400286 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioccc79542011-02-19 00:05:26 -0500287 self.fail("should raise exception if exchange doesn't get 200")
288 except FlowExchangeError:
289 pass
290
Joe Gregorioddb969a2012-07-11 11:04:12 -0400291 def test_urlencoded_exchange_failure(self):
292 http = HttpMockSequence([
293 ({'status': '400'}, "error=invalid_request"),
294 ])
295
296 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400297 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400298 self.fail("should raise exception if exchange doesn't get 200")
299 except FlowExchangeError, e:
300 self.assertEquals('invalid_request', str(e))
301
302 def test_exchange_failure_with_json_error(self):
303 # Some providers have "error" attribute as a JSON object
304 # in place of regular string.
305 # This test makes sure no strange object-to-string coversion
306 # exceptions are being raised instead of FlowExchangeError.
307 http = HttpMockSequence([
308 ({'status': '400'},
309 """ {"error": {
310 "type": "OAuthException",
311 "message": "Error validating verification code."} }"""),
312 ])
313
314 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400315 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400316 self.fail("should raise exception if exchange doesn't get 200")
317 except FlowExchangeError, e:
318 pass
319
Joe Gregorioccc79542011-02-19 00:05:26 -0500320 def test_exchange_success(self):
321 http = HttpMockSequence([
322 ({'status': '200'},
323 """{ "access_token":"SlAV32hkKG",
324 "expires_in":3600,
325 "refresh_token":"8xLOxBtZp8" }"""),
326 ])
327
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400328 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500329 self.assertEqual('SlAV32hkKG', credentials.access_token)
330 self.assertNotEqual(None, credentials.token_expiry)
331 self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
Joe Gregorioccc79542011-02-19 00:05:26 -0500332
Joe Gregorioddb969a2012-07-11 11:04:12 -0400333 def test_urlencoded_exchange_success(self):
334 http = HttpMockSequence([
335 ({'status': '200'}, "access_token=SlAV32hkKG&expires_in=3600"),
336 ])
337
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400338 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400339 self.assertEqual('SlAV32hkKG', credentials.access_token)
340 self.assertNotEqual(None, credentials.token_expiry)
341
342 def test_urlencoded_expires_param(self):
343 http = HttpMockSequence([
344 # Note the "expires=3600" where you'd normally
345 # have if named "expires_in"
346 ({'status': '200'}, "access_token=SlAV32hkKG&expires=3600"),
347 ])
348
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400349 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400350 self.assertNotEqual(None, credentials.token_expiry)
351
Joe Gregorioccc79542011-02-19 00:05:26 -0500352 def test_exchange_no_expires_in(self):
353 http = HttpMockSequence([
354 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
355 "refresh_token":"8xLOxBtZp8" }"""),
356 ])
357
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400358 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500359 self.assertEqual(None, credentials.token_expiry)
Joe Gregorioccc79542011-02-19 00:05:26 -0500360
Joe Gregorioddb969a2012-07-11 11:04:12 -0400361 def test_urlencoded_exchange_no_expires_in(self):
362 http = HttpMockSequence([
363 # This might be redundant but just to make sure
364 # urlencoded access_token gets parsed correctly
365 ({'status': '200'}, "access_token=SlAV32hkKG"),
366 ])
367
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400368 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400369 self.assertEqual(None, credentials.token_expiry)
370
Joe Gregorio4b4002f2012-06-14 15:41:01 -0400371 def test_exchange_fails_if_no_code(self):
372 http = HttpMockSequence([
373 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
374 "refresh_token":"8xLOxBtZp8" }"""),
375 ])
376
377 code = {'error': 'thou shall not pass'}
378 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400379 credentials = self.flow.step2_exchange(code, http=http)
Joe Gregorio4b4002f2012-06-14 15:41:01 -0400380 self.fail('should raise exception if no code in dictionary.')
381 except FlowExchangeError, e:
382 self.assertTrue('shall not pass' in str(e))
383
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500384 def test_exchange_id_token_fail(self):
385 http = HttpMockSequence([
386 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
387 "refresh_token":"8xLOxBtZp8",
388 "id_token": "stuff.payload"}"""),
389 ])
390
391 self.assertRaises(VerifyJwtTokenError, self.flow.step2_exchange,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400392 'some random code', http=http)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500393
394 def test_exchange_id_token_fail(self):
395 body = {'foo': 'bar'}
396 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
Joe Gregoriobd512b52011-12-06 15:39:26 -0500397 jwt = (base64.urlsafe_b64encode('stuff')+ '.' + payload + '.' +
398 base64.urlsafe_b64encode('signature'))
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500399
400 http = HttpMockSequence([
401 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
402 "refresh_token":"8xLOxBtZp8",
403 "id_token": "%s"}""" % jwt),
404 ])
405
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400406 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500407 self.assertEqual(credentials.id_token, body)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500408
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400409
410class FlowFromCachedClientsecrets(unittest.TestCase):
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400411
412 def test_flow_from_clientsecrets_cached(self):
413 cache_mock = CacheMock()
414 load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400415
416 flow = flow_from_clientsecrets(
417 'some_secrets', '', redirect_uri='oob', cache=cache_mock)
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400418 self.assertEquals('foo_client_secret', flow.client_secret)
419
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400420
Joe Gregorio32d852d2012-06-14 09:08:18 -0400421class CredentialsFromCodeTests(unittest.TestCase):
422 def setUp(self):
423 self.client_id = 'client_id_abc'
424 self.client_secret = 'secret_use_code'
425 self.scope = 'foo'
426 self.code = '12345abcde'
427 self.redirect_uri = 'postmessage'
428
429 def test_exchange_code_for_token(self):
430 http = HttpMockSequence([
431 ({'status': '200'},
432 """{ "access_token":"asdfghjkl",
433 "expires_in":3600 }"""),
434 ])
435 credentials = credentials_from_code(self.client_id, self.client_secret,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400436 self.scope, self.code, redirect_uri=self.redirect_uri,
437 http=http)
Joe Gregorio32d852d2012-06-14 09:08:18 -0400438 self.assertEquals(credentials.access_token, 'asdfghjkl')
439 self.assertNotEqual(None, credentials.token_expiry)
440
441 def test_exchange_code_for_token_fail(self):
442 http = HttpMockSequence([
443 ({'status': '400'}, '{"error":"invalid_request"}'),
444 ])
445
446 try:
447 credentials = credentials_from_code(self.client_id, self.client_secret,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400448 self.scope, self.code, redirect_uri=self.redirect_uri,
449 http=http)
Joe Gregorio32d852d2012-06-14 09:08:18 -0400450 self.fail("should raise exception if exchange doesn't get 200")
451 except FlowExchangeError:
452 pass
453
Joe Gregorio32d852d2012-06-14 09:08:18 -0400454 def test_exchange_code_and_file_for_token(self):
455 http = HttpMockSequence([
456 ({'status': '200'},
457 """{ "access_token":"asdfghjkl",
458 "expires_in":3600 }"""),
459 ])
460 credentials = credentials_from_clientsecrets_and_code(
461 datafile('client_secrets.json'), self.scope,
462 self.code, http=http)
463 self.assertEquals(credentials.access_token, 'asdfghjkl')
464 self.assertNotEqual(None, credentials.token_expiry)
465
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400466 def test_exchange_code_and_cached_file_for_token(self):
467 http = HttpMockSequence([
468 ({'status': '200'}, '{ "access_token":"asdfghjkl"}'),
469 ])
470 cache_mock = CacheMock()
471 load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
472
473 credentials = credentials_from_clientsecrets_and_code(
474 'some_secrets', self.scope,
475 self.code, http=http, cache=cache_mock)
476 self.assertEquals(credentials.access_token, 'asdfghjkl')
477
Joe Gregorio32d852d2012-06-14 09:08:18 -0400478 def test_exchange_code_and_file_for_token_fail(self):
479 http = HttpMockSequence([
480 ({'status': '400'}, '{"error":"invalid_request"}'),
481 ])
482
483 try:
484 credentials = credentials_from_clientsecrets_and_code(
485 datafile('client_secrets.json'), self.scope,
486 self.code, http=http)
487 self.fail("should raise exception if exchange doesn't get 200")
488 except FlowExchangeError:
489 pass
490
491
Joe Gregorio08cdcb82012-03-14 00:09:33 -0400492class MemoryCacheTests(unittest.TestCase):
493
494 def test_get_set_delete(self):
495 m = MemoryCache()
496 self.assertEqual(None, m.get('foo'))
497 self.assertEqual(None, m.delete('foo'))
498 m.set('foo', 'bar')
499 self.assertEqual('bar', m.get('foo'))
500 m.delete('foo')
501 self.assertEqual(None, m.get('foo'))
502
503
Joe Gregorioccc79542011-02-19 00:05:26 -0500504if __name__ == '__main__':
505 unittest.main()