Merge branch 'master' of ../martinsarsale-support-for-repeats
[arvados.git] / spec / google / api_client / discovery_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 'json'
18 require 'signet/oauth_1/client'
19 require 'httpadapter/adapters/net_http'
20
21 require 'google/api_client'
22 require 'google/api_client/version'
23 require 'google/api_client/parsers/json_parser'
24
25 describe Google::APIClient do
26   before do
27     @client = Google::APIClient.new
28   end
29
30   it 'should raise a type error for bogus authorization' do
31     (lambda do
32       Google::APIClient.new(:authorization => 42)
33     end).should raise_error(TypeError)
34   end
35
36   it 'should not be able to retrieve the discovery document for a bogus API' do
37     (lambda do
38       @client.discovery_document('bogus')
39     end).should raise_error(Google::APIClient::TransmissionError)
40     (lambda do
41       @client.discovered_api('bogus')
42     end).should raise_error(Google::APIClient::TransmissionError)
43   end
44
45   it 'should raise an error for bogus services' do
46     (lambda do
47       @client.discovered_api(42)
48     end).should raise_error(TypeError)
49   end
50
51   it 'should raise an error for bogus services' do
52     (lambda do
53       @client.preferred_version(42)
54     end).should raise_error(TypeError)
55   end
56
57   it 'should raise an error for bogus methods' do
58     (lambda do
59       @client.generate_request(42)
60     end).should raise_error(TypeError)
61   end
62
63   it 'should not return a preferred version for bogus service names' do
64     @client.preferred_version('bogus').should == nil
65   end
66
67   describe 'with the prediction API' do
68     before do
69       @client.authorization = nil
70       # The prediction API no longer exposes a v1, so we have to be
71       # careful about looking up the wrong API version.
72       @prediction = @client.discovered_api('prediction', 'v1.2')
73     end
74
75     it 'should correctly determine the discovery URI' do
76       @client.discovery_uri('prediction').should ===
77         'https://www.googleapis.com/discovery/v1/apis/prediction/v1/rest'
78     end
79
80     it 'should correctly determine the discovery URI if :user_ip is set' do
81       @client.user_ip = '127.0.0.1'
82       request = @client.generate_request(
83         :http_method => 'GET',
84         :uri => @client.discovery_uri('prediction', 'v1.2'),
85         :authenticated => false
86       )
87       http_method, uri, headers, body = request
88       uri.should === (
89         'https://www.googleapis.com/discovery/v1/apis/prediction/v1.2/rest' +
90         '?userIp=127.0.0.1'
91       )
92     end
93
94     it 'should correctly determine the discovery URI if :key is set' do
95       @client.key = 'qwerty'
96       request = @client.generate_request(
97         :http_method => 'GET',
98         :uri => @client.discovery_uri('prediction', 'v1.2'),
99         :authenticated => false
100       )
101       http_method, uri, headers, body = request
102       uri.should === (
103         'https://www.googleapis.com/discovery/v1/apis/prediction/v1.2/rest' +
104         '?key=qwerty'
105       )
106     end
107
108     it 'should correctly determine the discovery URI if both are set' do
109       @client.key = 'qwerty'
110       @client.user_ip = '127.0.0.1'
111       request = @client.generate_request(
112         :http_method => 'GET',
113         :uri => @client.discovery_uri('prediction', 'v1.2'),
114         :authenticated => false
115       )
116       http_method, uri, headers, body = request
117       uri.should === (
118         'https://www.googleapis.com/discovery/v1/apis/prediction/v1.2/rest' +
119         '?key=qwerty&userIp=127.0.0.1'
120       )
121     end
122
123     it 'should correctly generate API objects' do
124       @client.discovered_api('prediction', 'v1.2').name.should == 'prediction'
125       @client.discovered_api('prediction', 'v1.2').version.should == 'v1.2'
126       @client.discovered_api(:prediction, 'v1.2').name.should == 'prediction'
127       @client.discovered_api(:prediction, 'v1.2').version.should == 'v1.2'
128     end
129
130     it 'should discover methods' do
131       @client.discovered_method(
132         'prediction.training.insert', 'prediction', 'v1.2'
133       ).name.should == 'insert'
134       @client.discovered_method(
135         :'prediction.training.insert', :prediction, 'v1.2'
136       ).name.should == 'insert'
137       @client.discovered_method(
138         'prediction.training.delete', 'prediction', 'v1.2'
139       ).name.should == 'delete'
140     end
141
142     it 'should not find methods that are not in the discovery document' do
143       @client.discovered_method(
144         'prediction.bogus', 'prediction', 'v1.2'
145       ).should == nil
146     end
147
148     it 'should raise an error for bogus methods' do
149       (lambda do
150         @client.discovered_method(42, 'prediction', 'v1.2')
151       end).should raise_error(TypeError)
152     end
153
154     it 'should raise an error for bogus methods' do
155       (lambda do
156         @client.generate_request(@client.discovered_api('prediction', 'v1.2'))
157       end).should raise_error(TypeError)
158     end
159
160     it 'should correctly determine the preferred version' do
161       @client.preferred_version('prediction').version.should_not == 'v1'
162       @client.preferred_version(:prediction).version.should_not == 'v1'
163     end
164
165     it 'should generate valid requests' do
166       request = @client.generate_request(
167         :api_method => @prediction.training.insert,
168         :parameters => {'data' => '12345', }
169       )
170       method, uri, headers, body = request
171       method.should == 'POST'
172       uri.should ==
173         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
174       (headers.inject({}) { |h,(k,v)| h[k]=v; h }).should == {}
175       body.should respond_to(:each)
176     end
177     it 'should generate valid requests when repeated parameters are passed' do
178       request = @client.generate_request(
179         :api_method => @prediction.training.insert,
180         :parameters => [['data', '1'],['data','2']]
181       )
182       method, uri, headers, body = request
183       method.should == 'POST'
184       uri.should ==
185         'https://www.googleapis.com/prediction/v1.2/training?data=1&data=2'
186     end
187     it 'should generate requests against the correct URIs' do
188       request = @client.generate_request(
189         :api_method => @prediction.training.insert,
190         :parameters => {'data' => '12345'}
191       )
192       method, uri, headers, body = request
193       uri.should ==
194         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
195     end
196
197     it 'should generate requests against the correct URIs' do
198       request = @client.generate_request(
199         :api_method => @prediction.training.insert,
200         :parameters => {'data' => '12345'}
201       )
202       method, uri, headers, body = request
203       uri.should ==
204         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
205     end
206
207     it 'should allow modification to the base URIs for testing purposes' do
208       prediction = @client.discovered_api('prediction', 'v1.2')
209       prediction.method_base =
210         'https://testing-domain.googleapis.com/prediction/v1.2/'
211       request = @client.generate_request(
212         :api_method => prediction.training.insert,
213         :parameters => {'data' => '123'}
214       )
215       method, uri, headers, body = request
216       uri.should == (
217         'https://testing-domain.googleapis.com/' +
218         'prediction/v1.2/training?data=123'
219       )
220     end
221
222     it 'should generate OAuth 1 requests' do
223       @client.authorization = :oauth_1
224       @client.authorization.token_credential_key = '12345'
225       @client.authorization.token_credential_secret = '12345'
226       request = @client.generate_request(
227         :api_method => @prediction.training.insert,
228         :parameters => {'data' => '12345'}
229       )
230       method, uri, headers, body = request
231       headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
232       headers.keys.should include('Authorization')
233       headers['Authorization'].should =~ /^OAuth/
234     end
235
236     it 'should generate OAuth 2 requests' do
237       @client.authorization = :oauth_2
238       @client.authorization.access_token = '12345'
239       request = @client.generate_request(
240         :api_method => @prediction.training.insert,
241         :parameters => {'data' => '12345'}
242       )
243       method, uri, headers, body = request
244       headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
245       headers.keys.should include('Authorization')
246       headers['Authorization'].should =~ /^OAuth/
247     end
248
249     it 'should not be able to execute improperly authorized requests' do
250       @client.authorization = :oauth_1
251       @client.authorization.token_credential_key = '12345'
252       @client.authorization.token_credential_secret = '12345'
253       result = @client.execute(
254         @prediction.training.insert,
255         {'data' => '12345'}
256       )
257       status, headers, body = result.response
258       status.should == 401
259     end
260
261     it 'should not be able to execute improperly authorized requests' do
262       @client.authorization = :oauth_2
263       @client.authorization.access_token = '12345'
264       result = @client.execute(
265         @prediction.training.insert,
266         {'data' => '12345'}
267       )
268       status, headers, body = result.response
269       status.should == 401
270     end
271
272     it 'should not be able to execute improperly authorized requests' do
273       (lambda do
274         @client.authorization = :oauth_1
275         @client.authorization.token_credential_key = '12345'
276         @client.authorization.token_credential_secret = '12345'
277         result = @client.execute!(
278           @prediction.training.insert,
279           {'data' => '12345'}
280         )
281       end).should raise_error(Google::APIClient::ClientError)
282     end
283
284     it 'should not be able to execute improperly authorized requests' do
285       (lambda do
286         @client.authorization = :oauth_2
287         @client.authorization.access_token = '12345'
288         result = @client.execute!(
289           @prediction.training.insert,
290           {'data' => '12345'}
291         )
292       end).should raise_error(Google::APIClient::ClientError)
293     end
294
295     it 'should correctly handle unnamed parameters' do
296       @client.authorization = :oauth_2
297       @client.authorization.access_token = '12345'
298       result = @client.execute(
299         @prediction.training.insert,
300         {},
301         JSON.generate({"id" => "bucket/object"}),
302         {'Content-Type' => 'application/json'}
303       )
304       method, uri, headers, body = result.request
305       Hash[headers]['Content-Type'].should == 'application/json'
306     end
307   end
308
309   describe 'with the plus API' do
310     before do
311       @client.authorization = nil
312       @plus = @client.discovered_api('plus')
313     end
314
315     it 'should correctly determine the discovery URI' do
316       @client.discovery_uri('plus').should ===
317         'https://www.googleapis.com/discovery/v1/apis/plus/v1/rest'
318     end
319
320     it 'should find APIs that are in the discovery document' do
321       @client.discovered_api('plus').name.should == 'plus'
322       @client.discovered_api('plus').version.should == 'v1'
323       @client.discovered_api(:plus).name.should == 'plus'
324       @client.discovered_api(:plus).version.should == 'v1'
325     end
326
327     it 'should find methods that are in the discovery document' do
328       # TODO(bobaman) Fix this when the RPC names are correct
329       @client.discovered_method(
330         'plus.activities.list', 'plus'
331       ).name.should == 'list'
332     end
333
334     it 'should not find methods that are not in the discovery document' do
335       @client.discovered_method('plus.bogus', 'plus').should == nil
336     end
337
338     it 'should generate requests against the correct URIs' do
339       request = @client.generate_request(
340         :api_method => @plus.activities.list,
341         :parameters => {
342           'userId' => '107807692475771887386', 'collection' => 'public'
343         },
344         :authenticated => false
345       )
346       method, uri, headers, body = request
347       uri.should == (
348         'https://www.googleapis.com/plus/v1/' +
349         'people/107807692475771887386/activities/public'
350       )
351     end
352
353     it 'should correctly validate parameters' do
354       (lambda do
355         @client.generate_request(
356           :api_method => @plus.activities.list,
357           :parameters => {'alt' => 'json'},
358           :authenticated => false
359         )
360       end).should raise_error(ArgumentError)
361     end
362
363     it 'should correctly validate parameters' do
364       (lambda do
365         @client.generate_request(
366           :api_method => @plus.activities.list,
367           :parameters => {
368             'userId' => '107807692475771887386', 'collection' => 'bogus'
369           },
370           :authenticated => false
371         )
372       end).should raise_error(ArgumentError)
373     end
374   end
375
376   describe 'with the latitude API' do
377     before do
378       @client.authorization = nil
379       @latitude = @client.discovered_api('latitude')
380     end
381
382     it 'should correctly determine the discovery URI' do
383       @client.discovery_uri('latitude').should ===
384         'https://www.googleapis.com/discovery/v1/apis/latitude/v1/rest'
385     end
386
387     it 'should find APIs that are in the discovery document' do
388       @client.discovered_api('latitude').name.should == 'latitude'
389       @client.discovered_api('latitude').version.should == 'v1'
390     end
391
392     it 'should find methods that are in the discovery document' do
393       @client.discovered_method(
394         'latitude.currentLocation.get', 'latitude'
395       ).name.should == 'get'
396     end
397
398     it 'should not find methods that are not in the discovery document' do
399       @client.discovered_method('latitude.bogus', 'latitude').should == nil
400     end
401
402     it 'should generate requests against the correct URIs' do
403       request = @client.generate_request(
404         :api_method => 'latitude.currentLocation.get',
405         :authenticated => false
406       )
407       method, uri, headers, body = request
408       uri.should ==
409         'https://www.googleapis.com/latitude/v1/currentLocation'
410     end
411
412     it 'should generate requests against the correct URIs' do
413       request = @client.generate_request(
414         :api_method => @latitude.current_location.get,
415         :authenticated => false
416       )
417       method, uri, headers, body = request
418       uri.should ==
419         'https://www.googleapis.com/latitude/v1/currentLocation'
420     end
421
422     it 'should not be able to execute requests without authorization' do
423       result = @client.execute(
424         :api_method => 'latitude.currentLocation.get',
425         :authenticated => false
426       )
427       status, headers, body = result.response
428       status.should == 401
429     end
430   end
431
432   describe 'with the moderator API' do
433     before do
434       @client.authorization = nil
435       @moderator = @client.discovered_api('moderator')
436     end
437
438     it 'should correctly determine the discovery URI' do
439       @client.discovery_uri('moderator').should ===
440         'https://www.googleapis.com/discovery/v1/apis/moderator/v1/rest'
441     end
442
443     it 'should find APIs that are in the discovery document' do
444       @client.discovered_api('moderator').name.should == 'moderator'
445       @client.discovered_api('moderator').version.should == 'v1'
446     end
447
448     it 'should find methods that are in the discovery document' do
449       @client.discovered_method(
450         'moderator.profiles.get', 'moderator'
451       ).name.should == 'get'
452     end
453
454     it 'should not find methods that are not in the discovery document' do
455       @client.discovered_method('moderator.bogus', 'moderator').should == nil
456     end
457
458     it 'should generate requests against the correct URIs' do
459       request = @client.generate_request(
460         :api_method => 'moderator.profiles.get',
461         :authenticated => false
462       )
463       method, uri, headers, body = request
464       uri.should ==
465         'https://www.googleapis.com/moderator/v1/profiles/@me'
466     end
467
468     it 'should generate requests against the correct URIs' do
469       request = @client.generate_request(
470         :api_method => @moderator.profiles.get,
471         :authenticated => false
472       )
473       method, uri, headers, body = request
474       uri.should ==
475         'https://www.googleapis.com/moderator/v1/profiles/@me'
476     end
477
478     it 'should not be able to execute requests without authorization' do
479       result = @client.execute(
480         'moderator.profiles.get',
481         {},
482         '',
483         [],
484         {:authenticated => false}
485       )
486       status, headers, body = result.response
487       status.should == 401
488     end
489   end
490 end