Allow download destination to only respond to #write (#638)

According to the documentation the destination IO only needs to respond
to #write. However, the downloader breaks this by calling #flush.

We fix this by calling #flush only if the destination IO responds to
that method. We also add a test to enforce that the destination IO only
needs to respond to #write.
This commit is contained in:
Janko Marohnić 2018-12-04 22:09:11 +01:00 committed by Daniel Azuma
parent d6247a7794
commit e20e6bdffd
2 changed files with 21 additions and 8 deletions

View File

@ -99,7 +99,7 @@ module Google
@offset += next_chunk.bytesize
end
@download_io.flush
@download_io.flush if @download_io.respond_to?(:flush)
if @close_io_on_finish
result = nil
@ -109,7 +109,7 @@ module Google
check_status(http_res.status.to_i, http_res.header, http_res.body)
success(result, &block)
rescue => e
@download_io.flush
@download_io.flush if @download_io.respond_to?(:flush)
error(e, rethrow: true, &block)
end
end

View File

@ -96,6 +96,16 @@ RSpec.describe Google::Apis::Core::DownloadCommand do
end
end
context 'with filename destination' do
let(:dest) { File.join(Dir.mktmpdir, 'test.txt') }
let(:received) do
command.execute(client)
File.read(dest)
end
include_examples 'should download'
end
context 'with default destination' do
let(:dest) { nil }
let(:received) { command.execute(client).string }
@ -113,13 +123,16 @@ RSpec.describe Google::Apis::Core::DownloadCommand do
include_examples 'should download'
end
context 'with filename destination' do
let(:dest) { File.join(Dir.mktmpdir, 'test.txt') }
let(:received) do
command.execute(client)
File.read(dest)
end
context 'with #write destination' do
let(:dest) { WritableIO.new(StringIO.new) }
let(:received) { command.execute(client).io.string }
include_examples 'should download'
WritableIO = Struct.new(:io) do
def write(data)
io.write(data)
end
end
end
end