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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/support/shared_examples/models
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/support/shared_examples/models')
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb95
-rw-r--r--spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb245
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb24
12 files changed, 441 insertions, 95 deletions
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index fe99b1cacd9..42f82987989 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
@@ -9,19 +9,30 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
end
describe 'Validation' do
- before do
- allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
-
- instance.valid?
- end
-
context 'when presence validation is required' do
before do
skip unless validate_presence
end
- it 'validates presence' do
- expect(instance.errors[internal_id_attribute]).to include("can't be blank")
+ context 'when creating an object' do
+ before do
+ allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+ end
+
+ it 'raises an error if the internal id is blank' do
+ expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError)
+ end
+ end
+
+ context 'when updating an object' do
+ it 'raises an error if the internal id is blank' do
+ instance.save!
+
+ write_internal_id(nil)
+ allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+
+ expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError)
+ end
end
end
@@ -30,8 +41,27 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
skip if validate_presence
end
- it 'does not validate presence' do
- expect(instance.errors[internal_id_attribute]).to be_empty
+ context 'when creating an object' do
+ before do
+ allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+ end
+
+ it 'does not raise an error if the internal id is blank' do
+ expect(read_internal_id).to be_nil
+
+ expect { instance.save! }.not_to raise_error
+ end
+ end
+
+ context 'when updating an object' do
+ it 'does not raise an error if the internal id is blank' do
+ instance.save!
+
+ write_internal_id(nil)
+ allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+
+ expect { instance.save! }.not_to raise_error
+ end
end
end
end
@@ -76,6 +106,51 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
end
end
+ describe 'unsetting the instance internal id on rollback' do
+ context 'when the internal id has been changed' do
+ context 'when the internal id is automatically set' do
+ it 'clears it on the instance' do
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).to be_nil
+ end
+ end
+
+ context 'when the internal id is manually set' do
+ it 'does not clear it on the instance' do
+ write_internal_id(100)
+
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).not_to be_nil
+ end
+ end
+ end
+
+ context 'when the internal id has not been changed' do
+ it 'preserves the value on the instance' do
+ instance.save!
+ original_id = read_internal_id
+
+ expect(original_id).not_to be_nil
+
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).to eq(original_id)
+ end
+ end
+
+ def expect_iid_to_be_set_and_rollback
+ ActiveRecord::Base.transaction(requires_new: true) do
+ instance.save!
+
+ expect(read_internal_id).not_to be_nil
+
+ raise ActiveRecord::Rollback
+ end
+ end
+ end
+
describe 'supply of internal ids' do
let(:scope_value) { scope_attrs.each_value.first }
let(:method_name) { :"with_#{scope}_#{internal_id_attribute}_supply" }
diff --git a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb
deleted file mode 100644
index 2f0b95427d2..00000000000
--- a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'can housekeep repository' do
- context 'with a clean redis state', :clean_gitlab_redis_shared_state do
- describe '#pushes_since_gc' do
- context 'without any pushes' do
- it 'returns 0' do
- expect(resource.pushes_since_gc).to eq(0)
- end
- end
-
- context 'with a number of pushes' do
- it 'returns the number of pushes' do
- 3.times { resource.increment_pushes_since_gc }
-
- expect(resource.pushes_since_gc).to eq(3)
- end
- end
- end
-
- describe '#increment_pushes_since_gc' do
- it 'increments the number of pushes since the last GC' do
- 3.times { resource.increment_pushes_since_gc }
-
- expect(resource.pushes_since_gc).to eq(3)
- end
- end
-
- describe '#reset_pushes_since_gc' do
- it 'resets the number of pushes since the last GC' do
- 3.times { resource.increment_pushes_since_gc }
-
- resource.reset_pushes_since_gc
-
- expect(resource.pushes_since_gc).to eq(0)
- end
- end
-
- describe '#pushes_since_gc_redis_shared_state_key' do
- it 'returns the proper redis key format' do
- expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc")
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
index 85a2c6f1449..8deeecea30d 100644
--- a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
@@ -2,11 +2,12 @@
RSpec.shared_examples 'can move repository storage' do
let(:container) { raise NotImplementedError }
+ let(:repository) { container.repository }
describe '#set_repository_read_only!' do
it 'makes the repository read-only' do
expect { container.set_repository_read_only! }
- .to change(container, :repository_read_only?)
+ .to change { container.repository_read_only? }
.from(false)
.to(true)
end
@@ -28,7 +29,7 @@ RSpec.shared_examples 'can move repository storage' do
allow(container).to receive(:git_transfer_in_progress?) { true }
expect { container.set_repository_read_only!(skip_git_transfer_check: true) }
- .to change(container, :repository_read_only?)
+ .to change { container.repository_read_only? }
.from(false)
.to(true)
end
@@ -38,16 +39,16 @@ RSpec.shared_examples 'can move repository storage' do
describe '#set_repository_writable!' do
it 'sets repository_read_only to false' do
expect { container.set_repository_writable! }
- .to change(container, :repository_read_only)
+ .to change { container.repository_read_only? }
.from(true).to(false)
end
end
describe '#reference_counter' do
it 'returns a Gitlab::ReferenceCounter object' do
- expect(Gitlab::ReferenceCounter).to receive(:new).with(container.repository.gl_repository).and_call_original
+ expect(Gitlab::ReferenceCounter).to receive(:new).with(repository.gl_repository).and_call_original
- result = container.reference_counter(type: container.repository.repo_type)
+ result = container.reference_counter(type: repository.repo_type)
expect(result).to be_a Gitlab::ReferenceCounter
end
diff --git a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
index 826ee453919..1be4d9b80a4 100644
--- a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
@@ -152,36 +152,4 @@ RSpec.shared_examples 'model with repository' do
it { is_expected.to respond_to(:disk_path) }
it { is_expected.to respond_to(:gitlab_shell) }
end
-
- describe '.pick_repository_storage' do
- subject { described_class.pick_repository_storage }
-
- before do
- storages = {
- 'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'),
- 'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories')
- }
- allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- end
-
- it 'picks storage from ApplicationSetting' do
- expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked')
-
- expect(subject).to eq('picked')
- end
-
- it 'picks from the available storages based on weight', :request_store do
- stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- Gitlab::CurrentSettings.expire_current_application_settings
- Gitlab::CurrentSettings.current_application_settings
-
- settings = ApplicationSetting.last
- settings.repository_storages_weighted = { 'picked' => 100, 'default' => 0 }
- settings.save!
-
- expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 100 })
- expect(subject).to eq('picked')
- expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 0, 'picked' => 100 })
- end
- end
end
diff --git a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
index 2f0b95427d2..4006b8226ce 100644
--- a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
@@ -41,5 +41,11 @@ RSpec.shared_examples 'can housekeep repository' do
expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc")
end
end
+
+ describe '#git_garbage_collect_worker_klass' do
+ it 'defines a git gargabe collect worker' do
+ expect(resource.git_garbage_collect_worker_klass).to eq(expected_worker_class)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
index 4c617f3ba46..819cf6018fe 100644
--- a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
@@ -33,7 +33,7 @@ RSpec.shared_examples 'handles repository moves' do
subject { build(repository_storage_factory_key, container: container) }
it "does not allow the container to be read-only on create" do
- container.update!(repository_read_only: true)
+ container.set_repository_read_only!
expect(subject).not_to be_valid
expect(subject.errors[error_key].first).to match(/is read only/)
@@ -45,8 +45,8 @@ RSpec.shared_examples 'handles repository moves' do
context 'destination_storage_name' do
subject { build(repository_storage_factory_key) }
- it 'picks storage from ApplicationSetting' do
- expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked').at_least(:once)
+ it 'can pick new storage' do
+ expect(Repository).to receive(:pick_storage_shard).and_return('picked').at_least(:once)
expect(subject.destination_storage_name).to eq('picked')
end
@@ -99,6 +99,11 @@ RSpec.shared_examples 'handles repository moves' do
expect(container).not_to be_repository_read_only
end
+
+ it 'updates the updated_at column of the container', :aggregate_failures do
+ expect { storage_move.finish_replication! }.to change { container.updated_at }
+ expect(storage_move.container.updated_at).to be >= storage_move.updated_at
+ end
end
context 'and transits to failed' do
diff --git a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
index 38983f752f4..b73ff516670 100644
--- a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
@@ -11,6 +11,7 @@ RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container,
describe 'relationships' do
it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:architectures) }
+ it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:architecture) }
end
describe 'validations' do
diff --git a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
new file mode 100644
index 00000000000..02ced49ee94
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
@@ -0,0 +1,245 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
+ let_it_be(:container1, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:container2, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:distribution1, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container1) }
+ let_it_be(:distribution2, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container2) }
+ let_it_be(:architecture1_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) }
+ let_it_be(:architecture1_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) }
+ let_it_be(:architecture2_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) }
+ let_it_be(:architecture2_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) }
+ let_it_be(:component1_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) }
+ let_it_be(:component1_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) }
+ let_it_be(:component2_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) }
+ let_it_be(:component2_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) }
+
+ let_it_be_with_refind(:component_file_with_architecture) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1) }
+ let_it_be(:component_file_other_architecture, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_2) }
+ let_it_be(:component_file_other_component, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_2, architecture: architecture1_1) }
+ let_it_be(:component_file_other_compression_type, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, compression_type: :xz) }
+ let_it_be(:component_file_other_file_md5, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_md5: 'other_md5') }
+ let_it_be(:component_file_other_file_sha256, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_sha256: 'other_sha256') }
+ let_it_be(:component_file_other_container, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2_1, architecture: architecture2_1) }
+ let_it_be_with_refind(:component_file_with_file_type_source) { create("debian_#{container_type}_component_file", :source, component: component1_1) }
+ let_it_be(:component_file_with_file_type_di_packages, freeze: can_freeze) { create("debian_#{container_type}_component_file", :di_packages, component: component1_1, architecture: architecture1_1) }
+
+ subject { component_file_with_architecture }
+
+ describe 'relationships' do
+ context 'with stubbed uploader' do
+ before do
+ allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader|
+ allow(uploader).to receive(:dynamic_segment).and_return('stubbed')
+ end
+ end
+
+ it { is_expected.to belong_to(:component).class_name("Packages::Debian::#{container_type.capitalize}Component").inverse_of(:files) }
+ end
+
+ context 'with packages file_type' do
+ it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files) }
+ end
+
+ context 'with :source file_type' do
+ subject { component_file_with_file_type_source }
+
+ it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files).optional }
+ end
+ end
+
+ describe 'validations' do
+ describe "#component" do
+ before do
+ allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader|
+ allow(uploader).to receive(:dynamic_segment).and_return('stubbed')
+ end
+ end
+
+ it { is_expected.to validate_presence_of(:component) }
+ end
+
+ describe "#architecture" do
+ context 'with packages file_type' do
+ it { is_expected.to validate_presence_of(:architecture) }
+ end
+
+ context 'with :source file_type' do
+ subject { component_file_with_file_type_source }
+
+ it { is_expected.to validate_absence_of(:architecture) }
+ end
+ end
+
+ describe '#file_type' do
+ it { is_expected.to validate_presence_of(:file_type) }
+
+ it { is_expected.to allow_value(:packages).for(:file_type) }
+ end
+
+ describe '#compression_type' do
+ it { is_expected.not_to validate_presence_of(:compression_type) }
+
+ it { is_expected.to allow_value(nil).for(:compression_type) }
+ it { is_expected.to allow_value(:gz).for(:compression_type) }
+ end
+
+ describe '#file' do
+ subject { component_file_with_architecture.file }
+
+ context 'the uploader api' do
+ it { is_expected.to respond_to(:store_dir) }
+ it { is_expected.to respond_to(:cache_dir) }
+ it { is_expected.to respond_to(:work_dir) }
+ end
+ end
+
+ describe '#file_store' do
+ it { is_expected.to validate_presence_of(:file_store) }
+ end
+
+ describe '#file_md5' do
+ it { is_expected.to validate_presence_of(:file_md5) }
+ end
+
+ describe '#file_sha256' do
+ it { is_expected.to validate_presence_of(:file_sha256) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_container' do
+ subject { described_class.with_container(container2) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_container)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_codename_or_suite' do
+ subject { described_class.with_codename_or_suite(distribution2.codename) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_container)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_component_name' do
+ subject { described_class.with_component_name(component1_2.name) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_component)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_file_type' do
+ subject { described_class.with_file_type(:source) }
+
+ it do
+ # let_it_be_with_refind triggers a query
+ component_file_with_file_type_source
+
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_with_file_type_source)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_architecture_name' do
+ subject { described_class.with_architecture_name(architecture1_2.name) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_architecture)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_compression_type' do
+ subject { described_class.with_compression_type(:xz) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_compression_type)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_file_sha256' do
+ subject { described_class.with_file_sha256('other_sha256') }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_file_sha256)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+ end
+
+ describe 'callbacks' do
+ let(:component_file) { build("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, size: nil) }
+
+ subject { component_file.save! }
+
+ it 'updates metadata columns' do
+ expect(component_file)
+ .to receive(:update_file_store)
+ .and_call_original
+
+ expect(component_file)
+ .to receive(:update_column)
+ .with(:file_store, ::Packages::PackageFileUploader::Store::LOCAL)
+ .and_call_original
+
+ expect { subject }.to change { component_file.size }.from(nil).to(74)
+ end
+ end
+
+ describe '#relative_path' do
+ context 'with a Packages file_type' do
+ subject { component_file_with_architecture.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages") }
+ end
+
+ context 'with a Source file_type' do
+ subject { component_file_with_file_type_source.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/source/Source") }
+ end
+
+ context 'with a DI Packages file_type' do
+ subject { component_file_with_file_type_di_packages.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/debian-installer/binary-#{architecture1_1.name}/Packages") }
+ end
+
+ context 'with an xz compression_type' do
+ subject { component_file_other_compression_type.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages.xz") }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb
new file mode 100644
index 00000000000..bf6fc23116c
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distribution Component' do |factory, container, can_freeze|
+ let_it_be_with_refind(:component) { create(factory) } # rubocop:disable Rails/SaveBang
+ let_it_be(:component_same_distribution, freeze: can_freeze) { create(factory, distribution: component.distribution) }
+ let_it_be(:component_same_name, freeze: can_freeze) { create(factory, name: component.name) }
+
+ subject { component }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:components) }
+ it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:component) }
+ end
+
+ describe 'validations' do
+ describe "#distribution" do
+ it { is_expected.to validate_presence_of(:distribution) }
+ end
+
+ describe '#name' do
+ it { is_expected.to validate_presence_of(:name) }
+
+ it { is_expected.to allow_value('main').for(:name) }
+ it { is_expected.to allow_value('non-free').for(:name) }
+ it { is_expected.to allow_value('a' * 255).for(:name) }
+ it { is_expected.not_to allow_value('a' * 256).for(:name) }
+ it { is_expected.not_to allow_value('non/free').for(:name) }
+ it { is_expected.not_to allow_value('hé').for(:name) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_distribution' do
+ subject { described_class.with_distribution(component.distribution) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([component, component_same_distribution])
+ end
+ end
+
+ describe '.with_name' do
+ subject { described_class.with_name(component.name) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([component, component_same_name])
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index af87d30099f..b4ec146df14 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -17,7 +17,13 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
it { is_expected.to belong_to(container) }
it { is_expected.to belong_to(:creator).class_name('User') }
+ it { is_expected.to have_many(:components).class_name("Packages::Debian::#{container.capitalize}Component").inverse_of(:distribution) }
it { is_expected.to have_many(:architectures).class_name("Packages::Debian::#{container.capitalize}Architecture").inverse_of(:distribution) }
+
+ if container != :group
+ it { is_expected.to have_many(:publications).class_name('Packages::Debian::Publication').inverse_of(:distribution).with_foreign_key(:distribution_id) }
+ it { is_expected.to have_many(:packages).class_name('Packages::Package').through(:publications) }
+ end
end
describe 'validations' do
diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb
index 62da9e15259..89d30688b5c 100644
--- a/spec/support/shared_examples/models/wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/wiki_shared_examples.rb
@@ -154,6 +154,15 @@ RSpec.shared_examples 'wiki model' do
it 'returns true' do
expect(subject.empty?).to be(true)
end
+
+ context 'when the repository does not exist' do
+ let(:wiki_container) { wiki_container_without_repo }
+
+ it 'returns true and does not create the repo' do
+ expect(subject.empty?).to be(true)
+ expect(wiki.repository_exists?).to be false
+ end
+ end
end
context 'when the wiki has pages' do
diff --git a/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb
new file mode 100644
index 00000000000..e86f1e77447
--- /dev/null
+++ b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'model with Debian distributions' do
+ let(:container_type) { subject.class.name.downcase }
+ let!(:distributions) { create_list("debian_#{container_type}_distribution", 2, :with_file, container: subject) }
+ let!(:components) { create_list("debian_#{container_type}_component", 5, distribution: distributions[0]) }
+ let!(:component_files) { create_list("debian_#{container_type}_component_file", 3, component: components[0]) }
+
+ it 'removes distribution files on removal' do
+ distribution_file_paths = distributions.map do |distribution|
+ [distribution.file.path] +
+ distribution.component_files.map do |component_file|
+ component_file.file.path
+ end
+ end.flatten
+
+ expect { subject.destroy! }
+ .to change {
+ distribution_file_paths.select do |path|
+ File.exist? path
+ end.length
+ }.from(distribution_file_paths.length).to(0)
+ end
+end