File: lru_cache_spec.rb

package info (click to toggle)
ruby-puppet-forge 5.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,196 kB
  • sloc: ruby: 2,397; makefile: 3
file content (149 lines) | stat: -rw-r--r-- 4,378 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
require 'spec_helper'

describe PuppetForge::LruCache do
  it 'creates a cache key from a list of strings' do
    expect { subject.class.new_key('foo', 'bar', 'baz') }.not_to raise_error 
  end

  it 'creates a new instance' do
    expect { PuppetForge::LruCache.new(1) }.not_to raise_error
  end

  it 'raises an error if max_size is not a positive integer' do
    expect { PuppetForge::LruCache.new(-1) }.to raise_error(ArgumentError)
    expect { PuppetForge::LruCache.new(0) }.to raise_error(ArgumentError)
    expect { PuppetForge::LruCache.new(1.5) }.to raise_error(ArgumentError)
  end

  it 'defaults to a max_size of 30' do
    expect(PuppetForge::LruCache.new.max_size).to eq(30)
  end

  it 'allows max_size to be set via the max_size parameter' do
    expect(PuppetForge::LruCache.new(42).max_size).to eq(42)
  end

  it 'provides a #get method' do
    expect(PuppetForge::LruCache.new).to respond_to(:get)
  end

  it 'provides a #put method' do
    expect(PuppetForge::LruCache.new).to respond_to(:put)
  end

  it 'provides a #clear method' do
    expect(PuppetForge::LruCache.new).to respond_to(:clear)
  end

  context 'with environment variables' do
    around(:each) do |example|
      @old_max_size = ENV['PUPPET_FORGE_MAX_CACHE_SIZE']
      ENV['PUPPET_FORGE_MAX_CACHE_SIZE'] = '42'
      example.run
      ENV['PUPPET_FORGE_MAX_CACHE_SIZE'] = @old_max_size
    end

    it 'uses the value of the PUPPET_FORGE_MAX_CACHE_SIZE environment variable if present' do
      expect(PuppetForge::LruCache.new.max_size).to eq(42)
    end
  end

  context '#get' do
    it 'returns nil if the key is not present in the cache' do
      expect(PuppetForge::LruCache.new.get('foo')).to be_nil
    end

    it 'returns the cached value for the given key' do
      cache = PuppetForge::LruCache.new
      cache.put('foo', 'bar')
      expect(cache.get('foo')).to eq('bar')
    end

    it 'moves the key to the front of the LRU list' do
      cache = PuppetForge::LruCache.new
      cache.put('foo', 'bar')
      cache.put('baz', 'qux')
      cache.get('foo')
      expect(cache.send(:lru)).to eq(['foo', 'baz'])
    end

    it 'is thread-safe for get calls' do
      cache = PuppetForge::LruCache.new
    
      # Populate the cache with initial values
      cache.put('foo', 'bar')
      cache.put('baz', 'qux')
    
      # Create two threads for concurrent cache get operations
      thread_one = Thread.new do
        100.times { expect(cache.get('foo')).to eq('bar') }
      end
    
      thread_two = Thread.new do
        100.times { expect(cache.get('baz')).to eq('qux') }
      end
    
      # Wait for both threads to complete
      thread_one.join
      thread_two.join
    end    
  end

  context '#put' do
    it 'adds the key to the front of the LRU list' do
      cache = PuppetForge::LruCache.new
      cache.put('foo', 'bar')
      expect(cache.send(:lru)).to eq(['foo'])
    end

    it 'adds the value to the cache' do
      cache = PuppetForge::LruCache.new
      cache.put('foo', 'bar')
      expect(cache.send(:cache)).to eq({ 'foo' => 'bar' })
    end

    it 'removes the least recently used item if the cache is full' do
      cache = PuppetForge::LruCache.new(2)
      cache.put('foo', 'bar')
      cache.put('baz', 'qux')
      cache.put('quux', 'corge')
      expect(cache.send(:lru)).to eq(['quux', 'baz'])
    end

    it 'is thread-safe' do
      cache = PuppetForge::LruCache.new
    
      # Create two threads for concurrent cache operations
      thread_one = Thread.new do
        100.times { cache.put('foo', 'bar') }
      end
    
      thread_two = Thread.new do
        100.times { cache.put('baz', 'qux') }
      end
    
      # Wait for both threads to complete
      thread_one.join
      thread_two.join
    
      # At this point, we don't need to compare the LRU list,
      # because the order may change due to concurrent puts.
      
      # Instead, we simply expect the code to run without errors.
      expect { thread_one.value }.not_to raise_error
      expect { thread_two.value }.not_to raise_error
    end
    
  end

  context '#clear' do
    it 'clears the cache' do
      cache = PuppetForge::LruCache.new
      cache.put('foo', 'bar')
      cache.put('baz', 'qux')
      cache.clear
      expect(cache.send(:lru).empty?).to be_truthy
      expect(cache.send(:cache).empty?).to be_truthy
    end
  end
end