summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/cache/client_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/cache/client_spec.rb')
-rw-r--r--spec/lib/gitlab/cache/client_spec.rb162
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