diff options
Diffstat (limited to 'spec/workers')
28 files changed, 622 insertions, 141 deletions
diff --git a/spec/workers/authorized_project_update/project_create_worker_spec.rb b/spec/workers/authorized_project_update/project_create_worker_spec.rb new file mode 100644 index 00000000000..5ebfb60bc79 --- /dev/null +++ b/spec/workers/authorized_project_update/project_create_worker_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe AuthorizedProjectUpdate::ProjectCreateWorker do + let_it_be(:group) { create(:group, :private) } + let_it_be(:group_project) { create(:project, group: group) } + let_it_be(:group_user) { create(:user) } + + let(:access_level) { Gitlab::Access::MAINTAINER } + + subject(:worker) { described_class.new } + + it 'calls AuthorizedProjectUpdate::ProjectCreateService' do + expect_next_instance_of(AuthorizedProjectUpdate::ProjectCreateService) do |service| + expect(service).to(receive(:execute)) + end + + worker.perform(group_project.id) + end + + it 'returns ServiceResponse.success' do + result = worker.perform(group_project.id) + + expect(result.success?).to be_truthy + end + + context 'idempotence' do + before do + create(:group_member, access_level: Gitlab::Access::MAINTAINER, group: group, user: group_user) + ProjectAuthorization.delete_all + end + + include_examples 'an idempotent worker' do + let(:job_args) { group_project.id } + + it 'creates project authorization' do + subject + + project_authorization = ProjectAuthorization.where( + project_id: group_project.id, + user_id: group_user.id, + access_level: access_level) + + expect(project_authorization).to exist + expect(ProjectAuthorization.count).to eq(1) + end + end + end +end diff --git a/spec/workers/authorized_project_update/user_refresh_with_low_urgency_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_with_low_urgency_worker_spec.rb new file mode 100644 index 00000000000..fa029dae0fa --- /dev/null +++ b/spec/workers/authorized_project_update/user_refresh_with_low_urgency_worker_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker do + it 'is labeled as low urgency' do + expect(described_class.get_urgency).to eq(:low) + end + + it_behaves_like "refreshes user's project authorizations" +end diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb index 8ce0d4edd4f..93f22471c56 100644 --- a/spec/workers/authorized_projects_worker_spec.rb +++ b/spec/workers/authorized_projects_worker_spec.rb @@ -3,40 +3,5 @@ require 'spec_helper' describe AuthorizedProjectsWorker do - describe '#perform' do - let(:user) { create(:user) } - - subject(:job) { described_class.new } - - it "refreshes user's authorized projects" do - expect_any_instance_of(User).to receive(:refresh_authorized_projects) - - job.perform(user.id) - end - - context "when the user is not found" do - it "does nothing" do - expect_any_instance_of(User).not_to receive(:refresh_authorized_projects) - - job.perform(-1) - end - end - - it_behaves_like "an idempotent worker" do - let(:job_args) { user.id } - - it "does not change authorizations when run twice" do - group = create(:group) - create(:project, namespace: group) - group.add_developer(user) - - # Delete the authorization created by the after save hook of the member - # created above. - user.project_authorizations.delete_all - - expect { job.perform(user.id) }.to change { user.project_authorizations.reload.size }.by(1) - expect { job.perform(user.id) }.not_to change { user.project_authorizations.reload.size } - end - end - end + it_behaves_like "refreshes user's project authorizations" end diff --git a/spec/workers/ci/daily_report_results_worker_spec.rb b/spec/workers/ci/daily_build_group_report_results_worker_spec.rb index b6543b32b09..d9706982a62 100644 --- a/spec/workers/ci/daily_report_results_worker_spec.rb +++ b/spec/workers/ci/daily_build_group_report_results_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Ci::DailyReportResultsWorker do +describe Ci::DailyBuildGroupReportResultsWorker do describe '#perform' do let!(:pipeline) { create(:ci_pipeline) } @@ -12,7 +12,7 @@ describe Ci::DailyReportResultsWorker do let(:pipeline_id) { pipeline.id } it 'executes service' do - expect_any_instance_of(Ci::DailyReportResultService) + expect_any_instance_of(Ci::DailyBuildGroupReportResultService) .to receive(:execute).with(pipeline) subject @@ -23,7 +23,7 @@ describe Ci::DailyReportResultsWorker do let(:pipeline_id) { 123 } it 'does not execute service' do - expect_any_instance_of(Ci::DailyReportResultService) + expect_any_instance_of(Ci::DailyBuildGroupReportResultService) .not_to receive(:execute) expect { subject } diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb index 2fbaaf1131f..ae311a54cd1 100644 --- a/spec/workers/concerns/application_worker_spec.rb +++ b/spec/workers/concerns/application_worker_spec.rb @@ -21,6 +21,21 @@ describe ApplicationWorker do end end + describe '#logging_extras' do + it 'returns extra data to be logged that was set from #log_extra_metadata_on_done' do + instance.log_extra_metadata_on_done(:key1, "value1") + instance.log_extra_metadata_on_done(:key2, "value2") + + expect(instance.logging_extras).to eq({ 'extra.gitlab_foo_bar_dummy_worker.key1' => "value1", 'extra.gitlab_foo_bar_dummy_worker.key2' => "value2" }) + end + + context 'when nothing is set' do + it 'returns {}' do + expect(instance.logging_extras).to eq({}) + end + end + end + describe '#structured_payload' do let(:payload) { {} } diff --git a/spec/workers/create_commit_signature_worker_spec.rb b/spec/workers/create_commit_signature_worker_spec.rb index f40482f2361..fd5d99b3265 100644 --- a/spec/workers/create_commit_signature_worker_spec.rb +++ b/spec/workers/create_commit_signature_worker_spec.rb @@ -17,6 +17,25 @@ describe CreateCommitSignatureWorker do subject { described_class.new.perform(commit_shas, project.id) } context 'when a signature is found' do + it_behaves_like 'an idempotent worker' do + let(:job_args) { [commit_shas, project.id] } + + before do + # Removing the stub which can cause bugs for multiple calls to + # Project#commits_by. + allow(project).to receive(:commits_by).and_call_original + + # Making sure it still goes through all the perform execution. + allow_next_instance_of(::Commit) do |commit| + allow(commit).to receive(:signature_type).and_return(:PGP) + end + + allow_next_instance_of(::Gitlab::Gpg::Commit) do |gpg| + expect(gpg).to receive(:signature).once.and_call_original + end + end + end + it 'calls Gitlab::Gpg::Commit#signature' do commits.each do |commit| allow(commit).to receive(:signature_type).and_return(:PGP) diff --git a/spec/workers/design_management/new_version_worker_spec.rb b/spec/workers/design_management/new_version_worker_spec.rb new file mode 100644 index 00000000000..ef7cd8de108 --- /dev/null +++ b/spec/workers/design_management/new_version_worker_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe DesignManagement::NewVersionWorker do + describe '#perform' do + let(:worker) { described_class.new } + + context 'the id is wrong or out-of-date' do + let(:version_id) { -1 } + + it 'does not create system notes' do + expect(SystemNoteService).not_to receive(:design_version_added) + + worker.perform(version_id) + end + + it 'does not invoke GenerateImageVersionsService' do + expect(DesignManagement::GenerateImageVersionsService).not_to receive(:new) + + worker.perform(version_id) + end + + it 'logs the reason for this failure' do + expect(Sidekiq.logger).to receive(:warn) + .with(an_instance_of(ActiveRecord::RecordNotFound)) + + worker.perform(version_id) + end + end + + context 'the version id is valid' do + let_it_be(:version) { create(:design_version, :with_lfs_file, designs_count: 2) } + + it 'creates a system note' do + expect { worker.perform(version.id) }.to change { Note.system.count }.by(1) + end + + it 'invokes GenerateImageVersionsService' do + expect_next_instance_of(DesignManagement::GenerateImageVersionsService) do |service| + expect(service).to receive(:execute) + end + + worker.perform(version.id) + end + + it 'does not log anything' do + expect(Sidekiq.logger).not_to receive(:warn) + + worker.perform(version.id) + end + end + + context 'the version includes multiple types of action' do + let_it_be(:version) do + create(:design_version, :with_lfs_file, + created_designs: create_list(:design, 1, :with_lfs_file), + modified_designs: create_list(:design, 1)) + end + + it 'creates two system notes' do + expect { worker.perform(version.id) }.to change { Note.system.count }.by(2) + end + + it 'calls design_version_added' do + expect(SystemNoteService).to receive(:design_version_added).with(version) + + worker.perform(version.id) + end + end + end +end diff --git a/spec/workers/external_service_reactive_caching_worker_spec.rb b/spec/workers/external_service_reactive_caching_worker_spec.rb new file mode 100644 index 00000000000..45cce71b75b --- /dev/null +++ b/spec/workers/external_service_reactive_caching_worker_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ExternalServiceReactiveCachingWorker do + it_behaves_like 'reactive cacheable worker' +end diff --git a/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb b/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb index 80629cb875e..2de609761e2 100644 --- a/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb @@ -5,6 +5,8 @@ require 'spec_helper' describe Gitlab::JiraImport::ImportIssueWorker do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } + let_it_be(:jira_issue_label_1) { create(:label, project: project) } + let_it_be(:jira_issue_label_2) { create(:label, project: project) } let(:some_key) { 'some-key' } describe 'modules' do @@ -17,7 +19,13 @@ describe Gitlab::JiraImport::ImportIssueWorker do subject { described_class.new } describe '#perform', :clean_gitlab_redis_cache do - let(:issue_attrs) { build(:issue, project_id: project.id).as_json.compact } + let(:assignee_ids) { [user.id] } + let(:issue_attrs) do + build(:issue, project_id: project.id, title: 'jira issue') + .as_json.merge( + 'label_ids' => [jira_issue_label_1.id, jira_issue_label_2.id], 'assignee_ids' => assignee_ids + ).compact + end context 'when any exception raised while inserting to DB' do before do @@ -47,14 +55,39 @@ describe Gitlab::JiraImport::ImportIssueWorker do context 'when import label exists' do before do Gitlab::JiraImport.cache_import_label_id(project.id, label.id) - end - it 'does not record import failure' do subject.perform(project.id, 123, issue_attrs, some_key) + end + it 'does not record import failure' do expect(label.issues.count).to eq(1) expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.failed_issues_counter_cache_key(project.id)).to_i).to eq(0) end + + it 'creates an issue with the correct attributes' do + issue = Issue.last + + expect(issue.title).to eq('jira issue') + expect(issue.project).to eq(project) + expect(issue.labels).to match_array([label, jira_issue_label_1, jira_issue_label_2]) + expect(issue.assignees).to eq([user]) + end + + context 'when assignee_ids is nil' do + let(:assignee_ids) { nil } + + it 'creates an issue without assignee' do + expect(Issue.last.assignees).to be_empty + end + end + + context 'when assignee_ids is an empty array' do + let(:assignee_ids) { [] } + + it 'creates an issue without assignee' do + expect(Issue.last.assignees).to be_empty + end + end end end end diff --git a/spec/workers/gitlab/jira_import/stage/finish_import_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/finish_import_worker_spec.rb index 5c3c7dcccc1..4cb6f5e28b8 100644 --- a/spec/workers/gitlab/jira_import/stage/finish_import_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/finish_import_worker_spec.rb @@ -16,7 +16,7 @@ describe Gitlab::JiraImport::Stage::FinishImportWorker do stub_feature_flags(jira_issue_import: false) end - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' end context 'when feature flag enabled' do @@ -27,7 +27,7 @@ describe Gitlab::JiraImport::Stage::FinishImportWorker do end context 'when import did not start' do - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' end context 'when import started' do diff --git a/spec/workers/gitlab/jira_import/stage/import_attachments_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_attachments_worker_spec.rb index 478cb447dc5..e6d41ae8bb4 100644 --- a/spec/workers/gitlab/jira_import/stage/import_attachments_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/import_attachments_worker_spec.rb @@ -15,7 +15,7 @@ describe Gitlab::JiraImport::Stage::ImportAttachmentsWorker do stub_feature_flags(jira_issue_import: false) end - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end @@ -27,7 +27,7 @@ describe Gitlab::JiraImport::Stage::ImportAttachmentsWorker do end context 'when import did not start' do - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end diff --git a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb index 6470a293461..f2067522af4 100644 --- a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Gitlab::JiraImport::Stage::ImportIssuesWorker do + include JiraServiceHelper + let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, import_type: 'jira') } @@ -16,7 +18,7 @@ describe Gitlab::JiraImport::Stage::ImportIssuesWorker do stub_feature_flags(jira_issue_import: false) end - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end @@ -25,10 +27,11 @@ describe Gitlab::JiraImport::Stage::ImportIssuesWorker do before do stub_feature_flags(jira_issue_import: true) + stub_jira_service_test end context 'when import did not start' do - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end diff --git a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb index f1562395546..7f289de5422 100644 --- a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Gitlab::JiraImport::Stage::ImportLabelsWorker do + include JiraServiceHelper + let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, import_type: 'jira') } @@ -16,7 +18,7 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do stub_feature_flags(jira_issue_import: false) end - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end @@ -28,7 +30,7 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do end context 'when import did not start' do - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end @@ -36,7 +38,12 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do let!(:jira_service) { create(:jira_service, project: project) } before do + stub_jira_service_test + jira_import.start! + + WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=500&startAt=0') + .to_return(body: {}.to_json ) end it_behaves_like 'advance to next stage', :issues diff --git a/spec/workers/gitlab/jira_import/stage/import_notes_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_notes_worker_spec.rb index 956898c1abc..f9bdbd669d8 100644 --- a/spec/workers/gitlab/jira_import/stage/import_notes_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/import_notes_worker_spec.rb @@ -15,7 +15,7 @@ describe Gitlab::JiraImport::Stage::ImportNotesWorker do stub_feature_flags(jira_issue_import: false) end - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end @@ -27,7 +27,7 @@ describe Gitlab::JiraImport::Stage::ImportNotesWorker do end context 'when import did not start' do - it_behaves_like 'cannot do jira import' + it_behaves_like 'cannot do Jira import' it_behaves_like 'does not advance to next stage' end diff --git a/spec/workers/group_import_worker_spec.rb b/spec/workers/group_import_worker_spec.rb index 641aa45c9b0..bb7dc116a08 100644 --- a/spec/workers/group_import_worker_spec.rb +++ b/spec/workers/group_import_worker_spec.rb @@ -8,13 +8,52 @@ describe GroupImportWorker do subject { described_class.new } + before do + allow_next_instance_of(described_class) do |job| + allow(job).to receive(:jid).and_return(SecureRandom.hex(8)) + end + end + describe '#perform' do context 'when it succeeds' do - it 'calls the ImportService' do - expect_any_instance_of(::Groups::ImportExport::ImportService).to receive(:execute) + before do + expect_next_instance_of(::Groups::ImportExport::ImportService) do |service| + expect(service).to receive(:execute) + end + end + it 'calls the ImportService' do subject.perform(user.id, group.id) end + + context 'import state' do + it 'creates group import' do + expect(group.import_state).to be_nil + + subject.perform(user.id, group.id) + import_state = group.reload.import_state + + expect(import_state).to be_instance_of(GroupImportState) + expect(import_state.status_name).to eq(:finished) + expect(import_state.jid).not_to be_empty + end + + it 'sets the group import status to started' do + expect_next_instance_of(GroupImportState) do |import| + expect(import).to receive(:start!).and_call_original + end + + subject.perform(user.id, group.id) + end + + it 'sets the group import status to finished' do + expect_next_instance_of(GroupImportState) do |import| + expect(import).to receive(:finish!).and_call_original + end + + subject.perform(user.id, group.id) + end + end end context 'when it fails' do @@ -24,6 +63,22 @@ describe GroupImportWorker do expect { subject.perform(non_existing_record_id, group.id) }.to raise_exception(ActiveRecord::RecordNotFound) expect { subject.perform(user.id, non_existing_record_id) }.to raise_exception(ActiveRecord::RecordNotFound) end + + context 'import state' do + before do + expect_next_instance_of(::Groups::ImportExport::ImportService) do |service| + expect(service).to receive(:execute).and_raise(Gitlab::ImportExport::Error) + end + end + + it 'sets the group import status to failed' do + expect_next_instance_of(GroupImportState) do |import| + expect(import).to receive(:fail_op).and_call_original + end + + expect { subject.perform(user.id, group.id) }.to raise_exception(Gitlab::ImportExport::Error) + end + end end end end diff --git a/spec/workers/incident_management/process_alert_worker_spec.rb b/spec/workers/incident_management/process_alert_worker_spec.rb index 9f40833dfd7..938e72aa0f0 100644 --- a/spec/workers/incident_management/process_alert_worker_spec.rb +++ b/spec/workers/incident_management/process_alert_worker_spec.rb @@ -6,16 +6,24 @@ describe IncidentManagement::ProcessAlertWorker do let_it_be(:project) { create(:project) } describe '#perform' do - let(:alert) { :alert } - let(:create_issue_service) { spy(:create_issue_service) } + let(:alert_management_alert_id) { nil } + let(:alert_payload) { { alert: 'payload' } } + let(:new_issue) { create(:issue, project: project) } + let(:create_issue_service) { instance_double(IncidentManagement::CreateIssueService, execute: new_issue) } - subject { described_class.new.perform(project.id, alert) } + subject { described_class.new.perform(project.id, alert_payload, alert_management_alert_id) } + + before do + allow(IncidentManagement::CreateIssueService) + .to receive(:new).with(project, alert_payload) + .and_return(create_issue_service) + end it 'calls create issue service' do expect(Project).to receive(:find_by_id).and_call_original expect(IncidentManagement::CreateIssueService) - .to receive(:new).with(project, :alert) + .to receive(:new).with(project, alert_payload) .and_return(create_issue_service) expect(create_issue_service).to receive(:execute) @@ -26,7 +34,7 @@ describe IncidentManagement::ProcessAlertWorker do context 'with invalid project' do let(:invalid_project_id) { 0 } - subject { described_class.new.perform(invalid_project_id, alert) } + subject { described_class.new.perform(invalid_project_id, alert_payload) } it 'does not create issues' do expect(Project).to receive(:find_by_id).and_call_original @@ -35,5 +43,54 @@ describe IncidentManagement::ProcessAlertWorker do subject end end + + context 'when alert_management_alert_id is present' do + let!(:alert) { create(:alert_management_alert, project: project) } + let(:alert_management_alert_id) { alert.id } + + before do + allow(AlertManagement::Alert) + .to receive(:find_by_id) + .with(alert_management_alert_id) + .and_return(alert) + + allow(Gitlab::AppLogger).to receive(:warn).and_call_original + end + + context 'when alert can be updated' do + it 'updates AlertManagement::Alert#issue_id' do + expect { subject }.to change { alert.reload.issue_id }.to(new_issue.id) + end + + it 'does not write a warning to log' do + subject + + expect(Gitlab::AppLogger).not_to have_received(:warn) + end + end + + context 'when alert cannot be updated' do + before do + # invalidate alert + too_many_hosts = Array.new(AlertManagement::Alert::HOSTS_MAX_LENGTH + 1) { |_| 'host' } + alert.update_columns(hosts: too_many_hosts) + end + + it 'updates AlertManagement::Alert#issue_id' do + expect { subject }.not_to change { alert.reload.issue_id } + end + + it 'writes a worning to log' do + subject + + expect(Gitlab::AppLogger).to have_received(:warn).with( + message: 'Cannot link an Issue with Alert', + issue_id: new_issue.id, + alert_id: alert_management_alert_id, + alert_errors: { hosts: ['hosts array is over 255 chars'] } + ) + end + end + end end end diff --git a/spec/workers/merge_request_mergeability_check_worker_spec.rb b/spec/workers/merge_request_mergeability_check_worker_spec.rb index 2331664215f..8909af1f685 100644 --- a/spec/workers/merge_request_mergeability_check_worker_spec.rb +++ b/spec/workers/merge_request_mergeability_check_worker_spec.rb @@ -25,5 +25,16 @@ describe MergeRequestMergeabilityCheckWorker do subject.perform(merge_request.id) end end + + it_behaves_like 'an idempotent worker' do + let(:merge_request) { create(:merge_request) } + let(:job_args) { [merge_request.id] } + + it 'is mergeable' do + subject + + expect(merge_request).to be_mergeable + end + end end end diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb index b97a44c714d..ceea7c8d8f5 100644 --- a/spec/workers/namespaceless_project_destroy_worker_spec.rb +++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb @@ -79,19 +79,5 @@ describe NamespacelessProjectDestroyWorker do end end end - - context 'project has non-existing namespace' do - let!(:project) do - project = build(:project, namespace_id: non_existing_record_id) - project.save(validate: false) - project - end - - it 'deletes the project' do - subject.perform(project.id) - - expect(Project.unscoped.all).not_to include(project) - end - end end end diff --git a/spec/workers/new_release_worker_spec.rb b/spec/workers/new_release_worker_spec.rb index 9d8c5bbf919..de4e1bac48f 100644 --- a/spec/workers/new_release_worker_spec.rb +++ b/spec/workers/new_release_worker_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# TODO: Worker can be removed in 13.2: +# https://gitlab.com/gitlab-org/gitlab/-/issues/218231 require 'spec_helper' describe NewReleaseWorker do diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 3d24b5f753a..aab7a36189a 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -299,6 +299,31 @@ describe PostReceive do end end + context "master" do + let(:default_branch) { 'master' } + let(:oldrev) { '012345' } + let(:newrev) { '6789ab' } + let(:changes) do + <<~EOF + #{oldrev} #{newrev} refs/heads/#{default_branch} + 123456 789012 refs/heads/tést2 + EOF + end + + let(:raw_repo) { double('RawRepo') } + + it 'processes the changes on the master branch' do + expect_next_instance_of(Git::WikiPushService) do |service| + expect(service).to receive(:process_changes).and_call_original + end + expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch) + expect(project.wiki.repository).to receive(:raw).and_return(raw_repo) + expect(raw_repo).to receive(:raw_changes_between).once.with(oldrev, newrev).and_return([]) + + perform + end + end + context "branches" do let(:changes) do <<~EOF @@ -307,6 +332,12 @@ describe PostReceive do EOF end + before do + allow_next_instance_of(Git::WikiPushService) do |service| + allow(service).to receive(:process_changes) + end + end + it 'expires the branches cache' do expect(project.wiki.repository).to receive(:expire_branches_cache).once @@ -440,4 +471,17 @@ describe PostReceive do it_behaves_like 'snippet changes actions' end end + + describe 'processing design changes' do + let(:gl_repository) { "design-#{project.id}" } + + it 'does not do anything' do + worker = described_class.new + + expect(worker).not_to receive(:process_wiki_changes) + expect(worker).not_to receive(:process_project_changes) + + described_class.new.perform(gl_repository, key_id, base64_changes) + end + end end diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb index 21c300af7ac..d247668ac76 100644 --- a/spec/workers/process_commit_worker_spec.rb +++ b/spec/workers/process_commit_worker_spec.rb @@ -22,16 +22,26 @@ describe ProcessCommitWorker do worker.perform(project.id, -1, commit.to_hash) end - it 'processes the commit message' do - expect(worker).to receive(:process_commit_message).and_call_original + include_examples 'an idempotent worker' do + subject do + perform_multiple([project.id, user.id, commit.to_hash], worker: worker) + end - worker.perform(project.id, user.id, commit.to_hash) - end + it 'processes the commit message' do + expect(worker).to receive(:process_commit_message) + .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES) + .and_call_original - it 'updates the issue metrics' do - expect(worker).to receive(:update_issue_metrics).and_call_original + subject + end - worker.perform(project.id, user.id, commit.to_hash) + it 'updates the issue metrics' do + expect(worker).to receive(:update_issue_metrics) + .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES) + .and_call_original + + subject + end end end diff --git a/spec/workers/project_export_worker_spec.rb b/spec/workers/project_export_worker_spec.rb index 373e7f32530..4c49939d34e 100644 --- a/spec/workers/project_export_worker_spec.rb +++ b/spec/workers/project_export_worker_spec.rb @@ -17,14 +17,18 @@ describe ProjectExportWorker do context 'when it succeeds' do it 'calls the ExportService' do - expect_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute) + expect_next_instance_of(::Projects::ImportExport::ExportService) do |service| + expect(service).to receive(:execute) + end subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' }) end context 'export job' do before do - allow_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute) + allow_next_instance_of(::Projects::ImportExport::ExportService) do |service| + allow(service).to receive(:execute) + end end it 'creates an export job record for the project' do @@ -51,7 +55,7 @@ describe ProjectExportWorker do context 'when it fails' do it 'does not raise an exception when strategy is invalid' do - expect_any_instance_of(::Projects::ImportExport::ExportService).not_to receive(:execute) + expect(::Projects::ImportExport::ExportService).not_to receive(:new) expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.not_to raise_error end diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb index 57a4c2128b3..98856480b21 100644 --- a/spec/workers/project_update_repository_storage_worker_spec.rb +++ b/spec/workers/project_update_repository_storage_worker_spec.rb @@ -9,12 +9,40 @@ describe ProjectUpdateRepositoryStorageWorker do subject { described_class.new } describe "#perform" do - it "calls the update repository storage service" do - expect_next_instance_of(Projects::UpdateRepositoryStorageService) do |instance| - expect(instance).to receive(:execute).with('new_storage') + let(:service) { double(:update_repository_storage_service) } + + before do + allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage]) + end + + context 'without repository storage move' do + it "calls the update repository storage service" do + expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service) + expect(service).to receive(:execute) + + expect do + subject.perform(project.id, 'test_second_storage') + end.to change(ProjectRepositoryStorageMove, :count).by(1) + + storage_move = project.repository_storage_moves.last + expect(storage_move).to have_attributes( + source_storage_name: "default", + destination_storage_name: "test_second_storage" + ) end + end + + context 'with repository storage move' do + let!(:repository_storage_move) { create(:project_repository_storage_move) } - subject.perform(project.id, 'new_storage') + it "calls the update repository storage service" do + expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service) + expect(service).to receive(:execute) + + expect do + subject.perform(nil, nil, repository_storage_move.id) + end.not_to change(ProjectRepositoryStorageMove, :count) + end end end end diff --git a/spec/workers/reactive_caching_worker_spec.rb b/spec/workers/reactive_caching_worker_spec.rb index 603ce6160ce..dcb804a7e6e 100644 --- a/spec/workers/reactive_caching_worker_spec.rb +++ b/spec/workers/reactive_caching_worker_spec.rb @@ -3,47 +3,5 @@ require 'spec_helper' describe ReactiveCachingWorker do - describe '#perform' do - context 'when user configured kubernetes from CI/CD > Clusters' do - let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } - let(:project) { cluster.project } - let!(:environment) { create(:environment, project: project) } - - it 'calls #exclusively_update_reactive_cache!' do - expect_any_instance_of(Environment).to receive(:exclusively_update_reactive_cache!) - - described_class.new.perform("Environment", environment.id) - end - - context 'when ReactiveCaching::ExceededReactiveCacheLimit is raised' do - it 'avoids failing the job and tracks via Gitlab::ErrorTracking' do - allow_any_instance_of(Environment).to receive(:exclusively_update_reactive_cache!) - .and_raise(ReactiveCaching::ExceededReactiveCacheLimit) - - expect(Gitlab::ErrorTracking).to receive(:track_exception) - .with(kind_of(ReactiveCaching::ExceededReactiveCacheLimit)) - - described_class.new.perform("Environment", environment.id) - end - end - end - end - - describe 'worker context' do - it 'sets the related class on the job' do - described_class.perform_async('Environment', 1, 'other', 'argument') - - scheduled_job = described_class.jobs.first - - expect(scheduled_job).to include('meta.related_class' => 'Environment') - end - - it 'sets the related class on the job when it was passed as a class' do - described_class.perform_async(Project, 1, 'other', 'argument') - - scheduled_job = described_class.jobs.first - - expect(scheduled_job).to include('meta.related_class' => 'Project') - end - end + it_behaves_like 'reactive cacheable worker' end diff --git a/spec/workers/stage_update_worker_spec.rb b/spec/workers/stage_update_worker_spec.rb index 8a57cc6bbff..dc7158cfd2f 100644 --- a/spec/workers/stage_update_worker_spec.rb +++ b/spec/workers/stage_update_worker_spec.rb @@ -12,6 +12,15 @@ describe StageUpdateWorker do described_class.new.perform(stage.id) end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { [stage.id] } + + it 'results in the stage getting the skipped status' do + expect { subject }.to change { stage.reload.status }.from('pending').to('skipped') + expect { subject }.not_to change { stage.reload.status } + end + end end context 'when stage does not exist' do diff --git a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb index c4af829a5e2..8fe3f27c8b1 100644 --- a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb +++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb @@ -4,18 +4,27 @@ require 'spec_helper' describe UpdateHeadPipelineForMergeRequestWorker do describe '#perform' do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:merge_request) { create(:merge_request, source_project: project) } - let(:latest_sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + let_it_be(:latest_sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' } context 'when pipeline exists for the source project and branch' do - before do - create(:ci_empty_pipeline, project: project, ref: merge_request.source_branch, sha: latest_sha) - end + let_it_be(:pipeline) { create(:ci_empty_pipeline, project: project, ref: merge_request.source_branch, sha: latest_sha) } it 'updates the head_pipeline_id of the merge_request' do - expect { subject.perform(merge_request.id) }.to change { merge_request.reload.head_pipeline_id } + expect { subject.perform(merge_request.id) } + .to change { merge_request.reload.head_pipeline_id }.from(nil).to(pipeline.id) + end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { merge_request.id } + + it 'sets the pipeline as the head pipeline when run multiple times' do + subject + + expect(merge_request.reload.head_pipeline_id).to eq(pipeline.id) + end end context 'when merge request sha does not equal pipeline sha' do @@ -27,6 +36,15 @@ describe UpdateHeadPipelineForMergeRequestWorker do expect { subject.perform(merge_request.id) } .not_to change { merge_request.reload.head_pipeline_id } end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { merge_request.id } + + it 'does not update the head_pipeline_id when run multiple times' do + expect { subject } + .not_to change { merge_request.reload.head_pipeline_id } + end + end end end @@ -35,10 +53,19 @@ describe UpdateHeadPipelineForMergeRequestWorker do expect { subject.perform(merge_request.id) } .not_to change { merge_request.reload.head_pipeline_id } end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { merge_request.id } + + it 'does not update the head_pipeline_id when run multiple times' do + expect { subject } + .not_to change { merge_request.reload.head_pipeline_id } + end + end end context 'when a merge request pipeline exists' do - let!(:merge_request_pipeline) do + let_it_be(:merge_request_pipeline) do create(:ci_pipeline, project: project, source: :merge_request_event, @@ -52,6 +79,16 @@ describe UpdateHeadPipelineForMergeRequestWorker do .from(nil).to(merge_request_pipeline.id) end + it_behaves_like 'an idempotent worker' do + let(:job_args) { merge_request.id } + + it 'sets the merge request pipeline as the head pipeline when run multiple times' do + subject + + expect(merge_request.reload.head_pipeline_id).to eq(merge_request_pipeline.id) + end + end + context 'when branch pipeline exists' do let!(:branch_pipeline) do create(:ci_pipeline, project: project, source: :push, sha: latest_sha) @@ -62,6 +99,16 @@ describe UpdateHeadPipelineForMergeRequestWorker do .to change { merge_request.reload.head_pipeline_id } .from(nil).to(merge_request_pipeline.id) end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { merge_request.id } + + it 'sets the merge request pipeline as the head pipeline when run multiple times' do + subject + + expect(merge_request.reload.head_pipeline_id).to eq(merge_request_pipeline.id) + end + end end end end diff --git a/spec/workers/update_highest_role_worker_spec.rb b/spec/workers/update_highest_role_worker_spec.rb index 1e378a5a61e..3f377208a62 100644 --- a/spec/workers/update_highest_role_worker_spec.rb +++ b/spec/workers/update_highest_role_worker_spec.rb @@ -18,7 +18,6 @@ describe UpdateHighestRoleWorker, :clean_gitlab_redis_shared_state do let(:active_attributes) do { state: 'active', - ghost: false, user_type: nil } end @@ -54,7 +53,6 @@ describe UpdateHighestRoleWorker, :clean_gitlab_redis_shared_state do where(:additional_attributes) do [ { state: 'blocked' }, - { ghost: true }, { user_type: :alert_bot } ] end diff --git a/spec/workers/x509_issuer_crl_check_worker_spec.rb b/spec/workers/x509_issuer_crl_check_worker_spec.rb new file mode 100644 index 00000000000..f052812b86b --- /dev/null +++ b/spec/workers/x509_issuer_crl_check_worker_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe X509IssuerCrlCheckWorker do + subject(:worker) { described_class.new } + + let(:project) { create(:project, :public, :repository) } + let(:x509_signed_commit) { project.commit_by(oid: '189a6c924013fc3fe40d6f1ec1dc20214183bc97') } + let(:revoked_x509_signed_commit) { project.commit_by(oid: 'ed775cc81e5477df30c2abba7b6fdbb5d0baadae') } + + describe '#perform' do + context 'valid crl' do + before do + stub_request(:get, "http://ch.siemens.com/pki?ZZZZZZA6.crl") + .to_return(status: 200, body: File.read('spec/fixtures/x509/ZZZZZZA6.crl'), headers: {}) + end + + it 'changes certificate status for revoked certificates' do + revoked_x509_commit = Gitlab::X509::Commit.new(revoked_x509_signed_commit) + x509_commit = Gitlab::X509::Commit.new(x509_signed_commit) + issuer = revoked_x509_commit.signature.x509_certificate.x509_issuer + + expect(issuer).to eq(x509_commit.signature.x509_certificate.x509_issuer) + expect(revoked_x509_commit.signature.x509_certificate.good?).to be_truthy + expect(x509_commit.signature.x509_certificate.good?).to be_truthy + + worker.perform + revoked_x509_commit.signature.reload + + expect(revoked_x509_commit.signature.x509_certificate.revoked?).to be_truthy + expect(x509_commit.signature.x509_certificate.revoked?).to be_falsey + end + end + + context 'invalid crl' do + before do + stub_request(:get, "http://ch.siemens.com/pki?ZZZZZZA6.crl") + .to_return(status: 200, body: "trash", headers: {}) + end + + it 'does not change certificate status' do + revoked_x509_commit = Gitlab::X509::Commit.new(revoked_x509_signed_commit) + + expect(revoked_x509_commit.signature.x509_certificate.good?).to be_truthy + + worker.perform + revoked_x509_commit.signature.reload + + expect(revoked_x509_commit.signature.x509_certificate.revoked?).to be_falsey + end + end + + context 'not found crl' do + before do + stub_request(:get, "http://ch.siemens.com/pki?ZZZZZZA6.crl") + .to_return(status: 404, body: "not found", headers: {}) + end + + it 'does not change certificate status' do + revoked_x509_commit = Gitlab::X509::Commit.new(revoked_x509_signed_commit) + + expect(revoked_x509_commit.signature.x509_certificate.good?).to be_truthy + + worker.perform + revoked_x509_commit.signature.reload + + expect(revoked_x509_commit.signature.x509_certificate.revoked?).to be_falsey + end + end + + context 'unreachable crl' do + before do + stub_request(:get, "http://ch.siemens.com/pki?ZZZZZZA6.crl") + .to_raise(SocketError.new('Some HTTP error')) + end + + it 'does not change certificate status' do + revoked_x509_commit = Gitlab::X509::Commit.new(revoked_x509_signed_commit) + + expect(revoked_x509_commit.signature.x509_certificate.good?).to be_truthy + + worker.perform + revoked_x509_commit.signature.reload + + expect(revoked_x509_commit.signature.x509_certificate.revoked?).to be_falsey + end + end + end +end |