301 lines
10 KiB
Ruby
301 lines
10 KiB
Ruby
# Copyright 2015 Google Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
require 'spec_helper'
|
|
require 'google/apis/core/upload'
|
|
require 'google/apis/core/json_representation'
|
|
require 'hurley/test'
|
|
|
|
# TODO: JSON Response decoding
|
|
# TODO: Upload from IO
|
|
# TODO: Upload from file
|
|
|
|
RSpec.describe Google::Apis::Core::UploadIO do
|
|
context 'from_file' do
|
|
let(:upload_io) { Google::Apis::Core::UploadIO.from_file(file) }
|
|
|
|
context 'with text file' do
|
|
let(:file) { File.join(FIXTURES_DIR, 'files', 'test.txt') }
|
|
it 'should infer content type from file' do
|
|
expect(upload_io.content_type).to eql('text/plain')
|
|
end
|
|
|
|
it 'should allow overriding the mime type' do
|
|
io = Google::Apis::Core::UploadIO.from_file(file, content_type: 'application/json')
|
|
expect(io.content_type).to eql('application/json')
|
|
end
|
|
end
|
|
|
|
context 'with unknown type' do
|
|
let(:file) { File.join(FIXTURES_DIR, 'files', 'test.blah') }
|
|
it 'should use the default mime type' do
|
|
expect(upload_io.content_type).to eql('application/octet-stream')
|
|
end
|
|
|
|
it 'should allow overriding the mime type' do
|
|
io = Google::Apis::Core::UploadIO.from_file(file, content_type: 'application/json')
|
|
expect(io.content_type).to eql('application/json')
|
|
end
|
|
|
|
it 'should setup length of the stream' do
|
|
upload_io = Google::Apis::Core::UploadIO.from_file(file)
|
|
expect(upload_io.length).to eq File.size(file)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
context 'from_io' do
|
|
|
|
context 'with i/o stream' do
|
|
let(:io) { StringIO.new 'Hello google' }
|
|
|
|
it 'should setup default content-type' do
|
|
upload_io = Google::Apis::Core::UploadIO.from_io(io)
|
|
expect(upload_io.content_type).to eql Google::Apis::Core::UploadIO::OCTET_STREAM_CONTENT_TYPE
|
|
end
|
|
|
|
it 'should allow overring the mime type' do
|
|
upload_io = Google::Apis::Core::UploadIO.from_io(io, content_type: 'application/x-gzip')
|
|
expect(upload_io.content_type).to eq('application/x-gzip')
|
|
end
|
|
|
|
it 'should setup length of the stream' do
|
|
upload_io = Google::Apis::Core::UploadIO.from_io(io)
|
|
expect(upload_io.length).to eq 'Hello google'.length
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
RSpec.describe Google::Apis::Core::RawUploadCommand do
|
|
include TestHelpers
|
|
include_context 'HTTP client'
|
|
|
|
let(:command) do
|
|
command = Google::Apis::Core::RawUploadCommand.new(:post, 'https://www.googleapis.com/zoo/animals')
|
|
command.upload_source = file
|
|
command.upload_content_type = 'text/plain'
|
|
command
|
|
end
|
|
|
|
shared_examples 'should upload' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals').to_return(body: '')
|
|
end
|
|
|
|
it 'should send content' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with(body: "Hello world\n")).to have_been_made
|
|
end
|
|
|
|
it 'should send upload protocol' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Protocol'] == 'raw' }).to have_been_made
|
|
end
|
|
|
|
it 'should send content-type header' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Header-Content-Type'] == 'text/plain' }).to have_been_made
|
|
end
|
|
end
|
|
|
|
context('with StringIO input') do
|
|
let(:file) { StringIO.new("Hello world\n") }
|
|
include_examples 'should upload'
|
|
end
|
|
|
|
context('with IO input') do
|
|
let(:file) { File.open(File.join(FIXTURES_DIR, 'files', 'test.txt'), 'r') }
|
|
include_examples 'should upload'
|
|
|
|
it 'should not close stream' do
|
|
expect(file.closed?).to be false
|
|
end
|
|
end
|
|
|
|
context('with Tempfile input') do
|
|
let(:file) do
|
|
temp_file = Tempfile.new("tempfile")
|
|
temp_file.write("Hello world\n")
|
|
temp_file.rewind
|
|
temp_file
|
|
end
|
|
include_examples 'should upload'
|
|
|
|
it 'should not close stream' do
|
|
expect(file.closed?).to be false
|
|
end
|
|
end
|
|
|
|
context('with file path input') do
|
|
let(:file) { File.join(FIXTURES_DIR, 'files', 'test.txt') }
|
|
include_examples 'should upload'
|
|
end
|
|
|
|
context('with invalid input') do
|
|
let(:file) { -> {} }
|
|
it 'should raise client error' do
|
|
expect { command.execute(client) }.to raise_error(Google::Apis::ClientError)
|
|
end
|
|
end
|
|
end
|
|
|
|
RSpec.describe Google::Apis::Core::MultipartUploadCommand do
|
|
include TestHelpers
|
|
include_context 'HTTP client'
|
|
|
|
let(:command) do
|
|
command = Google::Apis::Core::MultipartUploadCommand.new(:post, 'https://www.googleapis.com/zoo/animals')
|
|
command.upload_source = StringIO.new('Hello world')
|
|
command.upload_content_type = 'text/plain'
|
|
command.body = 'metadata'
|
|
command
|
|
end
|
|
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals').to_return(body: %(Hello world))
|
|
end
|
|
|
|
it 'should send content' do
|
|
expected_body = <<EOF.gsub(/\n/, "\r\n")
|
|
--RubyApiClientUpload
|
|
Content-Type: application/json
|
|
|
|
metadata
|
|
--RubyApiClientUpload
|
|
Content-Length: 11
|
|
Content-Type: text/plain
|
|
Content-Transfer-Encoding: binary
|
|
|
|
Hello world
|
|
--RubyApiClientUpload--
|
|
|
|
EOF
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with(body: expected_body)).to have_been_made
|
|
end
|
|
|
|
it 'should send upload protocol' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Protocol'] == 'multipart' }).to have_been_made
|
|
end
|
|
end
|
|
|
|
RSpec.describe Google::Apis::Core::ResumableUploadCommand do
|
|
include TestHelpers
|
|
include_context 'HTTP client'
|
|
|
|
let(:command) do
|
|
command = Google::Apis::Core::ResumableUploadCommand.new(:post, 'https://www.googleapis.com/zoo/animals')
|
|
command.upload_source = StringIO.new('Hello world')
|
|
command.upload_content_type = 'text/plain'
|
|
command
|
|
end
|
|
|
|
context 'with uninterrupted upload' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-URL' => 'https://www.googleapis.com/zoo/animals' })
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'final' }, body: %(OK))
|
|
end
|
|
|
|
it 'should send upload protocol' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Protocol'] == 'resumable' }).to have_been_made
|
|
end
|
|
|
|
it 'should send start command' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Command'] == 'start' }).to have_been_made
|
|
end
|
|
|
|
it 'should send upload command' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with { |req| req.headers['X-Goog-Upload-Command'].include?('upload') }).to have_been_made
|
|
end
|
|
|
|
it 'should send upload content' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with(body: 'Hello world')).to have_been_made
|
|
end
|
|
end
|
|
|
|
context 'with retriable error on start' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.to_timeout
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-URL' => 'https://www.googleapis.com/zoo/animals' })
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-Size-Received' => '6' })
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'final' }, body: %(OK))
|
|
end
|
|
|
|
it 'should retry start command and continue' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with(body: 'Hello world')).to have_been_made
|
|
end
|
|
end
|
|
|
|
context 'with non-retriable authorization error on start' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.to_return(status: [401, 'unauthorized'], headers: { 'X-Goog-Upload-Status' => 'final' }, body: %(unauthorized))
|
|
end
|
|
|
|
it 'should propagate the original error' do
|
|
expect { command.execute(client) }.to raise_error Google::Apis::AuthorizationError
|
|
end
|
|
end
|
|
|
|
context 'with interruption' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-URL' => 'https://www.googleapis.com/zoo/animals' })
|
|
.to_return(status: [500, 'Server error'])
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-Size-Received' => '6' })
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'final' }, body: %(OK))
|
|
end
|
|
|
|
it 'should send remaining upload content after failure' do
|
|
command.execute(client)
|
|
expect(a_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.with(body: 'world')).to have_been_made
|
|
end
|
|
end
|
|
|
|
context 'with cancelled upload' do
|
|
before(:example) do
|
|
stub_request(:post, 'https://www.googleapis.com/zoo/animals')
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'active', 'X-Goog-Upload-URL' => 'https://www.googleapis.com/zoo/animals' })
|
|
.to_return(status: [500, 'Server error'])
|
|
.to_return(headers: { 'X-Goog-Upload-Status' => 'cancelled' })
|
|
end
|
|
|
|
it 'should raise error' do
|
|
expect { command.execute(client) }.to raise_error Google::Apis::ClientError
|
|
end
|
|
end
|
|
end
|