debian-mirror-gitlab/spec/services/protected_branches/cache_service_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

155 lines
4.8 KiB
Ruby
Raw Normal View History

2022-08-27 11:52:29 +05:30
# frozen_string_literal: true
# rubocop:disable Style/RedundantFetchBlock
#
require 'spec_helper'
2023-05-27 22:25:52 +05:30
RSpec.describe ProtectedBranches::CacheService, :clean_gitlab_redis_cache, feature_category: :compliance_management do
2023-03-04 22:38:38 +05:30
shared_examples 'execute with entity' do
subject(:service) { described_class.new(entity, user) }
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
let(:immediate_expiration) { 0 }
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
describe '#fetch' do
it 'caches the value' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
# Uses cached values
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
end
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
it 'sets expiry on the key' do
stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
2022-08-27 11:52:29 +05:30
end
2023-03-04 22:38:38 +05:30
it 'does not set an expiry on the key after the hash is already created' do
2022-08-27 11:52:29 +05:30
expect(service.fetch('main') { true }).to eq(true)
2023-03-04 22:38:38 +05:30
stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
2022-08-27 11:52:29 +05:30
expect(service.fetch('not-found') { false }).to eq(false)
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
2023-03-04 22:38:38 +05:30
end
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
context 'when CACHE_LIMIT is exceeded' do
before do
stub_const("#{described_class.name}::CACHE_LIMIT", 2)
end
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
it 'recreates cache' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
# Uses cached values
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
# Overflow
expect(service.fetch('new-branch') { true }).to eq(true)
# Refreshes values
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
end
2022-08-27 11:52:29 +05:30
end
2023-03-04 22:38:38 +05:30
context 'when dry_run is on' do
it 'does not use cached value' do
2022-08-27 11:52:29 +05:30
expect(service.fetch('main', dry_run: true) { true }).to eq(true)
2023-03-04 22:38:38 +05:30
expect(service.fetch('main', dry_run: true) { false }).to eq(false)
end
context 'when cache mismatch' do
it 'logs an error' do
expect(service.fetch('main', dry_run: true) { true }).to eq(true)
expect(Gitlab::AppLogger).to receive(:error).with(
{
'class' => described_class.name,
'message' => /Cache mismatch/,
'record_class' => entity.class.name,
'record_id' => entity.id,
'record_path' => entity.full_path
}
)
expect(service.fetch('main', dry_run: true) { false }).to eq(false)
end
end
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
context 'when cache matches' do
it 'does not log an error' do
expect(service.fetch('main', dry_run: true) { true }).to eq(true)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
expect(Gitlab::AppLogger).not_to receive(:error)
expect(service.fetch('main', dry_run: true) { true }).to eq(true)
end
2022-08-27 11:52:29 +05:30
end
end
2023-03-04 22:38:38 +05:30
end
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
describe '#refresh' do
it 'clears cached values' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
service.refresh
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
# Recreates cache
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
end
end
describe 'metrics' do
it 'records hit ratio metrics' do
expect_next_instance_of(Gitlab::Cache::Metrics) do |metrics|
expect(metrics).to receive(:increment_cache_miss).once
expect(metrics).to receive(:increment_cache_hit).exactly(4).times
2022-08-27 11:52:29 +05:30
end
2023-03-04 22:38:38 +05:30
5.times { service.fetch('main') { true } }
2022-08-27 11:52:29 +05:30
end
end
end
2023-03-04 22:38:38 +05:30
context 'with entity project' do
let_it_be_with_reload(:entity) { create(:project) }
let(:user) { entity.first_owner }
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
it_behaves_like 'execute with entity'
end
context 'with entity group' do
let_it_be_with_reload(:entity) { create(:group) }
let_it_be_with_reload(:user) { create(:user) }
2022-08-27 11:52:29 +05:30
2023-03-04 22:38:38 +05:30
before do
entity.add_owner(user)
2022-08-27 11:52:29 +05:30
end
2023-01-13 00:05:48 +05:30
2023-03-04 22:38:38 +05:30
context 'when feature flag enabled' do
it_behaves_like 'execute with entity'
end
context 'when feature flag disabled' do
before do
stub_feature_flags(group_protected_branches: false)
2023-01-13 00:05:48 +05:30
end
2023-03-04 22:38:38 +05:30
it_behaves_like 'execute with entity'
2023-01-13 00:05:48 +05:30
end
end
2022-08-27 11:52:29 +05:30
end
# rubocop:enable Style/RedundantFetchBlock