diff options
Diffstat (limited to 'spec/workers')
37 files changed, 1236 insertions, 189 deletions
diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb index 90ed1309d4a..0d6eb536c33 100644 --- a/spec/workers/authorized_projects_worker_spec.rb +++ b/spec/workers/authorized_projects_worker_spec.rb @@ -65,7 +65,6 @@ describe AuthorizedProjectsWorker do args_list = build_args_list(project.owner.id) push_bulk_args = { 'class' => described_class, - 'queue' => described_class.sidekiq_options['queue'], 'args' => args_list } diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb index 4f6e3474634..1c54cf55fa0 100644 --- a/spec/workers/background_migration_worker_spec.rb +++ b/spec/workers/background_migration_worker_spec.rb @@ -10,35 +10,4 @@ describe BackgroundMigrationWorker, :sidekiq do described_class.new.perform('Foo', [10, 20]) end end - - describe '.perform_bulk' do - it 'enqueues background migrations in bulk' do - Sidekiq::Testing.fake! do - described_class.perform_bulk([['Foo', [1]], ['Foo', [2]]]) - - expect(described_class.jobs.count).to eq 2 - expect(described_class.jobs).to all(include('enqueued_at')) - end - end - end - - describe '.perform_bulk_in' do - context 'when delay is valid' do - it 'correctly schedules background migrations' do - Sidekiq::Testing.fake! do - described_class.perform_bulk_in(1.minute, [['Foo', [1]], ['Foo', [2]]]) - - expect(described_class.jobs.count).to eq 2 - expect(described_class.jobs).to all(include('at')) - end - end - end - - context 'when delay is invalid' do - it 'raises an ArgumentError exception' do - expect { described_class.perform_bulk_in(-60, [['Foo']]) } - .to raise_error(ArgumentError) - end - end - end end diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb new file mode 100644 index 00000000000..0145563e0ed --- /dev/null +++ b/spec/workers/concerns/application_worker_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe ApplicationWorker do + let(:worker) do + Class.new do + def self.name + 'Gitlab::Foo::Bar::DummyWorker' + end + + include ApplicationWorker + end + end + + describe 'Sidekiq options' do + it 'sets the queue name based on the class name' do + expect(worker.sidekiq_options['queue']).to eq('foo_bar_dummy') + end + end + + describe '.queue' do + it 'returns the queue name' do + worker.sidekiq_options queue: :some_queue + + expect(worker.queue).to eq('some_queue') + end + end + + describe '.bulk_perform_async' do + it 'enqueues jobs in bulk' do + Sidekiq::Testing.fake! do + worker.bulk_perform_async([['Foo', [1]], ['Foo', [2]]]) + + expect(worker.jobs.count).to eq 2 + expect(worker.jobs).to all(include('enqueued_at')) + end + end + end + + describe '.bulk_perform_in' do + context 'when delay is valid' do + it 'correctly schedules jobs' do + Sidekiq::Testing.fake! do + worker.bulk_perform_in(1.minute, [['Foo', [1]], ['Foo', [2]]]) + + expect(worker.jobs.count).to eq 2 + expect(worker.jobs).to all(include('at')) + end + end + end + + context 'when delay is invalid' do + it 'raises an ArgumentError exception' do + expect { worker.bulk_perform_in(-60, [['Foo']]) } + .to raise_error(ArgumentError) + end + end + end +end diff --git a/spec/workers/concerns/cluster_queue_spec.rb b/spec/workers/concerns/cluster_queue_spec.rb index 1050651fa51..5049886b55c 100644 --- a/spec/workers/concerns/cluster_queue_spec.rb +++ b/spec/workers/concerns/cluster_queue_spec.rb @@ -3,7 +3,11 @@ require 'spec_helper' describe ClusterQueue do let(:worker) do Class.new do - include Sidekiq::Worker + def self.name + 'DummyWorker' + end + + include ApplicationWorker include ClusterQueue end end diff --git a/spec/workers/concerns/cronjob_queue_spec.rb b/spec/workers/concerns/cronjob_queue_spec.rb index 5d1336c21a6..3ae1c5f54d8 100644 --- a/spec/workers/concerns/cronjob_queue_spec.rb +++ b/spec/workers/concerns/cronjob_queue_spec.rb @@ -3,7 +3,11 @@ require 'spec_helper' describe CronjobQueue do let(:worker) do Class.new do - include Sidekiq::Worker + def self.name + 'DummyWorker' + end + + include ApplicationWorker include CronjobQueue end end diff --git a/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb b/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb deleted file mode 100644 index 512baec8b7e..00000000000 --- a/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' - -describe DedicatedSidekiqQueue do - let(:worker) do - Class.new do - def self.name - 'Foo::Bar::DummyWorker' - end - - include Sidekiq::Worker - include DedicatedSidekiqQueue - end - end - - describe 'queue names' do - it 'sets the queue name based on the class name' do - expect(worker.sidekiq_options['queue']).to eq('foo_bar_dummy') - end - end -end diff --git a/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb b/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb new file mode 100644 index 00000000000..4b9aa9a7ef8 --- /dev/null +++ b/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::NotifyUponDeath do + let(:worker_class) do + Class.new do + include Sidekiq::Worker + include Gitlab::GithubImport::NotifyUponDeath + end + end + + describe '.sidekiq_retries_exhausted' do + it 'notifies the JobWaiter when 3 arguments are given and the last is a String' do + job = { 'args' => [12, {}, '123abc'], 'jid' => '123' } + + expect(Gitlab::JobWaiter) + .to receive(:notify) + .with('123abc', '123') + + worker_class.sidekiq_retries_exhausted_block.call(job) + end + + it 'does not notify the JobWaiter when only 2 arguments are given' do + job = { 'args' => [12, {}], 'jid' => '123' } + + expect(Gitlab::JobWaiter) + .not_to receive(:notify) + + worker_class.sidekiq_retries_exhausted_block.call(job) + end + + it 'does not notify the JobWaiter when only 1 argument is given' do + job = { 'args' => [12], 'jid' => '123' } + + expect(Gitlab::JobWaiter) + .not_to receive(:notify) + + worker_class.sidekiq_retries_exhausted_block.call(job) + end + + it 'does not notify the JobWaiter when the last argument is not a String' do + job = { 'args' => [12, {}, 40], 'jid' => '123' } + + expect(Gitlab::JobWaiter) + .not_to receive(:notify) + + worker_class.sidekiq_retries_exhausted_block.call(job) + end + end +end diff --git a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb new file mode 100644 index 00000000000..68cfe9d5545 --- /dev/null +++ b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb @@ -0,0 +1,74 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ObjectImporter do + let(:worker) do + Class.new do + def self.name + 'DummyWorker' + end + + include(Gitlab::GithubImport::ObjectImporter) + + def counter_name + :dummy_counter + end + + def counter_description + 'This is a counter' + end + end.new + end + + describe '#import' do + it 'imports the object' do + representation_class = double(:representation_class) + importer_class = double(:importer_class) + importer_instance = double(:importer_instance) + representation = double(:representation) + project = double(:project, path_with_namespace: 'foo/bar') + client = double(:client) + + expect(worker) + .to receive(:representation_class) + .and_return(representation_class) + + expect(worker) + .to receive(:importer_class) + .and_return(importer_class) + + expect(representation_class) + .to receive(:from_json_hash) + .with(an_instance_of(Hash)) + .and_return(representation) + + expect(importer_class) + .to receive(:new) + .with(representation, project, client) + .and_return(importer_instance) + + expect(importer_instance) + .to receive(:execute) + + expect(worker.counter) + .to receive(:increment) + .with(project: 'foo/bar') + .and_call_original + + worker.import(project, client, { 'number' => 10 }) + end + end + + describe '#counter' do + it 'returns a Prometheus counter' do + expect(worker) + .to receive(:counter_name) + .and_call_original + + expect(worker) + .to receive(:counter_description) + .and_call_original + + worker.counter + end + end +end diff --git a/spec/workers/concerns/gitlab/github_import/queue_spec.rb b/spec/workers/concerns/gitlab/github_import/queue_spec.rb new file mode 100644 index 00000000000..9c69ee32da1 --- /dev/null +++ b/spec/workers/concerns/gitlab/github_import/queue_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Queue do + it 'sets the Sidekiq options for the worker' do + worker = Class.new do + def self.name + 'DummyWorker' + end + + include ApplicationWorker + include Gitlab::GithubImport::Queue + end + + expect(worker.sidekiq_options['queue']).to eq('github_importer') + end +end diff --git a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb new file mode 100644 index 00000000000..8de4059c4ae --- /dev/null +++ b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb @@ -0,0 +1,110 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ReschedulingMethods do + let(:worker) do + Class.new { include(Gitlab::GithubImport::ReschedulingMethods) }.new + end + + describe '#perform' do + context 'with a non-existing project' do + it 'does not perform any work' do + expect(worker) + .not_to receive(:try_import) + + worker.perform(-1, {}) + end + + it 'notifies any waiters so they do not wait forever' do + expect(worker) + .to receive(:notify_waiter) + .with('123') + + worker.perform(-1, {}, '123') + end + end + + context 'with an existing project' do + let(:project) { create(:project) } + + it 'notifies any waiters upon successfully importing the data' do + expect(worker) + .to receive(:try_import) + .with( + an_instance_of(Project), + an_instance_of(Gitlab::GithubImport::Client), + { 'number' => 2 } + ) + .and_return(true) + + expect(worker) + .to receive(:notify_waiter).with('123') + + worker.perform(project.id, { 'number' => 2 }, '123') + end + + it 'reschedules itself if the data could not be imported' do + expect(worker) + .to receive(:try_import) + .with( + an_instance_of(Project), + an_instance_of(Gitlab::GithubImport::Client), + { 'number' => 2 } + ) + .and_return(false) + + expect(worker) + .not_to receive(:notify_waiter) + + expect_any_instance_of(Gitlab::GithubImport::Client) + .to receive(:rate_limit_resets_in) + .and_return(14) + + expect(worker.class) + .to receive(:perform_in) + .with(14, project.id, { 'number' => 2 }, '123') + + worker.perform(project.id, { 'number' => 2 }, '123') + end + end + end + + describe '#try_import' do + it 'returns true when the import succeeds' do + expect(worker) + .to receive(:import) + .with(10, 20) + + expect(worker.try_import(10, 20)).to eq(true) + end + + it 'returns false when the import fails due to hitting the GitHub API rate limit' do + expect(worker) + .to receive(:import) + .with(10, 20) + .and_raise(Gitlab::GithubImport::RateLimitError) + + expect(worker.try_import(10, 20)).to eq(false) + end + end + + describe '#notify_waiter' do + it 'notifies the waiter if a waiter key is specified' do + expect(worker) + .to receive(:jid) + .and_return('abc123') + + expect(Gitlab::JobWaiter) + .to receive(:notify) + .with('123', 'abc123') + + worker.notify_waiter('123') + end + + it 'does not notify any waiters if no waiter key is specified' do + expect(Gitlab::JobWaiter) + .not_to receive(:notify) + + worker.notify_waiter(nil) + end + end +end diff --git a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb new file mode 100644 index 00000000000..241e8a2b6d3 --- /dev/null +++ b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::StageMethods do + let(:project) { create(:project) } + let(:worker) do + Class.new { include(Gitlab::GithubImport::StageMethods) }.new + end + + describe '#perform' do + it 'returns if no project could be found' do + expect(worker).not_to receive(:try_import) + + worker.perform(-1) + end + + it 'imports the data when the project exists' do + allow(worker) + .to receive(:find_project) + .with(project.id) + .and_return(project) + + expect(worker) + .to receive(:try_import) + .with( + an_instance_of(Gitlab::GithubImport::Client), + an_instance_of(Project) + ) + + worker.perform(project.id) + end + end + + describe '#try_import' do + it 'imports the project' do + client = double(:client) + + expect(worker) + .to receive(:import) + .with(client, project) + + worker.try_import(client, project) + end + + it 'reschedules the worker if RateLimitError was raised' do + client = double(:client, rate_limit_resets_in: 10) + + expect(worker) + .to receive(:import) + .with(client, project) + .and_raise(Gitlab::GithubImport::RateLimitError) + + expect(worker.class) + .to receive(:perform_in) + .with(10, project.id) + + worker.try_import(client, project) + end + end + + describe '#find_project' do + it 'returns a Project for an existing ID' do + project.update_column(:import_status, 'started') + + expect(worker.find_project(project.id)).to eq(project) + end + + it 'returns nil for a project that failed importing' do + project.update_column(:import_status, 'failed') + + expect(worker.find_project(project.id)).to be_nil + end + + it 'returns nil for a non-existing project ID' do + expect(worker.find_project(-1)).to be_nil + end + end +end diff --git a/spec/workers/concerns/pipeline_queue_spec.rb b/spec/workers/concerns/pipeline_queue_spec.rb index eac5a770e5f..dd911760948 100644 --- a/spec/workers/concerns/pipeline_queue_spec.rb +++ b/spec/workers/concerns/pipeline_queue_spec.rb @@ -3,7 +3,11 @@ require 'spec_helper' describe PipelineQueue do let(:worker) do Class.new do - include Sidekiq::Worker + def self.name + 'DummyWorker' + end + + include ApplicationWorker include PipelineQueue end end diff --git a/spec/workers/concerns/repository_check_queue_spec.rb b/spec/workers/concerns/repository_check_queue_spec.rb index 8868e969829..fdbbfcc90a5 100644 --- a/spec/workers/concerns/repository_check_queue_spec.rb +++ b/spec/workers/concerns/repository_check_queue_spec.rb @@ -3,7 +3,11 @@ require 'spec_helper' describe RepositoryCheckQueue do let(:worker) do Class.new do - include Sidekiq::Worker + def self.name + 'DummyWorker' + end + + include ApplicationWorker include RepositoryCheckQueue end end diff --git a/spec/workers/create_pipeline_worker_spec.rb b/spec/workers/create_pipeline_worker_spec.rb new file mode 100644 index 00000000000..02cb0f46cb4 --- /dev/null +++ b/spec/workers/create_pipeline_worker_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe CreatePipelineWorker do + describe '#perform' do + let(:worker) { described_class.new } + + context 'when a project not found' do + it 'does not call the Service' do + expect(Ci::CreatePipelineService).not_to receive(:new) + expect { worker.perform(99, create(:user).id, 'master', :web) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'when a user not found' do + let(:project) { create(:project) } + + it 'does not call the Service' do + expect(Ci::CreatePipelineService).not_to receive(:new) + expect { worker.perform(project.id, 99, project.default_branch, :web) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'when everything is ok' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:create_pipeline_service) { instance_double(Ci::CreatePipelineService) } + + it 'calls the Service' do + expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: project.default_branch).and_return(create_pipeline_service) + expect(create_pipeline_service).to receive(:execute).with(:web, any_args) + + worker.perform(project.id, user.id, project.default_branch, :web) + end + end + end +end diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index 30908534eb3..7ee0a51a263 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -1,44 +1,21 @@ require 'spec_helper' describe 'Every Sidekiq worker' do - let(:workers) do - root = Rails.root.join('app', 'workers') - concerns = root.join('concerns').to_s - - workers = Dir[root.join('**', '*.rb')] - .reject { |path| path.start_with?(concerns) } - - workers.map do |path| - ns = Pathname.new(path).relative_path_from(root).to_s.gsub('.rb', '') - - ns.camelize.constantize - end + it 'includes ApplicationWorker' do + expect(Gitlab::SidekiqConfig.workers).to all(include(ApplicationWorker)) end it 'does not use the default queue' do - workers.each do |worker| - expect(worker.sidekiq_options['queue'].to_s).not_to eq('default') - end + expect(Gitlab::SidekiqConfig.workers.map(&:queue)).not_to include('default') end it 'uses the cronjob queue when the worker runs as a cronjob' do - cron_workers = Settings.cron_jobs - .map { |job_name, options| options['job_class'].constantize } - .to_set - - workers.each do |worker| - next unless cron_workers.include?(worker) - - expect(worker.sidekiq_options['queue'].to_s).to eq('cronjob') - end + expect(Gitlab::SidekiqConfig.cron_workers.map(&:queue)).to all(eq('cronjob')) end it 'defines the queue in the Sidekiq configuration file' do - config = YAML.load_file(Rails.root.join('config', 'sidekiq_queues.yml').to_s) - queue_names = config[:queues].map { |(queue, _)| queue }.to_set + config_queue_names = Gitlab::SidekiqConfig.config_queues.to_set - workers.each do |worker| - expect(queue_names).to include(worker.sidekiq_options['queue'].to_s) - end + expect(Gitlab::SidekiqConfig.worker_queues).to all(be_in(config_queue_names)) end end diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb index bed5c5e2ecb..e1a56c72162 100644 --- a/spec/workers/expire_build_instance_artifacts_worker_spec.rb +++ b/spec/workers/expire_build_instance_artifacts_worker_spec.rb @@ -11,12 +11,8 @@ describe ExpireBuildInstanceArtifactsWorker do end context 'with expired artifacts' do - let(:artifacts_expiry) { { artifacts_expire_at: Time.now - 7.days } } - context 'when associated project is valid' do - let(:build) do - create(:ci_build, :artifacts, artifacts_expiry) - end + let(:build) { create(:ci_build, :artifacts, :expired) } it 'does expire' do expect(build.reload.artifacts_expired?).to be_truthy @@ -26,14 +22,14 @@ describe ExpireBuildInstanceArtifactsWorker do expect(build.reload.artifacts_file.exists?).to be_falsey end - it 'does nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).to be_nil + it 'does remove the job artifact record' do + expect(build.reload.job_artifacts_archive).to be_nil end end end context 'with not yet expired artifacts' do - let(:build) do + set(:build) do create(:ci_build, :artifacts, artifacts_expire_at: Time.now + 7.days) end @@ -45,8 +41,8 @@ describe ExpireBuildInstanceArtifactsWorker do expect(build.reload.artifacts_file.exists?).to be_truthy end - it 'does not nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).not_to be_nil + it 'does not remove the job artifact record' do + expect(build.reload.job_artifacts_archive).not_to be_nil end end @@ -61,13 +57,13 @@ describe ExpireBuildInstanceArtifactsWorker do expect(build.reload.artifacts_file.exists?).to be_truthy end - it 'does not nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).not_to be_nil + it 'does not remove the job artifact record' do + expect(build.reload.job_artifacts_archive).not_to be_nil end end context 'for expired artifacts' do - let(:build) { create(:ci_build, artifacts_expire_at: Time.now - 7.days) } + let(:build) { create(:ci_build, :expired) } it 'is still expired' do expect(build.reload.artifacts_expired?).to be_truthy diff --git a/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb new file mode 100644 index 00000000000..3be49a0dee8 --- /dev/null +++ b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_state do + let(:project) { create(:project, import_jid: '123') } + let(:worker) { described_class.new } + + describe '#perform' do + context 'when the project no longer exists' do + it 'does not perform any work' do + expect(worker).not_to receive(:wait_for_jobs) + + worker.perform(-1, { '123' => 2 }, :finish) + end + end + + context 'when there are remaining jobs' do + before do + allow(worker) + .to receive(:find_project) + .and_return(project) + end + + it 'reschedules itself' do + expect(worker) + .to receive(:wait_for_jobs) + .with({ '123' => 2 }) + .and_return({ '123' => 1 }) + + expect(described_class) + .to receive(:perform_in) + .with(described_class::INTERVAL, project.id, { '123' => 1 }, :finish) + + worker.perform(project.id, { '123' => 2 }, :finish) + end + end + + context 'when there are no remaining jobs' do + before do + allow(worker) + .to receive(:find_project) + .and_return(project) + + allow(worker) + .to receive(:wait_for_jobs) + .with({ '123' => 2 }) + .and_return({}) + end + + it 'schedules the next stage' do + expect(project) + .to receive(:refresh_import_jid_expiration) + + expect(Gitlab::GithubImport::Stage::FinishImportWorker) + .to receive(:perform_async) + .with(project.id) + + worker.perform(project.id, { '123' => 2 }, :finish) + end + + it 'raises KeyError when the stage name is invalid' do + expect { worker.perform(project.id, { '123' => 2 }, :kittens) } + .to raise_error(KeyError) + end + end + end + + describe '#wait_for_jobs' do + it 'waits for jobs to complete and returns a new pair of keys to wait for' do + waiter1 = double(:waiter1, jobs_remaining: 1, key: '123') + waiter2 = double(:waiter2, jobs_remaining: 0, key: '456') + + expect(Gitlab::JobWaiter) + .to receive(:new) + .ordered + .with(2, '123') + .and_return(waiter1) + + expect(Gitlab::JobWaiter) + .to receive(:new) + .ordered + .with(1, '456') + .and_return(waiter2) + + expect(waiter1) + .to receive(:wait) + .with(described_class::BLOCKING_WAIT_TIME) + + expect(waiter2) + .to receive(:wait) + .with(described_class::BLOCKING_WAIT_TIME) + + new_waiters = worker.wait_for_jobs({ '123' => 2, '456' => 1 }) + + expect(new_waiters).to eq({ '123' => 1 }) + end + end + + describe '#find_project' do + it 'returns a Project' do + project.update_column(:import_status, 'started') + + found = worker.find_project(project.id) + + expect(found).to be_an_instance_of(Project) + + # This test is there to make sure we only select the columns we care + # about. + expect(found.attributes).to eq({ 'id' => nil, 'import_jid' => '123' }) + end + + it 'returns nil if the project import is not running' do + expect(worker.find_project(project.id)).to be_nil + end + end +end diff --git a/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb new file mode 100644 index 00000000000..7c8c665a9b3 --- /dev/null +++ b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ImportDiffNoteWorker do + let(:worker) { described_class.new } + + describe '#import' do + it 'imports a diff note' do + project = double(:project, path_with_namespace: 'foo/bar') + client = double(:client) + importer = double(:importer) + hash = { + 'noteable_id' => 42, + 'path' => 'README.md', + 'commit_id' => '123abc', + 'diff_hunk' => "@@ -1 +1 @@\n-Hello\n+Hello world", + 'user' => { 'id' => 4, 'login' => 'alice' }, + 'note' => 'Hello world', + 'created_at' => Time.zone.now.to_s, + 'updated_at' => Time.zone.now.to_s + } + + expect(Gitlab::GithubImport::Importer::DiffNoteImporter) + .to receive(:new) + .with( + an_instance_of(Gitlab::GithubImport::Representation::DiffNote), + project, + client + ) + .and_return(importer) + + expect(importer) + .to receive(:execute) + + expect(worker.counter) + .to receive(:increment) + .with(project: 'foo/bar') + .and_call_original + + worker.import(project, client, hash) + end + end +end diff --git a/spec/workers/gitlab/github_import/import_issue_worker_spec.rb b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb new file mode 100644 index 00000000000..4116380ff4d --- /dev/null +++ b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ImportIssueWorker do + let(:worker) { described_class.new } + + describe '#import' do + it 'imports an issue' do + project = double(:project, path_with_namespace: 'foo/bar') + client = double(:client) + importer = double(:importer) + hash = { + 'iid' => 42, + 'title' => 'My Issue', + 'description' => 'This is my issue', + 'milestone_number' => 4, + 'state' => 'opened', + 'assignees' => [{ 'id' => 4, 'login' => 'alice' }], + 'label_names' => %w[bug], + 'user' => { 'id' => 4, 'login' => 'alice' }, + 'created_at' => Time.zone.now.to_s, + 'updated_at' => Time.zone.now.to_s, + 'pull_request' => false + } + + expect(Gitlab::GithubImport::Importer::IssueAndLabelLinksImporter) + .to receive(:new) + .with( + an_instance_of(Gitlab::GithubImport::Representation::Issue), + project, + client + ) + .and_return(importer) + + expect(importer) + .to receive(:execute) + + expect(worker.counter) + .to receive(:increment) + .with(project: 'foo/bar') + .and_call_original + + worker.import(project, client, hash) + end + end +end diff --git a/spec/workers/gitlab/github_import/import_note_worker_spec.rb b/spec/workers/gitlab/github_import/import_note_worker_spec.rb new file mode 100644 index 00000000000..0ca825a722b --- /dev/null +++ b/spec/workers/gitlab/github_import/import_note_worker_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ImportNoteWorker do + let(:worker) { described_class.new } + + describe '#import' do + it 'imports a note' do + project = double(:project, path_with_namespace: 'foo/bar') + client = double(:client) + importer = double(:importer) + hash = { + 'noteable_id' => 42, + 'noteable_type' => 'issues', + 'user' => { 'id' => 4, 'login' => 'alice' }, + 'note' => 'Hello world', + 'created_at' => Time.zone.now.to_s, + 'updated_at' => Time.zone.now.to_s + } + + expect(Gitlab::GithubImport::Importer::NoteImporter) + .to receive(:new) + .with( + an_instance_of(Gitlab::GithubImport::Representation::Note), + project, + client + ) + .and_return(importer) + + expect(importer) + .to receive(:execute) + + expect(worker.counter) + .to receive(:increment) + .with(project: 'foo/bar') + .and_call_original + + worker.import(project, client, hash) + end + end +end diff --git a/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb b/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb new file mode 100644 index 00000000000..d49f560af42 --- /dev/null +++ b/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ImportPullRequestWorker do + let(:worker) { described_class.new } + + describe '#import' do + it 'imports a pull request' do + project = double(:project, path_with_namespace: 'foo/bar') + client = double(:client) + importer = double(:importer) + hash = { + 'iid' => 42, + 'title' => 'My Pull Request', + 'description' => 'This is my pull request', + 'source_branch' => 'my-feature', + 'source_branch_sha' => '123abc', + 'target_branch' => 'master', + 'target_branch_sha' => '456def', + 'source_repository_id' => 400, + 'target_repository_id' => 200, + 'source_repository_owner' => 'alice', + 'state' => 'closed', + 'milestone_number' => 4, + 'user' => { 'id' => 4, 'login' => 'alice' }, + 'assignee' => { 'id' => 4, 'login' => 'alice' }, + 'created_at' => Time.zone.now.to_s, + 'updated_at' => Time.zone.now.to_s, + 'merged_at' => Time.zone.now.to_s + } + + expect(Gitlab::GithubImport::Importer::PullRequestImporter) + .to receive(:new) + .with( + an_instance_of(Gitlab::GithubImport::Representation::PullRequest), + project, + client + ) + .and_return(importer) + + expect(importer) + .to receive(:execute) + + expect(worker.counter) + .to receive(:increment) + .with(project: 'foo/bar') + .and_call_original + + worker.import(project, client, hash) + end + end +end diff --git a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb new file mode 100644 index 00000000000..073c6d7a2f5 --- /dev/null +++ b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb @@ -0,0 +1,95 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::RefreshImportJidWorker do + let(:worker) { described_class.new } + + describe '.perform_in_the_future' do + it 'schedules a job in the future' do + expect(described_class) + .to receive(:perform_in) + .with(1.minute.to_i, 10, '123') + + described_class.perform_in_the_future(10, '123') + end + end + + describe '#perform' do + let(:project) { create(:project, import_jid: '123abc') } + + context 'when the project does not exist' do + it 'does nothing' do + expect(Gitlab::SidekiqStatus) + .not_to receive(:running?) + + worker.perform(-1, '123') + end + end + + context 'when the job is running' do + it 'refreshes the import JID and reschedules itself' do + allow(worker) + .to receive(:find_project) + .with(project.id) + .and_return(project) + + expect(Gitlab::SidekiqStatus) + .to receive(:running?) + .with('123') + .and_return(true) + + expect(project) + .to receive(:refresh_import_jid_expiration) + + expect(worker.class) + .to receive(:perform_in_the_future) + .with(project.id, '123') + + worker.perform(project.id, '123') + end + end + + context 'when the job is no longer running' do + it 'returns' do + allow(worker) + .to receive(:find_project) + .with(project.id) + .and_return(project) + + expect(Gitlab::SidekiqStatus) + .to receive(:running?) + .with('123') + .and_return(false) + + expect(project) + .not_to receive(:refresh_import_jid_expiration) + + worker.perform(project.id, '123') + end + end + end + + describe '#find_project' do + it 'returns a Project' do + project = create(:project, import_status: 'started') + + expect(worker.find_project(project.id)).to be_an_instance_of(Project) + end + + it 'only selects the import JID field' do + project = create(:project, import_status: 'started', import_jid: '123abc') + + expect(worker.find_project(project.id).attributes) + .to eq({ 'id' => nil, 'import_jid' => '123abc' }) + end + + it 'returns nil for a project for which the import process failed' do + project = create(:project, import_status: 'failed') + + expect(worker.find_project(project.id)).to be_nil + end + + it 'returns nil for a non-existing project' do + expect(worker.find_project(-1)).to be_nil + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb b/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb new file mode 100644 index 00000000000..91e0cddb5d8 --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::FinishImportWorker do + let(:project) { create(:project) } + let(:worker) { described_class.new } + + describe '#perform' do + it 'marks the import as finished' do + expect(project).to receive(:after_import) + expect(worker).to receive(:report_import_time).with(project) + + worker.import(double(:client), project) + end + end + + describe '#report_import_time' do + it 'reports the total import time' do + expect(worker.histogram) + .to receive(:observe) + .with({ project: project.path_with_namespace }, a_kind_of(Numeric)) + .and_call_original + + expect(worker.counter) + .to receive(:increment) + .and_call_original + + expect(worker.logger).to receive(:info).with(an_instance_of(String)) + + worker.report_import_time(project) + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb new file mode 100644 index 00000000000..8c80d660287 --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::ImportBaseDataWorker do + let(:project) { create(:project) } + let(:worker) { described_class.new } + + describe '#import' do + it 'imports the base data of a project' do + importer = double(:importer) + client = double(:client) + + described_class::IMPORTERS.each do |klass| + expect(klass) + .to receive(:new) + .with(project, client) + .and_return(importer) + + expect(importer).to receive(:execute) + end + + expect(project).to receive(:refresh_import_jid_expiration) + + expect(Gitlab::GithubImport::Stage::ImportPullRequestsWorker) + .to receive(:perform_async) + .with(project.id) + + worker.import(client, project) + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb new file mode 100644 index 00000000000..ab347f5b75b --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::ImportIssuesAndDiffNotesWorker do + let(:project) { create(:project) } + let(:worker) { described_class.new } + + describe '#import' do + it 'imports the issues and diff notes' do + client = double(:client) + + described_class::IMPORTERS.each do |klass| + importer = double(:importer) + waiter = Gitlab::JobWaiter.new(2, '123') + + expect(klass) + .to receive(:new) + .with(project, client) + .and_return(importer) + + expect(importer) + .to receive(:execute) + .and_return(waiter) + end + + expect(Gitlab::GithubImport::AdvanceStageWorker) + .to receive(:perform_async) + .with(project.id, { '123' => 2 }, :notes) + + worker.import(client, project) + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb new file mode 100644 index 00000000000..098d2d55386 --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::ImportNotesWorker do + let(:project) { create(:project) } + let(:worker) { described_class.new } + + describe '#import' do + it 'imports all the notes' do + importer = double(:importer) + client = double(:client) + waiter = Gitlab::JobWaiter.new(2, '123') + + expect(Gitlab::GithubImport::Importer::NotesImporter) + .to receive(:new) + .with(project, client) + .and_return(importer) + + expect(importer) + .to receive(:execute) + .and_return(waiter) + + expect(Gitlab::GithubImport::AdvanceStageWorker) + .to receive(:perform_async) + .with(project.id, { '123' => 2 }, :finish) + + worker.import(client, project) + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb new file mode 100644 index 00000000000..2fc91a3e80a --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::ImportPullRequestsWorker do + let(:project) { create(:project) } + let(:worker) { described_class.new } + + describe '#import' do + it 'imports all the pull requests' do + importer = double(:importer) + client = double(:client) + waiter = Gitlab::JobWaiter.new(2, '123') + + expect(Gitlab::GithubImport::Importer::PullRequestsImporter) + .to receive(:new) + .with(project, client) + .and_return(importer) + + expect(importer) + .to receive(:execute) + .and_return(waiter) + + expect(project) + .to receive(:refresh_import_jid_expiration) + + expect(Gitlab::GithubImport::AdvanceStageWorker) + .to receive(:perform_async) + .with(project.id, { '123' => 2 }, :issues_and_diff_notes) + + worker.import(client, project) + end + end +end diff --git a/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb new file mode 100644 index 00000000000..adab535ac05 --- /dev/null +++ b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Stage::ImportRepositoryWorker do + let(:project) { double(:project, id: 4) } + let(:worker) { described_class.new } + + describe '#import' do + before do + expect(Gitlab::GithubImport::RefreshImportJidWorker) + .to receive(:perform_in_the_future) + .with(project.id, '123') + + expect(worker) + .to receive(:jid) + .and_return('123') + end + + context 'when the import succeeds' do + it 'schedules the importing of the base data' do + client = double(:client) + + expect_any_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) + .to receive(:execute) + .and_return(true) + + expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker) + .to receive(:perform_async) + .with(project.id) + + worker.import(client, project) + end + end + + context 'when the import fails' do + it 'does not schedule the importing of the base data' do + client = double(:client) + + expect_any_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) + .to receive(:execute) + .and_return(false) + + expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker) + .not_to receive(:perform_async) + + worker.import(client, project) + end + end + end +end diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index 75197039f5a..e7a4ac0f3d6 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -22,25 +22,32 @@ describe PipelineScheduleWorker do end context 'when there is a scheduled pipeline within next_run_at' do - it 'creates a new pipeline' do - expect { subject }.to change { project.pipelines.count }.by(1) - expect(Ci::Pipeline.last).to be_schedule + shared_examples 'successful scheduling' do + it 'creates a new pipeline' do + expect { subject }.to change { project.pipelines.count }.by(1) + expect(Ci::Pipeline.last).to be_schedule + + pipeline_schedule.reload + expect(pipeline_schedule.next_run_at).to be > Time.now + expect(pipeline_schedule).to eq(project.pipelines.last.pipeline_schedule) + expect(pipeline_schedule).to be_active + end end - it 'updates the next_run_at field' do - subject + it_behaves_like 'successful scheduling' - expect(pipeline_schedule.reload.next_run_at).to be > Time.now - end - - it 'sets the schedule on the pipeline' do - subject + context 'when the latest commit contains [ci skip]' do + before do + allow_any_instance_of(Ci::Pipeline) + .to receive(:git_commit_message) + .and_return('some commit [ci skip]') + end - expect(project.pipelines.last.pipeline_schedule).to eq(pipeline_schedule) + it_behaves_like 'successful scheduling' end end - context 'inactive schedule' do + context 'when the schedule is deactivated' do before do pipeline_schedule.deactivate! end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 05eecf5f0bb..5d9b0679796 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -66,19 +66,21 @@ describe PostReceive do end context "gitlab-ci.yml" do + let(:changes) { "123456 789012 refs/heads/feature\n654321 210987 refs/tags/tag" } + subject { described_class.new.perform(gl_repository, key_id, base64_changes) } context "creates a Ci::Pipeline for every change" do before do stub_ci_pipeline_to_return_yaml_file - # TODO, don't stub private methods - # - allow_any_instance_of(Ci::CreatePipelineService) - .to receive(:commit).and_return(OpenStruct.new(id: '123456')) + allow_any_instance_of(Project) + .to receive(:commit) + .and_return(project.commit) allow_any_instance_of(Repository) - .to receive(:branch_exists?).and_return(true) + .to receive(:branch_exists?) + .and_return(true) end it { expect { subject }.to change { Ci::Pipeline.count }.by(2) } diff --git a/spec/workers/project_migrate_hashed_storage_worker_spec.rb b/spec/workers/project_migrate_hashed_storage_worker_spec.rb index f5226dee0ad..2e3951e7afc 100644 --- a/spec/workers/project_migrate_hashed_storage_worker_spec.rb +++ b/spec/workers/project_migrate_hashed_storage_worker_spec.rb @@ -1,29 +1,53 @@ require 'spec_helper' -describe ProjectMigrateHashedStorageWorker do +describe ProjectMigrateHashedStorageWorker, :clean_gitlab_redis_shared_state do describe '#perform' do let(:project) { create(:project, :empty_repo) } let(:pending_delete_project) { create(:project, :empty_repo, pending_delete: true) } - it 'skips when project no longer exists' do - nonexistent_id = 999999999999 + context 'when have exclusive lease' do + before do + lease = subject.lease_for(project.id) - expect(::Projects::HashedStorageMigrationService).not_to receive(:new) - subject.perform(nonexistent_id) - end + allow(Gitlab::ExclusiveLease).to receive(:new).and_return(lease) + allow(lease).to receive(:try_obtain).and_return(true) + end + + it 'skips when project no longer exists' do + nonexistent_id = 999999999999 + + expect(::Projects::HashedStorageMigrationService).not_to receive(:new) + subject.perform(nonexistent_id) + end + + it 'skips when project is pending delete' do + expect(::Projects::HashedStorageMigrationService).not_to receive(:new) - it 'skips when project is pending delete' do - expect(::Projects::HashedStorageMigrationService).not_to receive(:new) + subject.perform(pending_delete_project.id) + end - subject.perform(pending_delete_project.id) + it 'delegates removal to service class' do + service = double('service') + expect(::Projects::HashedStorageMigrationService).to receive(:new).with(project, subject.logger).and_return(service) + expect(service).to receive(:execute) + + subject.perform(project.id) + end end - it 'delegates removal to service class' do - service = double('service') - expect(::Projects::HashedStorageMigrationService).to receive(:new).with(project, subject.logger).and_return(service) - expect(service).to receive(:execute) + context 'when dont have exclusive lease' do + before do + lease = subject.lease_for(project.id) + + allow(Gitlab::ExclusiveLease).to receive(:new).and_return(lease) + allow(lease).to receive(:try_obtain).and_return(false) + end + + it 'skips when dont have lease' do + expect(::Projects::HashedStorageMigrationService).not_to receive(:new) - subject.perform(project.id) + subject.perform(project.id) + end end end end diff --git a/spec/workers/reactive_caching_worker_spec.rb b/spec/workers/reactive_caching_worker_spec.rb index 5f4453c15d6..3da851de067 100644 --- a/spec/workers/reactive_caching_worker_spec.rb +++ b/spec/workers/reactive_caching_worker_spec.rb @@ -1,15 +1,28 @@ require 'spec_helper' describe ReactiveCachingWorker do - let(:project) { create(:kubernetes_project) } - let(:service) { project.deployment_service } - subject { described_class.new.perform("KubernetesService", service.id) } + let(:service) { project.deployment_platform } describe '#perform' do - it 'calls #exclusively_update_reactive_cache!' do - expect_any_instance_of(KubernetesService).to receive(:exclusively_update_reactive_cache!) + context 'when user configured kubernetes from Integration > Kubernetes' do + let(:project) { create(:kubernetes_project) } - subject + it 'calls #exclusively_update_reactive_cache!' do + expect_any_instance_of(KubernetesService).to receive(:exclusively_update_reactive_cache!) + + described_class.new.perform("KubernetesService", service.id) + end + end + + context 'when user configured kubernetes from CI/CD > Clusters' do + let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:project) { cluster.project } + + it 'calls #exclusively_update_reactive_cache!' do + expect_any_instance_of(Clusters::Platforms::Kubernetes).to receive(:exclusively_update_reactive_cache!) + + described_class.new.perform("Clusters::Platforms::Kubernetes", service.id) + end end end end diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index e881ec37ae5..74c85848b7e 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe RepositoryForkWorker do - let(:project) { create(:project, :repository, :import_scheduled) } - let(:fork_project) { create(:project, :repository, forked_from_project: project) } + let(:project) { create(:project, :repository) } + let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) } let(:shell) { Gitlab::Shell.new } subject { described_class.new } @@ -12,50 +12,39 @@ describe RepositoryForkWorker do end describe "#perform" do + def perform! + subject.perform(fork_project.id, '/test/path', project.disk_path) + end + + def expect_fork_repository + expect(shell).to receive(:fork_repository).with( + '/test/path', + project.disk_path, + fork_project.repository_storage_path, + fork_project.disk_path + ) + end + describe 'when a worker was reset without cleanup' do let(:jid) { '12345678' } - let(:started_project) { create(:project, :repository, :import_started) } it 'creates a new repository from a fork' do allow(subject).to receive(:jid).and_return(jid) - expect(shell).to receive(:fork_repository).with( - '/test/path', - project.full_path, - project.repository_storage_path, - fork_project.namespace.full_path - ).and_return(true) - - subject.perform( - project.id, - '/test/path', - project.full_path, - fork_project.namespace.full_path) + expect_fork_repository.and_return(true) + + perform! end end it "creates a new repository from a fork" do - expect(shell).to receive(:fork_repository).with( - '/test/path', - project.full_path, - project.repository_storage_path, - fork_project.namespace.full_path - ).and_return(true) + expect_fork_repository.and_return(true) - subject.perform( - project.id, - '/test/path', - project.full_path, - fork_project.namespace.full_path) + perform! end it 'flushes various caches' do - expect(shell).to receive(:fork_repository).with( - '/test/path', - project.full_path, - project.repository_storage_path, - fork_project.namespace.full_path - ).and_return(true) + expect_fork_repository.and_return(true) expect_any_instance_of(Repository).to receive(:expire_emptiness_caches) .and_call_original @@ -63,32 +52,22 @@ describe RepositoryForkWorker do expect_any_instance_of(Repository).to receive(:expire_exists_cache) .and_call_original - subject.perform(project.id, '/test/path', project.full_path, - fork_project.namespace.full_path) + perform! end it "handles bad fork" do - source_path = project.full_path - target_path = fork_project.namespace.full_path - error_message = "Unable to fork project #{project.id} for repository #{source_path} -> #{target_path}" + error_message = "Unable to fork project #{fork_project.id} for repository #{project.full_path} -> #{fork_project.full_path}" - expect(shell).to receive(:fork_repository).and_return(false) + expect_fork_repository.and_return(false) - expect do - subject.perform(project.id, '/test/path', source_path, target_path) - end.to raise_error(RepositoryForkWorker::ForkError, error_message) + expect { perform! }.to raise_error(RepositoryForkWorker::ForkError, error_message) end it 'handles unexpected error' do - source_path = project.full_path - target_path = fork_project.namespace.full_path - - allow_any_instance_of(Gitlab::Shell).to receive(:fork_repository).and_raise(RuntimeError) + expect_fork_repository.and_raise(RuntimeError) - expect do - subject.perform(project.id, '/test/path', source_path, target_path) - end.to raise_error(RepositoryForkWorker::ForkError) - expect(project.reload.import_status).to eq('failed') + expect { perform! }.to raise_error(RepositoryForkWorker::ForkError) + expect(fork_project.reload.import_status).to eq('failed') end end end diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index 5cff5108477..0af537647ad 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -59,5 +59,28 @@ describe RepositoryImportWorker do expect(project.reload.import_status).to eq('failed') end end + + context 'when using an asynchronous importer' do + it 'does not mark the import process as finished' do + service = double(:service) + + allow(Projects::ImportService) + .to receive(:new) + .and_return(service) + + allow(service) + .to receive(:execute) + .and_return(true) + + allow(service) + .to receive(:async?) + .and_return(true) + + expect_any_instance_of(Project) + .not_to receive(:import_finish) + + subject.perform(project.id) + end + end end end diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb index ac6f4fefb4e..bdc64c6785b 100644 --- a/spec/workers/stuck_ci_jobs_worker_spec.rb +++ b/spec/workers/stuck_ci_jobs_worker_spec.rb @@ -105,8 +105,8 @@ describe StuckCiJobsWorker do job.project.update(pending_delete: true) end - it 'does not drop job' do - expect_any_instance_of(Ci::Build).not_to receive(:drop) + it 'does drop job' do + expect_any_instance_of(Ci::Build).to receive(:drop).and_call_original worker.perform end end @@ -117,7 +117,7 @@ describe StuckCiJobsWorker do let(:worker2) { described_class.new } it 'is guard by exclusive lease when executed concurrently' do - expect(worker).to receive(:drop).at_least(:once) + expect(worker).to receive(:drop).at_least(:once).and_call_original expect(worker2).not_to receive(:drop) worker.perform allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).and_return(false) @@ -125,8 +125,8 @@ describe StuckCiJobsWorker do end it 'can be executed in sequence' do - expect(worker).to receive(:drop).at_least(:once) - expect(worker2).to receive(:drop).at_least(:once) + expect(worker).to receive(:drop).at_least(:once).and_call_original + expect(worker2).to receive(:drop).at_least(:once).and_call_original worker.perform worker2.perform end 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 new file mode 100644 index 00000000000..522e1566271 --- /dev/null +++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb @@ -0,0 +1,38 @@ +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' } + + 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 + + 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 } + end + + context 'when merge request sha does not equal pipeline sha' do + before do + merge_request.merge_request_diff.update(head_commit_sha: 'different_sha') + end + + it 'does not update head_pipeline_id' do + expect { subject.perform(merge_request.id) }.to raise_error(ArgumentError) + + expect(merge_request.reload.head_pipeline_id).to eq(nil) + end + end + end + + context 'when pipeline does not exist for the source project and branch' do + it 'does not update the head_pipeline_id of the merge_request' do + expect { subject.perform(merge_request.id) }.not_to change { merge_request.reload.head_pipeline_id } + end + end + end +end diff --git a/spec/workers/update_merge_requests_worker_spec.rb b/spec/workers/update_merge_requests_worker_spec.rb index 558ff9109ec..0fa19ac84bb 100644 --- a/spec/workers/update_merge_requests_worker_spec.rb +++ b/spec/workers/update_merge_requests_worker_spec.rb @@ -23,5 +23,17 @@ describe UpdateMergeRequestsWorker do perform end + + context 'when slow' do + before do + stub_const("UpdateMergeRequestsWorker::LOG_TIME_THRESHOLD", -1) + end + + it 'logs debug info' do + expect(Rails.logger).to receive(:info).with(a_string_matching(/\AUpdateMergeRequestsWorker#perform.*project_id=#{project.id},user_id=#{user.id},oldrev=#{oldrev},newrev=#{newrev},ref=#{ref}/)) + + perform + end + end end end |
