8c6515ea596175b0277561be923614ad6e6560a4
[arvados.git] / spec / google / api_client / media_spec.rb
1 # Copyright 2012 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 'google/api_client'
18 require 'google/api_client/version'
19
20 fixtures_path = File.expand_path('../../../fixtures', __FILE__)
21
22 describe Google::APIClient::UploadIO do
23   it 'should reject invalid file paths' do
24     expect(lambda do
25       media = Google::APIClient::UploadIO.new('doesnotexist', 'text/plain')
26     end).to raise_error
27   end
28
29   describe 'with a file' do
30     before do
31       @file = File.expand_path('files/sample.txt', fixtures_path)
32       @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
33     end
34
35     it 'should report the correct file length' do
36       expect(@media.length).to eq(File.size(@file))
37     end
38
39     it 'should have a mime type' do
40       expect(@media.content_type).to eq('text/plain')
41     end
42   end
43
44   describe 'with StringIO' do
45     before do
46       @content = "hello world"
47       @media = Google::APIClient::UploadIO.new(StringIO.new(@content), 'text/plain', 'test.txt')
48     end
49
50     it 'should report the correct file length' do
51       expect(@media.length).to eq(@content.length)
52     end
53
54     it 'should have a mime type' do
55       expect(@media.content_type).to eq('text/plain')
56     end
57   end
58 end
59
60 describe Google::APIClient::RangedIO do
61   before do
62     @source = StringIO.new("1234567890abcdef")
63     @io = Google::APIClient::RangedIO.new(@source, 1, 5)
64   end
65   
66   it 'should return the correct range when read entirely' do
67     expect(@io.read).to eq("23456")
68   end
69   
70   it 'should maintain position' do
71     expect(@io.read(1)).to eq('2')
72     expect(@io.read(2)).to eq('34')
73     expect(@io.read(2)).to eq('56')
74   end
75   
76   it 'should allow rewinds' do
77     expect(@io.read(2)).to eq('23')
78     @io.rewind()
79     expect(@io.read(2)).to eq('23')
80   end
81   
82   it 'should allow setting position' do
83     @io.pos = 3
84     expect(@io.read).to eq('56')
85   end
86   
87   it 'should not allow position to be set beyond range' do
88     @io.pos = 10
89     expect(@io.read).to eq('')
90   end
91   
92   it 'should return empty string when read amount is zero' do
93     expect(@io.read(0)).to eq('')
94   end
95   
96   it 'should return empty string at EOF if amount is nil' do
97     @io.read
98     expect(@io.read).to eq('')
99   end
100   
101   it 'should return nil at EOF if amount is positive int' do
102     @io.read
103     expect(@io.read(1)).to eq(nil)
104   end
105     
106 end
107
108 describe Google::APIClient::ResumableUpload do
109   CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
110
111   after do
112     # Reset client to not-quite-pristine state
113     CLIENT.key = nil
114     CLIENT.user_ip = nil
115   end
116
117   before do
118     @drive = CLIENT.discovered_api('drive', 'v1')
119     @file = File.expand_path('files/sample.txt', fixtures_path)
120     @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
121     @uploader = Google::APIClient::ResumableUpload.new(
122       :media => @media,
123       :api_method => @drive.files.insert,
124       :uri => 'https://www.googleapis.com/upload/drive/v1/files/12345')
125   end
126
127   it 'should consider 20x status as complete' do
128     request = @uploader.to_http_request
129     @uploader.process_http_response(mock_result(200))
130     expect(@uploader.complete?).to eq(true)
131   end
132
133   it 'should consider 30x status as incomplete' do
134     request = @uploader.to_http_request
135     @uploader.process_http_response(mock_result(308))
136     expect(@uploader.complete?).to eq(false)
137     expect(@uploader.expired?).to eq(false)
138   end
139
140   it 'should consider 40x status as fatal' do
141     request = @uploader.to_http_request
142     @uploader.process_http_response(mock_result(404))
143     expect(@uploader.expired?).to eq(true)
144   end
145
146   it 'should detect changes to location' do
147     request = @uploader.to_http_request
148     @uploader.process_http_response(mock_result(308, 'location' => 'https://www.googleapis.com/upload/drive/v1/files/abcdef'))
149     expect(@uploader.uri.to_s).to eq('https://www.googleapis.com/upload/drive/v1/files/abcdef')
150   end
151
152   it 'should resume from the saved range reported by the server' do    
153     @uploader.chunk_size = 200
154     @uploader.to_http_request # Send bytes 0-199, only 0-99 saved
155     @uploader.process_http_response(mock_result(308, 'range' => '0-99'))
156     method, url, headers, body = @uploader.to_http_request # Send bytes 100-299
157     expect(headers['Content-Range']).to eq("bytes 100-299/#{@media.length}")
158     expect(headers['Content-length']).to eq("200")
159   end
160
161   it 'should resync the offset after 5xx errors' do
162     @uploader.chunk_size = 200
163     @uploader.to_http_request
164     @uploader.process_http_response(mock_result(500)) # Invalidates range
165     method, url, headers, body = @uploader.to_http_request # Resync
166     expect(headers['Content-Range']).to eq("bytes */#{@media.length}")
167     expect(headers['Content-length']).to eq("0")
168     @uploader.process_http_response(mock_result(308, 'range' => '0-99'))
169     method, url, headers, body = @uploader.to_http_request # Send next chunk at correct range
170     expect(headers['Content-Range']).to eq("bytes 100-299/#{@media.length}")
171     expect(headers['Content-length']).to eq("200")
172   end
173
174   def mock_result(status, headers = {})
175     reference = Google::APIClient::Reference.new(:api_method => @drive.files.insert)
176     double('result', :status => status, :headers => headers, :reference => reference)
177   end
178
179 end