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
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/concerns/bulk_insert_safe_spec.rb')
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb146
1 files changed, 84 insertions, 62 deletions
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index 0cc355ea694..a8e56cb8bdd 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -22,6 +22,18 @@ describe BulkInsertSafe do
algorithm: 'aes-256-gcm',
key: Settings.attr_encrypted_db_key_base_32,
insecure_mode: false
+
+ default_value_for :enum_value, 'case_1'
+ default_value_for :secret_value, 'my-secret'
+ default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
+
+ def self.valid_list(count)
+ Array.new(count) { |n| new(name: "item-#{n}") }
+ end
+
+ def self.invalid_list(count)
+ Array.new(count) { new }
+ end
end
module InheritedUnsafeMethods
@@ -48,6 +60,8 @@ describe BulkInsertSafe do
t.text :encrypted_secret_value, null: false
t.string :encrypted_secret_value_iv, null: false
t.binary :sha_value, null: false, limit: 20
+
+ t.index :name, unique: true
end
end
@@ -60,87 +74,95 @@ describe BulkInsertSafe do
end
end
- def build_valid_items_for_bulk_insertion
- Array.new(10) do |n|
- BulkInsertItem.new(
- name: "item-#{n}",
- enum_value: 'case_1',
- secret_value: 'my-secret',
- sha_value: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
- )
+ describe BulkInsertItem do
+ it_behaves_like 'a BulkInsertSafe model', described_class do
+ let(:valid_items_for_bulk_insertion) { described_class.valid_list(10) }
+ let(:invalid_items_for_bulk_insertion) { described_class.invalid_list(10) }
end
- end
- def build_invalid_items_for_bulk_insertion
- Array.new(10) do
- BulkInsertItem.new(
- name: nil, # requires `name` to be set
- enum_value: 'case_1',
- secret_value: 'my-secret',
- sha_value: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
- )
+ context 'when inheriting class methods' do
+ it 'raises an error when method is not bulk-insert safe' do
+ expect { described_class.include(InheritedUnsafeMethods) }
+ .to raise_error(described_class::MethodNotAllowedError)
+ end
+
+ it 'does not raise an error when method is bulk-insert safe' do
+ expect { described_class.include(InheritedSafeMethods) }.not_to raise_error
+ end
end
- end
- it_behaves_like 'a BulkInsertSafe model', BulkInsertItem do
- let(:valid_items_for_bulk_insertion) { build_valid_items_for_bulk_insertion }
- let(:invalid_items_for_bulk_insertion) { build_invalid_items_for_bulk_insertion }
- end
+ context 'primary keys' do
+ it 'raises error if primary keys are set prior to insertion' do
+ item = described_class.new(name: 'valid', id: 10)
- context 'when inheriting class methods' do
- it 'raises an error when method is not bulk-insert safe' do
- expect { BulkInsertItem.include(InheritedUnsafeMethods) }.to(
- raise_error(subject::MethodNotAllowedError))
+ expect { described_class.bulk_insert!([item]) }
+ .to raise_error(described_class::PrimaryKeySetError)
+ end
end
- it 'does not raise an error when method is bulk-insert safe' do
- expect { BulkInsertItem.include(InheritedSafeMethods) }.not_to raise_error
- end
- end
+ describe '.bulk_insert!' do
+ it 'inserts items in the given number of batches' do
+ items = described_class.valid_list(10)
+
+ expect(ActiveRecord::InsertAll).to receive(:new).twice.and_call_original
- context 'primary keys' do
- it 'raises error if primary keys are set prior to insertion' do
- items = build_valid_items_for_bulk_insertion
- items.each_with_index do |item, n|
- item.id = n
+ described_class.bulk_insert!(items, batch_size: 5)
end
- expect { BulkInsertItem.bulk_insert!(items) }.to raise_error(subject::PrimaryKeySetError)
- end
- end
+ it 'items can be properly fetched from database' do
+ items = described_class.valid_list(10)
- describe '.bulk_insert!' do
- it 'inserts items in the given number of batches' do
- items = build_valid_items_for_bulk_insertion
- expect(items.size).to eq(10)
- expect(BulkInsertItem).to receive(:insert_all!).twice
+ described_class.bulk_insert!(items)
- BulkInsertItem.bulk_insert!(items, batch_size: 5)
- end
+ attribute_names = described_class.attribute_names - %w[id]
+ expect(described_class.last(items.size).pluck(*attribute_names)).to eq(
+ items.pluck(*attribute_names))
+ end
- it 'items can be properly fetched from database' do
- items = build_valid_items_for_bulk_insertion
+ it 'rolls back the transaction when any item is invalid' do
+ # second batch is bad
+ all_items = described_class.valid_list(10) +
+ described_class.invalid_list(10)
- BulkInsertItem.bulk_insert!(items)
+ expect do
+ described_class.bulk_insert!(all_items, batch_size: 2) rescue nil
+ end.not_to change { described_class.count }
+ end
- attribute_names = BulkInsertItem.attribute_names - %w[id]
- expect(BulkInsertItem.last(items.size).pluck(*attribute_names)).to eq(
- items.pluck(*attribute_names))
+ it 'does nothing and returns true when items are empty' do
+ expect(described_class.bulk_insert!([])).to be(true)
+ expect(described_class.count).to eq(0)
+ end
end
- it 'rolls back the transaction when any item is invalid' do
- # second batch is bad
- all_items = build_valid_items_for_bulk_insertion + build_invalid_items_for_bulk_insertion
- batch_size = all_items.size / 2
+ context 'when duplicate items are to be inserted' do
+ let!(:existing_object) { described_class.create!(name: 'duplicate', secret_value: 'old value') }
+ let(:new_object) { described_class.new(name: 'duplicate', secret_value: 'new value') }
+
+ describe '.bulk_insert!' do
+ context 'when skip_duplicates is set to false' do
+ it 'raises an exception' do
+ expect { described_class.bulk_insert!([new_object], skip_duplicates: false) }
+ .to raise_error(ActiveRecord::RecordNotUnique)
+ end
+ end
+
+ context 'when skip_duplicates is set to true' do
+ it 'does not update existing object' do
+ described_class.bulk_insert!([new_object], skip_duplicates: true)
+
+ expect(existing_object.reload.secret_value).to eq('old value')
+ end
+ end
+ end
- expect do
- BulkInsertItem.bulk_insert!(all_items, batch_size: batch_size) rescue nil
- end.not_to change { BulkInsertItem.count }
- end
+ describe '.bulk_upsert!' do
+ it 'updates existing object' do
+ described_class.bulk_upsert!([new_object], unique_by: %w[name])
- it 'does nothing and returns true when items are empty' do
- expect(BulkInsertItem.bulk_insert!([])).to be(true)
- expect(BulkInsertItem.count).to eq(0)
+ expect(existing_object.reload.secret_value).to eq('new value')
+ end
+ end
end
end
end