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
path: root/spec/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2024-01-24 00:09:27 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2024-01-24 00:09:27 +0300
commit17bb9dd270c78fad45851c6cc6ec6e6fdb3d23bf (patch)
treeaa7235893811d97055b3fc750d139a039ae95b0a /spec/lib
parentabd2c6b32aabff4654b6be9cb98b59dcd3193fc4 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb122
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/interpolation/text_interpolator_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/config/yaml/documents_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/yaml/loader_spec.rb237
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb37
-rw-r--r--spec/lib/gitlab/database/query_analyzer_spec.rb28
-rw-r--r--spec/lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/log_large_in_lists_spec.rb148
-rw-r--r--spec/lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb4
15 files changed, 456 insertions, 163 deletions
diff --git a/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb
deleted file mode 100644
index 73661a3da1f..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# rubocop:disable Layout/HashAlignment
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectImportLevel do
- let(:migration) do
- described_class.new(
- start_id: table(:namespaces).minimum(:id),
- end_id: table(:namespaces).maximum(:id),
- batch_table: :namespaces,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ApplicationRecord.connection
- )
- end
- # rubocop:enable Layout/HashAlignment
-
- let(:namespaces_table) { table(:namespaces) }
- let(:namespace_settings_table) { table(:namespace_settings) }
-
- let!(:user_namespace) do
- namespaces_table.create!(
- name: 'user_namespace',
- path: 'user_namespace',
- type: 'User',
- project_creation_level: 100
- )
- end
-
- let!(:group_namespace_nil) do
- namespaces_table.create!(
- name: 'group_namespace_nil',
- path: 'group_namespace_nil',
- type: 'Group',
- project_creation_level: nil
- )
- end
-
- let!(:group_namespace_0) do
- namespaces_table.create!(
- name: 'group_namespace_0',
- path: 'group_namespace_0',
- type: 'Group',
- project_creation_level: 0
- )
- end
-
- let!(:group_namespace_1) do
- namespaces_table.create!(
- name: 'group_namespace_1',
- path: 'group_namespace_1',
- type: 'Group',
- project_creation_level: 1
- )
- end
-
- let!(:group_namespace_2) do
- namespaces_table.create!(
- name: 'group_namespace_2',
- path: 'group_namespace_2',
- type: 'Group',
- project_creation_level: 2
- )
- end
-
- let!(:group_namespace_9999) do
- namespaces_table.create!(
- name: 'group_namespace_9999',
- path: 'group_namespace_9999',
- type: 'Group',
- project_creation_level: 9999
- )
- end
-
- subject(:perform_migration) { migration.perform }
-
- before do
- namespace_settings_table.create!(namespace_id: user_namespace.id)
- namespace_settings_table.create!(namespace_id: group_namespace_nil.id)
- namespace_settings_table.create!(namespace_id: group_namespace_0.id)
- namespace_settings_table.create!(namespace_id: group_namespace_1.id)
- namespace_settings_table.create!(namespace_id: group_namespace_2.id)
- namespace_settings_table.create!(namespace_id: group_namespace_9999.id)
- end
-
- describe 'Groups' do
- using RSpec::Parameterized::TableSyntax
-
- where(:namespace_id, :prev_level, :new_level) do
- lazy { group_namespace_0.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::NO_ACCESS
- lazy { group_namespace_1.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::MAINTAINER
- lazy { group_namespace_2.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::DEVELOPER
- end
-
- with_them do
- it 'backfills the correct project_import_level of Group namespaces' do
- expect { perform_migration }
- .to change { namespace_settings_table.find_by(namespace_id: namespace_id).project_import_level }
- .from(prev_level).to(new_level)
- end
- end
-
- it 'does not update `User` namespaces or values outside range' do
- expect { perform_migration }
- .not_to change { namespace_settings_table.find_by(namespace_id: user_namespace.id).project_import_level }
-
- expect { perform_migration }
- .not_to change { namespace_settings_table.find_by(namespace_id: group_namespace_9999.id).project_import_level }
- end
-
- it 'maintains default import_level if creation_level is nil' do
- project_import_level = namespace_settings_table.find_by(namespace_id: group_namespace_nil.id).project_import_level
-
- expect { perform_migration }
- .not_to change { project_import_level }
-
- expect(project_import_level).to eq(::Gitlab::Access::OWNER)
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index bcfab620bd9..6100974bbe8 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -145,7 +145,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base, feature_category: :pipe
it 'surfaces interpolation errors' do
expect(valid?).to be_falsy
expect(file.errors)
- .to include('`some-location.yml`: interpolation interrupted by errors, unknown interpolation key: `abcd`')
+ .to include('`some-location.yml`: unknown interpolation key: `abcd`')
end
end
diff --git a/spec/lib/gitlab/ci/config/interpolation/text_interpolator_spec.rb b/spec/lib/gitlab/ci/config/interpolation/text_interpolator_spec.rb
index 8655d3fb0b7..2e59b6982dd 100644
--- a/spec/lib/gitlab/ci/config/interpolation/text_interpolator_spec.rb
+++ b/spec/lib/gitlab/ci/config/interpolation/text_interpolator_spec.rb
@@ -34,17 +34,6 @@ RSpec.describe Gitlab::Ci::Config::Interpolation::TextInterpolator, feature_cate
end
end
- context 'when the header has an error while being parsed' do
- let(:header) { ::Gitlab::Config::Loader::Yaml.new('_!@malformedyaml:&') }
-
- it 'surfaces the error' do
- interpolator.interpolate!
-
- expect(interpolator).not_to be_valid
- expect(interpolator.error_message).to eq('Invalid configuration format')
- end
- end
-
context 'when spec header is missing but inputs are specified' do
let(:documents) { ::Gitlab::Ci::Config::Yaml::Documents.new([content]) }
diff --git a/spec/lib/gitlab/ci/config/yaml/documents_spec.rb b/spec/lib/gitlab/ci/config/yaml/documents_spec.rb
index babdea6623b..424fa4858a4 100644
--- a/spec/lib/gitlab/ci/config/yaml/documents_spec.rb
+++ b/spec/lib/gitlab/ci/config/yaml/documents_spec.rb
@@ -5,24 +5,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Yaml::Documents, feature_category: :pipeline_composition do
let(:documents) { described_class.new(yaml_documents) }
- describe '#valid?' do
- context 'when there are no errors' do
- let(:yaml_documents) { [::Gitlab::Config::Loader::Yaml.new('job:')] }
-
- it 'returns true' do
- expect(documents).to be_valid
- end
- end
-
- context 'when there are errors' do
- let(:yaml_documents) { [::Gitlab::Config::Loader::Yaml.new('_!@malformedyaml:&')] }
-
- it 'returns false' do
- expect(documents).not_to be_valid
- end
- end
- end
-
describe '#header' do
context 'when there are at least 2 documents and the first document has a `spec` keyword' do
let(:yaml_documents) { [::Gitlab::Config::Loader::Yaml.new('spec:'), ::Gitlab::Config::Loader::Yaml.new('job:')] }
diff --git a/spec/lib/gitlab/ci/config/yaml/loader_spec.rb b/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
index 684da1df43b..045cdf37037 100644
--- a/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
+++ b/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe ::Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_c
let_it_be(:project) { create(:project) }
let(:inputs) { { test_input: 'hello test' } }
+ let(:variables) { [] }
let(:yaml) do
<<~YAML
@@ -21,7 +22,7 @@ RSpec.describe ::Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_c
YAML
end
- subject(:result) { described_class.new(yaml, inputs: inputs).load }
+ subject(:result) { described_class.new(yaml, inputs: inputs, variables: variables).load }
it 'loads and interpolates CI config YAML' do
expected_config = { test_job: { script: ['echo "hello test"'] } }
@@ -57,6 +58,240 @@ RSpec.describe ::Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_c
expect(result.error).to eq('`test_input` input: required value has not been provided')
end
end
+
+ context 'when interpolating into a YAML key' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ ---
+ "$[[ inputs.test_input ]]_job":
+ script:
+ - echo "test"
+ YAML
+ end
+
+ it 'loads and interpolates CI config YAML' do
+ expected_config = { 'hello test_job': { script: ['echo "test"'] } }
+
+ expect(result).to be_valid
+ expect(result).to be_interpolated
+ expect(result.content).to eq(expected_config)
+ end
+ end
+
+ context 'when interpolating values of different types' do
+ let(:inputs) do
+ {
+ test_boolean: true,
+ test_number: 8,
+ test_string: 'test'
+ }
+ end
+
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_string:
+ type: string
+ test_boolean:
+ type: boolean
+ test_number:
+ type: number
+ ---
+ "$[[ inputs.test_string ]]_job":
+ allow_failure: $[[ inputs.test_boolean ]]
+ parallel: $[[ inputs.test_number ]]
+ YAML
+ end
+
+ it 'loads and interpolates CI config YAML' do
+ expected_config = { test_job: { allow_failure: true, parallel: 8 } }
+
+ expect(result).to be_valid
+ expect(result).to be_interpolated
+ expect(result.content).to eq(expected_config)
+ end
+ end
+
+ context 'when interpolating and expanding variables' do
+ let(:inputs) { { test_input: '$TEST_VAR' } }
+
+ let(:variables) do
+ Gitlab::Ci::Variables::Collection.new([
+ { key: 'TEST_VAR', value: 'test variable', masked: false }
+ ])
+ end
+
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ ---
+ "test_job":
+ script:
+ - echo "$[[ inputs.test_input | expand_vars ]]"
+ YAML
+ end
+
+ it 'loads and interpolates CI config YAML' do
+ expected_config = { test_job: { script: ['echo "test variable"'] } }
+
+ expect(result).to be_valid
+ expect(result).to be_interpolated
+ expect(result.content).to eq(expected_config)
+ end
+ end
+
+ context 'when using !reference' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ job_name:
+ default: .example_ref
+ ---
+ .example_ref:
+ script:
+ - echo "$[[ inputs.test_input ]]"
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+
+ build_job:
+ script: echo "build"
+ rules:
+ - !reference ["$[[ inputs.job_name ]]", "rules"]
+
+ test_job:
+ script:
+ - !reference [.example_ref, script]
+ YAML
+ end
+
+ it 'loads and interpolates CI config YAML' do
+ expect(result).to be_valid
+ expect(result).to be_interpolated
+ expect(result.content).to include('.example_ref': {
+ rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' }],
+ script: ['echo "hello test"']
+ })
+ expect(result.content.dig(:build_job, :rules).first.data[:seq]).to eq(['.example_ref', 'rules'])
+ expect(result.content).to include(
+ test_job: { script: [an_instance_of(::Gitlab::Ci::Config::Yaml::Tags::Reference)] }
+ )
+ end
+ end
+
+ context 'when there are too many interpolation blocks' do
+ let(:inputs) { { first_input: 'first', second_input: 'second' } }
+
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ first_input:
+ second_input:
+ ---
+ test_job:
+ script:
+ - echo "$[[ inputs.first_input ]]"
+ - echo "$[[ inputs.second_input ]]"
+ YAML
+ end
+
+ it 'returns an error result' do
+ stub_const('::Gitlab::Ci::Config::Interpolation::TextTemplate::MAX_BLOCKS', 1)
+
+ expect(result).not_to be_valid
+ expect(result.error).to eq('too many interpolation blocks')
+ end
+ end
+
+ context 'when a block is invalid' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ ---
+ test_job:
+ script:
+ - echo "$[[ inputs.test_input | expand_vars | truncate(0,1) ]]"
+ YAML
+ end
+
+ it 'returns an error result' do
+ stub_const('::Gitlab::Ci::Config::Interpolation::Block::MAX_FUNCTIONS', 1)
+
+ expect(result).not_to be_valid
+ expect(result.error).to eq('too many functions in interpolation block')
+ end
+ end
+
+ context 'when the YAML file is too large' do
+ it 'returns an error result' do
+ stub_application_setting(ci_max_total_yaml_size_bytes: 1)
+
+ expect(result).not_to be_valid
+ expect(result.error).to eq('config too large')
+ end
+ end
+
+ context 'when given an empty YAML file' do
+ let(:inputs) { {} }
+ let(:yaml) { '' }
+
+ it 'returns an error result' do
+ expect(result).not_to be_valid
+ expect(result.error).to eq('Invalid configuration format')
+ end
+ end
+
+ context 'when ci_text_interpolation is disabled' do
+ before do
+ stub_feature_flags(ci_text_interpolation: false)
+ end
+
+ it 'loads and interpolates CI config YAML' do
+ expected_config = { test_job: { script: ['echo "hello test"'] } }
+
+ expect(result).to be_valid
+ expect(result).to be_interpolated
+ expect(result.content).to eq(expected_config)
+ end
+
+ context 'when hash interpolation fails' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ ---
+ test_job:
+ script:
+ - echo "$[[ inputs.test_input | expand_vars | truncate(0,1) ]]"
+ YAML
+ end
+
+ it 'returns an error result' do
+ stub_const('::Gitlab::Ci::Config::Interpolation::Block::MAX_FUNCTIONS', 1)
+
+ expect(result).not_to be_valid
+ expect(result.error).to eq('interpolation interrupted by errors, too many functions in interpolation block')
+ end
+ end
+ end
end
describe '#load_uninterpolated_yaml' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index 4017076d29f..967cd1693a9 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -56,6 +56,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External, feature_category
let(:validation_service_url) { 'https://validation-service.external/' }
before do
+ stub_feature_flags(external_pipeline_validation_migration: false)
stub_env('EXTERNAL_VALIDATION_SERVICE_URL', validation_service_url)
allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('correlation-id')
end
@@ -84,6 +85,42 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External, feature_category
end
end
+ context 'when :external_pipeline_validation_migration feature flag is enabled' do
+ let(:migrated_validation_service_url) { 'https://runway.validation-service.external/' }
+
+ before do
+ stub_feature_flags(external_pipeline_validation_migration: project)
+ end
+
+ context 'when EXTERNAL_VALIDATION_SERVICE_RUNWAY_URL is NOT present' do
+ before do
+ stub_env('EXTERNAL_VALIDATION_SERVICE_RUNWAY_URL', nil)
+ end
+
+ it 'fallbacks to existing validation service URL' do
+ expect(::Gitlab::HTTP).to receive(:post) do |url, _params|
+ expect(url).to eq(validation_service_url)
+ end
+
+ perform!
+ end
+ end
+
+ context 'when EXTERNAL_VALIDATION_SERVICE_RUNWAY_URL is present' do
+ before do
+ stub_env('EXTERNAL_VALIDATION_SERVICE_RUNWAY_URL', migrated_validation_service_url)
+ end
+
+ it 'uses migrated validation service URL' do
+ expect(::Gitlab::HTTP).to receive(:post) do |url, _params|
+ expect(url).to eq(migrated_validation_service_url)
+ end
+
+ perform!
+ end
+ end
+ end
+
it 'respects the defined payload schema' do
expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
expect(params[:body]).to match_schema('/external_validation')
diff --git a/spec/lib/gitlab/database/query_analyzer_spec.rb b/spec/lib/gitlab/database/query_analyzer_spec.rb
index 0b849063562..20599bb89b6 100644
--- a/spec/lib/gitlab/database/query_analyzer_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzer_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
+ using RSpec::Parameterized::TableSyntax
+
let(:analyzer) { double(:query_analyzer) }
let(:user_analyzer) { double(:user_query_analyzer) }
let(:disabled_analyzer) { double(:disabled_query_analyzer) }
@@ -181,12 +183,34 @@ RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
end
- def process_sql(sql)
+ def process_sql(sql, event_name = 'load')
described_class.instance.within do
ApplicationRecord.load_balancer.read_write do |connection|
- described_class.instance.send(:process_sql, sql, connection)
+ described_class.instance.send(:process_sql, sql, connection, event_name)
end
end
end
end
+
+ describe '#normalize_event_name' do
+ where(:event, :parsed_event) do
+ 'Project Load' | 'load'
+ 'Namespaces::UserNamespace Create' | 'create'
+ 'Project Update' | 'update'
+ 'Project Destroy' | 'destroy'
+ 'Project Pluck' | 'pluck'
+ 'Project Insert' | 'insert'
+ 'Project Delete All' | 'delete_all'
+ 'Project Exists?' | 'exists?'
+ nil | ''
+ 'TRANSACTION' | 'transaction'
+ 'SCHEMA' | 'schema'
+ end
+
+ with_them do
+ it 'parses event name correctly' do
+ expect(described_class.instance.send(:normalize_event_name, event)).to eq(parsed_event)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer_spec.rb b/spec/lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer_spec.rb
index 0fe19041b6d..0c1c694a3e3 100644
--- a/spec/lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::Ci::PartitioningIdAnalyzer, que
def process_sql(model, sql)
Gitlab::Database::QueryAnalyzer.instance.within do
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb b/spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb
index 1f86c2ccbb0..8b053fa0291 100644
--- a/spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::Ci::PartitioningRoutingAnalyzer
def process_sql(model, sql)
Gitlab::Database::QueryAnalyzer.instance.within do
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
index 1909e134e66..fb00fbe27ba 100644
--- a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
@@ -99,7 +99,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_ana
def process_sql(model, sql)
Gitlab::Database::QueryAnalyzer.instance.within do
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
index 0664508fa8d..6a36db1870a 100644
--- a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection
def process_sql(model, sql)
Gitlab::Database::QueryAnalyzer.instance.within([analyzer]) do
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/log_large_in_lists_spec.rb b/spec/lib/gitlab/database/query_analyzers/log_large_in_lists_spec.rb
new file mode 100644
index 00000000000..5646c3ff3b6
--- /dev/null
+++ b/spec/lib/gitlab/database/query_analyzers/log_large_in_lists_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::QueryAnalyzers::LogLargeInLists, query_analyzers: false, feature_category: :database do
+ let(:analyzer) { described_class }
+ let(:fixture) { fixture_file("gitlab/database/query_analyzers/#{file}") }
+ let(:sql) { fixture.gsub('%IN_LIST%', arguments) }
+
+ # Reduce the in list size to 5 to help with testing
+ # Reduce the min query size to 50 to help with testing
+ before do
+ stub_const("#{described_class}::IN_SIZE_LIMIT", 5)
+ stub_const("#{described_class}::MIN_QUERY_SIZE", 50)
+ allow(analyzer).to receive(:backtrace).and_return([])
+ allow(analyzer).to receive(:suppressed?).and_return(true) # bypass suppressed? method to avoid false positives
+ end
+
+ after do
+ # Clears analyzers list after each test to reload the state of `enabled?` method
+ Thread.current[:query_analyzer_enabled_analyzers] = []
+ end
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(log_large_in_list_queries: true)
+ Gitlab::Database::QueryAnalyzer.instance.begin!([analyzer])
+ end
+
+ context 'when conditions are satisfied for logging' do
+ where(:file, :arguments, :result, :event_name) do
+ [
+ [
+ 'small_query_with_in_list.txt',
+ '1, 2, 3, 4, 5, 6',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "6", stacktrace: [], event_name: 'load' },
+ 'load'
+ ],
+ [
+ 'small_query_with_in_list.txt',
+ '1,2,3,4,5,6',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "6", stacktrace: [], event_name: 'pluck' },
+ 'pluck'
+ ],
+ [
+ 'small_query_with_in_list.txt',
+ 'SELECT id FROM projects where id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "10", stacktrace: [], event_name: 'load' },
+ 'load'
+ ],
+ [
+ 'large_query_with_in_list.txt',
+ '1,2,3,4,5,6',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "6", stacktrace: [], event_name: 'load' },
+ 'load'
+ ],
+ [
+ 'large_query_with_in_list.txt',
+ '1, 2, 3, 4, 5, 6',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "6", stacktrace: [], event_name: 'pluck' },
+ 'pluck'
+ ],
+ [
+ 'large_query_with_in_list.txt',
+ 'SELECT id FROM projects where id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)',
+ { message: 'large_in_list_found', matches: 1, in_list_size: "10", stacktrace: [], event_name: 'load' },
+ 'load'
+ ]
+ ]
+ end
+
+ with_them do
+ it 'logs all the occurrences' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(result)
+
+ process_sql(sql, event_name)
+ end
+ end
+ end
+
+ context 'when conditions are not satisfied for logging' do
+ where(:file, :arguments, :event_name) do
+ [
+ ['small_query_with_in_list.txt', '1, 2, 3, 4, 5', 'load'],
+ ['small_query_with_in_list.txt', '$1, $2, $3, $4, $5', 'load'],
+ ['small_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (1, 2, 3, 4, 5)', 'load'],
+ ['small_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (SELECT id FROM namespaces)', 'load'],
+ ['small_query_with_in_list.txt', '1, 2, 3, 4, 5', 'schema'],
+ ['large_query_with_in_list.txt', '1, 2, 3, 4, 5', 'load'],
+ ['large_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (1, 2, 3, 4, 5)', 'load'],
+ ['large_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (SELECT id FROM namespaces)', 'load'],
+ ['large_query_with_in_list.txt', '1, 2, 3, 4, 5', 'schema'],
+ ['small_query_without_in_list.txt', '', 'load'],
+ ['small_query_without_in_list.txt', '', 'schema']
+ ]
+ end
+
+ with_them do
+ it 'skips logging the occurrences' do
+ expect(Gitlab::AppLogger).not_to receive(:warn)
+
+ process_sql(sql, event_name)
+ end
+ end
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(log_large_in_list_queries: false)
+ Gitlab::Database::QueryAnalyzer.instance.begin!([analyzer])
+ end
+
+ where(:file, :arguments, :event_name) do
+ [
+ ['small_query_with_in_list.txt', '1, 2, 3, 4, 5, 6', 'load'],
+ ['small_query_with_in_list.txt', '$1, $2, $3, $4, $5, $6', 'load'],
+ ['small_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (1, 2, 3, 4, 5, 6)', 'load'],
+ ['small_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (1, 2, 3, 4, 5, 6)', 'load'],
+ ['small_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (SELECT id FROM namespaces)', 'load'],
+ ['small_query_with_in_list.txt', '1, 2, 3, 4, 5, 6', 'schema'],
+ ['large_query_with_in_list.txt', '1, 2, 3, 4, 5, 6', 'load'],
+ ['large_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8)', 'load'],
+ ['large_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN ($1, $2, $3, $4, $5, $6, $7)', 'load'],
+ ['large_query_with_in_list.txt', 'SELECT id FROM projects WHERE id IN (SELECT id FROM namespaces)', 'load'],
+ ['large_query_with_in_list.txt', '1, 2, 3, 4, 5, 6', 'schema'],
+ ['small_query_without_in_list.txt', '', 'load'],
+ ['small_query_without_in_list.txt', '', 'schema']
+ ]
+ end
+
+ with_them do
+ it 'skips logging the occurrences' do
+ expect(Gitlab::AppLogger).not_to receive(:warn)
+
+ process_sql(sql, event_name)
+ end
+ end
+ end
+
+ private
+
+ def process_sql(sql, event_name)
+ Gitlab::Database::QueryAnalyzer.instance.within do
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, ActiveRecord::Base.connection, event_name)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch_spec.rb b/spec/lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch_spec.rb
index 7fcdc59b691..00b16faab01 100644
--- a/spec/lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventSetOperatorMismatch, que
def process_sql(sql, model = ApplicationRecord)
Gitlab::Database::QueryAnalyzer.instance.within([analyzer]) do
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
diff --git a/spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb b/spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb
index b90f60e0301..8054743c9a9 100644
--- a/spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb
@@ -180,7 +180,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas,
yield if block_given?
# Skip load balancer and retrieve connection assigned to model
- Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection)
+ Gitlab::Database::QueryAnalyzer.instance.send(:process_sql, sql, model.retrieve_connection, 'load')
end
end
end
diff --git a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
index 4184c674823..844c3b54587 100644
--- a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
@@ -167,9 +167,9 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter, feature_category: :cloud
describe '#start' do
it "doesn't start running server" do
- expect_any_instance_of(::WEBrick::HTTPServer).not_to receive(:start)
+ expect(::WEBrick::HTTPServer).not_to receive(:new)
- expect { exporter.start }.not_to change { exporter.thread? }
+ exporter.start
end
end