summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
committerRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
commit6438df3a1e0fb944485cebf07976160184697d72 (patch)
tree00b09bfd170e77ae9391b1a2f5a93ef6839f2597 /spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
parent42bcd54d971da7ef2854b896a7b34f4ef8601067 (diff)
downloadgitlab-ce-6438df3a1e0fb944485cebf07976160184697d72.tar.gz
Add latest changes from gitlab-org/gitlab@13-8-stable-eev13.8.0-rc42
Diffstat (limited to 'spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb')
-rw-r--r--spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb113
1 files changed, 113 insertions, 0 deletions
diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
new file mode 100644
index 00000000000..8e74935e127
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20201211090634 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:identifiers) { table(:vulnerability_identifiers) }
+ let(:findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_feedback) { table(:vulnerability_feedback) }
+
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+ let(:user) { users.create!(username: 'john.doe', projects_limit: 5) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
+ let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'baz') }
+ let(:sast_report) { 0 }
+ let(:dependency_scanning_report) { 1 }
+ let(:dast_report) { 3 }
+ let(:secret_detection_report) { 4 }
+ let(:project_fingerprint) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_1) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_2) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_3) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) }
+ let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) }
+ let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) }
+ let(:uuid_1_components) { ['sast', identifier.fingerprint, location_fingerprint_1, project.id].join('-') }
+ let(:uuid_2_components) { ['dast', identifier.fingerprint, location_fingerprint_2, project.id].join('-') }
+ let(:uuid_3_components) { ['secret_detection', identifier.fingerprint, location_fingerprint_3, project.id].join('-') }
+ let(:expected_uuid_1) { Gitlab::UUID.v5(uuid_1_components) }
+ let(:expected_uuid_2) { Gitlab::UUID.v5(uuid_2_components) }
+ let(:expected_uuid_3) { Gitlab::UUID.v5(uuid_3_components) }
+ let(:finding_creator) do
+ -> (report_type, location_fingerprint) do
+ findings.create!(
+ project_id: project.id,
+ primary_identifier_id: identifier.id,
+ scanner_id: scanner.id,
+ report_type: report_type,
+ uuid: SecureRandom.uuid,
+ name: 'Foo',
+ location_fingerprint: Gitlab::Database::ShaAttribute.serialize(location_fingerprint),
+ project_fingerprint: Gitlab::Database::ShaAttribute.serialize(project_fingerprint),
+ metadata_version: '1',
+ severity: 0,
+ confidence: 5,
+ raw_metadata: '{}'
+ )
+ end
+ end
+
+ let(:feedback_creator) do
+ -> (category, project_fingerprint) do
+ vulnerability_feedback.create!(
+ project_id: project.id,
+ author_id: user.id,
+ feedback_type: 0,
+ category: category,
+ project_fingerprint: project_fingerprint
+ )
+ end
+ end
+
+ let!(:feedback_1) { feedback_creator.call(finding_1.report_type, project_fingerprint) }
+ let!(:feedback_2) { feedback_creator.call(finding_2.report_type, project_fingerprint) }
+ let!(:feedback_3) { feedback_creator.call(finding_3.report_type, project_fingerprint) }
+ let!(:feedback_4) { feedback_creator.call(finding_1.report_type, 'foo') }
+ let!(:feedback_5) { feedback_creator.call(dependency_scanning_report, project_fingerprint) }
+
+ subject(:populate_finding_uuids) { described_class.new.perform(feedback_1.id, feedback_5.id) }
+
+ before do
+ allow(Gitlab::BackgroundMigration::Logger).to receive(:info)
+ end
+
+ describe '#perform' do
+ it 'updates the `finding_uuid` attributes of the feedback records' do
+ expect { populate_finding_uuids }.to change { feedback_1.reload.finding_uuid }.from(nil).to(expected_uuid_1)
+ .and change { feedback_2.reload.finding_uuid }.from(nil).to(expected_uuid_2)
+ .and change { feedback_3.reload.finding_uuid }.from(nil).to(expected_uuid_3)
+ .and not_change { feedback_4.reload.finding_uuid }
+ .and not_change { feedback_5.reload.finding_uuid }
+
+ expect(Gitlab::BackgroundMigration::Logger).to have_received(:info).once
+ end
+
+ it 'preloads the finding and identifier records to prevent N+1 queries' do
+ # Load feedback records(1), load findings(2), load identifiers(3) and finally update feedback records one by one(6)
+ expect { populate_finding_uuids }.not_to exceed_query_limit(6)
+ end
+
+ context 'when setting the `finding_uuid` attribute of a feedback record fails' do
+ let(:expected_error) { RuntimeError.new }
+
+ before do
+ allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ allow_next_found_instance_of(described_class::VulnerabilityFeedback) do |feedback|
+ allow(feedback).to receive(:update_column).and_raise(expected_error)
+ end
+ end
+
+ it 'captures the errors and does not crash entirely' do
+ expect { populate_finding_uuids }.not_to raise_error
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).exactly(3).times
+ end
+ end
+ end
+end