diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-19 14:01:45 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-19 14:01:45 +0300 |
commit | 9297025d0b7ddf095eb618dfaaab2ff8f2018d8b (patch) | |
tree | 865198c01d1824a9b098127baa3ab980c9cd2c06 /spec/lib/gitlab/circuit_breaker/store_spec.rb | |
parent | 6372471f43ee03c05a7c1f8b0c6ac6b8a7431dbe (diff) |
Add latest changes from gitlab-org/gitlab@16-7-stable-eev16.7.0-rc42
Diffstat (limited to 'spec/lib/gitlab/circuit_breaker/store_spec.rb')
-rw-r--r-- | spec/lib/gitlab/circuit_breaker/store_spec.rb | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/spec/lib/gitlab/circuit_breaker/store_spec.rb b/spec/lib/gitlab/circuit_breaker/store_spec.rb new file mode 100644 index 00000000000..1b1983d4b52 --- /dev/null +++ b/spec/lib/gitlab/circuit_breaker/store_spec.rb @@ -0,0 +1,201 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::CircuitBreaker::Store, :clean_gitlab_redis_rate_limiting, feature_category: :ai_abstraction_layer do + let(:key) { 'key-1' } + let(:value) { 'value' } + let(:circuit_store) { described_class.new } + + shared_examples 'reliable circuit breaker store method' do + it 'does not raise an error when Redis::BaseConnectionError is encountered' do + allow(Gitlab::Redis::RateLimiting) + .to receive(:with) + .and_raise(Redis::BaseConnectionError) + + expect { subject }.not_to raise_error + end + end + + describe '#key?' do + subject(:key?) { circuit_store.key?(key) } + + it_behaves_like 'reliable circuit breaker store method' + + context 'when key exists' do + before do + circuit_store.store(key, value) + end + + it { is_expected.to eq(true) } + end + + context 'when key does not exist' do + it { is_expected.to eq(false) } + end + end + + describe '#store' do + let(:options) { {} } + + subject(:store) { circuit_store.store(key, value, options) } + + it_behaves_like 'reliable circuit breaker store method' + + it 'stores value for specified key without expiry by default' do + expect(store).to eq(value) + + with_redis do |redis| + expect(redis.get(key)).to eq(value) + expect(redis.ttl(key)).to eq(-1) + end + end + + context 'when expires option is set' do + let(:options) { { expires: 10 } } + + it 'stores value for specified key with expiry' do + expect(store).to eq(value) + + with_redis do |redis| + expect(redis.get(key)).to eq(value) + expect(redis.ttl(key)).to eq(10) + end + end + end + end + + describe '#increment' do + let(:options) { {} } + + subject(:increment) { circuit_store.increment(key, 1, options) } + + it_behaves_like 'reliable circuit breaker store method' + + context 'when key does not exist' do + it 'sets key and increments value' do + increment + + with_redis do |redis| + expect(redis.get(key).to_i).to eq(1) + expect(redis.ttl(key)).to eq(-1) + end + end + + context 'with expiry' do + let(:options) { { expires: 10 } } + + it 'sets key and increments value with expiration' do + increment + + with_redis do |redis| + expect(redis.get(key).to_i).to eq(1) + expect(redis.ttl(key)).to eq(10) + end + end + end + end + + context 'when key exists' do + before do + circuit_store.store(key, 1) + end + + it 'increments value' do + increment + + with_redis do |redis| + expect(redis.get(key).to_i).to eq(2) + expect(redis.ttl(key)).to eq(-1) + end + end + + context 'with expiry' do + let(:options) { { expires: 10 } } + + it 'increments value with expiration' do + increment + + with_redis do |redis| + expect(redis.get(key).to_i).to eq(2) + expect(redis.ttl(key)).to eq(10) + end + end + end + end + end + + describe '#load' do + subject(:load) { circuit_store.load(key) } + + it_behaves_like 'reliable circuit breaker store method' + + context 'when key exists' do + before do + circuit_store.store(key, value) + end + + it 'returns the value of the key' do + expect(load).to eq(value) + end + end + + context 'when key does not exist' do + it 'returns nil' do + expect(load).to be_nil + end + end + end + + describe '#values_at' do + let(:other_key) { 'key-2' } + let(:other_value) { 'value-2' } + + subject(:values_at) { circuit_store.values_at(key, other_key) } + + it_behaves_like 'reliable circuit breaker store method' + + context 'when keys exist' do + before do + circuit_store.store(key, value) + circuit_store.store(other_key, other_value) + end + + it 'returns values of keys' do + expect(values_at).to match_array([value, other_value]) + end + end + + context 'when some keys do not exist' do + before do + circuit_store.store(key, value) + end + + it 'returns values of keys with nil for non-existing ones' do + expect(values_at).to match_array([value, nil]) + end + end + end + + describe '#delete' do + subject(:delete) { circuit_store.delete(key) } + + before do + circuit_store.store(key, value) + end + + it_behaves_like 'reliable circuit breaker store method' + + it 'deletes key' do + delete + + with_redis do |redis| + expect(redis.exists?(key)).to eq(false) + end + end + end + + def with_redis(&block) + Gitlab::Redis::RateLimiting.with(&block) + end +end |