gitlab-ce/spec/workers/members/prune_deletions_worker_spec.rb

151 lines
4.4 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Members::PruneDeletionsWorker, :saas, feature_category: :seat_cost_management do
let(:worker) { described_class.new }
describe '#perform_work' do
subject(:perform_work) { worker.perform_work }
context 'with Members::DeletionSchedule records' do
let_it_be(:group) { create(:group) }
let_it_be(:owner) { create(:user) }
let_it_be(:user) { create(:user) }
before_all do
group.add_owner(owner)
group.add_developer(user)
create(:members_deletion_schedules, user: user, namespace: group, scheduled_by: owner)
end
it_behaves_like 'an idempotent worker' do
it 'destroys member records' do
expect do
perform_work
end.to change { group.members.count }.from(2).to(1)
end
context 'with many deletion schedules' do
it 'prunes schedules in batches' do
stub_const "Members::PruneDeletionsWorker::SCHEDULE_BATCH_SIZE", 5
create_list(:members_deletion_schedules, 10)
expect { perform_work }.to change { Members::DeletionSchedule.count }.from(11).to(6)
end
end
context 'with batches of memberships to destroy' do
before do
stub_const "Members::PruneDeletionsWorker::MEMBER_BATCH_SIZE", 1
create(:group, parent: group, owners: user)
end
it 'limits how many members are deleted per worker' do
expect(::Members::DestroyService).to receive(:new).exactly(1).time.and_call_original
perform_work
end
it 'logs monitoring data' do
allow(Gitlab::AppLogger).to receive(:info)
expect(Gitlab::AppLogger).to receive(:info).with(
message: 'Processed scheduled member deletion',
user_id: user.id,
namespace_id: group.id,
destroyed_count: 1,
destroy_duration_s: an_instance_of(Float)
)
perform_work
end
end
context 'when all matching member records are removed' do
let_it_be(:project) { create(:project, group: group) }
before_all do
project.add_developer(user)
end
it 'removes the Members::DeletionSchedule record' do
expect do
perform_work
end.to change { group.members.count }.from(2).to(1)
.and change { project.members.count }.from(1).to(0)
.and change { Members::DeletionSchedule.count }.from(1).to(0)
end
end
context 'when deletion takes too long' do
before do
allow_next_instance_of(Gitlab::Utils::ExecutionTracker) do |instance|
allow(instance).to receive(:over_limit?).and_return(true)
end
end
it 'returns early' do
expect(::Members::DestroyService).not_to receive(:new)
perform_work
end
end
end
end
context 'with no Members::DeletionSchedule records' do
it 'returns early' do
expect(::Members::DestroyService).not_to receive(:new)
perform_work
end
end
context 'when the scheduler does not have permission to remove the user' do
before do
group = create(:group)
user = create(:user)
other_user = create(:user)
group.add_owner(user)
create(:members_deletion_schedules, user: user, namespace: group, scheduled_by: other_user)
end
it 'deletes the schedule and does not remove the user' do
expect do
perform_work
end.to change { Members::DeletionSchedule.count }.from(1).to(0)
.and not_change { GroupMember.count }
end
end
end
describe '#max_running_jobs' do
subject { worker.max_running_jobs }
it { is_expected.to eq(described_class::MAX_RUNNING_JOBS) }
end
describe '#remaining_work_count' do
let_it_be(:deletion_schedules) do
create_list(:members_deletion_schedules, 2)
end
subject(:remaining_work_count) { worker.remaining_work_count }
context 'when there is remaining work' do
it { is_expected.to eq(described_class::MAX_RUNNING_JOBS + 1) }
end
context 'when there is no remaining work' do
before do
Members::DeletionSchedule.delete_all
end
it { is_expected.to eq(0) }
end
end
end