memcached_store 0.12.8 → 1.0.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.
- checksums.yaml +4 -4
- data/LICENSE +2 -2
- data/README.md +6 -2
- data/lib/active_support/cache/memcached_snappy_store.rb +6 -7
- data/lib/active_support/cache/memcached_store.rb +110 -78
- data/lib/memcached_store.rb +1 -1
- data/lib/memcached_store/version.rb +1 -1
- metadata +8 -22
- data/.gitignore +0 -20
- data/.travis.yml +0 -16
- data/Gemfile +0 -21
- data/Rakefile +0 -21
- data/lib/memcached_store/memcached_safety.rb +0 -88
- data/memcached_store.gemspec +0 -22
- data/shipit.rubygems.yml +0 -4
- data/test/test_helper.rb +0 -21
- data/test/test_memcached_safety.rb +0 -142
- data/test/test_memcached_snappy_store.rb +0 -172
- data/test/test_memcached_store.rb +0 -601
@@ -1,601 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
class TestMemcachedStore < ActiveSupport::TestCase
|
5
|
-
setup do
|
6
|
-
@cache = ActiveSupport::Cache.lookup_store(:memcached_store, expires_in: 60, support_cas: true)
|
7
|
-
@cache.clear
|
8
|
-
|
9
|
-
# Enable ActiveSupport notifications. Can be disabled in Rails 5.
|
10
|
-
Thread.current[:instrument_cache_store] = true
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_write_not_found
|
14
|
-
expect_not_found
|
15
|
-
assert_equal false, @cache.write('not_exist', 1)
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_fetch_not_found
|
19
|
-
expect_not_found
|
20
|
-
assert_equal nil, @cache.fetch('not_exist')
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_should_read_and_write_strings
|
24
|
-
assert @cache.write('foo', 'bar')
|
25
|
-
assert_equal 'bar', @cache.read('foo')
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_should_overwrite
|
29
|
-
@cache.write('foo', 'bar')
|
30
|
-
@cache.write('foo', 'baz')
|
31
|
-
assert_equal 'baz', @cache.read('foo')
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_fetch_without_cache_miss
|
35
|
-
@cache.write('foo', 'bar')
|
36
|
-
@cache.expects(:write).never
|
37
|
-
assert_equal 'bar', @cache.fetch('foo') { 'baz' }
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_fetch_with_cache_miss
|
41
|
-
@cache.expects(:write).with('foo', 'baz', @cache.options)
|
42
|
-
assert_equal 'baz', @cache.fetch('foo') { 'baz' }
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_fetch_with_forced_cache_miss
|
46
|
-
@cache.write('foo', 'bar')
|
47
|
-
@cache.expects(:read).never
|
48
|
-
@cache.expects(:write).with('foo', 'bar', @cache.options.merge(:force => true))
|
49
|
-
@cache.fetch('foo', :force => true) { 'bar' }
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_fetch_with_cached_nil
|
53
|
-
@cache.write('foo', nil)
|
54
|
-
@cache.expects(:write).never
|
55
|
-
assert_nil @cache.fetch('foo') { 'baz' }
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_cas
|
59
|
-
@cache.write('foo', nil)
|
60
|
-
assert @cache.cas('foo') {|value| assert_nil value; 'bar' }
|
61
|
-
assert_equal 'bar', @cache.read('foo')
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_cas_with_cache_miss
|
65
|
-
refute @cache.cas('not_exist') {|value| flunk }
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_cas_with_conflict
|
69
|
-
@cache.write('foo', 'bar')
|
70
|
-
refute @cache.cas('foo') {|value|
|
71
|
-
@cache.write('foo', 'baz')
|
72
|
-
'biz'
|
73
|
-
}
|
74
|
-
assert_equal 'baz', @cache.read('foo')
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_cas_multi_with_empty_set
|
78
|
-
refute @cache.cas_multi() {|hash| flunk }
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_cas_multi
|
82
|
-
@cache.write('foo', 'bar')
|
83
|
-
@cache.write('fud', 'biz')
|
84
|
-
assert @cache.cas_multi('foo', 'fud') {|hash| assert_equal({"foo" => "bar", "fud" => "biz"}, hash); {"foo" => "baz", "fud" => "buz"} }
|
85
|
-
assert_equal({"foo" => "baz", "fud" => "buz"}, @cache.read_multi('foo', 'fud'))
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_cas_multi_with_altered_key
|
89
|
-
@cache.write('foo', 'baz')
|
90
|
-
assert @cache.cas_multi('foo') {|hash| {'fu' => 'baz'}}
|
91
|
-
assert_nil @cache.read('fu')
|
92
|
-
assert_equal 'baz', @cache.read('foo')
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_cas_multi_with_cache_miss
|
96
|
-
assert @cache.cas_multi('not_exist') {|hash| assert hash.empty?; {} }
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_cas_multi_with_partial_miss
|
100
|
-
@cache.write('foo', 'baz')
|
101
|
-
assert @cache.cas_multi('foo', 'bar') {|hash| assert_equal({"foo" => "baz"}, hash); {} }
|
102
|
-
assert_equal 'baz', @cache.read('foo')
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_cas_multi_with_partial_update
|
106
|
-
@cache.write('foo', 'bar')
|
107
|
-
@cache.write('fud', 'biz')
|
108
|
-
assert @cache.cas_multi('foo', 'fud') {|hash| assert_equal({"foo" => "bar", "fud" => "biz"}, hash); {"foo" => "baz"} }
|
109
|
-
assert_equal({"foo" => "baz", "fud" => "biz"}, @cache.read_multi('foo', 'fud'))
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_cas_multi_with_partial_conflict
|
113
|
-
@cache.write('foo', 'bar')
|
114
|
-
@cache.write('fud', 'biz')
|
115
|
-
result = @cache.cas_multi('foo', 'fud') do |hash|
|
116
|
-
assert_equal({"foo" => "bar", "fud" => "biz"}, hash)
|
117
|
-
@cache.write('foo', 'bad')
|
118
|
-
{"foo" => "baz", "fud" => "buz"}
|
119
|
-
end
|
120
|
-
assert result
|
121
|
-
assert_equal({"foo" => "bad", "fud" => "buz"}, @cache.read_multi('foo', 'fud'))
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_should_read_and_write_hash
|
125
|
-
assert @cache.write('foo', {:a => "b"})
|
126
|
-
assert_equal({:a => "b"}, @cache.read('foo'))
|
127
|
-
end
|
128
|
-
|
129
|
-
def test_should_read_and_write_integer
|
130
|
-
assert @cache.write('foo', 1)
|
131
|
-
assert_equal 1, @cache.read('foo')
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_should_read_and_write_nil
|
135
|
-
assert @cache.write('foo', nil)
|
136
|
-
assert_equal nil, @cache.read('foo')
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_should_read_and_write_false
|
140
|
-
assert @cache.write('foo', false)
|
141
|
-
assert_equal false, @cache.read('foo')
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_read_multi
|
145
|
-
@cache.write('foo', 'bar')
|
146
|
-
@cache.write('fu', 'baz')
|
147
|
-
@cache.write('fud', 'biz')
|
148
|
-
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_read_multi_with_expires
|
152
|
-
time = Time.now
|
153
|
-
@cache.write('foo', 'bar', :expires_in => 10)
|
154
|
-
@cache.write('fu', 'baz')
|
155
|
-
@cache.write('fud', 'biz')
|
156
|
-
Time.stubs(:now).returns(time + 11)
|
157
|
-
assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu'))
|
158
|
-
end
|
159
|
-
|
160
|
-
def test_read_multi_not_found
|
161
|
-
expect_not_found
|
162
|
-
assert_equal({}, @cache.read_multi('foe', 'fue'))
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_read_and_write_compressed_small_data
|
166
|
-
@cache.write('foo', 'bar', :compress => true)
|
167
|
-
assert_equal 'bar', @cache.read('foo')
|
168
|
-
end
|
169
|
-
|
170
|
-
def test_read_and_write_compressed_large_data
|
171
|
-
@cache.write('foo', 'bar', :compress => true, :compress_threshold => 2)
|
172
|
-
assert_equal 'bar', @cache.read('foo')
|
173
|
-
end
|
174
|
-
|
175
|
-
def test_read_and_write_compressed_nil
|
176
|
-
@cache.write('foo', nil, :compress => true)
|
177
|
-
assert_nil @cache.read('foo')
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_cache_key
|
181
|
-
obj = Object.new
|
182
|
-
def obj.cache_key
|
183
|
-
:foo
|
184
|
-
end
|
185
|
-
@cache.write(obj, "bar")
|
186
|
-
assert_equal "bar", @cache.read("foo")
|
187
|
-
end
|
188
|
-
|
189
|
-
def test_param_as_cache_key
|
190
|
-
obj = Object.new
|
191
|
-
def obj.to_param
|
192
|
-
"foo"
|
193
|
-
end
|
194
|
-
@cache.write(obj, "bar")
|
195
|
-
assert_equal "bar", @cache.read("foo")
|
196
|
-
end
|
197
|
-
|
198
|
-
def test_array_as_cache_key
|
199
|
-
@cache.write([:fu, "foo"], "bar")
|
200
|
-
assert_equal "bar", @cache.read("fu/foo")
|
201
|
-
end
|
202
|
-
|
203
|
-
def test_hash_as_cache_key
|
204
|
-
@cache.write({:foo => 1, :fu => 2}, "bar")
|
205
|
-
assert_equal "bar", @cache.read("foo=1/fu=2")
|
206
|
-
end
|
207
|
-
|
208
|
-
def test_keys_are_case_sensitive
|
209
|
-
@cache.write("foo", "bar")
|
210
|
-
assert_nil @cache.read("FOO")
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_exist
|
214
|
-
@cache.write('foo', 'bar')
|
215
|
-
assert_equal true, @cache.exist?('foo')
|
216
|
-
assert_equal false, @cache.exist?('bar')
|
217
|
-
end
|
218
|
-
|
219
|
-
def test_nil_exist
|
220
|
-
@cache.write('foo', nil)
|
221
|
-
assert @cache.exist?('foo')
|
222
|
-
end
|
223
|
-
|
224
|
-
def test_delete
|
225
|
-
@cache.write('foo', 'bar')
|
226
|
-
assert @cache.exist?('foo')
|
227
|
-
assert @cache.delete('foo')
|
228
|
-
assert !@cache.exist?('foo')
|
229
|
-
|
230
|
-
assert @cache.delete('foo')
|
231
|
-
end
|
232
|
-
|
233
|
-
def test_original_store_objects_should_not_be_immutable
|
234
|
-
bar = 'bar'
|
235
|
-
@cache.write('foo', bar)
|
236
|
-
assert_nothing_raised { bar.gsub!(/.*/, 'baz') }
|
237
|
-
end
|
238
|
-
|
239
|
-
def test_expires_in
|
240
|
-
time = Time.local(2008, 4, 24)
|
241
|
-
Time.stubs(:now).returns(time)
|
242
|
-
|
243
|
-
@cache.write('foo', 'bar')
|
244
|
-
assert_equal 'bar', @cache.read('foo')
|
245
|
-
|
246
|
-
Time.stubs(:now).returns(time + 30)
|
247
|
-
assert_equal 'bar', @cache.read('foo')
|
248
|
-
|
249
|
-
Time.stubs(:now).returns(time + 61)
|
250
|
-
assert_nil @cache.read('foo')
|
251
|
-
end
|
252
|
-
|
253
|
-
def test_race_condition_protection
|
254
|
-
time = Time.now
|
255
|
-
@cache.write('foo', 'bar', :expires_in => 60)
|
256
|
-
Time.stubs(:now).returns(time + 61)
|
257
|
-
result = @cache.fetch('foo', :race_condition_ttl => 10) do
|
258
|
-
assert_equal 'bar', @cache.read('foo')
|
259
|
-
"baz"
|
260
|
-
end
|
261
|
-
assert_equal "baz", result
|
262
|
-
end
|
263
|
-
|
264
|
-
def test_race_condition_protection_is_limited
|
265
|
-
time = Time.now
|
266
|
-
@cache.write('foo', 'bar', :expires_in => 60)
|
267
|
-
Time.stubs(:now).returns(time + 71)
|
268
|
-
result = @cache.fetch('foo', :race_condition_ttl => 10) do
|
269
|
-
assert_equal nil, @cache.read('foo')
|
270
|
-
"baz"
|
271
|
-
end
|
272
|
-
assert_equal "baz", result
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_race_condition_protection_is_safe
|
276
|
-
time = Time.now
|
277
|
-
@cache.write('foo', 'bar', :expires_in => 60)
|
278
|
-
Time.stubs(:now).returns(time + 61)
|
279
|
-
begin
|
280
|
-
@cache.fetch('foo', :race_condition_ttl => 10) do
|
281
|
-
assert_equal 'bar', @cache.read('foo')
|
282
|
-
raise ArgumentError.new
|
283
|
-
end
|
284
|
-
rescue ArgumentError
|
285
|
-
end
|
286
|
-
assert_equal "bar", @cache.read('foo')
|
287
|
-
Time.stubs(:now).returns(time + 91)
|
288
|
-
assert_nil @cache.read('foo')
|
289
|
-
end
|
290
|
-
|
291
|
-
def test_crazy_key_characters
|
292
|
-
crazy_key = "#/:*(<+=> )&$%@?;'\"\'`~-"
|
293
|
-
assert @cache.write(crazy_key, "1", :raw => true)
|
294
|
-
assert_equal "1", @cache.read(crazy_key)
|
295
|
-
assert_equal "1", @cache.fetch(crazy_key)
|
296
|
-
assert @cache.delete(crazy_key)
|
297
|
-
assert_equal "2", @cache.fetch(crazy_key, :raw => true) { "2" }
|
298
|
-
assert_equal 3, @cache.increment(crazy_key)
|
299
|
-
assert_equal 2, @cache.decrement(crazy_key)
|
300
|
-
end
|
301
|
-
|
302
|
-
def test_really_long_keys
|
303
|
-
key = ""
|
304
|
-
900.times{key << "x"}
|
305
|
-
assert @cache.write(key, "bar")
|
306
|
-
assert_equal "bar", @cache.read(key)
|
307
|
-
assert_equal "bar", @cache.fetch(key)
|
308
|
-
assert_nil @cache.read("#{key}x")
|
309
|
-
assert_equal({key => "bar"}, @cache.read_multi(key))
|
310
|
-
assert @cache.delete(key)
|
311
|
-
end
|
312
|
-
|
313
|
-
def test_increment
|
314
|
-
@cache.write('foo', 1, :raw => true)
|
315
|
-
assert_equal 1, @cache.read('foo').to_i
|
316
|
-
assert_equal 2, @cache.increment('foo')
|
317
|
-
assert_equal 2, @cache.read('foo').to_i
|
318
|
-
assert_equal 3, @cache.increment('foo')
|
319
|
-
assert_equal 3, @cache.read('foo').to_i
|
320
|
-
assert_nil @cache.increment('bar')
|
321
|
-
end
|
322
|
-
|
323
|
-
def test_increment_not_found
|
324
|
-
expect_not_found
|
325
|
-
assert_equal nil, @cache.increment('not_exist')
|
326
|
-
end
|
327
|
-
|
328
|
-
def test_decrement
|
329
|
-
@cache.write('foo', 3, :raw => true)
|
330
|
-
assert_equal 3, @cache.read('foo').to_i
|
331
|
-
assert_equal 2, @cache.decrement('foo')
|
332
|
-
assert_equal 2, @cache.read('foo').to_i
|
333
|
-
assert_equal 1, @cache.decrement('foo')
|
334
|
-
assert_equal 1, @cache.read('foo').to_i
|
335
|
-
assert_nil @cache.decrement('bar')
|
336
|
-
end
|
337
|
-
|
338
|
-
def test_decrement_not_found
|
339
|
-
expect_not_found
|
340
|
-
assert_equal nil, @cache.decrement('not_exist')
|
341
|
-
end
|
342
|
-
|
343
|
-
def test_common_utf8_values
|
344
|
-
key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
|
345
|
-
assert @cache.write(key, "1", :raw => true)
|
346
|
-
assert_equal "1", @cache.read(key)
|
347
|
-
assert_equal "1", @cache.fetch(key)
|
348
|
-
assert @cache.delete(key)
|
349
|
-
assert_equal "2", @cache.fetch(key, :raw => true) { "2" }
|
350
|
-
assert_equal 3, @cache.increment(key)
|
351
|
-
assert_equal 2, @cache.decrement(key)
|
352
|
-
end
|
353
|
-
|
354
|
-
def test_retains_encoding
|
355
|
-
key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
|
356
|
-
assert @cache.write(key, "1", :raw => true)
|
357
|
-
assert_equal Encoding::UTF_8, key.encoding
|
358
|
-
end
|
359
|
-
|
360
|
-
def test_initialize_accepts_a_list_of_servers_in_options
|
361
|
-
options = {servers: ["localhost:21211"]}
|
362
|
-
cache = ActiveSupport::Cache.lookup_store(:memcached_store, options)
|
363
|
-
assert_equal 21211, cache.instance_variable_get(:@data).servers.first.port
|
364
|
-
end
|
365
|
-
|
366
|
-
def test_multiple_servers
|
367
|
-
options = {servers: ["localhost:21211", "localhost:11211"]}
|
368
|
-
cache = ActiveSupport::Cache.lookup_store(:memcached_store, options)
|
369
|
-
assert_equal [21211, 11211], cache.instance_variable_get(:@data).servers.map(&:port)
|
370
|
-
end
|
371
|
-
|
372
|
-
def test_namespace_without_servers
|
373
|
-
options = {namespace: 'foo:'}
|
374
|
-
cache = ActiveSupport::Cache.lookup_store(:memcached_store, options)
|
375
|
-
client = cache.instance_variable_get(:@data)
|
376
|
-
assert_equal [11211], client.servers.map(&:port)
|
377
|
-
assert_equal "", client.prefix_key, "should not send the namespace to the client"
|
378
|
-
assert_equal "foo::key", cache.send(:namespaced_key, "key", cache.options)
|
379
|
-
end
|
380
|
-
|
381
|
-
def test_reset
|
382
|
-
client = @cache.instance_variable_get(:@data)
|
383
|
-
client.expects(:reset).once
|
384
|
-
@cache.reset
|
385
|
-
end
|
386
|
-
|
387
|
-
def test_write_to_read_only_memcached_store_should_not_write
|
388
|
-
with_read_only(@cache) do
|
389
|
-
assert @cache.write("walrus", "awesome"), "Writing to a disabled memcached
|
390
|
-
store should return truthy to make clients not care"
|
391
|
-
|
392
|
-
assert_nil @cache.read("walrus"), "Key should have nil value in disabled cache"
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
|
-
def test_delete_with_read_only_memcached_store_should_not_delete
|
397
|
-
assert @cache.write("walrus", "big")
|
398
|
-
|
399
|
-
with_read_only(@cache) do
|
400
|
-
assert @cache.delete("walrus"), "Should return truthy when deleted to not raise in client"
|
401
|
-
end
|
402
|
-
|
403
|
-
assert_equal "big", @cache.read("walrus"), "Cache entry should not have been deleted from read only client"
|
404
|
-
end
|
405
|
-
|
406
|
-
def test_cas_with_read_only_memcached_store_should_not_s
|
407
|
-
called_block = false
|
408
|
-
@cache.write('walrus', 'slimy')
|
409
|
-
|
410
|
-
with_read_only(@cache) do
|
411
|
-
assert(@cache.cas('walrus') { |value|
|
412
|
-
assert_equal 'slimy', value
|
413
|
-
called_block = true
|
414
|
-
'full'
|
415
|
-
})
|
416
|
-
end
|
417
|
-
|
418
|
-
assert_equal 'slimy', @cache.read('walrus')
|
419
|
-
assert called_block, "CAS with read only should have called the inner block with an assertion"
|
420
|
-
end
|
421
|
-
|
422
|
-
def test_cas_multi_with_read_only_memcached_store_should_not_s
|
423
|
-
called_block = false
|
424
|
-
|
425
|
-
@cache.write('walrus', 'cool')
|
426
|
-
@cache.write('narwhal', 'horn')
|
427
|
-
|
428
|
-
with_read_only(@cache) do
|
429
|
-
assert(@cache.cas_multi('walrus', 'narwhal') {
|
430
|
-
called_block = true
|
431
|
-
{ "walrus" => "not cool", "narwhal" => "not with horns" }
|
432
|
-
})
|
433
|
-
end
|
434
|
-
|
435
|
-
assert_equal 'cool', @cache.read('walrus')
|
436
|
-
assert_equal 'horn', @cache.read('narwhal')
|
437
|
-
assert called_block, "CAS with read only should have called the inner block with an assertion"
|
438
|
-
end
|
439
|
-
|
440
|
-
def test_write_with_read_only_should_not_send_activesupport_notification
|
441
|
-
assert_notifications(/cache/, 0) do
|
442
|
-
with_read_only(@cache) do
|
443
|
-
assert @cache.write("walrus", "bestest")
|
444
|
-
end
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
def test_delete_with_read_only_should_not_send_activesupport_notification
|
449
|
-
assert_notifications(/cache/, 0) do
|
450
|
-
with_read_only(@cache) do
|
451
|
-
assert @cache.delete("walrus")
|
452
|
-
end
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
def test_fetch_with_expires_in_with_read_only_should_not_send_activesupport_notification
|
457
|
-
expires_in = 10
|
458
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
459
|
-
|
460
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
461
|
-
assert_notifications(/cache_write/, 0) do
|
462
|
-
with_read_only(@cache) do
|
463
|
-
@cache.fetch("walrus") { "no" }
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
end
|
468
|
-
|
469
|
-
def test_fetch_with_expired_entry_with_read_only_should_return_nil_and_not_delete_from_cache
|
470
|
-
expires_in = 10
|
471
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
472
|
-
|
473
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
474
|
-
with_read_only(@cache) do
|
475
|
-
value = @cache.fetch("walrus", expires_in: expires_in) { "no" }
|
476
|
-
|
477
|
-
assert_equal "no", value
|
478
|
-
refute @cache.fetch("walrus"), "Client should return nil for expired key"
|
479
|
-
assert_equal "yo", @cache.instance_variable_get(:@data).get("walrus").value
|
480
|
-
end
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
def test_fetch_with_expired_entry_and_race_condition_ttl_with_read_only_should_return_nil_and_not_delete_from_cache
|
485
|
-
expires_in = 10
|
486
|
-
race_condition_ttl = 10
|
487
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
488
|
-
|
489
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
490
|
-
with_read_only(@cache) do
|
491
|
-
value = @cache.fetch("walrus", expires_in: expires_in, race_condition_ttl: race_condition_ttl) { "no" }
|
492
|
-
|
493
|
-
assert_equal "no", value
|
494
|
-
assert_equal "no", @cache.fetch("walrus") { "no" }
|
495
|
-
refute @cache.fetch("walrus")
|
496
|
-
|
497
|
-
assert_equal "yo", @cache.instance_variable_get(:@data).get("walrus").value
|
498
|
-
end
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
def test_read_with_expired_with_read_only_entry_should_return_nil_and_not_delete_from_cache
|
503
|
-
expires_in = 10
|
504
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
505
|
-
|
506
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
507
|
-
with_read_only(@cache) do
|
508
|
-
refute @cache.read("walrus")
|
509
|
-
|
510
|
-
assert_equal "yo", @cache.instance_variable_get(:@data).get("walrus").value
|
511
|
-
end
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
|
-
def test_read_multi_with_expired_entry_should_return_nil_and_not_delete_from_cache
|
516
|
-
expires_in = 10
|
517
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
518
|
-
@cache.fetch("narwhal", expires_in: expires_in) { "yiir" }
|
519
|
-
|
520
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
521
|
-
with_read_only(@cache) do
|
522
|
-
assert_predicate @cache.read_multi("walrus", "narwhal"), :empty?
|
523
|
-
|
524
|
-
assert_equal "yo", @cache.instance_variable_get(:@data).get("walrus").value
|
525
|
-
assert_equal "yiir", @cache.instance_variable_get(:@data).get("narwhal").value
|
526
|
-
end
|
527
|
-
end
|
528
|
-
end
|
529
|
-
|
530
|
-
def test_fetch_with_race_condition_ttl_with_read_only_should_not_send_activesupport_notification
|
531
|
-
expires_in = 10
|
532
|
-
race_condition_ttl = 10
|
533
|
-
@cache.fetch("walrus", expires_in: expires_in) { "yo" }
|
534
|
-
|
535
|
-
Timecop.travel(Time.now + expires_in + 1) do
|
536
|
-
assert_notifications(/cache_write/, 0) do
|
537
|
-
with_read_only(@cache) do
|
538
|
-
@cache.fetch("walrus", expires_in: expires_in, race_condition_ttl: race_condition_ttl) { "no" }
|
539
|
-
end
|
540
|
-
end
|
541
|
-
end
|
542
|
-
end
|
543
|
-
|
544
|
-
def test_cas_with_read_only_should_send_activesupport_notification
|
545
|
-
@cache.write("walrus", "yes")
|
546
|
-
|
547
|
-
with_read_only(@cache) do
|
548
|
-
assert_notifications(/cache_cas/, 1) do
|
549
|
-
assert(@cache.cas("walrus") { |value| "no" })
|
550
|
-
end
|
551
|
-
end
|
552
|
-
|
553
|
-
assert_equal "yes", @cache.fetch("walrus")
|
554
|
-
end
|
555
|
-
|
556
|
-
def test_cas_multi_with_read_only_should_send_activesupport_notification
|
557
|
-
@cache.write("walrus", "yes")
|
558
|
-
@cache.write("narwhal", "yes")
|
559
|
-
|
560
|
-
with_read_only(@cache) do
|
561
|
-
assert_notifications(/cache_cas/, 1) do
|
562
|
-
assert(@cache.cas_multi("walrus", "narwhal") { |*values|
|
563
|
-
{ "walrus" => "no", "narwhal" => "no" }
|
564
|
-
})
|
565
|
-
end
|
566
|
-
end
|
567
|
-
|
568
|
-
assert_equal "yes", @cache.fetch("walrus")
|
569
|
-
assert_equal "yes", @cache.fetch("narwhal")
|
570
|
-
end
|
571
|
-
|
572
|
-
def test_logger_defaults_to_rails_logger
|
573
|
-
assert_equal Rails.logger, @cache.logger
|
574
|
-
end
|
575
|
-
|
576
|
-
private
|
577
|
-
|
578
|
-
def assert_notifications(pattern, num)
|
579
|
-
count = 0
|
580
|
-
subscriber = ActiveSupport::Notifications.subscribe(pattern) do |name, start, finish, id, payload|
|
581
|
-
count += 1
|
582
|
-
end
|
583
|
-
|
584
|
-
yield
|
585
|
-
|
586
|
-
assert_equal num, count, "Expected #{num} notifications for #{pattern}, but got #{count}"
|
587
|
-
ensure
|
588
|
-
ActiveSupport::Notifications.unsubscribe(subscriber)
|
589
|
-
end
|
590
|
-
|
591
|
-
def with_read_only(client)
|
592
|
-
previous, client.read_only = client.read_only, true
|
593
|
-
yield
|
594
|
-
ensure
|
595
|
-
client.read_only = previous
|
596
|
-
end
|
597
|
-
|
598
|
-
def expect_not_found
|
599
|
-
@cache.instance_variable_get(:@data).expects(:check_return_code).raises(Memcached::NotFound)
|
600
|
-
end
|
601
|
-
end
|