diff options
Diffstat (limited to 'spec/lib/gitlab/cache/client_spec.rb')
-rw-r--r-- | spec/lib/gitlab/cache/client_spec.rb | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/spec/lib/gitlab/cache/client_spec.rb b/spec/lib/gitlab/cache/client_spec.rb new file mode 100644 index 00000000000..638fed1a905 --- /dev/null +++ b/spec/lib/gitlab/cache/client_spec.rb @@ -0,0 +1,162 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management do + subject(:client) { described_class.new(metadata, backend: backend) } + + let(:backend) { Rails.cache } + let(:metadata) do + Gitlab::Cache::Metadata.new( + cache_identifier: cache_identifier, + feature_category: feature_category, + backing_resource: backing_resource + ) + end + + let(:cache_identifier) { 'MyClass#cache' } + let(:feature_category) { :source_code_management } + let(:backing_resource) { :cpu } + + let(:metadata_mock) do + Gitlab::Cache::Metadata.new( + cache_identifier: cache_identifier, + feature_category: feature_category + ) + end + + let(:metrics_mock) { Gitlab::Cache::Metrics.new(metadata_mock) } + + describe '.build_with_metadata' do + it 'builds a cache client with metrics support' do + attributes = { + cache_identifier: cache_identifier, + feature_category: feature_category, + backing_resource: backing_resource + } + + instance = described_class.build_with_metadata(**attributes) + + expect(instance).to be_a(described_class) + expect(instance.metadata).to have_attributes(**attributes) + end + end + + describe 'Methods', :use_clean_rails_memory_store_caching do + let(:expected_key) { 'key' } + + before do + allow(Gitlab::Cache::Metrics).to receive(:new).and_return(metrics_mock) + end + + describe '#read' do + context 'when key does not exist' do + it 'returns nil' do + expect(client.read('key')).to be_nil + end + + it 'increments cache miss' do + expect(metrics_mock).to receive(:increment_cache_miss) + + client.read('key') + end + end + + context 'when key exists' do + before do + backend.write(expected_key, 'value') + end + + it 'returns key value' do + expect(client.read('key')).to eq('value') + end + + it 'increments cache hit' do + expect(metrics_mock).to receive(:increment_cache_hit) + + client.read('key') + end + end + end + + describe '#write' do + it 'calls backend "#write" method with the expected key' do + expect(backend).to receive(:write).with(expected_key, 'value') + + client.write('key', 'value') + end + end + + describe '#exist?' do + it 'calls backend "#exist?" method with the expected key' do + expect(backend).to receive(:exist?).with(expected_key) + + client.exist?('key') + end + end + + describe '#delete' do + it 'calls backend "#delete" method with the expected key' do + expect(backend).to receive(:delete).with(expected_key) + + client.delete('key') + end + end + + # rubocop:disable Style/RedundantFetchBlock + describe '#fetch' do + it 'creates key in the specific format' do + client.fetch('key') { 'value' } + + expect(backend.fetch(expected_key)).to eq('value') + end + + it 'yields the block once' do + expect { |b| client.fetch('key', &b) }.to yield_control.once + end + + context 'when key already exists' do + before do + backend.write(expected_key, 'value') + end + + it 'does not redefine the value' do + expect(client.fetch('key') { 'new-value' }).to eq('value') + end + + it 'increments a cache hit' do + expect(metrics_mock).to receive(:increment_cache_hit) + + client.fetch('key') + end + + it 'does not measure the cache generation time' do + expect(metrics_mock).not_to receive(:observe_cache_generation) + + client.fetch('key') { 'new-value' } + end + end + + context 'when key does not exist' do + it 'caches the key' do + expect(client.fetch('key') { 'value' }).to eq('value') + + expect(client.fetch('key')).to eq('value') + end + + it 'increments a cache miss' do + expect(metrics_mock).to receive(:increment_cache_miss) + + client.fetch('key') + end + + it 'measures the cache generation time' do + expect(metrics_mock).to receive(:observe_cache_generation) + + client.fetch('key') { 'value' } + end + end + end + end + # rubocop:enable Style/RedundantFetchBlock +end |