diff options
Diffstat (limited to 'spec/support/shared_examples/lib')
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:">foo</a>', + input: '<a href="javascript:">foo</a>', output: '<a>foo</a>' }, 'protocol-based JS injection: long UTF-8 encoding' => { - input: '<a href="javascript:">foo</a>', + input: '<a href="javascript:">foo</a>', output: '<a>foo</a>' }, 'protocol-based JS injection: long UTF-8 encoding without semicolons' => { - input: '<a href=javascript:alert('XSS')>foo</a>', + input: '<a href=javascript:alert('XSS')>foo</a>', output: '<a>foo</a>' }, 'protocol-based JS injection: hex encoding' => { - input: '<a href="javascript:">foo</a>', + input: '<a href="javascript:">foo</a>', output: '<a>foo</a>' }, 'protocol-based JS injection: long hex encoding' => { - input: '<a href="javascript:">foo</a>', + input: '<a href="javascript:">foo</a>', output: '<a>foo</a>' }, 'protocol-based JS injection: hex encoding without semicolons' => { - input: '<a href=javascript:alert('XSS')>foo</a>', + input: '<a href=javascript:alert('XSS')>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="  javascript:alert(\'XSS\');">foo</a>', + input: '<a href="  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 |