diff options
Diffstat (limited to 'spec/models/packages')
-rw-r--r-- | spec/models/packages/debian/file_metadatum_spec.rb | 44 | ||||
-rw-r--r-- | spec/models/packages/debian/group_distribution_spec.rb | 7 | ||||
-rw-r--r-- | spec/models/packages/debian/project_distribution_spec.rb | 7 | ||||
-rw-r--r-- | spec/models/packages/dependency_spec.rb | 19 | ||||
-rw-r--r-- | spec/models/packages/event_spec.rb | 51 | ||||
-rw-r--r-- | spec/models/packages/npm/metadata_cache_spec.rb | 150 | ||||
-rw-r--r-- | spec/models/packages/npm/metadatum_spec.rb | 14 | ||||
-rw-r--r-- | spec/models/packages/package_file_spec.rb | 12 | ||||
-rw-r--r-- | spec/models/packages/package_spec.rb | 79 |
9 files changed, 349 insertions, 34 deletions
diff --git a/spec/models/packages/debian/file_metadatum_spec.rb b/spec/models/packages/debian/file_metadatum_spec.rb index 1215adfa6a1..e86c0a71c9a 100644 --- a/spec/models/packages/debian/file_metadatum_spec.rb +++ b/spec/models/packages/debian/file_metadatum_spec.rb @@ -2,15 +2,15 @@ require 'spec_helper' -RSpec.describe Packages::Debian::FileMetadatum, type: :model do - RSpec.shared_context 'Debian file metadatum' do |factory, trait| - let_it_be_with_reload(:debian_package_file) { create(factory, trait) } +RSpec.describe Packages::Debian::FileMetadatum, type: :model, feature_category: :package_registry do + RSpec.shared_context 'with Debian file metadatum' do |package_file_trait| + let_it_be_with_reload(:debian_package_file) { create(:debian_package_file, package_file_trait) } let(:debian_file_metadatum) { debian_package_file.debian_file_metadatum } subject { debian_file_metadatum } end - RSpec.shared_examples 'Test Debian file metadatum' do |has_component, has_architecture, has_fields, has_outdated| + RSpec.shared_examples 'Test Debian file metadatum' do |has_component, has_architecture, has_fields| describe 'relationships' do it { is_expected.to belong_to(:package_file) } end @@ -51,8 +51,8 @@ RSpec.describe Packages::Debian::FileMetadatum, type: :model do describe '#fields' do if has_fields it { is_expected.to validate_presence_of(:fields) } - it { is_expected.to allow_value({ 'a': 'b' }).for(:fields) } - it { is_expected.not_to allow_value({ 'a': { 'b': 'c' } }).for(:fields) } + it { is_expected.to allow_value({ a: 'b' }).for(:fields) } + it { is_expected.not_to allow_value({ a: { b: 'c' } }).for(:fields) } else it { is_expected.to validate_absence_of(:fields) } end @@ -69,23 +69,35 @@ RSpec.describe Packages::Debian::FileMetadatum, type: :model do end end end + + describe 'scopes' do + describe '.with_file_type' do + subject { described_class.with_file_type(package_file_trait) } + + it 'returns the matching file metadatum' do + expect(subject).to match_array([debian_file_metadatum]) + end + end + end end using RSpec::Parameterized::TableSyntax - where(:factory, :trait, :has_component, :has_architecture, :has_fields) do - :debian_package_file | :unknown | false | false | false - :debian_package_file | :source | true | false | false - :debian_package_file | :dsc | true | false | true - :debian_package_file | :deb | true | true | true - :debian_package_file | :udeb | true | true | true - :debian_package_file | :buildinfo | true | false | true - :debian_package_file | :changes | false | false | true + where(:package_file_trait, :has_component, :has_architecture, :has_fields) do + :unknown | false | false | false + :source | true | false | false + :dsc | true | false | true + :deb | true | true | true + :udeb | true | true | true + :ddeb | true | true | true + :buildinfo | true | false | true + :changes | false | false | true end with_them do - include_context 'Debian file metadatum', params[:factory], params[:trait] do - it_behaves_like 'Test Debian file metadatum', params[:has_component], params[:has_architecture], params[:has_fields], params[:has_outdated] + include_context 'with Debian file metadatum', params[:package_file_trait] do + it_behaves_like 'Test Debian file metadatum', + params[:has_component], params[:has_architecture], params[:has_fields] end end end diff --git a/spec/models/packages/debian/group_distribution_spec.rb b/spec/models/packages/debian/group_distribution_spec.rb index 90fb0d0e7d8..1af23ad3ac0 100644 --- a/spec/models/packages/debian/group_distribution_spec.rb +++ b/spec/models/packages/debian/group_distribution_spec.rb @@ -2,6 +2,9 @@ require 'spec_helper' -RSpec.describe Packages::Debian::GroupDistribution do - it_behaves_like 'Debian Distribution', :debian_group_distribution, :group, false +RSpec.describe Packages::Debian::GroupDistribution, feature_category: :package_registry do + include_context 'for Debian Distribution', :debian_group_distribution, false + + it_behaves_like 'Debian Distribution for common behavior' + it_behaves_like 'Debian Distribution with group container' end diff --git a/spec/models/packages/debian/project_distribution_spec.rb b/spec/models/packages/debian/project_distribution_spec.rb index 5f4041ad9fe..2b79cdb539f 100644 --- a/spec/models/packages/debian/project_distribution_spec.rb +++ b/spec/models/packages/debian/project_distribution_spec.rb @@ -2,6 +2,9 @@ require 'spec_helper' -RSpec.describe Packages::Debian::ProjectDistribution do - it_behaves_like 'Debian Distribution', :debian_project_distribution, :project, true +RSpec.describe Packages::Debian::ProjectDistribution, feature_category: :package_registry do + include_context 'for Debian Distribution', :debian_project_distribution, true + + it_behaves_like 'Debian Distribution for common behavior' + it_behaves_like 'Debian Distribution with project container' end diff --git a/spec/models/packages/dependency_spec.rb b/spec/models/packages/dependency_spec.rb index 1575dec98c9..80ec7f77fda 100644 --- a/spec/models/packages/dependency_spec.rb +++ b/spec/models/packages/dependency_spec.rb @@ -1,7 +1,11 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Packages::Dependency, type: :model do +RSpec.describe Packages::Dependency, type: :model, feature_category: :package_registry do + describe 'included modules' do + it { is_expected.to include_module(EachBatch) } + end + describe 'relationships' do it { is_expected.to have_many(:dependency_links) } end @@ -110,6 +114,19 @@ RSpec.describe Packages::Dependency, type: :model do end end + describe '.orphaned' do + let_it_be(:orphaned_dependencies) { create_list(:packages_dependency, 2) } + let_it_be(:linked_dependency) do + create(:packages_dependency).tap do |dependency| + create(:packages_dependency_link, dependency: dependency) + end + end + + it 'returns orphaned dependency records' do + expect(described_class.orphaned).to contain_exactly(*orphaned_dependencies) + end + end + def build_names_and_version_patterns(*package_dependencies) result = Hash.new { |h, dependency| h[dependency.name] = dependency.version_pattern } package_dependencies.each { |dependency| result[dependency] } diff --git a/spec/models/packages/event_spec.rb b/spec/models/packages/event_spec.rb new file mode 100644 index 00000000000..58c1c1e6e92 --- /dev/null +++ b/spec/models/packages/event_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Event, feature_category: :package_registry do + let(:event_type) { :push_package } + let(:event_scope) { :npm } + let(:originator_type) { :deploy_token } + + shared_examples 'handle forbidden event type' do |result: []| + let(:event_type) { :search } + + it { is_expected.to eq(result) } + end + + describe '.event_allowed?' do + subject { described_class.event_allowed?(event_type) } + + it { is_expected.to eq(true) } + + it_behaves_like 'handle forbidden event type', result: false + end + + describe '.unique_counters_for' do + subject { described_class.unique_counters_for(event_scope, event_type, originator_type) } + + it { is_expected.to contain_exactly('i_package_npm_deploy_token') } + + it_behaves_like 'handle forbidden event type' + + context 'when an originator type is quest' do + let(:originator_type) { :guest } + + it { is_expected.to eq([]) } + end + end + + describe '.counters_for' do + subject { described_class.counters_for(event_scope, event_type, originator_type) } + + it do + is_expected.to contain_exactly( + 'i_package_push_package', + 'i_package_push_package_by_deploy_token', + 'i_package_npm_push_package' + ) + end + + it_behaves_like 'handle forbidden event type' + end +end diff --git a/spec/models/packages/npm/metadata_cache_spec.rb b/spec/models/packages/npm/metadata_cache_spec.rb new file mode 100644 index 00000000000..5e7a710baf8 --- /dev/null +++ b/spec/models/packages/npm/metadata_cache_spec.rb @@ -0,0 +1,150 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Npm::MetadataCache, type: :model, feature_category: :package_registry do + let_it_be(:project) { create(:project) } + let_it_be(:package_name) { '@root/test' } + + it { is_expected.to be_a FileStoreMounter } + + describe 'relationships' do + it { is_expected.to belong_to(:project).inverse_of(:npm_metadata_caches) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:file) } + it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:size) } + + describe '#package_name' do + let_it_be(:npm_metadata_cache) { create(:npm_metadata_cache, package_name: package_name, project: project) } + + it { is_expected.to validate_presence_of(:package_name) } + + describe 'uniqueness' do + it 'ensures the package name is unique within a given project' do + expect do + create(:npm_metadata_cache, package_name: package_name, project: project) + end.to raise_error(ActiveRecord::RecordInvalid, 'Validation failed: Package name has already been taken') + end + + it 'allows duplicate file names in different projects' do + expect do + create(:npm_metadata_cache, package_name: package_name, project: create(:project)) + end.not_to raise_error + end + end + + describe 'format' do + it { is_expected.to allow_value('my.app-11.07.2018').for(:package_name) } + it { is_expected.to allow_value('@group-1/package').for(:package_name) } + it { is_expected.to allow_value('@any-scope/package').for(:package_name) } + it { is_expected.to allow_value('unscoped-package').for(:package_name) } + + it { is_expected.not_to allow_value('my(dom$$$ain)com.my-app').for(:package_name) } + it { is_expected.not_to allow_value('@inv@lid-scope/package').for(:package_name) } + it { is_expected.not_to allow_value('@scope/../../package').for(:package_name) } + it { is_expected.not_to allow_value('@scope%2e%2e%fpackage').for(:package_name) } + it { is_expected.not_to allow_value('@scope/sub/package').for(:package_name) } + end + end + end + + describe '.find_or_build' do + subject { described_class.find_or_build(package_name: package_name, project_id: project.id) } + + context 'when a metadata cache exists' do + let_it_be(:npm_metadata_cache) { create(:npm_metadata_cache, package_name: package_name, project: project) } + + it 'finds an existing metadata cache' do + expect(subject).to eq(npm_metadata_cache) + end + end + + context 'when a metadata cache not found' do + let(:package_name) { 'not_existing' } + + it 'builds a new instance', :aggregate_failures do + expect(subject).not_to be_persisted + expect(subject.package_name).to eq(package_name) + expect(subject.project_id).to eq(project.id) + end + end + end + + describe 'save callbacks' do + describe 'object_storage_key' do + let(:object_storage_key) do + Gitlab::HashedPath.new( + 'packages', 'metadata_caches', 'npm', OpenSSL::Digest::SHA256.hexdigest(package_name), + root_hash: project.id + ) + end + + before do + allow(Gitlab::HashedPath).to receive(:new).and_return(object_storage_key) + end + + context 'when the record is created' do + let(:npm_metadata_cache) { build(:npm_metadata_cache, package_name: package_name, project: project) } + + it 'sets object_storage_key' do + npm_metadata_cache.save! + + expect(npm_metadata_cache.object_storage_key).to eq(object_storage_key.to_s) + end + + context 'when using `update!`' do + let(:metadata_content) { {}.to_json } + + it 'sets object_storage_key' do + npm_metadata_cache.update!( + file: CarrierWaveStringFile.new(metadata_content), + size: metadata_content.bytesize + ) + + expect(npm_metadata_cache.object_storage_key).to eq(object_storage_key.to_s) + end + end + end + + context 'when the record is updated' do + let_it_be(:npm_metadata_cache) { create(:npm_metadata_cache, package_name: package_name, project: project) } + + let(:existing_object_storage_key) { npm_metadata_cache.object_storage_key } + let(:new_package_name) { 'updated_package_name' } + + it 'does not update object_storage_key' do + existing_object_storage_key = npm_metadata_cache.object_storage_key + + npm_metadata_cache.update!(package_name: new_package_name) + + expect(npm_metadata_cache.object_storage_key).to eq(existing_object_storage_key) + end + end + end + end + + describe 'readonly attributes' do + describe 'object_storage_key' do + let_it_be(:npm_metadata_cache) { create(:npm_metadata_cache) } + + it 'sets object_storage_key' do + expect(npm_metadata_cache.object_storage_key).to be_present + end + + context 'when the record is persisted' do + let(:new_object_storage_key) { 'object/storage/updated_key' } + + it 'does not re-set object_storage_key' do + npm_metadata_cache.object_storage_key = new_object_storage_key + + npm_metadata_cache.save! + + expect(npm_metadata_cache.object_storage_key).not_to eq(new_object_storage_key) + end + end + end + end +end diff --git a/spec/models/packages/npm/metadatum_spec.rb b/spec/models/packages/npm/metadatum_spec.rb index ff8cce5310e..92daddded7e 100644 --- a/spec/models/packages/npm/metadatum_spec.rb +++ b/spec/models/packages/npm/metadatum_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Packages::Npm::Metadatum, type: :model do +RSpec.describe Packages::Npm::Metadatum, type: :model, feature_category: :package_registry do describe 'relationships' do it { is_expected.to belong_to(:package).inverse_of(:npm_metadatum) } end @@ -47,4 +47,16 @@ RSpec.describe Packages::Npm::Metadatum, type: :model do end end end + + describe 'scopes' do + describe '.package_id_in' do + let_it_be(:package) { create(:npm_package) } + let_it_be(:metadatum_1) { create(:npm_metadatum, package: package) } + let_it_be(:metadatum_2) { create(:npm_metadatum) } + + it 'returns metadatums with the given package ids' do + expect(described_class.package_id_in([package.id])).to contain_exactly(metadatum_1) + end + end + end end diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb index 9b341034aaa..c9db1efc64a 100644 --- a/spec/models/packages/package_file_spec.rb +++ b/spec/models/packages/package_file_spec.rb @@ -153,6 +153,7 @@ RSpec.describe Packages::PackageFile, type: :model do let_it_be(:debian_changes) { debian_package.package_files.last } let_it_be(:debian_deb) { create(:debian_package_file, package: debian_package) } let_it_be(:debian_udeb) { create(:debian_package_file, :udeb, package: debian_package) } + let_it_be(:debian_ddeb) { create(:debian_package_file, :ddeb, package: debian_package) } let_it_be(:debian_contrib) do create(:debian_package_file, package: debian_package).tap do |pf| @@ -177,6 +178,17 @@ RSpec.describe Packages::PackageFile, type: :model do describe '#with_debian_architecture_name' do it { expect(described_class.with_debian_architecture_name('mipsel')).to contain_exactly(debian_mipsel) } end + + describe '#with_debian_unknown_since' do + let_it_be(:incoming) { create(:debian_incoming, project: project) } + + before do + incoming.package_files.first.debian_file_metadatum.update! updated_at: 1.day.ago + incoming.package_files.second.update! updated_at: 1.day.ago, status: :error + end + + it { expect(described_class.with_debian_unknown_since(1.hour.ago)).to contain_exactly(incoming.package_files.first) } + end end describe '.for_helm_with_channel' do diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index 992cc5c4354..e79459e0c7c 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -682,24 +682,20 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis end end - describe "#unique_debian_package_name" do + describe "uniqueness for package type debian" do let!(:package) { create(:debian_package) } - it "will allow a Debian package with same project, name and version, but different distribution" do - new_package = build(:debian_package, project: package.project, name: package.name, version: package.version) - expect(new_package).to be_valid - end - it "will not allow a Debian package with same project, name, version and distribution" do new_package = build(:debian_package, project: package.project, name: package.name, version: package.version) new_package.debian_publication.distribution = package.debian_publication.distribution expect(new_package).not_to be_valid - expect(new_package.errors.to_a).to include('Debian package already exists in Distribution') + expect(new_package.errors.to_a).to include('Name has already been taken') end - it "will allow a Debian package with same project, name, version, but no distribution" do + it "will not allow a Debian package with same project, name, version, but no distribution" do new_package = build(:debian_package, project: package.project, name: package.name, version: package.version, published_in: nil) - expect(new_package).to be_valid + expect(new_package).not_to be_valid + expect(new_package.errors.to_a).to include('Name has already been taken') end context 'with pending_destruction package' do @@ -713,7 +709,7 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis end end - Packages::Package.package_types.keys.without('conan', 'debian').each do |pt| + Packages::Package.package_types.keys.without('conan').each do |pt| context "project id, name, version and package type uniqueness for package type #{pt}" do let(:package) { create("#{pt}_package") } @@ -722,6 +718,15 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis expect(new_package).not_to be_valid expect(new_package.errors.to_a).to include("Name has already been taken") end + + context 'with pending_destruction package' do + let!(:package) { create("#{pt}_package", :pending_destruction) } + + it "will allow a #{pt} package with same project, name, version and package_type" do + new_package = build("#{pt}_package", project: package.project, name: package.name, version: package.version) + expect(new_package).to be_valid + end + end end end end @@ -842,6 +847,14 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis is_expected.to match_array([package]) end end + + describe '.preload_conan_metadatum' do + subject { described_class.preload_conan_metadatum } + + it 'loads conan metadatum' do + expect(subject.first.association(:conan_metadatum)).to be_loaded + end + end end describe '.without_nuget_temporary_name' do @@ -1235,8 +1248,18 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis let_it_be(:first_build_info) { create(:package_build_info, :with_pipeline, package: package) } let_it_be(:second_build_info) { create(:package_build_info, :with_pipeline, package: package) } - it 'returns the first build info' do - expect(package.original_build_info).to eq(first_build_info) + it 'returns the last build info' do + expect(package.original_build_info).to eq(second_build_info) + end + + context 'with packages_display_last_pipeline disabled' do + before do + stub_feature_flags(packages_display_last_pipeline: false) + end + + it 'returns the first build info' do + expect(package.original_build_info).to eq(first_build_info) + end end end end @@ -1402,4 +1425,36 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis .to change(package, :last_downloaded_at).from(nil).to(instance_of(ActiveSupport::TimeWithZone)) end end + + describe "#publish_creation_event" do + let_it_be(:project) { create(:project) } + + let(:version) { '-' } + let(:package_type) { :generic } + + subject { described_class.create!(project: project, name: 'incoming', version: version, package_type: package_type) } + + context 'when package is generic' do + it 'publishes an event' do + expect { subject } + .to publish_event(::Packages::PackageCreatedEvent) + .with({ + project_id: project.id, + id: kind_of(Numeric), + name: "incoming", + version: "-", + package_type: 'generic' + }) + end + end + + context 'when package is not generic' do + let(:package_type) { :debian } + let(:version) { 1 } + + it 'does not create event' do + expect { subject }.not_to publish_event(::Packages::PackageCreatedEvent) + end + end + end end |