Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab')
-rw-r--r--spec/lib/gitlab/checks/snippet_check_spec.rb4
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb22
-rw-r--r--spec/lib/gitlab/graphql/docs/renderer_spec.rb96
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/incoming_email_spec.rb11
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb34
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb125
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb52
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb38
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb15
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb6
11 files changed, 390 insertions, 15 deletions
diff --git a/spec/lib/gitlab/checks/snippet_check_spec.rb b/spec/lib/gitlab/checks/snippet_check_spec.rb
index 7cb29debd1e..7cfcde7183f 100644
--- a/spec/lib/gitlab/checks/snippet_check_spec.rb
+++ b/spec/lib/gitlab/checks/snippet_check_spec.rb
@@ -19,7 +19,7 @@ describe Gitlab::Checks::SnippetCheck do
let(:newrev) { '0000000000000000000000000000000000000000' }
it 'raises an error' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can not create or delete branches.')
+ expect { subject.exec }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can not create or delete branches.')
end
end
@@ -27,7 +27,7 @@ describe Gitlab::Checks::SnippetCheck do
let(:oldrev) { '0000000000000000000000000000000000000000' }
it 'raises an error' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can not create or delete branches.')
+ expect { subject.exec }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can not create or delete branches.')
end
end
end
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index de19db38176..a68ac8ee8fe 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -26,7 +26,7 @@ describe Gitlab::GitAccessSnippet do
let(:actor) { build(:deploy_key) }
it 'does not allow push and pull access' do
- expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:authentication_mechanism])
+ expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:authentication_mechanism])
end
end
@@ -76,8 +76,8 @@ describe Gitlab::GitAccessSnippet do
it 'blocks access when the user did not accept terms' do
message = /must accept the Terms of Service in order to perform this action/
- expect { push_access_check }.to raise_unauthorized(message)
- expect { pull_access_check }.to raise_unauthorized(message)
+ expect { push_access_check }.to raise_forbidden(message)
+ expect { pull_access_check }.to raise_forbidden(message)
end
it 'allows access when the user accepted the terms' do
@@ -101,13 +101,13 @@ describe Gitlab::GitAccessSnippet do
if Ability.allowed?(user, :update_snippet, snippet)
expect { push_access_check }.not_to raise_error
else
- expect { push_access_check }.to raise_error(described_class::UnauthorizedError)
+ expect { push_access_check }.to raise_error(described_class::ForbiddenError)
end
if Ability.allowed?(user, :read_snippet, snippet)
expect { pull_access_check }.not_to raise_error
else
- expect { pull_access_check }.to raise_error(described_class::UnauthorizedError)
+ expect { pull_access_check }.to raise_error(described_class::ForbiddenError)
end
end
end
@@ -154,7 +154,7 @@ describe Gitlab::GitAccessSnippet do
with_them do
it "respects accessibility" do
- error_class = described_class::UnauthorizedError
+ error_class = described_class::ForbiddenError
if Ability.allowed?(user, :update_snippet, snippet)
expect { push_access_check }.not_to raise_error
@@ -180,7 +180,7 @@ describe Gitlab::GitAccessSnippet do
allow(::Gitlab::Database).to receive(:read_only?).and_return(true)
allow(::Gitlab::Geo).to receive(:secondary_with_primary?).and_return(true)
- expect { push_access_check }.to raise_unauthorized(/You can't push code to a read-only GitLab instance/)
+ expect { push_access_check }.to raise_forbidden(/You can't push code to a read-only GitLab instance/)
end
end
@@ -198,10 +198,10 @@ describe Gitlab::GitAccessSnippet do
it 'raises error if SnippetCheck raises error' do
expect_next_instance_of(Gitlab::Checks::SnippetCheck) do |check|
- allow(check).to receive(:exec).and_raise(Gitlab::GitAccess::UnauthorizedError, 'foo')
+ allow(check).to receive(:exec).and_raise(Gitlab::GitAccess::ForbiddenError, 'foo')
end
- expect { push_access_check }.to raise_unauthorized('foo')
+ expect { push_access_check }.to raise_forbidden('foo')
end
end
@@ -215,7 +215,7 @@ describe Gitlab::GitAccessSnippet do
raise_error(Gitlab::GitAccess::NotFoundError, Gitlab::GitAccess::ERROR_MESSAGES[:project_not_found])
end
- def raise_unauthorized(message)
- raise_error(Gitlab::GitAccess::UnauthorizedError, message)
+ def raise_forbidden(message)
+ raise_error(Gitlab::GitAccess::ForbiddenError, message)
end
end
diff --git a/spec/lib/gitlab/graphql/docs/renderer_spec.rb b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
new file mode 100644
index 00000000000..5ba70bb8f0a
--- /dev/null
+++ b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Docs::Renderer do
+ describe '#contents' do
+ # Returns a Schema that uses the given `type`
+ def mock_schema(type)
+ query_type = Class.new(GraphQL::Schema::Object) do
+ graphql_name 'QueryType'
+
+ field :foo, type, null: true
+ end
+
+ GraphQL::Schema.define(query: query_type)
+ end
+
+ let_it_be(:template) { Rails.root.join('lib/gitlab/graphql/docs/templates/', 'default.md.haml') }
+
+ subject(:contents) do
+ described_class.new(
+ mock_schema(type).graphql_definition,
+ output_dir: nil,
+ template: template
+ ).contents
+ end
+
+ context 'A type with a field with a [Array] return type' do
+ let(:type) do
+ Class.new(GraphQL::Schema::Object) do
+ graphql_name 'ArrayTest'
+
+ field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description'
+ end
+ end
+
+ specify do
+ expectation = <<~DOC
+ ## ArrayTest
+
+ | Name | Type | Description |
+ | --- | ---- | ---------- |
+ | `foo` | String! => Array | A description |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
+
+ context 'A type with fields defined in reverse alphabetical order' do
+ let(:type) do
+ Class.new(GraphQL::Schema::Object) do
+ graphql_name 'OrderingTest'
+
+ field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field'
+ field :bar, GraphQL::STRING_TYPE, null: false, description: 'A description of bar field'
+ end
+ end
+
+ specify do
+ expectation = <<~DOC
+ ## OrderingTest
+
+ | Name | Type | Description |
+ | --- | ---- | ---------- |
+ | `bar` | String! | A description of bar field |
+ | `foo` | String! | A description of foo field |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
+
+ context 'A type with a deprecated field' do
+ let(:type) do
+ Class.new(GraphQL::Schema::Object) do
+ graphql_name 'DeprecatedTest'
+
+ field :foo, GraphQL::STRING_TYPE, null: false, deprecation_reason: 'This is deprecated', description: 'A description'
+ end
+ end
+
+ specify do
+ expectation = <<~DOC
+ ## DeprecatedTest
+
+ | Name | Type | Description |
+ | --- | ---- | ---------- |
+ | `foo` **{warning-solid}** | String! | **Deprecated:** This is deprecated |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index db45b9c42fd..d97d76cf35e 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -192,6 +192,7 @@ ci_pipelines:
- environments
- chat_data
- source_pipeline
+- ref_status
- source_bridge
- source_job
- sourced_pipelines
@@ -359,6 +360,7 @@ project:
- ci_pipelines
- all_pipelines
- stages
+- ci_refs
- builds
- runner_projects
- runners
diff --git a/spec/lib/gitlab/incoming_email_spec.rb b/spec/lib/gitlab/incoming_email_spec.rb
index f5a6ea4d5b0..2dd45d18ee9 100644
--- a/spec/lib/gitlab/incoming_email_spec.rb
+++ b/spec/lib/gitlab/incoming_email_spec.rb
@@ -89,6 +89,17 @@ describe Gitlab::IncomingEmail do
it 'does not match emails with extra bits' do
expect(described_class.key_from_address('somereplies+somekey@example.com.someotherdomain.com')).to be nil
end
+
+ context 'when a custom wildcard address is used' do
+ let(:wildcard_address) { 'custom.address+%{key}@example.com' }
+
+ it 'finds key if email matches address pattern' do
+ key = described_class.key_from_address(
+ 'custom.address+foo@example.com', wildcard_address: wildcard_address
+ )
+ expect(key).to eq('foo')
+ end
+ end
end
context 'self.key_from_fallback_message_id' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb
new file mode 100644
index 00000000000..b6e47afc7e8
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SidekiqMiddleware::DuplicateJobs::Client, :clean_gitlab_redis_queues do
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDeduplicationWorker'
+ end
+
+ include ApplicationWorker
+
+ def perform(*args)
+ end
+ end
+ end
+
+ before do
+ stub_const('TestDeduplicationWorker', worker_class)
+ end
+
+ describe '#call' do
+ it 'adds a correct duplicate tag to the jobs', :aggregate_failures do
+ TestDeduplicationWorker.bulk_perform_async([['args1'], ['args2'], ['args1']])
+
+ job1, job2, job3 = TestDeduplicationWorker.jobs
+
+ expect(job1['duplicate-of']).to be_nil
+ expect(job2['duplicate-of']).to be_nil
+ expect(job3['duplicate-of']).to eq(job1['jid'])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
new file mode 100644
index 00000000000..2334439461e
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gitlab_redis_queues do
+ subject(:duplicate_job) do
+ described_class.new(job, queue)
+ end
+
+ let(:job) { { 'class' => 'AuthorizedProjectsWorker', 'args' => [1], 'jid' => '123' } }
+ let(:queue) { 'authorized_projects' }
+
+ let(:idempotency_key) do
+ hash = Digest::SHA256.hexdigest("#{job['class']}:#{job['args'].join('-')}")
+ "#{Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE}:duplicate:#{queue}:#{hash}"
+ end
+
+ describe '#schedule' do
+ it 'calls schedule on the strategy' do
+ expect do |block|
+ expect_next_instance_of(Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting) do |strategy|
+ expect(strategy).to receive(:schedule).with(job, &block)
+ end
+
+ duplicate_job.schedule(&block)
+ end.to yield_control
+ end
+ end
+
+ describe '#perform' do
+ it 'calls perform on the strategy' do
+ expect do |block|
+ expect_next_instance_of(Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting) do |strategy|
+ expect(strategy).to receive(:perform).with(job, &block)
+ end
+
+ duplicate_job.perform(&block)
+ end.to yield_control
+ end
+ end
+
+ describe '#check!' do
+ context 'when there was no job in the queue yet' do
+ it { expect(duplicate_job.check!).to eq('123') }
+
+ it "adds a key with ttl set to #{described_class::DUPLICATE_KEY_TTL}" do
+ expect { duplicate_job.check! }
+ .to change { read_idempotency_key_with_ttl(idempotency_key) }
+ .from([nil, -2])
+ .to(['123', be_within(1).of(described_class::DUPLICATE_KEY_TTL)])
+ end
+ end
+
+ context 'when there was already a job with same arguments in the same queue' do
+ before do
+ set_idempotency_key(idempotency_key, 'existing-key')
+ end
+
+ it { expect(duplicate_job.check!).to eq('existing-key') }
+
+ it "does not change the existing key's TTL" do
+ expect { duplicate_job.check! }
+ .not_to change { read_idempotency_key_with_ttl(idempotency_key) }
+ .from(['existing-key', -1])
+ end
+
+ it 'sets the existing jid' do
+ duplicate_job.check!
+
+ expect(duplicate_job.existing_jid).to eq('existing-key')
+ end
+ end
+ end
+
+ describe '#delete!' do
+ context "when we didn't track the definition" do
+ it { expect { duplicate_job.delete! }.not_to raise_error }
+ end
+
+ context 'when the key exists in redis' do
+ before do
+ set_idempotency_key(idempotency_key, 'existing-key')
+ end
+
+ it 'removes the key from redis' do
+ expect { duplicate_job.delete! }
+ .to change { read_idempotency_key_with_ttl(idempotency_key) }
+ .from(['existing-key', -1])
+ .to([nil, -2])
+ end
+ end
+ end
+
+ describe '#duplicate?' do
+ it "raises an error if the check wasn't performed" do
+ expect { duplicate_job.duplicate? }.to raise_error /Call `#check!` first/
+ end
+
+ it 'returns false if the existing jid equals the job jid' do
+ duplicate_job.check!
+
+ expect(duplicate_job.duplicate?).to be(false)
+ end
+
+ it 'returns false if the existing jid is different from the job jid' do
+ set_idempotency_key(idempotency_key, 'a different jid')
+ duplicate_job.check!
+
+ expect(duplicate_job.duplicate?).to be(true)
+ end
+ end
+
+ def set_idempotency_key(key, value = '1')
+ Sidekiq.redis { |r| r.set(key, value) }
+ end
+
+ def read_idempotency_key_with_ttl(key)
+ Sidekiq.redis do |redis|
+ redis.pipelined do |p|
+ p.get(key)
+ p.ttl(key)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb
new file mode 100644
index 00000000000..0ea248fbcf1
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SidekiqMiddleware::DuplicateJobs::Server, :clean_gitlab_redis_queues do
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDeduplicationWorker'
+ end
+
+ include ApplicationWorker
+
+ def perform(*args)
+ end
+ end
+ end
+
+ before do
+ stub_const('TestDeduplicationWorker', worker_class)
+ end
+
+ around do |example|
+ Sidekiq::Testing.inline! { example.run }
+ end
+
+ before(:context) do
+ Sidekiq::Testing.server_middleware do |chain|
+ chain.add described_class
+ end
+ end
+
+ after(:context) do
+ Sidekiq::Testing.server_middleware do |chain|
+ chain.remove described_class
+ end
+ end
+
+ describe '#call' do
+ it 'removes the stored job from redis' do
+ bare_job = { 'class' => 'TestDeduplicationWorker', 'args' => ['hello'] }
+ job_definition = Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new(bare_job.dup, 'test_deduplication')
+
+ expect(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ .to receive(:new).with(a_hash_including(bare_job), 'test_deduplication')
+ .and_return(job_definition).twice # once in client middleware
+ expect(job_definition).to receive(:delete!).and_call_original
+
+ TestDeduplicationWorker.perform_async('hello')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
new file mode 100644
index 00000000000..f40e829f9a5
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting do
+ let(:fake_duplicate_job) do
+ instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ end
+
+ subject(:strategy) { described_class.new(fake_duplicate_job) }
+
+ describe '#schedule' do
+ it 'checks for duplicates before yielding' do
+ expect(fake_duplicate_job).to receive(:check!).ordered.and_return('a jid')
+ expect(fake_duplicate_job).to receive(:duplicate?).ordered.and_return(false)
+ expect { |b| strategy.schedule({}, &b) }.to yield_control
+ end
+
+ it 'adds the jid of the existing job to the job hash' do
+ allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
+ job_hash = {}
+
+ expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
+ expect(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+
+ strategy.schedule(job_hash) {}
+
+ expect(job_hash).to include('duplicate-of' => 'the jid')
+ end
+ end
+
+ describe '#perform' do
+ it 'deletes the lock before executing' do
+ expect(fake_duplicate_job).to receive(:delete!).ordered
+ expect { |b| strategy.perform({}, &b) }.to yield_control
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb
new file mode 100644
index 00000000000..6ecc2a3a5f8
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies do
+ describe '.for' do
+ it 'returns the right class for `until_executing`' do
+ expect(described_class.for(:until_executing)).to eq(described_class::UntilExecuting)
+ end
+
+ it 'raises an UnknownStrategyError when passing an unknown key' do
+ expect { described_class.for(:unknown) }.to raise_error(described_class::UnknownStrategyError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 19242d25e27..2f325fd5052 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -46,7 +46,8 @@ describe Gitlab::SidekiqMiddleware do
Gitlab::SidekiqMiddleware::MemoryKiller,
Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
Gitlab::SidekiqMiddleware::WorkerContext::Server,
- Gitlab::SidekiqMiddleware::AdminMode::Server
+ Gitlab::SidekiqMiddleware::AdminMode::Server,
+ Gitlab::SidekiqMiddleware::DuplicateJobs::Server
]
end
let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
@@ -117,7 +118,8 @@ describe Gitlab::SidekiqMiddleware do
Gitlab::SidekiqMiddleware::ClientMetrics,
Gitlab::SidekiqMiddleware::WorkerContext::Client,
Labkit::Middleware::Sidekiq::Client,
- Gitlab::SidekiqMiddleware::AdminMode::Client
+ Gitlab::SidekiqMiddleware::AdminMode::Client,
+ Gitlab::SidekiqMiddleware::DuplicateJobs::Client
]
end