Switched to using RSpec's let method for memoization.
[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     (lambda do
25       media = Google::APIClient::UploadIO.new('doesnotexist', 'text/plain')
26     end).should 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       @media.length.should == File.size(@file)
37     end
38
39     it 'should have a mime type' do
40       @media.content_type.should == '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       @media.length.should == @content.length
52     end
53
54     it 'should have a mime type' do
55       @media.content_type.should == 'text/plain'
56     end
57   end
58 end
59
60 describe Google::APIClient::ResumableUpload do
61   let(:client) { Google::APIClient.new }
62
63   before do
64     @drive = client.discovered_api('drive', 'v1')
65     @file = File.expand_path('files/sample.txt', fixtures_path)
66     @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
67     @uploader = Google::APIClient::ResumableUpload.new(
68       mock_result(308),
69       @media,
70       'https://www.googleapis.com/upload/drive/v1/files/12345')
71   end
72
73   it 'should consider 20x status as complete' do
74     api_client = stub('api', :execute => mock_result(200))
75     @uploader.send_chunk(api_client)
76     @uploader.complete?.should == true
77   end
78
79   it 'should consider 30x status as incomplete' do
80     api_client = stub('api', :execute => mock_result(308))
81     @uploader.send_chunk(api_client)
82     @uploader.complete?.should == false
83     @uploader.expired?.should == false
84   end
85
86   it 'should consider 40x status as fatal' do
87     api_client = stub('api', :execute => mock_result(404))
88     @uploader.send_chunk(api_client)
89     @uploader.expired?.should == true
90   end
91
92   it 'should detect changes to location' do
93     api_client = stub('api', :execute => mock_result(308, 'location' => 'https://www.googleapis.com/upload/drive/v1/files/abcdef'))
94     @uploader.send_chunk(api_client)
95     @uploader.location.should == 'https://www.googleapis.com/upload/drive/v1/files/abcdef'
96   end
97
98   it 'should resume from the saved range reported by the server' do
99     api_client = mock('api')
100     api_client.should_receive(:execute).and_return(mock_result(308, 'range' => '0-99'))
101     api_client.should_receive(:execute).with(
102       hash_including(:headers => hash_including(
103         "Content-Range" => "bytes 100-299/#{@media.length}",
104         "Content-Length" => "200"
105       ))).and_return(mock_result(308))
106
107     @uploader.chunk_size = 200
108     @uploader.send_chunk(api_client) # Send bytes 0-199, only 0-99 saved
109     @uploader.send_chunk(api_client) # Send bytes 100-299
110   end
111
112   it 'should resync the offset after 5xx errors' do
113     api_client = mock('api')
114     api_client.should_receive(:execute).and_return(mock_result(500))
115     api_client.should_receive(:execute).with(
116       hash_including(:headers => hash_including(
117         "Content-Range" => "bytes */#{@media.length}",
118         "Content-Length" => "0"
119       ))).and_return(mock_result(308, 'range' => '0-99'))
120     api_client.should_receive(:execute).with(
121       hash_including(:headers => hash_including(
122         "Content-Range" => "bytes 100-299/#{@media.length}",
123         "Content-Length" => "200"
124       ))).and_return(mock_result(308))
125
126     @uploader.chunk_size = 200
127     @uploader.send_chunk(api_client) # 500, invalidate
128     @uploader.send_chunk(api_client) # Just resyncs, doesn't actually upload
129     @uploader.send_chunk(api_client) # Send next chunk at correct range
130   end
131
132   def mock_result(status, headers = {})
133     reference = Google::APIClient::Reference.new(:api_method => @drive.files.insert)
134     stub('result', :status => status, :headers => headers, :reference => reference)
135   end
136
137 end