4944bb958c00ffac229f56f69a6bb0d41b81cdf7
[arvados.git] / spec / google / api_client_spec.rb
1 # Copyright 2010 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 require 'spec_helper'
16
17 require 'faraday'
18 require 'signet/oauth_1/client'
19 require 'google/api_client'
20
21 shared_examples_for 'configurable user agent' do
22   include ConnectionHelpers
23   
24   it 'should allow the user agent to be modified' do
25     client.user_agent = 'Custom User Agent/1.2.3'
26     expect(client.user_agent).to eq('Custom User Agent/1.2.3')
27   end
28
29   it 'should allow the user agent to be set to nil' do
30     client.user_agent = nil
31     expect(client.user_agent).to eq(nil)
32   end
33
34   it 'should not allow the user agent to be used with bogus values' do
35     expect(lambda do
36       client.user_agent = 42
37       client.execute(:uri=>'https://www.google.com/')
38     end).to raise_error(TypeError)
39   end
40
41   it 'should transmit a User-Agent header when sending requests' do
42     client.user_agent = 'Custom User Agent/1.2.3'
43
44     conn = stub_connection do |stub|
45       stub.get('/') do |env|
46         headers = env[:request_headers]
47         expect(headers).to have_key('User-Agent')
48         expect(headers['User-Agent']).to eq(client.user_agent)
49         [200, {}, ['']]
50       end
51     end
52     client.execute(:uri=>'https://www.google.com/', :connection => conn)
53     conn.verify
54   end
55 end
56
57 describe Google::APIClient do
58   include ConnectionHelpers
59
60   let(:client) { Google::APIClient.new(:application_name => 'API Client Tests') }
61
62   it 'should make its version number available' do
63     expect(Google::APIClient::VERSION::STRING).to be_instance_of(String)
64   end
65
66   it 'should default to OAuth 2' do
67     expect(Signet::OAuth2::Client).to be === client.authorization
68   end
69
70   describe 'configure for no authentication' do
71     before do
72       client.authorization = nil
73     end
74     it_should_behave_like 'configurable user agent'
75   end
76     
77   describe 'configured for OAuth 1' do
78     before do
79       client.authorization = :oauth_1
80       client.authorization.token_credential_key = 'abc'
81       client.authorization.token_credential_secret = '123'
82     end
83
84     it 'should use the default OAuth1 client configuration' do
85       expect(client.authorization.temporary_credential_uri.to_s).to eq(
86         'https://www.google.com/accounts/OAuthGetRequestToken'
87       )
88       expect(client.authorization.authorization_uri.to_s).to include(
89         'https://www.google.com/accounts/OAuthAuthorizeToken'
90       )
91       expect(client.authorization.token_credential_uri.to_s).to eq(
92         'https://www.google.com/accounts/OAuthGetAccessToken'
93       )
94       expect(client.authorization.client_credential_key).to eq('anonymous')
95       expect(client.authorization.client_credential_secret).to eq('anonymous')
96     end
97
98     it_should_behave_like 'configurable user agent'
99   end
100
101   describe 'configured for OAuth 2' do
102     before do
103       client.authorization = :oauth_2
104       client.authorization.access_token = '12345'
105     end
106
107     # TODO
108     it_should_behave_like 'configurable user agent'
109   end
110   
111   describe 'when executing requests' do
112     before do
113       @prediction = client.discovered_api('prediction', 'v1.2')
114       client.authorization = :oauth_2
115       @connection = stub_connection do |stub|
116         stub.post('/prediction/v1.2/training?data=12345') do |env|
117           expect(env[:request_headers]['Authorization']).to eq('Bearer 12345')
118           [200, {}, '{}']
119         end
120       end
121     end
122
123     after do
124       @connection.verify
125     end
126     
127     it 'should use default authorization' do
128       client.authorization.access_token = "12345"
129       client.execute(  
130         :api_method => @prediction.training.insert,
131         :parameters => {'data' => '12345'},
132         :connection => @connection
133       )
134     end
135
136     it 'should use request scoped authorization when provided' do
137       client.authorization.access_token = "abcdef"
138       new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
139       client.execute(  
140         :api_method => @prediction.training.insert,
141         :parameters => {'data' => '12345'},
142         :authorization => new_auth,
143         :connection => @connection
144       )
145     end
146     
147     it 'should accept options with batch/request style execute' do
148       client.authorization.access_token = "abcdef"
149       new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
150       request = client.generate_request(
151         :api_method => @prediction.training.insert,
152         :parameters => {'data' => '12345'}
153       )
154       client.execute(
155         request,
156         :authorization => new_auth,
157         :connection => @connection
158       )
159     end
160     
161     
162     it 'should accept options in array style execute' do
163        client.authorization.access_token = "abcdef"
164        new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
165        client.execute(  
166          @prediction.training.insert, {'data' => '12345'}, '', {},
167          { :authorization => new_auth, :connection => @connection }         
168        )
169      end
170   end  
171
172   describe 'when retries enabled' do
173     before do
174       client.retries = 2
175     end
176
177     after do
178       @connection.verify
179     end
180     
181     it 'should follow redirects' do
182       client.authorization = nil
183       @connection = stub_connection do |stub|
184         stub.get('/foo') do |env|
185           [302, {'location' => 'https://www.google.com/bar'}, '{}']
186         end
187         stub.get('/bar') do |env|
188           [200, {}, '{}']
189         end
190       end
191
192       client.execute(  
193         :uri => 'https://www.gogole.com/foo',
194         :connection => @connection
195       )
196     end
197
198     it 'should refresh tokens on 401 tokens' do
199       client.authorization.access_token = '12345'
200       expect(client.authorization).to receive(:fetch_access_token!)
201
202       @connection = stub_connection do |stub|
203         stub.get('/foo') do |env|
204           [401, {}, '{}']
205         end
206         stub.get('/foo') do |env|
207           [200, {}, '{}']
208         end
209       end
210
211       client.execute(  
212         :uri => 'https://www.gogole.com/foo',
213         :connection => @connection
214       )
215     end
216
217
218     it 'should not attempt multiple token refreshes' do
219       client.authorization.access_token = '12345'
220       expect(client.authorization).to receive(:fetch_access_token!).once
221
222       @connection = stub_connection do |stub|
223         stub.get('/foo') do |env|
224           [401, {}, '{}']
225         end
226       end
227
228       client.execute(  
229         :uri => 'https://www.gogole.com/foo',
230         :connection => @connection
231       )
232     end
233
234     it 'should not retry on client errors' do
235       count = 0
236       @connection = stub_connection do |stub|
237         stub.get('/foo') do |env|
238           expect(count).to eq(0)
239           count += 1
240           [403, {}, '{}']
241         end
242       end
243
244       client.execute(  
245         :uri => 'https://www.gogole.com/foo',
246         :connection => @connection,
247         :authenticated => false
248       )
249     end
250
251     it 'should retry on 500 errors' do
252       client.authorization = nil
253
254       @connection = stub_connection do |stub|
255         stub.get('/foo') do |env|
256           [500, {}, '{}']
257         end
258         stub.get('/foo') do |env|
259           [200, {}, '{}']
260         end
261       end
262
263       expect(client.execute(  
264         :uri => 'https://www.gogole.com/foo',
265         :connection => @connection
266       ).status).to eq(200)
267
268     end
269
270     it 'should fail after max retries' do
271       client.authorization = nil
272       count = 0
273       @connection = stub_connection do |stub|
274         stub.get('/foo') do |env|
275           count += 1
276           [500, {}, '{}']
277         end
278       end
279
280       expect(client.execute(  
281         :uri => 'https://www.gogole.com/foo',
282         :connection => @connection
283       ).status).to eq(500)
284       expect(count).to eq(3)
285     end
286
287   end  
288 end