124 lines
4.0 KiB
Ruby
124 lines
4.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe BulkImports::FileDownloadService do
|
|
describe '#execute' do
|
|
let_it_be(:config) { build(:bulk_import_configuration) }
|
|
let_it_be(:content_type) { 'application/octet-stream' }
|
|
let_it_be(:filename) { 'file_download_service_spec' }
|
|
let_it_be(:tmpdir) { Dir.tmpdir }
|
|
let_it_be(:filepath) { File.join(tmpdir, filename) }
|
|
|
|
let(:chunk_double) { double('chunk', size: 1000, code: 200) }
|
|
let(:response_double) do
|
|
double(
|
|
code: 200,
|
|
success?: true,
|
|
parsed_response: {},
|
|
headers: {
|
|
'content-length' => 100,
|
|
'content-type' => content_type
|
|
}
|
|
)
|
|
end
|
|
|
|
subject { described_class.new(configuration: config, relative_url: '/test', dir: tmpdir, filename: filename) }
|
|
|
|
before do
|
|
allow_next_instance_of(BulkImports::Clients::Http) do |client|
|
|
allow(client).to receive(:head).and_return(response_double)
|
|
allow(client).to receive(:stream).and_yield(chunk_double)
|
|
end
|
|
end
|
|
|
|
it 'downloads file' do
|
|
subject.execute
|
|
|
|
expect(File.exist?(filepath)).to eq(true)
|
|
expect(File.read(filepath)).to include('chunk')
|
|
end
|
|
|
|
context 'when url is not valid' do
|
|
it 'raises an error' do
|
|
stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
|
|
|
|
double = instance_double(BulkImports::Configuration, url: 'https://localhost', access_token: 'token')
|
|
service = described_class.new(configuration: double, relative_url: '/test', dir: tmpdir, filename: filename)
|
|
|
|
expect { service.execute }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError)
|
|
end
|
|
end
|
|
|
|
context 'when content-type is not valid' do
|
|
let(:content_type) { 'invalid' }
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content type')
|
|
end
|
|
end
|
|
|
|
context 'when content-length is not valid' do
|
|
context 'when content-length exceeds limit' do
|
|
before do
|
|
stub_const("#{described_class}::FILE_SIZE_LIMIT", 1)
|
|
end
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content length')
|
|
end
|
|
end
|
|
|
|
context 'when content-length is missing' do
|
|
let(:response_double) { double(success?: true, headers: { 'content-type' => content_type }) }
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content length')
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when partially downloaded file exceeds limit' do
|
|
before do
|
|
stub_const("#{described_class}::FILE_SIZE_LIMIT", 150)
|
|
end
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid downloaded file')
|
|
end
|
|
end
|
|
|
|
context 'when chunk code is not 200' do
|
|
let(:chunk_double) { double('chunk', size: 1000, code: 307) }
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'File download error 307')
|
|
end
|
|
end
|
|
|
|
context 'when file is a symlink' do
|
|
let_it_be(:symlink) { File.join(tmpdir, 'symlink') }
|
|
|
|
before do
|
|
FileUtils.ln_s(File.join(tmpdir, filename), symlink)
|
|
end
|
|
|
|
subject { described_class.new(configuration: config, relative_url: '/test', dir: tmpdir, filename: 'symlink') }
|
|
|
|
it 'raises an error and removes the file' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid downloaded file')
|
|
|
|
expect(File.exist?(symlink)).to eq(false)
|
|
end
|
|
end
|
|
|
|
context 'when dir is not in tmpdir' do
|
|
subject { described_class.new(configuration: config, relative_url: '/test', dir: '/etc', filename: filename) }
|
|
|
|
it 'raises an error' do
|
|
expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid target directory')
|
|
end
|
|
end
|
|
end
|
|
end
|