mob-dalli 1.1.4

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.
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ class TestCompatibility < Test::Unit::TestCase
4
+
5
+ def setup
6
+ require 'dalli/memcache-client'
7
+ end
8
+
9
+ context 'dalli in memcache-client mode' do
10
+
11
+ should 'handle old raw flag to set/add/replace' do
12
+ memcached do |dc|
13
+ assert_equal "STORED\r\n", dc.set('abc', 123, 5, true)
14
+ assert_equal '123', dc.get('abc', true)
15
+
16
+ assert_equal "NOT_STORED\r\n", dc.add('abc', 456, 5, true)
17
+ assert_equal '123', dc.get('abc', true)
18
+
19
+ assert_equal "STORED\r\n", dc.replace('abc', 456, 5, false)
20
+ assert_equal 456, dc.get('abc', false)
21
+
22
+ assert_equal "DELETED\r\n", dc.delete('abc')
23
+ assert_equal "NOT_DELETED\r\n", dc.delete('abc')
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ def teardown
30
+ Dalli::Client.compatibility_mode = false
31
+ end
32
+
33
+ end
@@ -0,0 +1,450 @@
1
+ require 'helper'
2
+ require 'memcached_mock'
3
+
4
+ class TestDalli < Test::Unit::TestCase
5
+
6
+ should "default to localhost:11211" do
7
+ dc = Dalli::Client.new
8
+ ring = dc.send(:ring)
9
+ s1 = ring.servers.first.hostname
10
+ assert_equal 1, ring.servers.size
11
+ dc.close
12
+
13
+ dc = Dalli::Client.new('localhost:11211')
14
+ ring = dc.send(:ring)
15
+ s2 = ring.servers.first.hostname
16
+ assert_equal 1, ring.servers.size
17
+ dc.close
18
+
19
+ dc = Dalli::Client.new(['localhost:11211'])
20
+ ring = dc.send(:ring)
21
+ s3 = ring.servers.first.hostname
22
+ assert_equal 1, ring.servers.size
23
+ dc.close
24
+
25
+ assert_equal s1, s2
26
+ assert_equal s2, s3
27
+ end
28
+
29
+ context 'using unix sockets' do
30
+ should 'pass smoke test' do
31
+ memcached(nil,'',{:unix => true}) do |dc|
32
+ # get/set
33
+ dc.flush
34
+ assert_nil dc.get(:a)
35
+ assert dc.set(:a,1)
36
+ assert_equal 1, dc.get(:a)
37
+
38
+ # replace
39
+ dc.set(:a,1)
40
+ dc.replace(:a,2)
41
+ assert_equal 2, dc.get(:a)
42
+
43
+ # delete
44
+ dc.delete(:a)
45
+ assert_nil dc.get(:a)
46
+
47
+ # fetch
48
+ executed, expected = false, 1
49
+
50
+ value = dc.fetch(:fetched) do
51
+ executed = true
52
+ expected
53
+ end
54
+
55
+ assert executed
56
+ assert_equal expected, value
57
+
58
+ executed = false
59
+ value = dc.fetch(:fetched) do
60
+ executed = true
61
+ expected
62
+ end
63
+
64
+ assert !executed
65
+ assert_equal expected, value
66
+
67
+ # cas
68
+ dc.set(:a,1)
69
+ 3.times { dc.cas(:a){|a| a+=1} }
70
+ assert_equal 4, dc.get(:a)
71
+
72
+ # get_multi
73
+ resp = dc.get_multi(%w(b c d))
74
+ assert_equal({}, resp)
75
+ dc.set("b",1)
76
+ dc.set("c",11)
77
+ resp = dc.get_multi(%w(b c d))
78
+ assert_equal({"b" => 1, "c" => 11}, resp)
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'using a live server' do
84
+
85
+ should "support get/set" do
86
+ memcached do |dc|
87
+ dc.flush
88
+
89
+ val1 = "1234567890"*105000
90
+ assert_error Dalli::DalliError, /too large/ do
91
+ dc.set('a', val1)
92
+ val2 = dc.get('a')
93
+ assert_equal val1, val2
94
+ end
95
+
96
+ val1 = "1234567890"*100000
97
+ dc.set('a', val1)
98
+ val2 = dc.get('a')
99
+ assert_equal val1, val2
100
+
101
+ assert_equal true, dc.set('a', nil)
102
+ assert_nil dc.get('a')
103
+ end
104
+ end
105
+
106
+ should "support the fetch operation" do
107
+ memcached do |dc|
108
+ dc.flush
109
+
110
+ expected = { 'blah' => 'blerg!' }
111
+ executed = false
112
+ value = dc.fetch('fetch_key') do
113
+ executed = true
114
+ expected
115
+ end
116
+ assert_equal expected, value
117
+ assert_equal true, executed
118
+
119
+ executed = false
120
+ value = dc.fetch('fetch_key') do
121
+ executed = true
122
+ expected
123
+ end
124
+ assert_equal expected, value
125
+ assert_equal false, executed
126
+ end
127
+ end
128
+
129
+ should "support the cas operation" do
130
+ memcached do |dc|
131
+ dc.flush
132
+
133
+ expected = { 'blah' => 'blerg!' }
134
+
135
+ resp = dc.cas('cas_key') do |value|
136
+ fail('Value should not exist')
137
+ end
138
+ assert_nil resp
139
+
140
+ mutated = { 'blah' => 'foo!' }
141
+ dc.set('cas_key', expected)
142
+ resp = dc.cas('cas_key') do |value|
143
+ assert_equal expected, value
144
+ mutated
145
+ end
146
+ assert_equal true, resp
147
+
148
+ resp = dc.get('cas_key')
149
+ assert_equal mutated, resp
150
+ end
151
+ end
152
+
153
+ should "support multi-get" do
154
+ memcached do |dc|
155
+ dc.close
156
+ dc.flush
157
+ resp = dc.get_multi(%w(a b c d e f))
158
+ assert_equal({}, resp)
159
+
160
+ dc.set('a', 'foo')
161
+ dc.set('b', 123)
162
+ dc.set('c', %w(a b c))
163
+ resp = dc.get_multi(%w(a b c d e f))
164
+ assert_equal({ 'a' => 'foo', 'b' => 123, 'c' => %w(a b c) }, resp)
165
+
166
+ # Perform a huge multi-get with 10,000 elements.
167
+ arr = []
168
+ dc.multi do
169
+ 10_000.times do |idx|
170
+ dc.set idx, idx
171
+ arr << idx
172
+ end
173
+ end
174
+
175
+ result = dc.get_multi(arr)
176
+ assert_equal(10_000, result.size)
177
+ assert_equal(1000, result['1000'])
178
+ end
179
+ end
180
+
181
+ should 'support raw incr/decr' do
182
+ memcached do |client|
183
+ client.flush
184
+
185
+ assert_equal true, client.set('fakecounter', 0, 0, :raw => true)
186
+ assert_equal 1, client.incr('fakecounter', 1)
187
+ assert_equal 2, client.incr('fakecounter', 1)
188
+ assert_equal 3, client.incr('fakecounter', 1)
189
+ assert_equal 1, client.decr('fakecounter', 2)
190
+ assert_equal "1", client.get('fakecounter', :raw => true)
191
+
192
+ resp = client.incr('mycounter', 0)
193
+ assert_nil resp
194
+
195
+ resp = client.incr('mycounter', 1, 0, 2)
196
+ assert_equal 2, resp
197
+ resp = client.incr('mycounter', 1)
198
+ assert_equal 3, resp
199
+
200
+ resp = client.set('rawcounter', 10, 0, :raw => true)
201
+ assert_equal true, resp
202
+
203
+ resp = client.get('rawcounter', :raw => true)
204
+ assert_equal '10', resp
205
+
206
+ resp = client.incr('rawcounter', 1)
207
+ assert_equal 11, resp
208
+ end
209
+ end
210
+
211
+ should "support incr/decr operations" do
212
+ memcached do |dc|
213
+ dc.flush
214
+
215
+ resp = dc.decr('counter', 100, 5, 0)
216
+ assert_equal 0, resp
217
+
218
+ resp = dc.decr('counter', 10)
219
+ assert_equal 0, resp
220
+
221
+ resp = dc.incr('counter', 10)
222
+ assert_equal 10, resp
223
+
224
+ current = 10
225
+ 100.times do |x|
226
+ resp = dc.incr('counter', 10)
227
+ assert_equal current + ((x+1)*10), resp
228
+ end
229
+
230
+ resp = dc.decr('10billion', 0, 5, 10)
231
+ # go over the 32-bit mark to verify proper (un)packing
232
+ resp = dc.incr('10billion', 10_000_000_000)
233
+ assert_equal 10_000_000_010, resp
234
+
235
+ resp = dc.decr('10billion', 1)
236
+ assert_equal 10_000_000_009, resp
237
+
238
+ resp = dc.decr('10billion', 0)
239
+ assert_equal 10_000_000_009, resp
240
+
241
+ resp = dc.incr('10billion', 0)
242
+ assert_equal 10_000_000_009, resp
243
+
244
+ assert_nil dc.incr('DNE', 10)
245
+ assert_nil dc.decr('DNE', 10)
246
+
247
+ resp = dc.incr('big', 100, 5, 0xFFFFFFFFFFFFFFFE)
248
+ assert_equal 0xFFFFFFFFFFFFFFFE, resp
249
+ resp = dc.incr('big', 1)
250
+ assert_equal 0xFFFFFFFFFFFFFFFF, resp
251
+
252
+ # rollover the 64-bit value, we'll get something undefined.
253
+ resp = dc.incr('big', 1)
254
+ assert_not_equal 0x10000000000000000, resp
255
+ dc.reset
256
+ end
257
+ end
258
+
259
+ should 'support the append and prepend operations' do
260
+ memcached do |dc|
261
+ resp = dc.flush
262
+ assert_equal true, dc.set('456', 'xyz', 0, :raw => true)
263
+ assert_equal true, dc.prepend('456', '0')
264
+ assert_equal true, dc.append('456', '9')
265
+ assert_equal '0xyz9', dc.get('456', :raw => true)
266
+ assert_equal '0xyz9', dc.get('456')
267
+
268
+ assert_equal false, dc.append('nonexist', 'abc')
269
+ assert_equal false, dc.prepend('nonexist', 'abc')
270
+ end
271
+ end
272
+
273
+ should "pass a simple smoke test" do
274
+ memcached do |dc|
275
+ resp = dc.flush
276
+ assert_not_nil resp
277
+ assert_equal [true, true], resp
278
+
279
+ assert_equal true, dc.set(:foo, 'bar')
280
+ assert_equal 'bar', dc.get(:foo)
281
+
282
+ resp = dc.get('123')
283
+ assert_equal nil, resp
284
+
285
+ resp = dc.set('123', 'xyz')
286
+ assert_equal true, resp
287
+
288
+ resp = dc.get('123')
289
+ assert_equal 'xyz', resp
290
+
291
+ resp = dc.set('123', 'abc')
292
+ assert_equal true, resp
293
+
294
+ dc.prepend('123', '0')
295
+ dc.append('123', '0')
296
+
297
+ assert_raises Dalli::DalliError do
298
+ resp = dc.get('123')
299
+ end
300
+
301
+ dc.close
302
+ dc = nil
303
+
304
+ dc = Dalli::Client.new('localhost:19122')
305
+
306
+ resp = dc.set('456', 'xyz', 0, :raw => true)
307
+ assert_equal true, resp
308
+
309
+ resp = dc.prepend '456', '0'
310
+ assert_equal true, resp
311
+
312
+ resp = dc.append '456', '9'
313
+ assert_equal true, resp
314
+
315
+ resp = dc.get('456', :raw => true)
316
+ assert_equal '0xyz9', resp
317
+
318
+ resp = dc.stats
319
+ assert_equal Hash, resp.class
320
+
321
+ dc.close
322
+ end
323
+ end
324
+
325
+ should "support multithreaded access" do
326
+ memcached do |cache|
327
+ cache.flush
328
+ workers = []
329
+
330
+ cache.set('f', 'zzz')
331
+ assert_equal true, (cache.cas('f') do |value|
332
+ value << 'z'
333
+ end)
334
+ assert_equal 'zzzz', cache.get('f')
335
+
336
+ # Have a bunch of threads perform a bunch of operations at the same time.
337
+ # Verify the result of each operation to ensure the request and response
338
+ # are not intermingled between threads.
339
+ 10.times do
340
+ workers << Thread.new do
341
+ 100.times do
342
+ cache.set('a', 9)
343
+ cache.set('b', 11)
344
+ inc = cache.incr('cat', 10, 0, 10)
345
+ cache.set('f', 'zzz')
346
+ assert_not_nil(cache.cas('f') do |value|
347
+ value << 'z'
348
+ end)
349
+ assert_equal false, cache.add('a', 11)
350
+ assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
351
+ inc = cache.incr('cat', 10)
352
+ assert_equal 0, inc % 5
353
+ dec = cache.decr('cat', 5)
354
+ assert_equal 11, cache.get('b')
355
+ end
356
+ end
357
+ end
358
+
359
+ workers.each { |w| w.join }
360
+ cache.flush
361
+ end
362
+ end
363
+
364
+ should "handle namespaced keys" do
365
+ memcached do |dc|
366
+ dc = Dalli::Client.new('localhost:19122', :namespace => 'a')
367
+ dc.set('namespaced', 1)
368
+ dc2 = Dalli::Client.new('localhost:19122', :namespace => 'b')
369
+ dc2.set('namespaced', 2)
370
+ assert_equal 1, dc.get('namespaced')
371
+ assert_equal 2, dc2.get('namespaced')
372
+ end
373
+ end
374
+
375
+ should "handle namespaced keys in multi_get" do
376
+ memcached do |dc|
377
+ dc = Dalli::Client.new('localhost:19122', :namespace => 'a')
378
+ dc.set('a', 1)
379
+ dc.set('b', 2)
380
+ assert_equal({'a' => 1, 'b' => 2}, dc.get_multi('a', 'b'))
381
+ end
382
+ end
383
+
384
+ should "handle application marshalling issues" do
385
+ memcached do |dc|
386
+ old = Dalli.logger
387
+ Dalli.logger = Logger.new(nil)
388
+ begin
389
+ assert_equal false, dc.set('a', Proc.new { true })
390
+ ensure
391
+ Dalli.logger = old
392
+ end
393
+ end
394
+ end
395
+
396
+ context 'with compression' do
397
+ should 'allow large values' do
398
+ memcached do |dc|
399
+ dalli = Dalli::Client.new(dc.instance_variable_get(:@servers), :compression => true)
400
+
401
+ value = "0"*1024*1024
402
+ assert_raise Dalli::DalliError, /too large/ do
403
+ dc.set('verylarge', value)
404
+ end
405
+ dalli.set('verylarge', value)
406
+ end
407
+ end
408
+ end
409
+
410
+ context 'in low memory conditions' do
411
+
412
+ should 'handle error response correctly' do
413
+ memcached(19125, '-m 1 -M') do |dc|
414
+ failed = false
415
+ value = "1234567890"*100
416
+ 1_000.times do |idx|
417
+ begin
418
+ assert_equal true, dc.set(idx, value)
419
+ rescue Dalli::DalliError
420
+ failed = true
421
+ assert((800..960).include?(idx), "unexpected failure on iteration #{idx}")
422
+ break
423
+ end
424
+ end
425
+ assert failed, 'did not fail under low memory conditions'
426
+ end
427
+ end
428
+
429
+ should 'fit more values with compression' do
430
+ memcached(19126, '-m 1 -M') do |dc|
431
+ dalli = Dalli::Client.new('localhost:19126', :compression => true)
432
+ failed = false
433
+ value = "1234567890"*1000
434
+ 10_000.times do |idx|
435
+ begin
436
+ assert_equal true, dalli.set(idx, value)
437
+ rescue Dalli::DalliError
438
+ failed = true
439
+ assert((6000..7800).include?(idx), "unexpected failure on iteration #{idx}")
440
+ break
441
+ end
442
+ end
443
+ assert failed, 'did not fail under low memory conditions'
444
+ end
445
+ end
446
+
447
+ end
448
+
449
+ end
450
+ end