diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 09:08:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 09:08:42 +0000 |
commit | b76ae638462ab0f673e5915986070518dd3f9ad3 (patch) | |
tree | bdab0533383b52873be0ec0eb4d3c66598ff8b91 /spec/initializers | |
parent | 434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff) | |
download | gitlab-ce-b76ae638462ab0f673e5915986070518dd3f9ad3.tar.gz |
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'spec/initializers')
-rw-r--r-- | spec/initializers/00_rails_disable_joins_spec.rb | 288 | ||||
-rw-r--r-- | spec/initializers/0_log_deprecations_spec.rb | 74 | ||||
-rw-r--r-- | spec/initializers/database_config_spec.rb | 57 | ||||
-rw-r--r-- | spec/initializers/lograge_spec.rb | 3 | ||||
-rw-r--r-- | spec/initializers/rails_asset_host_spec.rb | 38 |
5 files changed, 422 insertions, 38 deletions
diff --git a/spec/initializers/00_rails_disable_joins_spec.rb b/spec/initializers/00_rails_disable_joins_spec.rb new file mode 100644 index 00000000000..78e78b6810b --- /dev/null +++ b/spec/initializers/00_rails_disable_joins_spec.rb @@ -0,0 +1,288 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'DisableJoins' do + let(:primary_model) do + Class.new(ApplicationRecord) do + self.table_name = '_test_primary_records' + + def self.name + 'TestPrimary' + end + end + end + + let(:bridge_model) do + Class.new(ApplicationRecord) do + self.table_name = '_test_bridge_records' + + def self.name + 'TestBridge' + end + end + end + + let(:secondary_model) do + Class.new(ApplicationRecord) do + self.table_name = '_test_secondary_records' + + def self.name + 'TestSecondary' + end + end + end + + context 'passing disable_joins as an association option' do + context 'when the association is a bare has_one' do + it 'disallows the disable_joins option' do + expect do + primary_model.has_one :test_bridge, disable_joins: true + end.to raise_error(ArgumentError, /Unknown key: :disable_joins/) + end + end + + context 'when the association is a belongs_to' do + it 'disallows the disable_joins option' do + expect do + bridge_model.belongs_to :test_secondary, disable_joins: true + end.to raise_error(ArgumentError, /Unknown key: :disable_joins/) + end + end + + context 'when the association is has_one :through' do + it 'allows the disable_joins option' do + primary_model.has_one :test_bridge + bridge_model.belongs_to :test_secondary + + expect do + primary_model.has_one :test_secondary, through: :test_bridge, disable_joins: true + end.not_to raise_error + end + end + + context 'when the association is a bare has_many' do + it 'disallows the disable_joins option' do + expect do + primary_model.has_many :test_bridges, disable_joins: true + end.to raise_error(ArgumentError, /Unknown key: :disable_joins/) + end + end + + context 'when the association is a has_many :through' do + it 'allows the disable_joins option' do + primary_model.has_many :test_bridges + bridge_model.belongs_to :test_secondary + + expect do + primary_model.has_many :test_secondaries, through: :test_bridges, disable_joins: true + end.not_to raise_error + end + end + end + + context 'querying has_one :through when disable_joins is set' do + before do + create_tables(<<~SQL) + CREATE TABLE _test_primary_records ( + id serial NOT NULL PRIMARY KEY); + + CREATE TABLE _test_bridge_records ( + id serial NOT NULL PRIMARY KEY, + primary_record_id int NOT NULL, + secondary_record_id int NOT NULL); + + CREATE TABLE _test_secondary_records ( + id serial NOT NULL PRIMARY KEY); + SQL + + primary_model.has_one :test_bridge, anonymous_class: bridge_model, foreign_key: :primary_record_id + bridge_model.belongs_to :test_secondary, anonymous_class: secondary_model, foreign_key: :secondary_record_id + primary_model.has_one :test_secondary, through: :test_bridge, anonymous_class: secondary_model, + disable_joins: -> { joins_disabled_flag } + + primary_record = primary_model.create! + secondary_record = secondary_model.create! + bridge_model.create!(primary_record_id: primary_record.id, secondary_record_id: secondary_record.id) + end + + context 'when disable_joins evaluates to true' do + let(:joins_disabled_flag) { true } + + it 'executes separate queries' do + primary_record = primary_model.first + + query_count = ActiveRecord::QueryRecorder.new { primary_record.test_secondary }.count + + expect(query_count).to eq(2) + end + end + + context 'when disable_joins evalutes to false' do + let(:joins_disabled_flag) { false } + + it 'executes a single query' do + primary_record = primary_model.first + + query_count = ActiveRecord::QueryRecorder.new { primary_record.test_secondary }.count + + expect(query_count).to eq(1) + end + end + end + + context 'querying has_many :through when disable_joins is set' do + before do + create_tables(<<~SQL) + CREATE TABLE _test_primary_records ( + id serial NOT NULL PRIMARY KEY); + + CREATE TABLE _test_bridge_records ( + id serial NOT NULL PRIMARY KEY, + primary_record_id int NOT NULL); + + CREATE TABLE _test_secondary_records ( + id serial NOT NULL PRIMARY KEY, + bridge_record_id int NOT NULL); + SQL + + primary_model.has_many :test_bridges, anonymous_class: bridge_model, foreign_key: :primary_record_id + bridge_model.has_many :test_secondaries, anonymous_class: secondary_model, foreign_key: :bridge_record_id + primary_model.has_many :test_secondaries, through: :test_bridges, anonymous_class: secondary_model, + disable_joins: -> { disabled_join_flag } + + primary_record = primary_model.create! + bridge_record = bridge_model.create!(primary_record_id: primary_record.id) + secondary_model.create!(bridge_record_id: bridge_record.id) + end + + context 'when disable_joins evaluates to true' do + let(:disabled_join_flag) { true } + + it 'executes separate queries' do + primary_record = primary_model.first + + query_count = ActiveRecord::QueryRecorder.new { primary_record.test_secondaries.first }.count + + expect(query_count).to eq(2) + end + end + + context 'when disable_joins evalutes to false' do + let(:disabled_join_flag) { false } + + it 'executes a single query' do + primary_record = primary_model.first + + query_count = ActiveRecord::QueryRecorder.new { primary_record.test_secondaries.first }.count + + expect(query_count).to eq(1) + end + end + end + + context 'querying STI relationships' do + let(:child_bridge_model) do + Class.new(bridge_model) do + def self.name + 'ChildBridge' + end + end + end + + let(:child_secondary_model) do + Class.new(secondary_model) do + def self.name + 'ChildSecondary' + end + end + end + + before do + create_tables(<<~SQL) + CREATE TABLE _test_primary_records ( + id serial NOT NULL PRIMARY KEY); + + CREATE TABLE _test_bridge_records ( + id serial NOT NULL PRIMARY KEY, + primary_record_id int NOT NULL, + type text); + + CREATE TABLE _test_secondary_records ( + id serial NOT NULL PRIMARY KEY, + bridge_record_id int NOT NULL, + type text); + SQL + + primary_model.has_many :child_bridges, anonymous_class: child_bridge_model, foreign_key: :primary_record_id + child_bridge_model.has_one :child_secondary, anonymous_class: child_secondary_model, foreign_key: :bridge_record_id + primary_model.has_many :child_secondaries, through: :child_bridges, anonymous_class: child_secondary_model, disable_joins: true + + primary_record = primary_model.create! + parent_bridge_record = bridge_model.create!(primary_record_id: primary_record.id) + child_bridge_record = child_bridge_model.create!(primary_record_id: primary_record.id) + + secondary_model.create!(bridge_record_id: child_bridge_record.id) + child_secondary_model.create!(bridge_record_id: parent_bridge_record.id) + child_secondary_model.create!(bridge_record_id: child_bridge_record.id) + end + + it 'filters correctly by the STI type across multiple queries' do + primary_record = primary_model.first + + query_recorder = ActiveRecord::QueryRecorder.new do + expect(primary_record.child_secondaries.count).to eq(1) + end + + expect(query_recorder.count).to eq(2) + end + end + + context 'querying polymorphic relationships' do + before do + create_tables(<<~SQL) + CREATE TABLE _test_primary_records ( + id serial NOT NULL PRIMARY KEY); + + CREATE TABLE _test_bridge_records ( + id serial NOT NULL PRIMARY KEY, + primaryable_id int NOT NULL, + primaryable_type text NOT NULL); + + CREATE TABLE _test_secondary_records ( + id serial NOT NULL PRIMARY KEY, + bridgeable_id int NOT NULL, + bridgeable_type text NOT NULL); + SQL + + primary_model.has_many :test_bridges, anonymous_class: bridge_model, foreign_key: :primaryable_id, as: :primaryable + bridge_model.has_one :test_secondaries, anonymous_class: secondary_model, foreign_key: :bridgeable_id, as: :bridgeable + primary_model.has_many :test_secondaries, through: :test_bridges, anonymous_class: secondary_model, disable_joins: true + + primary_record = primary_model.create! + primary_bridge_record = bridge_model.create!(primaryable_id: primary_record.id, primaryable_type: 'TestPrimary') + nonprimary_bridge_record = bridge_model.create!(primaryable_id: primary_record.id, primaryable_type: 'NonPrimary') + + secondary_model.create!(bridgeable_id: primary_bridge_record.id, bridgeable_type: 'TestBridge') + secondary_model.create!(bridgeable_id: nonprimary_bridge_record.id, bridgeable_type: 'TestBridge') + secondary_model.create!(bridgeable_id: primary_bridge_record.id, bridgeable_type: 'NonBridge') + end + + it 'filters correctly by the polymorphic type across multiple queries' do + primary_record = primary_model.first + + query_recorder = ActiveRecord::QueryRecorder.new do + expect(primary_record.test_secondaries.count).to eq(1) + end + + expect(query_recorder.count).to eq(2) + end + end + + def create_tables(table_sql) + ApplicationRecord.connection.execute(table_sql) + + bridge_model.reset_column_information + secondary_model.reset_column_information + end +end diff --git a/spec/initializers/0_log_deprecations_spec.rb b/spec/initializers/0_log_deprecations_spec.rb new file mode 100644 index 00000000000..35bceb2f132 --- /dev/null +++ b/spec/initializers/0_log_deprecations_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe '0_log_deprecations' do + def load_initializer + load Rails.root.join('config/initializers/0_log_deprecations.rb') + end + + let(:env_var) { '1' } + + before do + stub_env('GITLAB_LOG_DEPRECATIONS', env_var) + load_initializer + end + + after do + # reset state changed by initializer + Warning.clear + ActiveSupport::Notifications.unsubscribe('deprecation.rails') + end + + context 'for Ruby deprecations' do + context 'when catching deprecations through Kernel#warn' do + it 'also logs them to deprecation logger' do + expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( + message: 'ABC gem is deprecated', + source: 'ruby' + ) + + expect { warn('ABC gem is deprecated') }.to output.to_stderr + end + end + + context 'for other messages from Kernel#warn' do + it 'does not log them to deprecation logger' do + expect(Gitlab::DeprecationJsonLogger).not_to receive(:info) + + expect { warn('Sure is hot today') }.to output.to_stderr + end + end + + context 'when disabled via environment' do + let(:env_var) { '0' } + + it 'does not log them to deprecation logger' do + expect(Gitlab::DeprecationJsonLogger).not_to receive(:info) + + expect { warn('ABC gem is deprecated') }.to output.to_stderr + end + end + end + + context 'for Rails deprecations' do + it 'logs them to deprecation logger' do + expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( + message: match(/^DEPRECATION WARNING: ABC will be removed/), + source: 'rails' + ) + + expect { ActiveSupport::Deprecation.warn('ABC will be removed') }.to output.to_stderr + end + + context 'when disabled via environment' do + let(:env_var) { '0' } + + it 'does not log them to deprecation logger' do + expect(Gitlab::DeprecationJsonLogger).not_to receive(:info) + + expect { ActiveSupport::Deprecation.warn('ABC will be removed') }.to output.to_stderr + end + end + end +end diff --git a/spec/initializers/database_config_spec.rb b/spec/initializers/database_config_spec.rb index f1b353d4012..5ddfbd64c23 100644 --- a/spec/initializers/database_config_spec.rb +++ b/spec/initializers/database_config_spec.rb @@ -21,37 +21,31 @@ RSpec.describe 'Database config initializer' do let(:max_threads) { 8 } - context "no existing pool size is set" do - before do - stub_database_config(pool_size: nil) - end + it 'retains the correct database name for the connection' do + previous_db_name = Gitlab::Database.main.scope.connection.pool.db_config.name - it "sets it based on the max number of worker threads" do - expect { subject }.to change { Gitlab::Database.config['pool'] }.from(nil).to(18) + subject - expect(ActiveRecord::Base.connection_db_config.pool).to eq(18) - end + expect(Gitlab::Database.main.scope.connection.pool.db_config.name).to eq(previous_db_name) end - context "the existing pool size is smaller than the max number of worker threads" do - before do - stub_database_config(pool_size: 1) - end + context 'when no custom headroom is specified' do + it 'sets the pool size based on the number of worker threads' do + old = ActiveRecord::Base.connection_db_config.pool - it "sets it based on the max number of worker threads" do - expect { subject }.to change { Gitlab::Database.config['pool'] }.from(1).to(18) + expect(old).not_to eq(18) - expect(ActiveRecord::Base.connection_db_config.pool).to eq(18) + expect { subject } + .to change { ActiveRecord::Base.connection_db_config.pool } + .from(old) + .to(18) end - end - context "and the existing pool size is larger than the max number of worker threads" do - before do - stub_database_config(pool_size: 100) - end + it 'overwrites custom pool settings' do + config = Gitlab::Database.main.config.merge(pool: 42) - it "sets it based on the max number of worker threads" do - expect { subject }.to change { Gitlab::Database.config['pool'] }.from(100).to(18) + allow(Gitlab::Database.main).to receive(:config).and_return(config) + subject expect(ActiveRecord::Base.connection_db_config.pool).to eq(18) end @@ -61,25 +55,16 @@ RSpec.describe 'Database config initializer' do let(:headroom) { 15 } before do - stub_database_config(pool_size: 1) stub_env("DB_POOL_HEADROOM", headroom) end it "adds headroom on top of the calculated size" do - expect { subject }.to change { Gitlab::Database.config['pool'] } - .from(1) - .to(max_threads + headroom) + old = ActiveRecord::Base.connection_db_config.pool - expect(ActiveRecord::Base.connection_db_config.pool).to eq(max_threads + headroom) + expect { subject } + .to change { ActiveRecord::Base.connection_db_config.pool } + .from(old) + .to(23) end end - - def stub_database_config(pool_size:) - original_config = Gitlab::Database.config - - config = original_config.dup - config['pool'] = pool_size - - allow(Gitlab::Database).to receive(:config).and_return(config) - end end diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb index a1fd9be299b..4d2aa6e74de 100644 --- a/spec/initializers/lograge_spec.rb +++ b/spec/initializers/lograge_spec.rb @@ -120,7 +120,6 @@ RSpec.describe 'lograge', type: :request do context 'with a log subscriber' do include_context 'parsed logs' - include_context 'clear DB Load Balancing configuration' let(:subscriber) { Lograge::LogSubscribers::ActionController.new } @@ -212,7 +211,7 @@ RSpec.describe 'lograge', type: :request do end before do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') + ApplicationRecord.connection.execute('SELECT pg_sleep(0.1);') end context 'when RequestStore is enabled', :request_store do diff --git a/spec/initializers/rails_asset_host_spec.rb b/spec/initializers/rails_asset_host_spec.rb new file mode 100644 index 00000000000..eb69c1fa85b --- /dev/null +++ b/spec/initializers/rails_asset_host_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Rails asset host initializer' do + def load_initializer + load Rails.root.join('config/initializers/rails_asset_host.rb') + end + + around do |example| + old_asset_host = Rails.application.config.action_controller.asset_host + + example.run + + Rails.application.config.action_controller.asset_host = old_asset_host + ActionController::Base.asset_host = old_asset_host + end + + subject { Rails.application.config.action_controller.asset_host } + + it 'uses no asset host by default' do + load_initializer + + expect(subject).to be nil + end + + context 'with cdn_host defined in gitlab.yml' do + before do + stub_config_setting(cdn_host: 'https://gitlab.example.com') + end + + it 'returns https://gitlab.example.com' do + load_initializer + + expect(subject).to eq('https://gitlab.example.com') + end + end +end |