blob: 14beb972cf8b4715074b7f9ee21143acbb7951c4 [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 Gregorio562b7312011-09-15 09:06:38 -040025import datetime
Joe Gregorioe1de4162011-02-23 11:30:29 -050026import httplib2
Joe Gregorioccc79542011-02-19 00:05:26 -050027import unittest
28import urlparse
Joe Gregorioe1de4162011-02-23 11:30:29 -050029
Joe Gregorioccc79542011-02-19 00:05:26 -050030try:
31 from urlparse import parse_qs
32except ImportError:
33 from cgi import parse_qs
34
Joe Gregorio562b7312011-09-15 09:06:38 -040035try: # pragma: no cover
36 import simplejson
37except ImportError: # pragma: no cover
38 try:
39 # Try to import from django, should work on App Engine
40 from django.utils import simplejson
41 except ImportError:
42 # Should work for Python2.6 and higher.
43 import json as simplejson
44
Joe Gregorioccc79542011-02-19 00:05:26 -050045from apiclient.http import HttpMockSequence
46from oauth2client.client import AccessTokenCredentials
47from oauth2client.client import AccessTokenCredentialsError
48from oauth2client.client import AccessTokenRefreshError
JacobMoshenko8e905102011-06-20 09:53:10 -040049from oauth2client.client import AssertionCredentials
Joe Gregorioccc79542011-02-19 00:05:26 -050050from oauth2client.client import FlowExchangeError
51from oauth2client.client import OAuth2Credentials
52from oauth2client.client import OAuth2WebServerFlow
53
54
55class OAuth2CredentialsTests(unittest.TestCase):
56
57 def setUp(self):
58 access_token = "foo"
59 client_id = "some_client_id"
60 client_secret = "cOuDdkfjxxnv+"
61 refresh_token = "1/0/a.df219fjls0"
Joe Gregorio562b7312011-09-15 09:06:38 -040062 token_expiry = datetime.datetime.utcnow()
Joe Gregorioccc79542011-02-19 00:05:26 -050063 token_uri = "https://www.google.com/accounts/o8/oauth2/token"
64 user_agent = "refresh_checker/1.0"
65 self.credentials = OAuth2Credentials(
66 access_token, client_id, client_secret,
67 refresh_token, token_expiry, token_uri,
68 user_agent)
69
70 def test_token_refresh_success(self):
71 http = HttpMockSequence([
72 ({'status': '401'}, ''),
73 ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'),
74 ({'status': '200'}, 'echo_request_headers'),
75 ])
76 http = self.credentials.authorize(http)
77 resp, content = http.request("http://example.com")
78 self.assertEqual(content['authorization'], 'OAuth 1/3w')
79
80 def test_token_refresh_failure(self):
81 http = HttpMockSequence([
82 ({'status': '401'}, ''),
83 ({'status': '400'}, '{"error":"access_denied"}'),
84 ])
85 http = self.credentials.authorize(http)
86 try:
87 http.request("http://example.com")
88 self.fail("should raise AccessTokenRefreshError exception")
89 except AccessTokenRefreshError:
90 pass
91
92 def test_non_401_error_response(self):
93 http = HttpMockSequence([
94 ({'status': '400'}, ''),
95 ])
96 http = self.credentials.authorize(http)
97 resp, content = http.request("http://example.com")
98 self.assertEqual(400, resp.status)
99
Joe Gregorio562b7312011-09-15 09:06:38 -0400100 def test_to_from_json(self):
101 json = self.credentials.to_json()
102 instance = OAuth2Credentials.from_json(json)
103 self.assertEquals(type(instance), OAuth2Credentials)
104 self.assertEquals(self.credentials.__dict__, instance.__dict__)
105
Joe Gregorioccc79542011-02-19 00:05:26 -0500106
107class AccessTokenCredentialsTests(unittest.TestCase):
108
109 def setUp(self):
110 access_token = "foo"
111 user_agent = "refresh_checker/1.0"
112 self.credentials = AccessTokenCredentials(access_token, user_agent)
113
114 def test_token_refresh_success(self):
115 http = HttpMockSequence([
116 ({'status': '401'}, ''),
117 ])
118 http = self.credentials.authorize(http)
119 try:
120 resp, content = http.request("http://example.com")
121 self.fail("should throw exception if token expires")
122 except AccessTokenCredentialsError:
123 pass
124 except Exception:
125 self.fail("should only throw AccessTokenCredentialsError")
126
127 def test_non_401_error_response(self):
128 http = HttpMockSequence([
129 ({'status': '400'}, ''),
130 ])
131 http = self.credentials.authorize(http)
Joe Gregorio83cd4392011-06-20 10:11:35 -0400132 resp, content = http.request('http://example.com')
Joe Gregorioccc79542011-02-19 00:05:26 -0500133 self.assertEqual(400, resp.status)
134
Joe Gregorio83cd4392011-06-20 10:11:35 -0400135 def test_auth_header_sent(self):
136 http = HttpMockSequence([
137 ({'status': '200'}, 'echo_request_headers'),
138 ])
139 http = self.credentials.authorize(http)
140 resp, content = http.request('http://example.com')
141 self.assertEqual(content['authorization'], 'OAuth foo')
Joe Gregorioccc79542011-02-19 00:05:26 -0500142
JacobMoshenko8e905102011-06-20 09:53:10 -0400143class TestAssertionCredentials(unittest.TestCase):
144 assertion_text = "This is the assertion"
145 assertion_type = "http://www.google.com/assertionType"
146
147 class AssertionCredentialsTestImpl(AssertionCredentials):
148
149 def _generate_assertion(self):
150 return TestAssertionCredentials.assertion_text
151
152 def setUp(self):
153 user_agent = "fun/2.0"
154 self.credentials = self.AssertionCredentialsTestImpl(self.assertion_type,
155 user_agent)
156
157 def test_assertion_body(self):
158 body = urlparse.parse_qs(self.credentials._generate_refresh_request_body())
159 self.assertEqual(body['assertion'][0], self.assertion_text)
160 self.assertEqual(body['assertion_type'][0], self.assertion_type)
161
162 def test_assertion_refresh(self):
163 http = HttpMockSequence([
164 ({'status': '200'}, '{"access_token":"1/3w"}'),
165 ({'status': '200'}, 'echo_request_headers'),
166 ])
167 http = self.credentials.authorize(http)
168 resp, content = http.request("http://example.com")
169 self.assertEqual(content['authorization'], 'OAuth 1/3w')
170
171
Joe Gregorioccc79542011-02-19 00:05:26 -0500172class OAuth2WebServerFlowTest(unittest.TestCase):
173
174 def setUp(self):
175 self.flow = OAuth2WebServerFlow(
176 client_id='client_id+1',
177 client_secret='secret+1',
178 scope='foo',
179 user_agent='unittest-sample/1.0',
180 )
181
182 def test_construct_authorize_url(self):
183 authorize_url = self.flow.step1_get_authorize_url('oob')
184
185 parsed = urlparse.urlparse(authorize_url)
186 q = parse_qs(parsed[4])
187 self.assertEqual(q['client_id'][0], 'client_id+1')
188 self.assertEqual(q['response_type'][0], 'code')
189 self.assertEqual(q['scope'][0], 'foo')
190 self.assertEqual(q['redirect_uri'][0], 'oob')
191
192 def test_exchange_failure(self):
193 http = HttpMockSequence([
JacobMoshenko8e905102011-06-20 09:53:10 -0400194 ({'status': '400'}, '{"error":"invalid_request"}'),
Joe Gregorioccc79542011-02-19 00:05:26 -0500195 ])
196
197 try:
198 credentials = self.flow.step2_exchange('some random code', http)
199 self.fail("should raise exception if exchange doesn't get 200")
200 except FlowExchangeError:
201 pass
202
203 def test_exchange_success(self):
204 http = HttpMockSequence([
205 ({'status': '200'},
206 """{ "access_token":"SlAV32hkKG",
207 "expires_in":3600,
208 "refresh_token":"8xLOxBtZp8" }"""),
209 ])
210
211 credentials = self.flow.step2_exchange('some random code', http)
212 self.assertEqual(credentials.access_token, 'SlAV32hkKG')
213 self.assertNotEqual(credentials.token_expiry, None)
214 self.assertEqual(credentials.refresh_token, '8xLOxBtZp8')
215
Joe Gregorioccc79542011-02-19 00:05:26 -0500216 def test_exchange_no_expires_in(self):
217 http = HttpMockSequence([
218 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
219 "refresh_token":"8xLOxBtZp8" }"""),
220 ])
221
222 credentials = self.flow.step2_exchange('some random code', http)
223 self.assertEqual(credentials.token_expiry, None)
224
225
226if __name__ == '__main__':
227 unittest.main()