debian-mirror-gitlab/spec/services/packages/cleanup/execute_policy_service_spec.rb
2023-05-27 22:25:52 +05:30

163 lines
6.8 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::Cleanup::ExecutePolicyService, feature_category: :package_registry do
let_it_be(:project) { create(:project) }
let_it_be_with_reload(:policy) { create(:packages_cleanup_policy, project: project) }
let(:service) { described_class.new(policy) }
describe '#execute' do
subject(:execute) { service.execute }
context 'with the keep_n_duplicated_files parameter' do
let_it_be(:package1) { create(:package, project: project) }
let_it_be(:package2) { create(:package, project: project) }
let_it_be(:package3) { create(:package, project: project) }
let_it_be(:package4) { create(:package, :pending_destruction, project: project) }
let_it_be(:package_file1_1) { create(:package_file, package: package1, file_name: 'file_name1') }
let_it_be(:package_file1_2) { create(:package_file, package: package1, file_name: 'file_name1') }
let_it_be(:package_file1_3) { create(:package_file, package: package1, file_name: 'file_name1') }
let_it_be(:package_file1_4) { create(:package_file, package: package1, file_name: 'file_name2') }
let_it_be(:package_file1_5) { create(:package_file, package: package1, file_name: 'file_name2') }
let_it_be(:package_file1_6) { create(:package_file, package: package1, file_name: 'file_name2') }
let_it_be(:package_file1_7) do
create(:package_file, :pending_destruction, package: package1, file_name: 'file_name2')
end
let_it_be(:package_file2_1) { create(:package_file, package: package2, file_name: 'file_name1') }
let_it_be(:package_file2_2) { create(:package_file, package: package2, file_name: 'file_name1') }
let_it_be(:package_file2_3) { create(:package_file, package: package2, file_name: 'file_name1') }
let_it_be(:package_file2_4) { create(:package_file, package: package2, file_name: 'file_name1') }
let_it_be(:package_file3_1) { create(:package_file, package: package3, file_name: 'file_name_test') }
let_it_be(:package_file4_1) { create(:package_file, package: package4, file_name: 'file_name1') }
let_it_be(:package_file4_2) { create(:package_file, package: package4, file_name: 'file_name1') }
let(:package_files_1) { package1.package_files.installable }
let(:package_files_2) { package2.package_files.installable }
let(:package_files_3) { package3.package_files.installable }
context 'set to less than the total number of duplicated files' do
before do
# for each package file duplicate, we keep only the most recent one
policy.update!(keep_n_duplicated_package_files: '1')
end
shared_examples 'keeping the most recent package files' do
let(:response_payload) do
{
counts: {
marked_package_files_total_count: 7,
unique_package_id_and_file_name_total_count: 3
},
timeout: false
}
end
it 'only keeps the most recent package files' do
expect { execute }.to change { ::Packages::PackageFile.installable.count }.by(-7)
expect(package_files_1).to contain_exactly(package_file1_3, package_file1_6)
expect(package_files_2).to contain_exactly(package_file2_4)
expect(package_files_3).to contain_exactly(package_file3_1)
expect(execute).to be_success
expect(execute.message).to eq("Packages cleanup policy executed for project #{project.id}")
expect(execute.payload).to eq(response_payload)
end
end
it_behaves_like 'keeping the most recent package files'
context 'when the service needs to loop' do
before do
stub_const("#{described_class.name}::DUPLICATED_FILES_BATCH_SIZE", 2)
end
it_behaves_like 'keeping the most recent package files' do
before do
expect(::Packages::MarkPackageFilesForDestructionService)
.to receive(:new).exactly(3).times.and_call_original
end
end
context 'when a timeout is hit' do
let(:response_payload) do
{
counts: {
marked_package_files_total_count: 4,
unique_package_id_and_file_name_total_count: 3
},
timeout: true
}
end
let(:service_timeout_response) do
ServiceResponse.error(
message: 'Timeout while marking package files as pending destruction',
payload: { marked_package_files_count: 0 }
)
end
before do
mock_service_timeout(on_iteration: 3)
end
it 'keeps part of the most recent package files' do
expect { execute }
.to change { ::Packages::PackageFile.installable.count }.by(-4)
.and not_change { package_files_2.count } # untouched because of the timeout
.and not_change { package_files_3.count } # untouched because of the timeout
expect(package_files_1).to contain_exactly(package_file1_3, package_file1_6)
expect(execute).to be_success
expect(execute.message).to eq("Packages cleanup policy executed for project #{project.id}")
expect(execute.payload).to eq(response_payload)
end
def mock_service_timeout(on_iteration:)
execute_call_count = 1
expect_next_instances_of(::Packages::MarkPackageFilesForDestructionService, 3) do |service|
expect(service).to receive(:execute).and_wrap_original do |m, *args|
# timeout if we are on the right iteration
if execute_call_count == on_iteration
service_timeout_response
else
execute_call_count += 1
m.call(*args)
end
end
end
end
end
end
end
context 'set to more than the total number of duplicated files' do
before do
# using the biggest value for keep_n_duplicated_package_files
policy.update!(keep_n_duplicated_package_files: '50')
end
it 'keeps all package files' do
expect { execute }.not_to change { ::Packages::PackageFile.installable.count }
end
end
context 'set to all' do
before do
policy.update!(keep_n_duplicated_package_files: 'all')
end
it 'skips the policy' do
expect(::Packages::MarkPackageFilesForDestructionService).not_to receive(:new)
expect { execute }.not_to change { ::Packages::PackageFile.installable.count }
end
end
end
end
end