diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-16 21:25:58 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-16 21:25:58 +0300 |
commit | a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch) | |
tree | fb69158581673816a8cd895f9d352dcb3c678b1e /spec/services/bulk_imports/file_download_service_spec.rb | |
parent | d16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff) |
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
Diffstat (limited to 'spec/services/bulk_imports/file_download_service_spec.rb')
-rw-r--r-- | spec/services/bulk_imports/file_download_service_spec.rb | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/spec/services/bulk_imports/file_download_service_spec.rb b/spec/services/bulk_imports/file_download_service_spec.rb new file mode 100644 index 00000000000..0961ddce553 --- /dev/null +++ b/spec/services/bulk_imports/file_download_service_spec.rb @@ -0,0 +1,133 @@ +# 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 + + shared_examples 'downloads file' do + it 'downloads file' do + subject.execute + + expect(File.exist?(filepath)).to eq(true) + expect(File.read(filepath)).to include('chunk') + end + end + + include_examples 'downloads file' + + context 'when content-type is application/gzip' do + let_it_be(:content_type) { 'application/gzip' } + + include_examples 'downloads file' + 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 |