From 833c162c3ddb1fc772c5d2fdb8fd353f27510448 Mon Sep 17 00:00:00 2001 From: Malik Parvez <84777619+malikparvez@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:31:24 +0530 Subject: [PATCH] Adding spec for thread safety --- spec/unit/forge/lru_cache_spec.rb | 66 ++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/spec/unit/forge/lru_cache_spec.rb b/spec/unit/forge/lru_cache_spec.rb index f33ddc5..380ea05 100644 --- a/spec/unit/forge/lru_cache_spec.rb +++ b/spec/unit/forge/lru_cache_spec.rb @@ -67,18 +67,26 @@ expect(cache.send(:lru)).to eq(['foo', 'baz']) end - # The below test is non-deterministic but I'm not sure how to unit - # test thread-safety. - # it 'is thread-safe' do - # cache = PuppetForge::LruCache.new - # cache.put('foo', 'bar') - # cache.put('baz', 'qux') - # threads = [] - # threads << Thread.new { 100.times { cache.get('foo') } } - # threads << Thread.new { 100.times { cache.get('baz') } } - # threads.each(&:join) - # expect(cache.send(:lru)).to eq(['baz', 'foo']) - # 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 @@ -102,16 +110,30 @@ expect(cache.send(:lru)).to eq(['quux', 'baz']) end - # The below test is non-deterministic but I'm not sure how to unit - # test thread-safety. - # it 'is thread-safe' do - # cache = PuppetForge::LruCache.new - # threads = [] - # threads << Thread.new { 100.times { cache.put('foo', 'bar') } } - # threads << Thread.new { 100.times { cache.put('baz', 'qux') } } - # threads.each(&:join) - # expect(cache.send(:lru)).to eq(['baz', 'foo']) - # 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