blob: c954d5ebd929a2570e046b2f55062a93b261d9c3 [file] [log] [blame]
Joe Gregorio562b7312011-09-15 09:06:38 -04001#!/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
18"""Oauth2client.file tests
19
20Unit tests for oauth2client.file
21"""
22
23__author__ = 'jcgregorio@google.com (Joe Gregorio)'
24
Joe Gregoriod2ee4d82011-09-15 14:32:45 -040025import copy
Joe Beda17311fb2011-09-20 14:43:08 -070026import datetime
27import httplib2
Joe Gregorio562b7312011-09-15 09:06:38 -040028import os
29import pickle
Joe Gregorio9b8bec62012-01-17 11:35:32 -050030import stat
Joe Beda17311fb2011-09-20 14:43:08 -070031import tempfile
Joe Gregorio562b7312011-09-15 09:06:38 -040032import unittest
Joe Gregorio562b7312011-09-15 09:06:38 -040033
Joe Gregoriod2ee4d82011-09-15 14:32:45 -040034from apiclient.http import HttpMockSequence
dhermes@google.coma9eb0bb2013-02-06 09:19:01 -080035from oauth2client import GOOGLE_TOKEN_URI
Joe Gregorio0fd18532012-08-24 15:54:40 -040036from oauth2client import file
37from oauth2client import locked_file
Joe Gregorio549230c2012-01-11 10:38:05 -050038from oauth2client import multistore_file
Joe Gregorioe2233cd2013-01-24 15:46:23 -050039from oauth2client import util
Joe Gregorio549230c2012-01-11 10:38:05 -050040from oauth2client.anyjson import simplejson
Joe Gregorio562b7312011-09-15 09:06:38 -040041from oauth2client.client import AccessTokenCredentials
42from oauth2client.client import AssertionCredentials
Joe Gregorio549230c2012-01-11 10:38:05 -050043from oauth2client.client import OAuth2Credentials
Joe Gregorio562b7312011-09-15 09:06:38 -040044
45
Joe Beda17311fb2011-09-20 14:43:08 -070046FILENAME = tempfile.mktemp('oauth2client_test.data')
Joe Gregorio562b7312011-09-15 09:06:38 -040047
48
49class OAuth2ClientFileTests(unittest.TestCase):
50
51 def tearDown(self):
52 try:
53 os.unlink(FILENAME)
54 except OSError:
55 pass
56
57 def setUp(self):
58 try:
59 os.unlink(FILENAME)
60 except OSError:
61 pass
62
Joe Gregorioe2233cd2013-01-24 15:46:23 -050063 def create_test_credentials(self):
64 access_token = 'foo'
65 client_secret = 'cOuDdkfjxxnv+'
66 refresh_token = '1/0/a.df219fjls0'
67 token_expiry = datetime.datetime.utcnow()
68 token_uri = 'https://www.google.com/accounts/o8/oauth2/token'
69 user_agent = 'refresh_checker/1.0'
70 client_id = 'some_client_id'
71
72 credentials = OAuth2Credentials(
73 access_token, client_id, client_secret,
74 refresh_token, token_expiry, token_uri,
75 user_agent)
76 return credentials
77
Joe Gregorio562b7312011-09-15 09:06:38 -040078 def test_non_existent_file_storage(self):
Joe Gregorio0fd18532012-08-24 15:54:40 -040079 s = file.Storage(FILENAME)
Joe Gregorio562b7312011-09-15 09:06:38 -040080 credentials = s.get()
81 self.assertEquals(None, credentials)
82
Joe Gregorio0fd18532012-08-24 15:54:40 -040083 def test_no_sym_link_credentials(self):
84 if hasattr(os, 'symlink'):
85 SYMFILENAME = FILENAME + '.sym'
86 os.symlink(FILENAME, SYMFILENAME)
87 s = file.Storage(SYMFILENAME)
88 try:
89 s.get()
90 self.fail('Should have raised an exception.')
91 except file.CredentialsFileSymbolicLinkError:
92 pass
93 finally:
94 os.unlink(SYMFILENAME)
95
Joe Gregorio562b7312011-09-15 09:06:38 -040096 def test_pickle_and_json_interop(self):
97 # Write a file with a pickled OAuth2Credentials.
Joe Gregorioe2233cd2013-01-24 15:46:23 -050098 credentials = self.create_test_credentials()
Joe Gregorio562b7312011-09-15 09:06:38 -040099
100 f = open(FILENAME, 'w')
101 pickle.dump(credentials, f)
102 f.close()
103
Joe Gregorioec555842011-10-27 11:10:39 -0400104 # Storage should be not be able to read that object, as the capability to
105 # read and write credentials as pickled objects has been removed.
Joe Gregorio0fd18532012-08-24 15:54:40 -0400106 s = file.Storage(FILENAME)
Joe Gregorioec555842011-10-27 11:10:39 -0400107 read_credentials = s.get()
108 self.assertEquals(None, read_credentials)
Joe Gregorio562b7312011-09-15 09:06:38 -0400109
110 # Now write it back out and confirm it has been rewritten as JSON
111 s.put(credentials)
Joe Gregorio0fd18532012-08-24 15:54:40 -0400112 f = open(FILENAME)
Joe Gregorio562b7312011-09-15 09:06:38 -0400113 data = simplejson.load(f)
114 f.close()
115
116 self.assertEquals(data['access_token'], 'foo')
117 self.assertEquals(data['_class'], 'OAuth2Credentials')
Joe Beda17311fb2011-09-20 14:43:08 -0700118 self.assertEquals(data['_module'], OAuth2Credentials.__module__)
Joe Gregorio562b7312011-09-15 09:06:38 -0400119
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400120 def test_token_refresh(self):
Joe Gregorioe2233cd2013-01-24 15:46:23 -0500121 credentials = self.create_test_credentials()
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400122
Joe Gregorio0fd18532012-08-24 15:54:40 -0400123 s = file.Storage(FILENAME)
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400124 s.put(credentials)
125 credentials = s.get()
126 new_cred = copy.copy(credentials)
127 new_cred.access_token = 'bar'
128 s.put(new_cred)
129
130 credentials._refresh(lambda x: x)
131 self.assertEquals(credentials.access_token, 'bar')
132
Joe Gregorioec75dc12012-02-06 13:40:42 -0500133 def test_credentials_delete(self):
Joe Gregorioe2233cd2013-01-24 15:46:23 -0500134 credentials = self.create_test_credentials()
Joe Gregorioec75dc12012-02-06 13:40:42 -0500135
Joe Gregorio0fd18532012-08-24 15:54:40 -0400136 s = file.Storage(FILENAME)
Joe Gregorioec75dc12012-02-06 13:40:42 -0500137 s.put(credentials)
138 credentials = s.get()
139 self.assertNotEquals(None, credentials)
140 s.delete()
141 credentials = s.get()
142 self.assertEquals(None, credentials)
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400143
Joe Gregorio562b7312011-09-15 09:06:38 -0400144 def test_access_token_credentials(self):
145 access_token = 'foo'
146 user_agent = 'refresh_checker/1.0'
147
148 credentials = AccessTokenCredentials(access_token, user_agent)
149
Joe Gregorio0fd18532012-08-24 15:54:40 -0400150 s = file.Storage(FILENAME)
Joe Gregorio562b7312011-09-15 09:06:38 -0400151 credentials = s.put(credentials)
152 credentials = s.get()
153
154 self.assertNotEquals(None, credentials)
155 self.assertEquals('foo', credentials.access_token)
Joe Gregorio9b8bec62012-01-17 11:35:32 -0500156 mode = os.stat(FILENAME).st_mode
157
158 if os.name == 'posix':
159 self.assertEquals('0600', oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
160
161 def test_read_only_file_fail_lock(self):
Joe Gregorioe2233cd2013-01-24 15:46:23 -0500162 credentials = self.create_test_credentials()
Joe Gregorio9b8bec62012-01-17 11:35:32 -0500163
164 open(FILENAME, 'a+b').close()
165 os.chmod(FILENAME, 0400)
166
167 store = multistore_file.get_credential_storage(
168 FILENAME,
169 credentials.client_id,
170 credentials.user_agent,
171 ['some-scope', 'some-other-scope'])
172
173 store.put(credentials)
174 if os.name == 'posix':
175 self.assertTrue(store._multistore._read_only)
176 os.chmod(FILENAME, 0600)
177
Joe Gregorio0fd18532012-08-24 15:54:40 -0400178 def test_multistore_no_symbolic_link_files(self):
179 if hasattr(os, 'symlink'):
180 SYMFILENAME = FILENAME + 'sym'
181 os.symlink(FILENAME, SYMFILENAME)
182 store = multistore_file.get_credential_storage(
183 SYMFILENAME,
184 'some_client_id',
185 'user-agent/1.0',
186 ['some-scope', 'some-other-scope'])
187 try:
188 store.get()
189 self.fail('Should have raised an exception.')
190 except locked_file.CredentialsFileSymbolicLinkError:
191 pass
192 finally:
193 os.unlink(SYMFILENAME)
Joe Gregorio562b7312011-09-15 09:06:38 -0400194
195 def test_multistore_non_existent_file(self):
196 store = multistore_file.get_credential_storage(
197 FILENAME,
198 'some_client_id',
199 'user-agent/1.0',
Joe Gregoriof2f8a5a2011-10-14 15:11:29 -0400200 ['some-scope', 'some-other-scope'])
Joe Gregorio562b7312011-09-15 09:06:38 -0400201
202 credentials = store.get()
203 self.assertEquals(None, credentials)
204
205 def test_multistore_file(self):
Joe Gregorioe2233cd2013-01-24 15:46:23 -0500206 credentials = self.create_test_credentials()
Joe Gregorio562b7312011-09-15 09:06:38 -0400207
208 store = multistore_file.get_credential_storage(
209 FILENAME,
210 credentials.client_id,
211 credentials.user_agent,
Joe Gregoriof2f8a5a2011-10-14 15:11:29 -0400212 ['some-scope', 'some-other-scope'])
Joe Gregorio562b7312011-09-15 09:06:38 -0400213
214 store.put(credentials)
215 credentials = store.get()
216
217 self.assertNotEquals(None, credentials)
218 self.assertEquals('foo', credentials.access_token)
219
Joe Gregorioec75dc12012-02-06 13:40:42 -0500220 store.delete()
221 credentials = store.get()
222
223 self.assertEquals(None, credentials)
224
Joe Gregorio9b8bec62012-01-17 11:35:32 -0500225 if os.name == 'posix':
226 self.assertEquals('0600', oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
227
Joe Gregorioe2233cd2013-01-24 15:46:23 -0500228 def test_multistore_file_custom_key(self):
229 credentials = self.create_test_credentials()
230
231 custom_key = {'myapp': 'testing', 'clientid': 'some client'}
232 store = multistore_file.get_credential_storage_custom_key(
233 FILENAME, custom_key)
234
235 store.put(credentials)
236 stored_credentials = store.get()
237
238 self.assertNotEquals(None, stored_credentials)
239 self.assertEqual(credentials.access_token, stored_credentials.access_token)
240
241 store.delete()
242 stored_credentials = store.get()
243
244 self.assertEquals(None, stored_credentials)
245
246 def test_multistore_file_custom_string_key(self):
247 credentials = self.create_test_credentials()
248
249 # store with string key
250 store = multistore_file.get_credential_storage_custom_string_key(
251 FILENAME, 'mykey')
252
253 store.put(credentials)
254 stored_credentials = store.get()
255
256 self.assertNotEquals(None, stored_credentials)
257 self.assertEqual(credentials.access_token, stored_credentials.access_token)
258
259 # try retrieving with a dictionary
260 store_dict = multistore_file.get_credential_storage_custom_string_key(
261 FILENAME, {'key': 'mykey'})
262 stored_credentials = store.get()
263 self.assertNotEquals(None, stored_credentials)
264 self.assertEqual(credentials.access_token, stored_credentials.access_token)
265
266 store.delete()
267 stored_credentials = store.get()
268
269 self.assertEquals(None, stored_credentials)
270
271 def test_multistore_file_backwards_compatibility(self):
272 credentials = self.create_test_credentials()
273 scopes = ['scope1', 'scope2']
274
275 # store the credentials using the legacy key method
276 store = multistore_file.get_credential_storage(
277 FILENAME, 'client_id', 'user_agent', scopes)
278 store.put(credentials)
279
280 # retrieve the credentials using a custom key that matches the legacy key
281 key = {'clientId': 'client_id', 'userAgent': 'user_agent',
282 'scope': util.scopes_to_string(scopes)}
283 store = multistore_file.get_credential_storage_custom_key(FILENAME, key)
284 stored_credentials = store.get()
285
286 self.assertEqual(credentials.access_token, stored_credentials.access_token)
287
Joe Gregorio562b7312011-09-15 09:06:38 -0400288if __name__ == '__main__':
289 unittest.main()