diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-28 03:09:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-28 03:09:08 +0300 |
commit | f54a50aa826d0eedcf2e56f51462613bc132f826 (patch) | |
tree | 7194aca23f9af822ea55966a6f477b3d8d68ee47 /spec/services/snippets | |
parent | c77fda905a8619b756163c10a75171dc9cfe7084 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/services/snippets')
-rw-r--r-- | spec/services/snippets/bulk_destroy_service_spec.rb | 161 | ||||
-rw-r--r-- | spec/services/snippets/create_service_spec.rb | 2 | ||||
-rw-r--r-- | spec/services/snippets/destroy_service_spec.rb | 81 | ||||
-rw-r--r-- | spec/services/snippets/update_service_spec.rb | 2 |
4 files changed, 240 insertions, 6 deletions
diff --git a/spec/services/snippets/bulk_destroy_service_spec.rb b/spec/services/snippets/bulk_destroy_service_spec.rb new file mode 100644 index 00000000000..f03d7496f94 --- /dev/null +++ b/spec/services/snippets/bulk_destroy_service_spec.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Snippets::BulkDestroyService do + let_it_be(:project) { create(:project) } + let(:user) { create(:user) } + let!(:personal_snippet) { create(:personal_snippet, :repository, author: user) } + let!(:project_snippet) { create(:project_snippet, :repository, project: project, author: user) } + let(:snippets) { user.snippets } + let(:gitlab_shell) { Gitlab::Shell.new } + let(:service_user) { user } + + before do + project.add_developer(user) + end + + subject { described_class.new(service_user, snippets) } + + describe '#execute' do + it 'deletes the snippets in bulk' do + response = nil + + expect(Repositories::ShellDestroyService).to receive(:new).with(personal_snippet.repository).and_call_original + expect(Repositories::ShellDestroyService).to receive(:new).with(project_snippet.repository).and_call_original + + aggregate_failures do + expect do + response = subject.execute + end.to change(Snippet, :count).by(-2) + + expect(response).to be_success + expect(repository_exists?(personal_snippet)).to be_falsey + expect(repository_exists?(project_snippet)).to be_falsey + end + end + + context 'when snippets is empty' do + let(:snippets) { Snippet.none } + + it 'returns a ServiceResponse success response' do + response = subject.execute + + expect(response).to be_success + expect(response.message).to eq 'No snippets found.' + end + end + + shared_examples 'error is raised' do + it 'returns error' do + response = subject.execute + + aggregate_failures do + expect(response).to be_error + expect(response.message).to eq error_message + end + end + + it 'no record is deleted' do + expect do + subject.execute + end.not_to change(Snippet, :count) + end + end + + context 'when user does not have access to remove the snippet' do + let(:service_user) { create(:user) } + + it_behaves_like 'error is raised' do + let(:error_message) { "You don't have access to delete these snippets." } + end + end + + context 'when an error is raised deleting the repository' do + before do + allow_next_instance_of(Repositories::DestroyService) do |instance| + allow(instance).to receive(:execute).and_return({ status: :error }) + end + end + + it_behaves_like 'error is raised' do + let(:error_message) { 'Failed to delete snippet repositories.' } + end + + it 'tries to rollback the repository' do + expect(subject).to receive(:attempt_rollback_repositories) + + subject.execute + end + end + + context 'when an error is raised deleting the records' do + before do + allow(snippets).to receive(:destroy_all).and_raise(ActiveRecord::ActiveRecordError) + end + + it_behaves_like 'error is raised' do + let(:error_message) { 'Failed to remove snippets.' } + end + + it 'tries to rollback the repository' do + expect(subject).to receive(:attempt_rollback_repositories) + + subject.execute + end + end + + context 'when snippet does not have a repository attached' do + let!(:snippet_without_repo) { create(:personal_snippet, author: user) } + + it 'does not schedule anything for the snippet without repository and return success' do + response = nil + + expect(Repositories::ShellDestroyService).to receive(:new).with(personal_snippet.repository).and_call_original + expect(Repositories::ShellDestroyService).to receive(:new).with(project_snippet.repository).and_call_original + + expect do + response = subject.execute + end.to change(Snippet, :count).by(-3) + + expect(response).to be_success + end + end + end + + describe '#attempt_rollback_repositories' do + before do + Repositories::DestroyService.new(personal_snippet.repository).execute + end + + it 'rollbacks the repository' do + error_msg = personal_snippet.disk_path + "+#{personal_snippet.id}+deleted.git" + expect(repository_exists?(personal_snippet, error_msg)).to be_truthy + + subject.__send__(:attempt_rollback_repositories) + + aggregate_failures do + expect(repository_exists?(personal_snippet, error_msg)).to be_falsey + expect(repository_exists?(personal_snippet)).to be_truthy + end + end + + context 'when an error is raised' do + before do + allow_next_instance_of(Repositories::DestroyRollbackService) do |instance| + allow(instance).to receive(:execute).and_return({ status: :error }) + end + end + + it 'logs the error' do + expect(Gitlab::AppLogger).to receive(:error).with(/\ARepository .* in path .* could not be rolled back\z/).twice + + subject.__send__(:attempt_rollback_repositories) + end + end + end + + def repository_exists?(snippet, path = snippet.disk_path + ".git") + gitlab_shell.repository_exists?(snippet.snippet_repository.shard_name, path) + end +end diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb index a1cbec6748a..37b203c2341 100644 --- a/spec/services/snippets/create_service_spec.rb +++ b/spec/services/snippets/create_service_spec.rb @@ -18,7 +18,7 @@ describe Snippets::CreateService do let(:extra_opts) { {} } let(:creator) { admin } - subject { Snippets::CreateService.new(project, creator, opts).execute } + subject { described_class.new(project, creator, opts).execute } let(:snippet) { subject.payload[:snippet] } diff --git a/spec/services/snippets/destroy_service_spec.rb b/spec/services/snippets/destroy_service_spec.rb index bb035d275ab..840dc11a740 100644 --- a/spec/services/snippets/destroy_service_spec.rb +++ b/spec/services/snippets/destroy_service_spec.rb @@ -8,7 +8,7 @@ describe Snippets::DestroyService do let_it_be(:other_user) { create(:user) } describe '#execute' do - subject { Snippets::DestroyService.new(user, snippet).execute } + subject { described_class.new(user, snippet).execute } context 'when snippet is nil' do let(:snippet) { nil } @@ -30,7 +30,7 @@ describe Snippets::DestroyService do shared_examples 'an unsuccessful destroy' do it 'does not delete the snippet' do - expect { subject }.to change { Snippet.count }.by(0) + expect { subject }.not_to change { Snippet.count } end it 'returns ServiceResponse error' do @@ -38,8 +38,63 @@ describe Snippets::DestroyService do end end + shared_examples 'deletes the snippet repository' do + it 'removes the snippet repository' do + expect(snippet.repository.exists?).to be_truthy + expect(GitlabShellWorker).to receive(:perform_in) + expect_next_instance_of(Repositories::DestroyService) do |instance| + expect(instance).to receive(:execute).and_call_original + end + + expect(subject).to be_success + end + + context 'when the repository deletion service raises an error' do + before do + allow_next_instance_of(Repositories::DestroyService) do |instance| + allow(instance).to receive(:execute).and_return({ status: :error }) + end + end + + it_behaves_like 'an unsuccessful destroy' + + it 'does not try to rollback repository' do + expect(Repositories::DestroyRollbackService).not_to receive(:new) + + subject + end + end + + context 'when a destroy error is raised' do + before do + allow(snippet).to receive(:destroy!).and_raise(ActiveRecord::ActiveRecordError) + end + + it_behaves_like 'an unsuccessful destroy' + + it 'attempts to rollback the repository' do + expect(Repositories::DestroyRollbackService).to receive(:new).and_call_original + + subject + end + end + + context 'when repository is nil' do + it 'does not schedule anything and return success' do + allow(snippet).to receive(:repository).and_return(nil) + + expect(GitlabShellWorker).not_to receive(:perform_in) + expect_next_instance_of(Repositories::DestroyService) do |instance| + expect(instance).to receive(:execute).and_call_original + end + + expect(subject).to be_success + end + end + end + context 'when ProjectSnippet' do - let!(:snippet) { create(:project_snippet, project: project, author: author) } + let!(:snippet) { create(:project_snippet, :repository, project: project, author: author) } context 'when user is able to admin_project_snippet' do let(:author) { user } @@ -49,6 +104,7 @@ describe Snippets::DestroyService do end it_behaves_like 'a successful destroy' + it_behaves_like 'deletes the snippet repository' end context 'when user is not able to admin_project_snippet' do @@ -59,12 +115,13 @@ describe Snippets::DestroyService do end context 'when PersonalSnippet' do - let!(:snippet) { create(:personal_snippet, author: author) } + let!(:snippet) { create(:personal_snippet, :repository, author: author) } context 'when user is able to admin_personal_snippet' do let(:author) { user } it_behaves_like 'a successful destroy' + it_behaves_like 'deletes the snippet repository' end context 'when user is not able to admin_personal_snippet' do @@ -73,5 +130,21 @@ describe Snippets::DestroyService do it_behaves_like 'an unsuccessful destroy' end end + + context 'when the repository does not exists' do + let(:snippet) { create(:personal_snippet, author: user) } + + it 'does not schedule anything and return success' do + expect(snippet.repository).not_to be_nil + expect(snippet.repository.exists?).to be_falsey + + expect(GitlabShellWorker).not_to receive(:perform_in) + expect_next_instance_of(Repositories::DestroyService) do |instance| + expect(instance).to receive(:execute).and_call_original + end + + expect(subject).to be_success + end + end end end diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb index b8215f9779d..4858a0512ad 100644 --- a/spec/services/snippets/update_service_spec.rb +++ b/spec/services/snippets/update_service_spec.rb @@ -18,7 +18,7 @@ describe Snippets::UpdateService do let(:updater) { user } subject do - Snippets::UpdateService.new( + described_class.new( project, updater, options |