lrucache 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Guardfile CHANGED
@@ -10,5 +10,6 @@ guard 'rspec', :cli => '-c --format documentation -r ./spec/spec_helper.rb',
10
10
  :version => 2 do
11
11
  watch(%r{^spec/.+_spec\.rb})
12
12
  watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
+ watch('lib/lrucache.rb') { "spec/lrucache_spec.rb" }
13
14
  watch('spec/spec_helper.rb') { "spec" }
14
15
  end
data/README.md CHANGED
@@ -21,7 +21,7 @@ Example
21
21
 
22
22
  TTL (time-to-live)
23
23
  ==================
24
- cache = LRUCache.new(:expires => 1.hour)
24
+ cache = LRUCache.new(:ttl => 1.hour)
25
25
  cache.store("banana", "yellow")
26
26
  cache.store("monkey", "banana", Time.now + 3.days)
27
27
  # or ...
data/lib/lrucache.rb CHANGED
@@ -4,13 +4,14 @@ require "priority_queue"
4
4
  # Not thread-safe!
5
5
  class LRUCache
6
6
 
7
- attr_reader :default, :max_size
7
+ attr_reader :default, :max_size, :ttl
8
8
 
9
9
  def initialize(opts={})
10
- @max_size = (opts[:max_size] || 100).to_i
10
+ @max_size = Integer(opts[:max_size] || 100)
11
11
  @default = opts[:default]
12
- @expires = (opts[:expires] || 0).to_f
13
- raise "max_size must be greather than zero" unless @max_size > 0
12
+ @ttl = Float(opts[:ttl] || 0)
13
+ raise "max_size must be greater than zero" unless @max_size > 0
14
+ raise "ttl must be positive or zero" unless @ttl >= 0
14
15
  @pqueue = PriorityQueue.new
15
16
  @data = {}
16
17
  @counter = 0
@@ -19,6 +20,7 @@ class LRUCache
19
20
  def clear
20
21
  @data.clear
21
22
  @pqueue.delete_min until @pqueue.empty?
23
+ @counter = 0 #might as well
22
24
  end
23
25
 
24
26
  def include?(key)
@@ -34,38 +36,48 @@ class LRUCache
34
36
  end
35
37
  end
36
38
 
37
- def store(key, value, expires=nil)
38
- expire_lru! unless @data.include?(key) || @data.size < @max_size
39
- expiration =
40
- if expires.nil?
41
- (@expires > 0) ? (Time.now + @expires) : nil
42
- elsif expires.is_a?(Time)
43
- expires
39
+ def store(key, value, ttl=nil)
40
+ evict_lru! unless @data.include?(key) || @data.size < @max_size
41
+ ttl ||= @ttl
42
+ expires =
43
+ if ttl.is_a?(Time)
44
+ ttl
44
45
  else
45
- expires = expires.to_f
46
- (expires > 0) ? (Time.now + expires) : nil
46
+ ttl = Float(ttl)
47
+ (ttl > 0) ? (Time.now + ttl) : nil
47
48
  end
48
- @data[key] = [value, expiration]
49
+ @data[key] = [value, expires]
49
50
  access(key)
50
51
  end
51
52
 
52
53
  alias :[]= :store
53
54
 
54
- def fetch(key)
55
+ def fetch(key, ttl=nil)
55
56
  datum = @data[key]
56
- return @default if datum.nil?
57
- value, expires = datum
58
- if expires.nil? || expires > Time.now # no expiration, or not expired
59
- access(key)
57
+ unless datum.nil?
58
+ value, expires = datum
59
+ if expires.nil? || expires > Time.now # no expiration, or not expired
60
+ access(key)
61
+ return value
62
+ else # expired
63
+ delete(key)
64
+ end
65
+ end
66
+ if block_given?
67
+ value = yield
68
+ store(key, value, ttl)
60
69
  value
61
- else # expired
62
- delete(key)
70
+ else
63
71
  @default
64
72
  end
65
73
  end
66
74
 
67
75
  alias :[] :fetch
68
76
 
77
+ def empty?
78
+ size == 0
79
+ end
80
+
69
81
  def size
70
82
  @data.size
71
83
  end
@@ -75,13 +87,13 @@ class LRUCache
75
87
  end
76
88
 
77
89
  def delete(key)
78
- @data.delete(key)
79
90
  @pqueue.delete(key)
91
+ @data.delete(key)
80
92
  end
81
93
 
82
94
  private
83
95
 
84
- def expire_lru!
96
+ def evict_lru!
85
97
  key, priority = @pqueue.delete_min
86
98
  @data.delete(key) unless priority.nil?
87
99
  end
@@ -1,3 +1,3 @@
1
1
  class LRUCache
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,102 +1,471 @@
1
1
  describe LRUCache do
2
- it "should never exceed its max_size" do
3
- c = LRUCache.new(:max_size => 7)
4
- (1..100).each do |i|
5
- c[i] = rand(2**16)
6
- c.size.should <= 7
2
+ describe ".new" do
3
+
4
+ it "should default :max_size to 100" do
5
+ LRUCache.new.max_size.should == 100
6
+ end
7
+ it "should accept a :max_size parameter" do
8
+ LRUCache.new(:max_size => 7).max_size.should == 7
9
+ end
10
+ it "should raise an exception if :max_size parameter can't be converted to an integer" do
11
+ expect { LRUCache.new(:max_size => "moocow") }.to raise_exception
12
+ end
13
+ it "should raise an exception if :max_size parameter is converted to a negative integer" do
14
+ expect { LRUCache.new(:max_size => -1) }.to raise_exception
15
+ end
16
+
17
+ it "should default :default to nil" do
18
+ LRUCache.new.default.should be_nil
19
+ end
20
+ it "should accept a :default parameter" do
21
+ default = double(:default)
22
+ LRUCache.new(:default => default).default.should == default
23
+ end
24
+
25
+ it "should default :ttl to 0 (no expiration)" do
26
+ LRUCache.new.ttl.should == 0
27
+ end
28
+ it "should accept a :ttl parameter" do
29
+ LRUCache.new(:ttl => 98.6).ttl.should == 98.6
30
+ end
31
+ it "should raise an exception if :ttl parameter can't be converted to a float" do
32
+ expect { LRUCache.new(:ttl => "moocow") }.to raise_exception
33
+ end
34
+ it "should raise an exception if :ttl parameter is converted to a negative float" do
35
+ expect { LRUCache.new(:ttl => -1) }.to raise_exception
36
+ end
37
+
38
+ it "should initially be empty" do
39
+ LRUCache.new.should be_empty
7
40
  end
8
- c.size.should == 7
9
41
  end
10
42
 
11
- it "should expire the eldest entries first" do
12
- c = LRUCache.new(:max_size => 3)
13
- c[1] = 'a'
14
- c[2] = 'b'
15
- c[3] = 'c'
16
- c[2].should == 'b'
17
- c[1].should == 'a'
18
- c[3].should == 'c'
19
- c[4] = 'd' # Out of space! Throws out the least-recently used (2 => 'b').
20
- c.keys.sort.should == [1,3,4]
21
- c[5] = 'e'
22
- c.keys.sort.should == [3,4,5]
23
- c[1] = 'a'
24
- c.keys.sort.should == [1,4,5]
43
+ describe ".clear" do
44
+ it "should empty the hash and the priority queue" do
45
+ c = LRUCache.new
46
+ 10.times { c[rand(2**16)] = :x }
47
+ c.should_not be_empty
48
+ c.instance_variable_get(:@data).should_not be_empty
49
+ c.instance_variable_get(:@pqueue).should_not be_empty
50
+
51
+ c.clear
52
+
53
+ c.should be_empty
54
+ c.instance_variable_get(:@data).should be_empty
55
+ c.instance_variable_get(:@pqueue).should be_empty
56
+ end
25
57
  end
26
58
 
27
- it "should return the default value for expired and non-existent entries" do
28
- default = double(:default)
29
- c = LRUCache.new(:max_size => 3, :default => default)
30
- c[:a].should == default
31
- c[:a] = 'a'
32
- c[:a].should == 'a'
33
- c[:b] = 'b'
34
- c[:c] = 'c'
35
- c[:d] = 'd'
36
- c[:a].should == default
59
+ describe ".include?(key)" do
60
+ before(:each) { @cache = LRUCache.new }
61
+ context "when the key is not present" do
62
+ it "should return false" do
63
+ @cache.include?(:a).should be_false
64
+ end
65
+ it "should not affect priorities" do
66
+ @cache.should_not_receive(:access)
67
+ @cache.include?(:a)
68
+ end
69
+ end
70
+ context "when the key is present, but the value has expired" do
71
+ before(:each) do
72
+ now = Time.now
73
+ Timecop.freeze(now) { @cache.store(:a, 'a', now + 10) }
74
+ Timecop.freeze(now + 20)
75
+ end
76
+ after(:each) do
77
+ Timecop.return
78
+ end
79
+ it "should return false" do
80
+ @cache.include?(:a).should be_false
81
+ end
82
+ it "should delete the key" do
83
+ @cache.should_receive(:delete).with(:a)
84
+ @cache.include?(:a)
85
+ end
86
+ it "should not affect priorities" do
87
+ @cache.should_not_receive(:access)
88
+ @cache.include?(:a)
89
+ end
90
+ end
91
+ context "when the key is present, and the value has no expiration" do
92
+ before(:each) do
93
+ @cache.store(:a, 'a', nil)
94
+ end
95
+ it "should return true" do
96
+ @cache.include?(:a).should be_true
97
+ end
98
+ it "should update the key's access stamp" do
99
+ @cache.should_receive(:access).with(:a)
100
+ @cache.include?(:a)
101
+ end
102
+ end
103
+ context "when the key is present, and the value has not yet expired" do
104
+ before(:each) do
105
+ now = Time.now
106
+ Timecop.freeze(now)
107
+ @cache.store(:a, 'a', now + 10)
108
+ end
109
+ after(:each) do
110
+ Timecop.return
111
+ end
112
+ it "should return true" do
113
+ @cache.include?(:a).should be_true
114
+ end
115
+ it "should update the key's access stamp" do
116
+ @cache.should_receive(:access).with(:a)
117
+ @cache.include?(:a)
118
+ end
119
+ end
37
120
  end
38
121
 
39
- it "should honor TTL" do
40
- c = LRUCache.new(:expires => 20)
41
- now = Time.now
42
- Timecop.freeze(now) do
43
- c.store(:a, 'a')
44
- c.store(:b, 'b', now + 50)
45
- c.store(:c, 'c', 50)
46
- c[:a].should == 'a'
47
- c[:b].should == 'b'
48
- c[:c].should == 'c'
49
- c.size.should == 3
50
- end
51
- Timecop.freeze(now + 19) do
52
- c[:a].should == 'a'
53
- c[:b].should == 'b'
54
- c[:c].should == 'c'
55
- c.size.should == 3
56
- end
57
- Timecop.freeze(now + 49) do
58
- c[:a].should be_nil
59
- c[:b].should == 'b'
60
- c[:c].should == 'c'
61
- c.size.should == 2
62
- end
63
- Timecop.freeze(now + 50) do
64
- c[:a].should be_nil
65
- c[:b].should be_nil
66
- c[:c].should be_nil
67
- c.size.should == 0
122
+ describe ".store(key, value, ttl=nil)" do
123
+ context "regarding evictions" do
124
+ before(:each) do
125
+ @cache = LRUCache.new(:max_size => 2)
126
+ end
127
+ context "when the cache is not full" do
128
+ context "and the key is not present" do
129
+ it "should not evict an entry" do
130
+ @cache.should_not_receive(:evict_lru!)
131
+ @cache.store(:a, 'a')
132
+ end
133
+ it "should store the value" do
134
+ @cache.store(:a, 'a')
135
+ @cache.fetch(:a).should == 'a'
136
+ end
137
+ it "should update the key's access stamp" do
138
+ @cache.should_receive(:access).with(:a)
139
+ @cache.store(:a, 'a')
140
+ end
141
+ end
142
+ context "and the key is present" do
143
+ it "should not evict an entry" do
144
+ @cache.should_not_receive(:evict_lru!)
145
+ @cache.store(:a, 'a')
146
+ end
147
+ it "should store the value" do
148
+ @cache.store(:a, 'a')
149
+ @cache.fetch(:a).should == 'a'
150
+ end
151
+ it "should update the key's access stamp" do
152
+ @cache.should_receive(:access).with(:a)
153
+ @cache.store(:a, 'a')
154
+ end
155
+ end
156
+ end
157
+ context "when the cache is full" do
158
+ before(:each) do
159
+ @cache = LRUCache.new(:max_size => 2)
160
+ @cache[:b] = 'b'
161
+ @cache[:c] = 'c'
162
+ @lru = :b
163
+ end
164
+ context "and the key is not present" do
165
+ it "should evict the least-recently used entry from the cache" do
166
+ @cache.keys.should include(@lru)
167
+ @cache.store(:a, 'a')
168
+ @cache.keys.should_not include(@lru)
169
+ end
170
+ it "should store the value" do
171
+ @cache.store(:a, 'a')
172
+ @cache.fetch(:a).should == 'a'
173
+ end
174
+ it "should update the key's access stamp" do
175
+ @cache.should_receive(:access).with(:a)
176
+ @cache.store(:a, 'a')
177
+ end
178
+ end
179
+ context "and the key is present" do
180
+ it "should not evict an entry" do
181
+ @cache.should_not_receive(:evict_lru!)
182
+ @cache.store(:c, 'c')
183
+ end
184
+ it "should store the value" do
185
+ @cache.store(:c, 'c')
186
+ @cache.fetch(:c).should == 'c'
187
+ end
188
+ it "should update the key's access stamp" do
189
+ @cache.should_receive(:access).with(:c)
190
+ @cache.store(:c, 'c')
191
+ end
192
+ end
193
+ end
194
+ end
195
+ context "when ttl is not given and the cache's default ttl is zero" do
196
+ it "should set the entry with no expiration time" do
197
+ c = LRUCache.new(:ttl => 0)
198
+ c.store(:a,'a')
199
+ stored = c.instance_variable_get(:@data)[:a]
200
+ stored.should == ['a', nil]
201
+ end
202
+ end
203
+ context "when ttl is not given and the cache's default ttl is greater than zero" do
204
+ it "should set the entry to expire that many seconds in the future" do
205
+ c = LRUCache.new(:ttl => 1)
206
+ now = Time.now
207
+ Timecop.freeze(now) { c.store(:a,'a') }
208
+ stored = c.instance_variable_get(:@data)[:a]
209
+ stored.last.should == now + 1
210
+ end
211
+ end
212
+ context "when ttl is a Time" do
213
+ it "should set the entry to expire at the given time" do
214
+ c = LRUCache.new
215
+ ttl = Time.now + 246
216
+ c.store(:a, 'a', ttl)
217
+ stored = c.instance_variable_get(:@data)[:a]
218
+ stored.last.should == ttl
219
+ end
220
+ end
221
+ context "when ttl can be parsed as a float" do
222
+ it "should set the entry to expire that many seconds in the future" do
223
+ c = LRUCache.new
224
+ now = Time.now
225
+ Timecop.freeze(now) { c.store(:a, 'a', "98.6") }
226
+ stored = c.instance_variable_get(:@data)[:a]
227
+ stored.last.should == now + 98.6
228
+ end
229
+ end
230
+ context "when ttl cannot be parsed as a float" do
231
+ it "should raise an exception" do
232
+ c = LRUCache.new
233
+ expect { c.store(:a, 'a', "moocow") }.to raise_exception
234
+ end
68
235
  end
69
- c[:a].should be_nil
70
- c[:b].should be_nil
71
- c[:c].should be_nil
72
- c.size.should == 0
73
236
  end
74
237
 
75
- it "should have a default max_size of 100" do
76
- LRUCache.new.max_size.should == 100
77
- LRUCache.new(:max_size => 82).max_size.should == 82
238
+ describe ".fetch(key, ttl=nil)" do
239
+ context "when no block is given" do
240
+ context "and the key does not exist" do
241
+ before(:each) do
242
+ @default = double(:default)
243
+ @cache = LRUCache.new(:default => @default)
244
+ end
245
+ it "should return the default value" do
246
+ @cache.fetch(:a).should == @default
247
+ end
248
+ it "should not affect the priorities" do
249
+ @cache.should_not_receive(:access)
250
+ @cache.fetch(:a)
251
+ end
252
+ end
253
+ context "and the key has been evicted" do
254
+ before(:each) do
255
+ @cache = LRUCache.new(:max_size => 2)
256
+ @cache[:a] = 'a'
257
+ @cache[:b] = 'b'
258
+ @cache[:c] = 'c'
259
+ end
260
+ it "should return the default value" do
261
+ @cache.fetch(:a).should == @default
262
+ end
263
+ it "should not affect the priorities" do
264
+ @cache.should_not_receive(:access)
265
+ @cache.fetch(:a)
266
+ end
267
+ end
268
+ context "and the key has expired" do
269
+ before(:each) do
270
+ @cache = LRUCache.new(:ttl => 10)
271
+ now = Time.now
272
+ Timecop.freeze(now) { @cache[:a] = 'a' }
273
+ Timecop.freeze(now + 20)
274
+ end
275
+ after(:each) do
276
+ Timecop.return
277
+ end
278
+ it "should return the default value" do
279
+ @cache.fetch(:a).should == @default
280
+ end
281
+ it "should not affect the priorities" do
282
+ @cache.should_not_receive(:access)
283
+ @cache.fetch(:a)
284
+ end
285
+ it "should delete the key" do
286
+ @cache.should_receive(:delete).with(:a)
287
+ @cache.fetch(:a)
288
+ end
289
+ end
290
+ context "and the key is present and un-expired" do
291
+ before(:each) do
292
+ @cache = LRUCache.new(:ttl => nil)
293
+ @cache[:a] = 'a'
294
+ end
295
+ it "should return the cached value" do
296
+ @cache.fetch(:a).should == 'a'
297
+ end
298
+ it "should update the key's access stamp" do
299
+ @cache.should_receive(:access).with(:a)
300
+ @cache.fetch(:a)
301
+ end
302
+ end
303
+ end
304
+ context "when a block is given" do
305
+ context "when the key does not exist" do
306
+ it "should call the block and store and return the result" do
307
+ c = LRUCache.new
308
+ ttl = double(:ttl)
309
+ result = double(:result)
310
+ c.should_receive(:store).with(:a, result, ttl)
311
+ c.fetch(:a, ttl){ result }.should == result
312
+ end
313
+ end
314
+ context "when the key has been evicted" do
315
+ it "should call the block and store and return the result" do
316
+ c = LRUCache.new
317
+ c[:a] = 'a'
318
+ c.send(:evict_lru!)
319
+ ttl = double(:ttl)
320
+ result = double(:result)
321
+ c.should_receive(:store).with(:a, result, ttl)
322
+ c.fetch(:a, ttl){ result }.should == result
323
+ end
324
+ end
325
+ context "when the key has expired" do
326
+ it "should call the block and store and return the result" do
327
+ c = LRUCache.new
328
+ now = Time.now
329
+ Timecop.freeze(now) { c.store(:a, 'a', now + 10) }
330
+ Timecop.freeze(now + 20) do
331
+ ttl = double(:ttl)
332
+ result = double(:result)
333
+ c.should_receive(:store).with(:a, result, ttl)
334
+ c.fetch(:a, ttl){ result }.should == result
335
+ end
336
+ end
337
+ end
338
+ context "when the key is present and un-expired" do
339
+ it "should return the cached value without calling the block" do
340
+ c = LRUCache.new(:ttl => nil)
341
+ c[:a] = 'a'
342
+ c.fetch(:a) { raise 'fail' }.should == 'a'
343
+ end
344
+ end
345
+ end
78
346
  end
79
347
 
80
- it "can be cleared" do
81
- c = LRUCache.new
82
- (1..100).each {|i| c[i] = rand(2**16)}
83
- c.size.should == 100
84
- c.clear
85
- c.size.should == 0
86
- c.keys.should == []
348
+ describe ".empty?" do
349
+ it "should return true if and only if size is zero" do
350
+ c = LRUCache.new
351
+ c.empty?.should be_true
352
+ c[:a] = 'a'
353
+ c.empty?.should be_false
354
+ c.clear
355
+ c.empty?.should be_true
356
+ end
87
357
  end
88
358
 
89
- describe ".include?(key)" do
90
- it "affects the access time of the key" do
91
- c = LRUCache.new(:max_size => 3)
359
+ describe ".size and .keys" do
360
+ it "should return a count / list of entries in the cache" do
361
+ c = LRUCache.new(:max_size => 10)
362
+ (1..10).each do |i|
363
+ c.size.should == i-1
364
+ c[i] = :x
365
+ c.size.should == i
366
+ c.keys.sort.should == (1..i).to_a
367
+ end
368
+ (1..3).each do |i|
369
+ c.delete(i)
370
+ c.size.should == 10 - i
371
+ c.keys.sort.should == ((i+1)..10).to_a
372
+ end
373
+ (1..3).each do |i|
374
+ c[i] = :x
375
+ c.size.should == 7+i
376
+ c.keys.sort.should == (1..i).to_a + (4..10).to_a
377
+ end
378
+ (1..10).each do |i|
379
+ c[i] = :x
380
+ c.size.should == 10
381
+ c.keys.sort.should == (1..10).to_a
382
+ end
383
+ c.clear
384
+ c.size.should == 0
385
+ c.keys.should == []
386
+ end
387
+ it "may include expired entries" do
388
+ c = LRUCache.new(:ttl => 10, :max_size => 100)
389
+ now = Time.now
390
+ (0..19).each do |i|
391
+ Timecop.freeze(now + i) do
392
+ c[i] = :x
393
+ c.size.should == i+1
394
+ c.keys.sort.should == (0..i).to_a
395
+ end
396
+ end
397
+ Timecop.freeze(now + 20) do
398
+ c.size.should == 20
399
+ (0..19).each do |i|
400
+ c.include?(i)
401
+ end
402
+ c.size.should == 9
403
+ c.keys.sort.should == (11..19).to_a
404
+ end
405
+ end
406
+ it "should always return a value less than or equal to the cache's max_size" do
407
+ c = LRUCache.new(:max_size => 7)
408
+ (1..100).each do |i|
409
+ c[i] = :x
410
+ c.size.should <= 7
411
+ end
412
+ end
413
+ end
414
+
415
+
416
+ describe ".delete(key)" do
417
+ it "should remove the key from the internal hash and priority queue" do
418
+ c = LRUCache.new
419
+ c[:a] = 'a'
420
+ c.instance_variable_get(:@data).should include(:a)
421
+ c.instance_variable_get(:@pqueue).should include([:a,1])
422
+ c.delete(:a)
423
+ c.instance_variable_get(:@data).should_not include(:a)
424
+ c.instance_variable_get(:@pqueue).should_not include([:a,1])
425
+ end
426
+ end
427
+
428
+ describe ".evict_lru!" do
429
+ it "should find the least-recently used entry, and delete it" do
430
+ c = LRUCache.new
92
431
  c[1] = 'a'
93
432
  c[2] = 'b'
94
433
  c[3] = 'c'
95
- c.include?(1).should be_true
96
434
  c[4] = 'd'
97
- c[5] = 'e'
98
- c.include?(1).should be_true
99
- c.include?(2).should be_false
435
+ c[:dne1].should be_nil # Doesn't affect LRU.
436
+ c[2].should == 'b'
437
+ c[1].should == 'a'
438
+ c[3].should == 'c'
439
+ c[4].should == 'd'
440
+ c[:dne2].should be_nil # Doesn't affect LRU.
441
+ c.keys.sort.should == [1,2,3,4]
442
+ c.send(:evict_lru!)
443
+ c.keys.sort.should == [1,3,4]
444
+ c.send(:evict_lru!)
445
+ c.keys.sort.should == [3,4]
446
+ c.send(:evict_lru!)
447
+ c.keys.sort.should == [4]
448
+ c.send(:evict_lru!)
449
+ c.keys.should == []
450
+ c.send(:evict_lru!)
451
+ c.keys.should == []
452
+ end
453
+ it "should leave the internal hash the same size as the priority queue" do
454
+ c = LRUCache.new
455
+ expected_size = 0
456
+ counter = 0
457
+ 100.times do
458
+ if rand < 0.8
459
+ c[counter += 1] = :x
460
+ expected_size += 1
461
+ else
462
+ c.send(:evict_lru!)
463
+ expected_size -= 1
464
+ end
465
+ expected_size = [expected_size,0].max
466
+ c.instance_variable_get(:@data).size.should == expected_size
467
+ c.instance_variable_get(:@pqueue).count.should == expected_size
468
+ end
100
469
  end
101
470
  end
102
471
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lrucache
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 0
9
8
  - 1
10
- version: 0.0.1
9
+ - 0
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chris Johnson