1515import unittest2
1616
1717
18- class TestCredentials (unittest2 .TestCase ):
18+ class Test_get_for_service_account_p12 (unittest2 .TestCase ):
1919
20- def test_get_for_service_account_p12_wo_scope (self ):
20+ def _callFUT (self , client_email , private_key_path , scope = None ):
21+ from gcloud .credentials import get_for_service_account_p12
22+ return get_for_service_account_p12 (client_email , private_key_path ,
23+ scope = scope )
24+
25+ def test_wo_scope (self ):
2126 from tempfile import NamedTemporaryFile
2227 from gcloud import credentials
2328 from gcloud ._testing import _Monkey
@@ -28,8 +33,7 @@ def test_get_for_service_account_p12_wo_scope(self):
2833 with NamedTemporaryFile () as file_obj :
2934 file_obj .write (PRIVATE_KEY )
3035 file_obj .flush ()
31- found = credentials .get_for_service_account_p12 (
32- CLIENT_EMAIL , file_obj .name )
36+ found = self ._callFUT (CLIENT_EMAIL , file_obj .name )
3337 self .assertTrue (found is client ._signed )
3438 expected_called_with = {
3539 'service_account_name' : CLIENT_EMAIL ,
@@ -38,7 +42,7 @@ def test_get_for_service_account_p12_wo_scope(self):
3842 }
3943 self .assertEqual (client ._called_with , expected_called_with )
4044
41- def test_get_for_service_account_p12_w_scope (self ):
45+ def test_w_scope (self ):
4246 from tempfile import NamedTemporaryFile
4347 from gcloud import credentials
4448 from gcloud ._testing import _Monkey
@@ -50,8 +54,8 @@ def test_get_for_service_account_p12_w_scope(self):
5054 with NamedTemporaryFile () as file_obj :
5155 file_obj .write (PRIVATE_KEY )
5256 file_obj .flush ()
53- found = credentials . get_for_service_account_p12 (
54- CLIENT_EMAIL , file_obj . name , SCOPE )
57+ found = self . _callFUT ( CLIENT_EMAIL , file_obj . name ,
58+ scope = SCOPE )
5559 self .assertTrue (found is client ._signed )
5660 expected_called_with = {
5761 'service_account_name' : CLIENT_EMAIL ,
@@ -61,6 +65,192 @@ def test_get_for_service_account_p12_w_scope(self):
6165 self .assertEqual (client ._called_with , expected_called_with )
6266
6367
68+ class Test__store_user_credential (unittest2 .TestCase ):
69+
70+ def _callFUT (self , credential ):
71+ from gcloud .credentials import _store_user_credential
72+ return _store_user_credential (credential )
73+
74+ def test_user_input_no (self ):
75+ import six .moves
76+ from gcloud ._testing import _Monkey
77+
78+ _called_messages = []
79+
80+ def fake_input (message ):
81+ _called_messages .append (message )
82+ # 'y' or 'Y' are the only acceptable values.
83+ return 'neither yes nor no'
84+
85+ with _Monkey (six .moves , input = fake_input ):
86+ self ._callFUT (None )
87+
88+ self .assertEqual (
89+ _called_messages ,
90+ ['Would you like to store your tokens for future use? [y/n] ' ])
91+
92+ def test_user_input_yes (self ):
93+ import json
94+ import six .moves
95+ import tempfile
96+
97+ from gcloud ._testing import _Monkey
98+ from oauth2client .client import OAuth2Credentials
99+
100+ _called_messages = []
101+ # In reverse order so we can use .pop().
102+ TEMPFILE = tempfile .mktemp ()
103+ responses = [TEMPFILE , 'y' ]
104+
105+ def fake_input (message ):
106+ _called_messages .append (message )
107+ return responses .pop ()
108+
109+ CLIENT_ID = 'FOO'
110+ CLIENT_SECRET = 'BAR'
111+ REFRESH_TOKEN = 'BAZ'
112+ CREDENTIALS = OAuth2Credentials (None , CLIENT_ID , CLIENT_SECRET ,
113+ REFRESH_TOKEN , None , None , None )
114+ with _Monkey (six .moves , input = fake_input ):
115+ self ._callFUT (CREDENTIALS )
116+
117+ self .assertEqual (
118+ _called_messages ,
119+ ['Would you like to store your tokens for future use? [y/n] ' ,
120+ 'Please name the file where you wish to store them: ' ])
121+
122+ with open (TEMPFILE , 'r' ) as file_obj :
123+ STORED_CREDS = json .load (file_obj )
124+
125+ expected_creds = {
126+ 'client_id' : CLIENT_ID ,
127+ 'client_secret' : CLIENT_SECRET ,
128+ 'refresh_token' : REFRESH_TOKEN ,
129+ 'type' : 'authorized_user' ,
130+ }
131+ self .assertEqual (STORED_CREDS , expected_creds )
132+
133+
134+ class Test_get_credentials_from_user_flow (unittest2 .TestCase ):
135+
136+ def _callFUT (self , scope , client_secrets_file = None ):
137+ from gcloud .credentials import get_credentials_from_user_flow
138+ return get_credentials_from_user_flow (
139+ scope , client_secrets_file = client_secrets_file )
140+
141+ def test_no_tty (self ):
142+ import sys
143+ from gcloud ._testing import _Monkey
144+
145+ STDOUT = _MockStdout (isatty = False )
146+ with _Monkey (sys , stdout = STDOUT ):
147+ with self .assertRaises (EnvironmentError ):
148+ self ._callFUT (None )
149+
150+ def test_filename_from_environ (self ):
151+ import os
152+ import sys
153+
154+ from gcloud ._testing import _Monkey
155+ from oauth2client import client
156+
157+ STDOUT = _MockStdout (isatty = True )
158+ FILENAME = 'FOO'
159+ GCLOUD_KEY = 'GCLOUD_CLIENT_SECRETS'
160+ FAKE_ENVIRON = {GCLOUD_KEY : FILENAME }
161+
162+ _called_keys = []
163+
164+ def fake_getenv (key ):
165+ _called_keys .append (key )
166+ return FAKE_ENVIRON .get (key )
167+
168+ _called_filenames = []
169+
170+ def fake_loadfile (filename ):
171+ _called_filenames .append (filename )
172+ return 'NOT_INSTALLED_TYPE' , None
173+
174+ with _Monkey (sys , stdout = STDOUT ):
175+ with _Monkey (os , getenv = fake_getenv ):
176+ with _Monkey (client .clientsecrets , loadfile = fake_loadfile ):
177+ with self .assertRaises (ValueError ):
178+ self ._callFUT (None )
179+
180+ self .assertEqual (_called_keys , [GCLOUD_KEY ])
181+ self .assertEqual (_called_filenames , [FILENAME ])
182+
183+ def test_succeeds (self ):
184+ import argparse
185+ import sys
186+
187+ from gcloud ._testing import _Monkey
188+ from gcloud import credentials
189+ from oauth2client import client
190+ from oauth2client .file import Storage
191+ from oauth2client import tools
192+
193+ STDOUT = _MockStdout (isatty = True )
194+ SCOPE = 'SCOPE'
195+ FILENAME = 'FILENAME'
196+ REDIRECT_URI = 'REDIRECT_URI'
197+ MOCK_CLIENT_INFO = {'redirect_uris' : [REDIRECT_URI ]}
198+ FLOW = object ()
199+ CLIENT_ID = 'FOO'
200+ CLIENT_SECRET = 'BAR'
201+ REFRESH_TOKEN = 'BAZ'
202+ CREDENTIALS = client .OAuth2Credentials (None , CLIENT_ID , CLIENT_SECRET ,
203+ REFRESH_TOKEN , None , None , None )
204+
205+ _called_loadfile = []
206+
207+ def fake_loadfile (* args , ** kwargs ):
208+ _called_loadfile .append ((args , kwargs ))
209+ return client .clientsecrets .TYPE_INSTALLED , MOCK_CLIENT_INFO
210+
211+ _called_flow_from_clientsecrets = []
212+
213+ def mock_flow (client_secrets_file , scope , redirect_uri = None ):
214+ _called_flow_from_clientsecrets .append (
215+ (client_secrets_file , scope , redirect_uri ))
216+ return FLOW
217+
218+ _called_run_flow = []
219+
220+ def mock_run_flow (flow , storage , flags ):
221+ _called_run_flow .append ((flow , storage , flags ))
222+ return CREDENTIALS
223+
224+ _called_store_user_credential = []
225+
226+ def store_cred (credential ):
227+ _called_store_user_credential .append (credential )
228+
229+ with _Monkey (sys , stdout = STDOUT ):
230+ with _Monkey (client .clientsecrets , loadfile = fake_loadfile ):
231+ with _Monkey (client , flow_from_clientsecrets = mock_flow ):
232+ with _Monkey (tools , run_flow = mock_run_flow ):
233+ with _Monkey (credentials ,
234+ _store_user_credential = store_cred ):
235+ with _Monkey (argparse ,
236+ ArgumentParser = _MockArgumentParser ):
237+ self ._callFUT (SCOPE ,
238+ client_secrets_file = FILENAME )
239+
240+ self .assertEqual (_called_loadfile , [((FILENAME ,), {})])
241+ self .assertEqual (_called_flow_from_clientsecrets ,
242+ [(FILENAME , SCOPE , REDIRECT_URI )])
243+
244+ # Unpack expects a single output
245+ run_flow_input , = _called_run_flow
246+ self .assertEqual (len (run_flow_input ), 3 )
247+ self .assertEqual (run_flow_input [0 ], FLOW )
248+ self .assertTrue (isinstance (run_flow_input [1 ], Storage ))
249+ self .assertTrue (run_flow_input [2 ] is _MockArgumentParser ._MARKER )
250+
251+ self .assertEqual (_called_store_user_credential , [CREDENTIALS ])
252+
253+
64254class _Credentials (object ):
65255
66256 service_account_name = 'testing@example.com'
@@ -85,3 +275,24 @@ def get_application_default():
85275 def SignedJwtAssertionCredentials (self , ** kw ):
86276 self ._called_with = kw
87277 return self ._signed
278+
279+
280+ class _MockStdout (object ):
281+
282+ def __init__ (self , isatty = True ):
283+ self ._isatty = isatty
284+
285+ def isatty (self ):
286+ return self ._isatty
287+
288+
289+ class _MockArgumentParser (object ):
290+
291+ _MARKER = object ()
292+
293+ def __init__ (self , * args , ** kwargs ):
294+ self ._args = args
295+ self ._kwargs = kwargs
296+
297+ def parse_args (self ):
298+ return self ._MARKER
0 commit comments