1 # Copyright 2012 Google Inc.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 require 'google/api_client'
18 require 'google/api_client/version'
20 fixtures_path = File.expand_path('../../../fixtures', __FILE__)
22 describe Google::APIClient::UploadIO do
23 it 'should reject invalid file paths' do
25 media = Google::APIClient::UploadIO.new('doesnotexist', 'text/plain')
26 end).should raise_error
29 describe 'with a file' do
31 @file = File.expand_path('files/sample.txt', fixtures_path)
32 @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
35 it 'should report the correct file length' do
36 @media.length.should == File.size(@file)
39 it 'should have a mime type' do
40 @media.content_type.should == 'text/plain'
44 describe 'with StringIO' do
46 @content = "hello world"
47 @media = Google::APIClient::UploadIO.new(StringIO.new(@content), 'text/plain', 'test.txt')
50 it 'should report the correct file length' do
51 @media.length.should == @content.length
54 it 'should have a mime type' do
55 @media.content_type.should == 'text/plain'
60 describe Google::APIClient::ResumableUpload do
61 CLIENT = Google::APIClient.new
64 # Reset client to not-quite-pristine state
70 @drive = CLIENT.discovered_api('drive', 'v1')
71 @file = File.expand_path('files/sample.txt', fixtures_path)
72 @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
73 @uploader = Google::APIClient::ResumableUpload.new(
76 'https://www.googleapis.com/upload/drive/v1/files/12345')
79 it 'should consider 20x status as complete' do
80 api_client = stub('api', :execute => mock_result(200))
81 @uploader.send_chunk(api_client)
82 @uploader.complete?.should == true
85 it 'should consider 30x status as incomplete' do
86 api_client = stub('api', :execute => mock_result(308))
87 @uploader.send_chunk(api_client)
88 @uploader.complete?.should == false
89 @uploader.expired?.should == false
92 it 'should consider 40x status as fatal' do
93 api_client = stub('api', :execute => mock_result(404))
94 @uploader.send_chunk(api_client)
95 @uploader.expired?.should == true
98 it 'should detect changes to location' do
99 api_client = stub('api', :execute => mock_result(308, 'location' => 'https://www.googleapis.com/upload/drive/v1/files/abcdef'))
100 @uploader.send_chunk(api_client)
101 @uploader.location.should == 'https://www.googleapis.com/upload/drive/v1/files/abcdef'
104 it 'should resume from the saved range reported by the server' do
105 api_client = mock('api')
106 api_client.should_receive(:execute).and_return(mock_result(308, 'range' => '0-99'))
107 api_client.should_receive(:execute).with(
108 hash_including(:headers => hash_including(
109 "Content-Range" => "bytes 100-299/#{@media.length}",
110 "Content-Length" => "200"
111 ))).and_return(mock_result(308))
113 @uploader.chunk_size = 200
114 @uploader.send_chunk(api_client) # Send bytes 0-199, only 0-99 saved
115 @uploader.send_chunk(api_client) # Send bytes 100-299
118 it 'should resync the offset after 5xx errors' do
119 api_client = mock('api')
120 api_client.should_receive(:execute).and_return(mock_result(500))
121 api_client.should_receive(:execute).with(
122 hash_including(:headers => hash_including(
123 "Content-Range" => "bytes */#{@media.length}",
124 "Content-Length" => "0"
125 ))).and_return(mock_result(308, 'range' => '0-99'))
126 api_client.should_receive(:execute).with(
127 hash_including(:headers => hash_including(
128 "Content-Range" => "bytes 100-299/#{@media.length}",
129 "Content-Length" => "200"
130 ))).and_return(mock_result(308))
132 @uploader.chunk_size = 200
133 @uploader.send_chunk(api_client) # 500, invalidate
134 @uploader.send_chunk(api_client) # Just resyncs, doesn't actually upload
135 @uploader.send_chunk(api_client) # Send next chunk at correct range
138 def mock_result(status, headers = {})
139 reference = Google::APIClient::Reference.new(:api_method => @drive.files.insert)
140 stub('result', :status => status, :headers => headers, :reference => reference)