summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/lib
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support/shared_examples/lib')
-rw-r--r--spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb26
-rw-r--r--spec/support/shared_examples/lib/cache_helpers_shared_examples.rb139
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb126
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/sentry/client_shared_examples.rb49
8 files changed, 211 insertions, 141 deletions
diff --git a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
index b5c07f45d59..47655f86558 100644
--- a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
@@ -45,62 +45,62 @@ RSpec.shared_examples 'XSS prevention' do
# Adapted from the Sanitize test suite: http://git.io/vczrM
protocols = {
'protocol-based JS injection: simple, no spaces' => {
- input: '<a href="javascript:alert(\'XSS\');">foo</a>',
+ input: '<a href="javascript:alert(\'XSS\');">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: simple, spaces before' => {
- input: '<a href="javascript :alert(\'XSS\');">foo</a>',
+ input: '<a href="javascript :alert(\'XSS\');">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: simple, spaces after' => {
- input: '<a href="javascript: alert(\'XSS\');">foo</a>',
+ input: '<a href="javascript: alert(\'XSS\');">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: simple, spaces before and after' => {
- input: '<a href="javascript : alert(\'XSS\');">foo</a>',
+ input: '<a href="javascript : alert(\'XSS\');">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: preceding colon' => {
- input: '<a href=":javascript:alert(\'XSS\');">foo</a>',
+ input: '<a href=":javascript:alert(\'XSS\');">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: UTF-8 encoding' => {
- input: '<a href="javascript&#58;">foo</a>',
+ input: '<a href="javascript&#58;">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: long UTF-8 encoding' => {
- input: '<a href="javascript&#0058;">foo</a>',
+ input: '<a href="javascript&#0058;">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: long UTF-8 encoding without semicolons' => {
- input: '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
+ input: '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: hex encoding' => {
- input: '<a href="javascript&#x3A;">foo</a>',
+ input: '<a href="javascript&#x3A;">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: long hex encoding' => {
- input: '<a href="javascript&#x003A;">foo</a>',
+ input: '<a href="javascript&#x003A;">foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: hex encoding without semicolons' => {
- input: '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
+ input: '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
output: '<a>foo</a>'
},
'protocol-based JS injection: null char' => {
- input: "<a href=java\0script:alert(\"XSS\")>foo</a>",
+ input: "<a href=java\0script:alert(\"XSS\")>foo</a>",
output: '<a href="java"></a>'
},
@@ -115,7 +115,7 @@ RSpec.shared_examples 'XSS prevention' do
},
'protocol-based JS injection: spaces and entities' => {
- input: '<a href=" &#14; javascript:alert(\'XSS\');">foo</a>',
+ input: '<a href=" &#14; javascript:alert(\'XSS\');">foo</a>',
output: '<a href="">foo</a>'
},
diff --git a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
index 845fa78a827..82a9e8130f7 100644
--- a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
+++ b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
@@ -43,6 +43,54 @@ RSpec.shared_examples_for 'object cache helper' do
subject
end
end
+
+ context 'when a caller id is present' do
+ let(:transaction) { Gitlab::Metrics::WebTransaction.new({}) }
+ let(:caller_id) { 'caller_id' }
+
+ before do
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current).and_return(transaction)
+ allow(transaction).to receive(:increment)
+ allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return(caller_id)
+ end
+
+ context 'when feature flag is off' do
+ before do
+ stub_feature_flags(add_timing_to_certain_cache_actions: false)
+ end
+
+ it 'does not call increment' do
+ expect(transaction).not_to receive(:increment).with(:cached_object_operations_total, any_args)
+
+ subject
+ end
+
+ it 'does not call histogram' do
+ expect(Gitlab::Metrics).not_to receive(:histogram)
+
+ subject
+ end
+
+ it "is valid JSON" do
+ parsed = Gitlab::Json.parse(subject.to_s)
+
+ expect(parsed).to be_a(Hash)
+ expect(parsed["id"]).to eq(presentable.id)
+ end
+ end
+
+ it 'increments the counter' do
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, 1, { caller_id: caller_id, render_type: :object, cache_hit: false }).once
+
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, 0, { caller_id: caller_id, render_type: :object, cache_hit: true }).once
+
+ subject
+ end
+ end
end
RSpec.shared_examples_for 'collection cache helper' do
@@ -98,4 +146,95 @@ RSpec.shared_examples_for 'collection cache helper' do
subject
end
end
+
+ context 'when a caller id is present' do
+ let(:transaction) { Gitlab::Metrics::WebTransaction.new({}) }
+ let(:caller_id) { 'caller_id' }
+
+ before do
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current).and_return(transaction)
+ allow(transaction).to receive(:increment)
+ allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return(caller_id)
+ end
+
+ context 'when feature flag is off' do
+ before do
+ stub_feature_flags(add_timing_to_certain_cache_actions: false)
+ end
+
+ it 'does not call increment' do
+ expect(transaction).not_to receive(:increment).with(:cached_object_operations_total, any_args)
+
+ subject
+ end
+
+ it 'does not call histogram' do
+ expect(Gitlab::Metrics).not_to receive(:histogram)
+
+ subject
+ end
+
+ it "is valid JSON" do
+ parsed = Gitlab::Json.parse(subject.to_s)
+
+ expect(parsed).to be_an(Array)
+
+ presentable.each_with_index do |item, i|
+ expect(parsed[i]["id"]).to eq(item.id)
+ end
+ end
+ end
+
+ context 'when presentable has a group by clause' do
+ let(:presentable) { MergeRequest.group(:id) }
+
+ it "returns the presentables" do
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, 0, { caller_id: caller_id, render_type: :collection, cache_hit: true }).once
+
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, MergeRequest.count, { caller_id: caller_id, render_type: :collection, cache_hit: false }).once
+
+ parsed = Gitlab::Json.parse(subject.to_s)
+
+ expect(parsed).to be_an(Array)
+
+ presentable.each_with_index do |item, i|
+ expect(parsed[i]["id"]).to eq(item.id)
+ end
+ end
+ end
+
+ context 'when the presentables all miss' do
+ it 'increments the counters' do
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, 0, { caller_id: caller_id, render_type: :collection, cache_hit: true }).once
+
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, presentable.size, { caller_id: caller_id, render_type: :collection, cache_hit: false }).once
+
+ subject
+ end
+ end
+
+ context 'when the presents hit' do
+ it 'increments the counters' do
+ subject
+
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, presentable.size, { caller_id: caller_id, render_type: :collection, cache_hit: true }).once
+
+ expect(transaction)
+ .to receive(:increment)
+ .with(:cached_object_operations_total, 0, { caller_id: caller_id, render_type: :collection, cache_hit: false }).once
+
+ instance.public_send(method, presentable, **kwargs)
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index b786d7e5527..10f58748698 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -131,7 +131,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'logs contains "section_start"' do
- let(:log) { "section_start:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_end:1506417477:a_section\r\033[0K"}
+ let(:log) { "section_start:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_end:1506417477:a_section\r\033[0K" }
it "returns only one section" do
expect(sections).not_to be_empty
@@ -144,7 +144,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'missing section_end' do
- let(:log) { "section_start:1506417476:a_section\r\033[0KSome logs\nNo section_end\n"}
+ let(:log) { "section_start:1506417476:a_section\r\033[0KSome logs\nNo section_end\n" }
it "returns no sections" do
expect(sections).to be_empty
@@ -152,7 +152,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'missing section_start' do
- let(:log) { "Some logs\nNo section_start\nsection_end:1506417476:a_section\r\033[0K"}
+ let(:log) { "Some logs\nNo section_start\nsection_end:1506417476:a_section\r\033[0K" }
it "returns no sections" do
expect(sections).to be_empty
@@ -160,7 +160,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'inverted section_start section_end' do
- let(:log) { "section_end:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_start:1506417477:a_section\r\033[0K"}
+ let(:log) { "section_end:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_start:1506417477:a_section\r\033[0K" }
it "returns no sections" do
expect(sections).to be_empty
@@ -169,7 +169,7 @@ RSpec.shared_examples 'common trace features' do
end
describe '#write' do
- subject { trace.send(:write, mode) { } }
+ subject { trace.send(:write, mode) {} }
let(:mode) { 'wb' }
@@ -370,15 +370,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
end
end
- shared_examples 'read successfully with StringIO' do
- it 'yields with source' do
- trace.read do |stream|
- expect(stream).to be_a(Gitlab::Ci::Trace::Stream)
- expect(stream.stream).to be_a(StringIO)
- end
- end
- end
-
shared_examples 'failed to read' do
it 'yields without source' do
trace.read do |stream|
@@ -404,14 +395,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
it_behaves_like 'read successfully with IO'
end
- context 'when db trace exists' do
- before do
- build.send(:write_attribute, :trace, "data")
- end
-
- it_behaves_like 'read successfully with StringIO'
- end
-
context 'when no sources exist' do
it_behaves_like 'failed to read'
end
@@ -462,25 +445,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(trace.exist?).to be(false)
end
end
-
- context 'stored in database' do
- before do
- build.send(:write_attribute, :trace, "data")
- end
-
- it "trace exist" do
- expect(trace.exist?).to be(true)
- end
-
- it "can be erased" do
- trace.erase!
- expect(trace.exist?).to be(false)
- end
-
- it "returns database data" do
- expect(trace.raw).to eq("data")
- end
- end
end
describe '#archive!' do
@@ -520,24 +484,12 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(build.trace.exist?).to be_truthy
expect(build.job_artifacts_trace.file.exists?).to be_truthy
expect(build.job_artifacts_trace.file.filename).to eq('job.log')
- expect(build.old_trace).to be_nil
expect(src_checksum)
.to eq(described_class.sha256_hexdigest(build.job_artifacts_trace.file.path))
expect(build.job_artifacts_trace.file_sha256).to eq(src_checksum)
end
end
- shared_examples 'source trace in database stays intact' do |error:|
- it do
- expect { subject }.to raise_error(error)
-
- build.reload
- expect(build.trace.exist?).to be_truthy
- expect(build.job_artifacts_trace).to be_nil
- expect(build.old_trace).to eq(trace_content)
- end
- end
-
context 'when job does not have trace artifact' do
context 'when trace file stored in default path' do
let!(:build) { create(:ci_build, :success, :trace_live) }
@@ -564,58 +516,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
it_behaves_like 'source trace file stays intact', error: ActiveRecord::RecordInvalid
end
end
-
- context 'when trace is stored in database' do
- let(:build) { create(:ci_build, :success) }
- let(:trace_content) { 'Sample trace' }
- let(:src_checksum) { Digest::SHA256.hexdigest(trace_content) }
-
- before do
- build.update_column(:trace, trace_content)
- end
-
- it_behaves_like 'archive trace in database'
-
- context 'when failed to create clone file' do
- before do
- allow(IO).to receive(:copy_stream).and_return(0)
- end
-
- it_behaves_like 'source trace in database stays intact', error: Gitlab::Ci::Trace::ArchiveError
- end
-
- context 'when failed to create job artifact record' do
- before do
- allow_any_instance_of(Ci::JobArtifact).to receive(:save).and_return(false)
- allow_any_instance_of(Ci::JobArtifact).to receive_message_chain(:errors, :full_messages)
- .and_return(%w[Error Error])
- end
-
- it_behaves_like 'source trace in database stays intact', error: ActiveRecord::RecordInvalid
- end
-
- context 'when there is a validation error on Ci::Build' do
- before do
- allow_any_instance_of(Ci::Build).to receive(:save).and_return(false)
- allow_any_instance_of(Ci::Build).to receive_message_chain(:errors, :full_messages)
- .and_return(%w[Error Error])
- end
-
- context "when erase old trace with 'save'" do
- before do
- build.send(:write_attribute, :trace, nil)
- build.save # rubocop:disable Rails/SaveBang
- end
-
- it 'old trace is not deleted' do
- build.reload
- expect(build.trace.raw).to eq(trace_content)
- end
- end
-
- it_behaves_like 'archive trace in database'
- end
- end
end
context 'when job has trace artifact' do
@@ -645,22 +545,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
subject { trace.erase! }
context 'when it is a live trace' do
- context 'when trace is stored in database' do
- let(:build) { create(:ci_build) }
-
- before do
- build.update_column(:trace, 'sample trace')
- end
-
- it { expect(trace.raw).not_to be_nil }
-
- it "removes trace" do
- subject
-
- expect(trace.raw).to be_nil
- end
- end
-
context 'when trace is stored in file storage' do
let(:build) { create(:ci_build, :trace_live) }
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
index beec072e474..9ffc55f7e7e 100644
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
+++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'deployment metrics examples' do
+RSpec.shared_examples 'deployment metrics examples' do
def create_deployment(args)
project = args[:project]
environment = project.environments.production.first || create(:environment, :production, project: project)
diff --git a/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb
index 771ab89972c..a28fefcfc58 100644
--- a/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'marks background migration job records' do
it 'marks each job record as succeeded after processing' do
create(:background_migration_job, class_name: "::#{described_class.name.demodulize}",
- arguments: arguments)
+ arguments: arguments)
expect(::Gitlab::Database::BackgroundMigrationJob).to receive(:mark_all_as_succeeded).and_call_original
@@ -14,7 +14,7 @@ RSpec.shared_examples 'marks background migration job records' do
it 'returns the number of job records marked as succeeded' do
create(:background_migration_job, class_name: "::#{described_class.name.demodulize}",
- arguments: arguments)
+ arguments: arguments)
jobs_updated = subject.perform(*arguments)
diff --git a/spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb
index 1f7325df11a..243dc1d195b 100644
--- a/spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb
@@ -144,7 +144,7 @@ RSpec.shared_examples 'cacheable diff collection' do
end
end
-shared_examples_for 'sortable diff files' do
+RSpec.shared_examples_for 'sortable diff files' do
subject { described_class.new(diffable, **collection_default_args) }
describe '#raw_diff_files' do
@@ -170,7 +170,7 @@ shared_examples_for 'sortable diff files' do
end
end
-shared_examples_for 'unsortable diff files' do
+RSpec.shared_examples_for 'unsortable diff files' do
subject { described_class.new(diffable, **collection_default_args) }
describe '#raw_diff_files' do
diff --git a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
index ead8b174d46..ec7b2794703 100644
--- a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
@@ -25,7 +25,7 @@ RSpec.shared_examples 'SQL set operator' do |operator_keyword|
empty_relation = User.none.select(:id)
set_operator = described_class.new([empty_relation, relation_1, relation_2])
- expect {User.where("users.id IN (#{set_operator.to_sql})").to_a}.not_to raise_error
+ expect { User.where("users.id IN (#{set_operator.to_sql})").to_a }.not_to raise_error
expect(set_operator.to_sql).to eq("(#{to_sql(relation_1)})\n#{operator_keyword}\n(#{to_sql(relation_2)})")
end
diff --git a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
index d73c7b6848d..1c0e0061385 100644
--- a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
+++ b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
@@ -43,7 +43,7 @@ RSpec.shared_examples 'maps Sentry exceptions' do |http_method|
}
exceptions.each do |exception, message|
- context "#{exception}" do
+ context exception do
before do
stub_request(
http_method || :get,
@@ -58,3 +58,50 @@ RSpec.shared_examples 'maps Sentry exceptions' do |http_method|
end
end
end
+
+# Expects to following variables:
+# - subject
+# - sentry_api_response
+# - sentry_url, token - only if enabled_by_default: false
+RSpec.shared_examples 'Sentry API response size limit' do |enabled_by_default: false|
+ let(:invalid_deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
+
+ before do
+ allow(Gitlab::Utils::DeepSize)
+ .to receive(:new)
+ .with(sentry_api_response, any_args)
+ .and_return(invalid_deep_size)
+ end
+
+ if enabled_by_default
+ it 'raises an exception when response is too large' do
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError,
+ 'Sentry API response is too big. Limit is 1 MB.')
+ end
+ else
+ context 'when guarded by feature flag' do
+ let(:client) do
+ ErrorTracking::SentryClient.new(sentry_url, token, validate_size_guarded_by_feature_flag: feature_flag)
+ end
+
+ context 'with feature flag enabled' do
+ let(:feature_flag) { true }
+
+ it 'raises an exception when response is too large' do
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError,
+ 'Sentry API response is too big. Limit is 1 MB.')
+ end
+ end
+
+ context 'with feature flag disabled' do
+ let(:feature_flag) { false }
+
+ it 'does not check the limit and thus not raise' do
+ expect { subject }.not_to raise_error
+
+ expect(Gitlab::Utils::DeepSize).not_to have_received(:new)
+ end
+ end
+ end
+ end
+end