Merge pull request #3 from robertkaplow/master
[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 generate API objects' do
81       @client.discovered_api('prediction', 'v1.2').name.should == 'prediction'
82       @client.discovered_api('prediction', 'v1.2').version.should == 'v1.2'
83       @client.discovered_api(:prediction, 'v1.2').name.should == 'prediction'
84       @client.discovered_api(:prediction, 'v1.2').version.should == 'v1.2'
85     end
86
87     it 'should discover methods' do
88       @client.discovered_method(
89         'prediction.training.insert', 'prediction', 'v1.2'
90       ).name.should == 'insert'
91       @client.discovered_method(
92         :'prediction.training.insert', :prediction, 'v1.2'
93       ).name.should == 'insert'
94       @client.discovered_method(
95         'prediction.training.delete', 'prediction', 'v1.2'
96       ).name.should == 'delete'
97     end
98
99     it 'should not find methods that are not in the discovery document' do
100       @client.discovered_method(
101         'prediction.bogus', 'prediction', 'v1.2'
102       ).should == nil
103     end
104
105     it 'should raise an error for bogus methods' do
106       (lambda do
107         @client.discovered_method(42, 'prediction', 'v1.2')
108       end).should raise_error(TypeError)
109     end
110
111     it 'should raise an error for bogus methods' do
112       (lambda do
113         @client.generate_request(@client.discovered_api('prediction', 'v1.2'))
114       end).should raise_error(TypeError)
115     end
116
117     it 'should correctly determine the preferred version' do
118       @client.preferred_version('prediction').version.should_not == 'v1'
119       @client.preferred_version(:prediction).version.should_not == 'v1'
120     end
121
122     it 'should generate valid requests' do
123       request = @client.generate_request(
124         :api_method => @prediction.training.insert,
125         :parameters => {'data' => '12345', }
126       )
127       method, uri, headers, body = request
128       method.should == 'POST'
129       uri.should ==
130         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
131       (headers.inject({}) { |h,(k,v)| h[k]=v; h }).should == {}
132       body.should respond_to(:each)
133     end
134
135     it 'should generate requests against the correct URIs' do
136       request = @client.generate_request(
137         :api_method => @prediction.training.insert,
138         :parameters => {'data' => '12345'}
139       )
140       method, uri, headers, body = request
141       uri.should ==
142         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
143     end
144
145     it 'should generate requests against the correct URIs' do
146       request = @client.generate_request(
147         :api_method => @prediction.training.insert,
148         :parameters => {'data' => '12345'}
149       )
150       method, uri, headers, body = request
151       uri.should ==
152         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
153     end
154
155     it 'should allow modification to the base URIs for testing purposes' do
156       prediction = @client.discovered_api('prediction', 'v1.2')
157       prediction.method_base =
158         'https://testing-domain.googleapis.com/prediction/v1.2/'
159       request = @client.generate_request(
160         :api_method => prediction.training.insert,
161         :parameters => {'data' => '123'}
162       )
163       method, uri, headers, body = request
164       uri.should == (
165         'https://testing-domain.googleapis.com/' +
166         'prediction/v1.2/training?data=123'
167       )
168     end
169
170     it 'should generate OAuth 1 requests' do
171       @client.authorization = :oauth_1
172       @client.authorization.token_credential_key = '12345'
173       @client.authorization.token_credential_secret = '12345'
174       request = @client.generate_request(
175         :api_method => @prediction.training.insert,
176         :parameters => {'data' => '12345'}
177       )
178       method, uri, headers, body = request
179       headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
180       headers.keys.should include('Authorization')
181       headers['Authorization'].should =~ /^OAuth/
182     end
183
184     it 'should generate OAuth 2 requests' do
185       @client.authorization = :oauth_2
186       @client.authorization.access_token = '12345'
187       request = @client.generate_request(
188         :api_method => @prediction.training.insert,
189         :parameters => {'data' => '12345'}
190       )
191       method, uri, headers, body = request
192       headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
193       headers.keys.should include('Authorization')
194       headers['Authorization'].should =~ /^OAuth/
195     end
196
197     it 'should not be able to execute improperly authorized requests' do
198       @client.authorization = :oauth_1
199       @client.authorization.token_credential_key = '12345'
200       @client.authorization.token_credential_secret = '12345'
201       result = @client.execute(
202         @prediction.training.insert,
203         {'data' => '12345'}
204       )
205       status, headers, body = result.response
206       status.should == 401
207     end
208
209     it 'should not be able to execute improperly authorized requests' do
210       @client.authorization = :oauth_2
211       @client.authorization.access_token = '12345'
212       result = @client.execute(
213         @prediction.training.insert,
214         {'data' => '12345'}
215       )
216       status, headers, body = result.response
217       status.should == 401
218     end
219
220     it 'should not be able to execute improperly authorized requests' do
221       (lambda do
222         @client.authorization = :oauth_1
223         @client.authorization.token_credential_key = '12345'
224         @client.authorization.token_credential_secret = '12345'
225         result = @client.execute!(
226           @prediction.training.insert,
227           {'data' => '12345'}
228         )
229       end).should raise_error(Google::APIClient::ClientError)
230     end
231
232     it 'should not be able to execute improperly authorized requests' do
233       (lambda do
234         @client.authorization = :oauth_2
235         @client.authorization.access_token = '12345'
236         result = @client.execute!(
237           @prediction.training.insert,
238           {'data' => '12345'}
239         )
240       end).should raise_error(Google::APIClient::ClientError)
241     end
242
243     it 'should correctly handle unnamed parameters' do
244       @client.authorization = :oauth_2
245       @client.authorization.access_token = '12345'
246       result = @client.execute(
247         @prediction.training.insert,
248         {},
249         JSON.generate({"id" => "bucket/object"}),
250         {'Content-Type' => 'application/json'}
251       )
252       method, uri, headers, body = result.request
253       Hash[headers]['Content-Type'].should == 'application/json'
254     end
255   end
256
257   describe 'with the buzz API' do
258     before do
259       @client.authorization = nil
260       @buzz = @client.discovered_api('buzz')
261     end
262
263     it 'should correctly determine the discovery URI' do
264       @client.discovery_uri('buzz').should ===
265         'https://www.googleapis.com/discovery/v1/apis/buzz/v1/rest'
266     end
267
268     it 'should find APIs that are in the discovery document' do
269       @client.discovered_api('buzz').name.should == 'buzz'
270       @client.discovered_api('buzz').version.should == 'v1'
271       @client.discovered_api(:buzz).name.should == 'buzz'
272       @client.discovered_api(:buzz).version.should == 'v1'
273     end
274
275     it 'should find methods that are in the discovery document' do
276       # TODO(bobaman) Fix this when the RPC names are correct
277       @client.discovered_method(
278         'chili.activities.list', 'buzz'
279       ).name.should == 'list'
280     end
281
282     it 'should not find methods that are not in the discovery document' do
283       @client.discovered_method('buzz.bogus', 'buzz').should == nil
284     end
285
286     it 'should fail for string RPC names that do not match API name' do
287       (lambda do
288         @client.generate_request(
289           :api_method => 'chili.activities.list',
290           :parameters => {'alt' => 'json'},
291           :authenticated => false
292         )
293       end).should raise_error(Google::APIClient::TransmissionError)
294     end
295
296     it 'should generate requests against the correct URIs' do
297       request = @client.generate_request(
298         :api_method => @buzz.activities.list,
299         :parameters => {'userId' => 'hikingfan', 'scope' => '@public'},
300         :authenticated => false
301       )
302       method, uri, headers, body = request
303       uri.should ==
304         'https://www.googleapis.com/buzz/v1/activities/hikingfan/@public'
305     end
306
307     it 'should correctly validate parameters' do
308       (lambda do
309         @client.generate_request(
310           :api_method => @buzz.activities.list,
311           :parameters => {'alt' => 'json'},
312           :authenticated => false
313         )
314       end).should raise_error(ArgumentError)
315     end
316
317     it 'should correctly validate parameters' do
318       (lambda do
319         @client.generate_request(
320           :api_method => @buzz.activities.list,
321           :parameters => {'userId' => 'hikingfan', 'scope' => '@bogus'},
322           :authenticated => false
323         )
324       end).should raise_error(ArgumentError)
325     end
326
327     it 'should be able to execute requests without authorization' do
328       result = @client.execute(
329         @buzz.activities.list,
330         {'alt' => 'json', 'userId' => 'hikingfan', 'scope' => '@public'},
331         '',
332         [],
333         :authenticated => false
334       )
335       status, headers, body = result.response
336       status.should == 200
337     end
338
339     it 'should not be able to execute requests without authorization' do
340       result = @client.execute(
341         @buzz.activities.list,
342         'alt' => 'json', 'userId' => '@me', 'scope' => '@self'
343       )
344       status, headers, body = result.response
345       status.should == 401
346     end
347   end
348
349   describe 'with the latitude API' do
350     before do
351       @client.authorization = nil
352       @latitude = @client.discovered_api('latitude')
353     end
354
355     it 'should correctly determine the discovery URI' do
356       @client.discovery_uri('latitude').should ===
357         'https://www.googleapis.com/discovery/v1/apis/latitude/v1/rest'
358     end
359
360     it 'should find APIs that are in the discovery document' do
361       @client.discovered_api('latitude').name.should == 'latitude'
362       @client.discovered_api('latitude').version.should == 'v1'
363     end
364
365     it 'should find methods that are in the discovery document' do
366       @client.discovered_method(
367         'latitude.currentLocation.get', 'latitude'
368       ).name.should == 'get'
369     end
370
371     it 'should not find methods that are not in the discovery document' do
372       @client.discovered_method('latitude.bogus', 'latitude').should == nil
373     end
374
375     it 'should generate requests against the correct URIs' do
376       request = @client.generate_request(
377         :api_method => 'latitude.currentLocation.get',
378         :authenticated => false
379       )
380       method, uri, headers, body = request
381       uri.should ==
382         'https://www.googleapis.com/latitude/v1/currentLocation'
383     end
384
385     it 'should generate requests against the correct URIs' do
386       request = @client.generate_request(
387         :api_method => @latitude.current_location.get,
388         :authenticated => false
389       )
390       method, uri, headers, body = request
391       uri.should ==
392         'https://www.googleapis.com/latitude/v1/currentLocation'
393     end
394
395     it 'should not be able to execute requests without authorization' do
396       result = @client.execute(
397         :api_method => 'latitude.currentLocation.get',
398         :authenticated => false
399       )
400       status, headers, body = result.response
401       status.should == 401
402     end
403   end
404
405   describe 'with the moderator API' do
406     before do
407       @client.authorization = nil
408       @moderator = @client.discovered_api('moderator')
409     end
410
411     it 'should correctly determine the discovery URI' do
412       @client.discovery_uri('moderator').should ===
413         'https://www.googleapis.com/discovery/v1/apis/moderator/v1/rest'
414     end
415
416     it 'should find APIs that are in the discovery document' do
417       @client.discovered_api('moderator').name.should == 'moderator'
418       @client.discovered_api('moderator').version.should == 'v1'
419     end
420
421     it 'should find methods that are in the discovery document' do
422       @client.discovered_method(
423         'moderator.profiles.get', 'moderator'
424       ).name.should == 'get'
425     end
426
427     it 'should not find methods that are not in the discovery document' do
428       @client.discovered_method('moderator.bogus', 'moderator').should == nil
429     end
430
431     it 'should generate requests against the correct URIs' do
432       request = @client.generate_request(
433         :api_method => 'moderator.profiles.get',
434         :authenticated => false
435       )
436       method, uri, headers, body = request
437       uri.should ==
438         'https://www.googleapis.com/moderator/v1/profiles/@me'
439     end
440
441     it 'should generate requests against the correct URIs' do
442       request = @client.generate_request(
443         :api_method => @moderator.profiles.get,
444         :authenticated => false
445       )
446       method, uri, headers, body = request
447       uri.should ==
448         'https://www.googleapis.com/moderator/v1/profiles/@me'
449     end
450
451     it 'should not be able to execute requests without authorization' do
452       result = @client.execute(
453         'moderator.profiles.get',
454         {},
455         '',
456         [],
457         {:authenticated => false}
458       )
459       status, headers, body = result.response
460       status.should == 401
461     end
462   end
463 end