diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-09 18:09:27 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-09 18:09:27 +0300 |
commit | be769d5fcced48143e92f83c997b7d5ba14873e1 (patch) | |
tree | 985b5acc88e4c235771bc19f5e9e7c746deaf9b3 /spec/lib | |
parent | 3fd585614449ccab7fdab083f210c09eb16a6ed2 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
8 files changed, 198 insertions, 144 deletions
diff --git a/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_database_adapter_spec.rb b/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_database_adapter_spec.rb new file mode 100644 index 00000000000..cfe5572fb51 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_database_adapter_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Adapters::ForeignKeyDatabaseAdapter, feature_category: :database do + subject(:adapter) { described_class.new(query_result) } + + let(:query_result) do + { + 'schema' => 'public', + 'foreign_key_name' => 'fk_2e88fb7ce9', + 'table_name' => 'members', + 'foreign_key_definition' => 'FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE' + } + end + + describe '#name' do + it { expect(adapter.name).to eq('public.fk_2e88fb7ce9') } + end + + describe '#table_name' do + it { expect(adapter.table_name).to eq('members') } + end + + describe '#statement' do + it { expect(adapter.statement).to eq('FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE') } + end +end diff --git a/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_structure_sql_adapter_spec.rb b/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_structure_sql_adapter_spec.rb new file mode 100644 index 00000000000..f7ae0c0f892 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/adapters/foreign_key_structure_sql_adapter_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Adapters::ForeignKeyStructureSqlAdapter, feature_category: :database do + subject(:adapter) { described_class.new(stmt) } + + let(:stmt) { PgQuery.parse(sql).tree.stmts.first.stmt.alter_table_stmt } + + where(:sql, :name, :table_name, :statement) do + [ + [ + 'ALTER TABLE ONLY public.issues ADD CONSTRAINT fk_05f1e72feb FOREIGN KEY (author_id) REFERENCES users (id) ' \ + 'ON DELETE SET NULL', + 'public.fk_05f1e72feb', + 'issues', + 'FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL' + ], + [ + 'ALTER TABLE public.import_failures ADD CONSTRAINT fk_9a9b9ba21c FOREIGN KEY (user_id) REFERENCES users(id) ' \ + 'ON DELETE CASCADE', + 'public.fk_9a9b9ba21c', + 'import_failures', + 'FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE' + ] + ] + end + + with_them do + describe '#name' do + it { expect(adapter.name).to eq(name) } + end + + describe '#table_name' do + it { expect(adapter.table_name).to eq(table_name) } + end + + describe '#statement' do + it { expect(adapter.statement).to eq(statement) } + end + end +end diff --git a/spec/lib/gitlab/database/schema_validation/schema_objects/foreign_key_spec.rb b/spec/lib/gitlab/database/schema_validation/schema_objects/foreign_key_spec.rb new file mode 100644 index 00000000000..7500ad44f82 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/schema_objects/foreign_key_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::SchemaObjects::ForeignKey, feature_category: :database do + subject(:foreign_key) { described_class.new(adapter) } + + let(:database_adapter) { 'Gitlab::Database::SchemaValidation::Adapters::ForeignKeyDatabaseAdapter' } + let(:adapter) do + instance_double(database_adapter, name: 'public.fk_1d37cddf91', table_name: 'vulnerabilities', + statement: 'FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL') + end + + describe '#name' do + it { expect(foreign_key.name).to eq('public.fk_1d37cddf91') } + end + + describe '#table_name' do + it { expect(foreign_key.table_name).to eq('vulnerabilities') } + end + + describe '#statement' do + it { expect(foreign_key.statement).to eq('FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL') } + end +end diff --git a/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb index 036ad6424f0..e8c08277d52 100644 --- a/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb +++ b/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb @@ -12,13 +12,16 @@ RSpec.describe Gitlab::Database::SchemaValidation::Validators::BaseValidator, fe Gitlab::Database::SchemaValidation::Validators::ExtraTableColumns, Gitlab::Database::SchemaValidation::Validators::ExtraIndexes, Gitlab::Database::SchemaValidation::Validators::ExtraTriggers, + Gitlab::Database::SchemaValidation::Validators::ExtraForeignKeys, Gitlab::Database::SchemaValidation::Validators::MissingTables, Gitlab::Database::SchemaValidation::Validators::MissingTableColumns, Gitlab::Database::SchemaValidation::Validators::MissingIndexes, Gitlab::Database::SchemaValidation::Validators::MissingTriggers, + Gitlab::Database::SchemaValidation::Validators::MissingForeignKeys, Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionTables, Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionIndexes, - Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionTriggers + Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionTriggers, + Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionForeignKeys ]) end end diff --git a/spec/lib/gitlab/database/schema_validation/validators/different_definition_foreign_keys_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/different_definition_foreign_keys_spec.rb new file mode 100644 index 00000000000..ffebffc3ad2 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/validators/different_definition_foreign_keys_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionForeignKeys, + feature_category: :database do + include_examples 'foreign key validators', described_class, ['public.wrong_definition_fk'] +end diff --git a/spec/lib/gitlab/database/schema_validation/validators/extra_foreign_keys_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/extra_foreign_keys_spec.rb new file mode 100644 index 00000000000..053153aa214 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/validators/extra_foreign_keys_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Validators::ExtraForeignKeys, feature_category: :database do + include_examples 'foreign key validators', described_class, ['public.extra_fk'] +end diff --git a/spec/lib/gitlab/database/schema_validation/validators/missing_foreign_keys_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/missing_foreign_keys_spec.rb new file mode 100644 index 00000000000..a47804abb91 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/validators/missing_foreign_keys_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Validators::MissingForeignKeys, feature_category: :database do + include_examples 'foreign key validators', described_class, %w[public.fk_rails_536b96bff1 public.missing_fk] +end diff --git a/spec/lib/gitlab/patch/redis_cache_store_spec.rb b/spec/lib/gitlab/patch/redis_cache_store_spec.rb index 1b3813d03a2..4095cbbfcde 100644 --- a/spec/lib/gitlab/patch/redis_cache_store_spec.rb +++ b/spec/lib/gitlab/patch/redis_cache_store_spec.rb @@ -3,193 +3,127 @@ require 'spec_helper' RSpec.describe Gitlab::Patch::RedisCacheStore, :use_clean_rails_redis_caching, feature_category: :scalability do + let(:cache) { Rails.cache } + before do - Rails.cache.write('x', 1) - Rails.cache.write('y', 2) - Rails.cache.write('z', 3) + cache.write('x', 1) + cache.write('y', 2) + cache.write('z', 3) - Rails.cache.write('{user1}:x', 1) - Rails.cache.write('{user1}:y', 2) - Rails.cache.write('{user1}:z', 3) + cache.write('{user1}:x', 1) + cache.write('{user1}:y', 2) + cache.write('{user1}:z', 3) end describe '#read_multi_mget' do - it 'runs multi-key command if no cross-slot command is expected' do - Rails.cache.redis.with do |redis| - if Gitlab::Redis::ClusterUtil.cluster?(redis) - expect(redis).to receive(:pipelined).once.and_call_original - else - expect(redis).not_to receive(:pipelined) - end - end - - expect( - Rails.cache.fetch_multi('{user1}:x', '{user1}:y', '{user1}:z') { |key| key } - ).to eq({ '{user1}:x' => 1, '{user1}:y' => 2, '{user1}:z' => 3 }) - end - - context 'when deleting large amount of keys' do - it 'batches get into pipelines of 100' do - Rails.cache.redis.with do |redis| - expect(redis).to receive(:pipelined).at_least(2).and_call_original - end - - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - Rails.cache.read_multi(*Array.new(101) { |i| i }) - end - end - end - - shared_examples "fetches multiple keys" do |patched| - it 'reads multiple keys' do - if patched - Rails.cache.redis.with do |redis| - expect(redis).to receive(:pipelined).at_least(1).and_call_original - end - end - - Gitlab::Redis::Cache.with do |redis| - unless Gitlab::Redis::ClusterUtil.cluster?(redis) - expect(::Feature).to receive(:enabled?) - .with(:feature_flag_state_logs, { default_enabled_if_undefined: nil, type: :ops }) - .exactly(:once) - .and_call_original - - expect(::Feature).to receive(:enabled?) - .with(:enable_rails_cache_pipeline_patch) - .exactly(:once) - .and_call_original - end - end - + shared_examples 'reading using cache stores' do + it 'gets multiple cross-slot keys' do expect( Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do # fetch_multi requires a block and we have to specifically test it # as it is used in the Gitlab project - Rails.cache.fetch_multi('x', 'y', 'z') { |key| key } + cache.fetch_multi('x', 'y', 'z') { |key| key } end ).to eq({ 'x' => 1, 'y' => 2, 'z' => 3 }) end - end - shared_examples 'reading using non redis cache stores' do |klass| - it 'does not affect non Redis::Cache cache stores' do - klass.cache_store.redis.with do |redis| - expect(redis).not_to receive(:pipelined) unless Gitlab::Redis::ClusterUtil.cluster?(redis) - end + it 'gets multiple keys' do + expect( + cache.fetch_multi('{user1}:x', '{user1}:y', '{user1}:z') { |key| key } + ).to eq({ '{user1}:x' => 1, '{user1}:y' => 2, '{user1}:z' => 3 }) + end + + context 'when reading large amount of keys' do + it 'batches get into pipelines of 100' do + cache.redis.with do |redis| + if Gitlab::Redis::ClusterUtil.cluster?(redis) + expect(redis).to receive(:pipelined).at_least(2).and_call_original + else + expect(redis).to receive(:mget).and_call_original + end + end - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - klass.cache_store.fetch_multi('x', 'y', 'z') { |key| key } + Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do + cache.read_multi(*Array.new(101) { |i| i }) + end end end end - context 'when reading from non redis-cache stores' do - it_behaves_like 'reading using non redis cache stores', Gitlab::Redis::FeatureFlag - it_behaves_like 'reading using non redis cache stores', Gitlab::Redis::RepositoryCache + context 'when cache is Rails.cache' do + let(:cache) { Rails.cache } + + it_behaves_like 'reading using cache stores' end - context 'when feature flag is disabled' do - before do - stub_feature_flags(enable_rails_cache_pipeline_patch: false) - end + context 'when cache is feature flag cache store' do + let(:cache) { Gitlab::Redis::FeatureFlag.cache_store } - it_behaves_like 'fetches multiple keys' + it_behaves_like 'reading using cache stores' end - it_behaves_like 'fetches multiple keys', true + context 'when cache is repository cache store' do + let(:cache) { Gitlab::Redis::RepositoryCache.cache_store } + + it_behaves_like 'reading using cache stores' + end end describe '#delete_multi_entries' do - shared_examples "deletes multiple keys" do |patched| - it 'deletes multiple keys' do - if patched - Rails.cache.redis.with do |redis| - expect(redis).to receive(:pipelined).at_least(1).and_call_original - end - end - - Gitlab::Redis::Cache.with do |redis| - unless Gitlab::Redis::ClusterUtil.cluster?(redis) - expect(::Feature).to receive(:enabled?) - .with(:feature_flag_state_logs, { default_enabled_if_undefined: nil, type: :ops }) - .exactly(:once) - .and_call_original - - expect(::Feature).to receive(:enabled?) - .with(:enable_rails_cache_pipeline_patch) - .exactly(:once) - .and_call_original - end - end + shared_examples 'deleting using cache stores' do + it 'deletes multiple cross-slot keys' do + expect(Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do + cache.delete_multi(%w[x y z]) + end).to eq(3) + end + it 'deletes multiple keys' do expect( - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - Rails.cache.delete_multi(%w[x y z]) - end + cache.delete_multi(%w[{user1}:x {user1}:y {user1}:z]) ).to eq(3) end - end - shared_examples 'deleting using non redis cache stores' do |klass| - it 'does not affect non Redis::Cache cache stores' do - klass.cache_store.redis.with do |redis| - expect(redis).not_to receive(:pipelined) unless Gitlab::Redis::ClusterUtil.cluster?(redis) + context 'when deleting large amount of keys' do + before do + 200.times { |i| cache.write(i, i) } end - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - klass.cache_store.delete_multi(%w[x y z]) + it 'calls pipeline multiple times' do + cache.redis.with do |redis| + # no expectation on number of times as it could vary depending on cluster size + # if the Redis is a Redis Cluster + if Gitlab::Redis::ClusterUtil.cluster?(redis) + expect(redis).to receive(:pipelined).at_least(2).and_call_original + else + expect(redis).to receive(:del).and_call_original + end + end + + expect( + Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do + cache.delete_multi(Array(0..199)) + end + ).to eq(200) end end end - context 'when deleting from non redis-cache stores' do - it_behaves_like 'deleting using non redis cache stores', Gitlab::Redis::FeatureFlag - it_behaves_like 'deleting using non redis cache stores', Gitlab::Redis::RepositoryCache - end - - context 'when deleting large amount of keys' do - before do - 200.times { |i| Rails.cache.write(i, i) } - end + context 'when cache is Rails.cache' do + let(:cache) { Rails.cache } - it 'calls pipeline multiple times' do - Rails.cache.redis.with do |redis| - # no expectation on number of times as it could vary depending on cluster size - # if the Redis is a Redis Cluster - expect(redis).to receive(:pipelined).at_least(2).and_call_original - end - - expect( - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - Rails.cache.delete_multi(Array(0..199)) - end - ).to eq(200) - end + it_behaves_like 'deleting using cache stores' end - it 'runs multi-key command if no cross-slot command is expected' do - Rails.cache.redis.with do |redis| - if Gitlab::Redis::ClusterUtil.cluster?(redis) - expect(redis).to receive(:pipelined).once.and_call_original - else - expect(redis).not_to receive(:pipelined) - end - end + context 'when cache is feature flag cache store' do + let(:cache) { Gitlab::Redis::FeatureFlag.cache_store } - expect( - Rails.cache.delete_multi(%w[{user1}:x {user1}:y {user1}:z]) - ).to eq(3) + it_behaves_like 'deleting using cache stores' end - context 'when feature flag is disabled' do - before do - stub_feature_flags(enable_rails_cache_pipeline_patch: false) - end + context 'when cache is repository cache store' do + let(:cache) { Gitlab::Redis::RepositoryCache.cache_store } - it_behaves_like 'deletes multiple keys' + it_behaves_like 'deleting using cache stores' end - - it_behaves_like 'deletes multiple keys', true end end |