jashmenn-dalli 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ $TESTING = true
2
+ require 'rubygems'
3
+ # require 'simplecov'
4
+ # SimpleCov.start
5
+ RAILS_VERSION = ENV['RAILS_VERSION'] || '~> 3.0.0'
6
+ #puts "Testing with Rails #{RAILS_VERSION}"
7
+ gem 'rails', RAILS_VERSION
8
+
9
+ require 'test/unit'
10
+ require 'shoulda'
11
+ require 'memcached_mock'
12
+ require 'mocha'
13
+
14
+ require 'dalli'
15
+ require 'logger'
16
+
17
+ Dalli.logger = Logger.new(STDOUT)
18
+ Dalli.logger.level = Logger::ERROR
19
+
20
+ class Test::Unit::TestCase
21
+ include MemcachedMock::Helper
22
+
23
+ def rails3?
24
+ RAILS_VERSION =~ /3\.0\./
25
+ end
26
+
27
+ def assert_error(error, regexp=nil, &block)
28
+ ex = assert_raise(error, &block)
29
+ assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
30
+ end
31
+
32
+ def with_activesupport
33
+ case
34
+ when rails3?
35
+ require 'active_support/all'
36
+ else
37
+ require 'active_support'
38
+ require 'active_support/cache/dalli_store23'
39
+ end
40
+ yield
41
+ end
42
+
43
+ def with_actionpack
44
+ case
45
+ when rails3?
46
+ require 'action_dispatch'
47
+ require 'action_controller'
48
+ # when '2.3.0'
49
+ # raise NotImplementedError
50
+ end
51
+ yield
52
+ end
53
+
54
+ end
@@ -0,0 +1,106 @@
1
+ require "socket"
2
+
3
+ $started = {}
4
+
5
+ module MemcachedMock
6
+ def self.start(port=19123, &block)
7
+ server = TCPServer.new("localhost", port)
8
+ session = server.accept
9
+ block.call session
10
+ end
11
+
12
+ def self.delayed_start(port=19123, wait=1, &block)
13
+ server = TCPServer.new("localhost", port)
14
+ sleep wait
15
+ block.call server
16
+ end
17
+
18
+ module Helper
19
+ # Forks the current process and starts a new mock Memcached server on
20
+ # port 22122.
21
+ #
22
+ # memcached_mock(lambda {|sock| socket.write('123') }) do
23
+ # assert_equal "PONG", Dalli::Client.new('localhost:22122').get('abc')
24
+ # end
25
+ #
26
+ def memcached_mock(proc, meth = :start)
27
+ begin
28
+ pid = fork do
29
+ trap("TERM") { exit }
30
+
31
+ MemcachedMock.send(meth) do |*args|
32
+ proc.call(*args)
33
+ end
34
+ end
35
+
36
+ sleep 0.3 # Give time for the socket to start listening.
37
+ yield
38
+ ensure
39
+ if pid
40
+ Process.kill("TERM", pid)
41
+ Process.wait(pid)
42
+ end
43
+ end
44
+ end
45
+
46
+ PATHS = %w(
47
+ /usr/local/bin/
48
+ /opt/local/bin/
49
+ /usr/bin/
50
+ )
51
+
52
+ def find_memcached
53
+ output = `memcached -h | head -1`.strip
54
+ if output && output =~ /^memcached (\d.\d.\d+)/ && $1 > '1.4'
55
+ return (puts "Found #{output} in PATH"; '')
56
+ end
57
+ PATHS.each do |path|
58
+ output = `memcached -h | head -1`.strip
59
+ if output && output =~ /^memcached (\d\.\d\.\d+)/ && $1 > '1.4'
60
+ return (puts "Found #{output} in #{path}"; path)
61
+ end
62
+ end
63
+
64
+ raise Errno::ENOENT, "Unable to find memcached 1.4+ locally"
65
+ nil
66
+ end
67
+
68
+ def memcached(port=19122, args='')
69
+ Memcached.path ||= find_memcached
70
+ cmd = "#{Memcached.path}memcached #{args} -p #{port}"
71
+ $started[port] ||= begin
72
+ #puts "Starting: #{cmd}..."
73
+ pid = IO.popen(cmd).pid
74
+ at_exit do
75
+ begin
76
+ Process.kill("TERM", pid)
77
+ Process.wait(pid)
78
+ rescue Errno::ECHILD, Errno::ESRCH
79
+ end
80
+ end
81
+ sleep 0.1
82
+ pid
83
+ end
84
+
85
+ yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"])
86
+ end
87
+
88
+ def memcached_kill(port)
89
+ pid = $started.delete(port)
90
+ if pid
91
+ begin
92
+ Process.kill("TERM", pid)
93
+ Process.wait(pid)
94
+ rescue Errno::ECHILD, Errno::ESRCH
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+
102
+ module Memcached
103
+ class << self
104
+ attr_accessor :path
105
+ end
106
+ end
@@ -0,0 +1,177 @@
1
+ require 'helper'
2
+
3
+ class TestActiveSupport < Test::Unit::TestCase
4
+ context 'active_support caching' do
5
+
6
+ should 'support fetch' do
7
+ with_activesupport do
8
+ memcached do
9
+ connect
10
+ mvalue = @mc.fetch('somekeywithoutspaces', :expires_in => 1.second) { 123 }
11
+ dvalue = @dalli.fetch('someotherkeywithoutspaces', :expires_in => 1.second) { 123 }
12
+ assert_equal 123, dvalue
13
+ assert_equal mvalue, dvalue
14
+
15
+ o = Object.new
16
+ o.instance_variable_set :@foo, 'bar'
17
+ mvalue = @mc.fetch(rand_key, :raw => true) { o }
18
+ dvalue = @dalli.fetch(rand_key, :raw => true) { o }
19
+ assert_equal mvalue, dvalue
20
+ assert_equal o, mvalue
21
+
22
+ mvalue = @mc.fetch(rand_key) { o }
23
+ dvalue = @dalli.fetch(rand_key) { o }
24
+ assert_equal mvalue, dvalue
25
+ assert_equal o, dvalue
26
+ end
27
+ end
28
+ end
29
+
30
+ should 'support keys with spaces on Rails3' do
31
+ with_activesupport do
32
+ memcached do
33
+ connect
34
+ case
35
+ when rails3?
36
+ dvalue = @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
37
+ mvalue = @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
38
+ assert_equal mvalue, dvalue
39
+ else
40
+ assert_raises ArgumentError do
41
+ @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
42
+ end
43
+ assert_raises ArgumentError do
44
+ @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ should 'support read_multi' do
52
+ with_activesupport do
53
+ memcached do
54
+ connect
55
+ x = rand_key
56
+ y = rand_key
57
+ assert_equal({}, @mc.read_multi(x, y))
58
+ assert_equal({}, @dalli.read_multi(x, y))
59
+ @dalli.write(x, '123')
60
+ @dalli.write(y, 123)
61
+ @mc.write(x, '123')
62
+ @mc.write(y, 123)
63
+ assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
64
+ assert_equal({ x => '123', y => 123 }, @mc.read_multi(x, y))
65
+ end
66
+ end
67
+ end
68
+
69
+ should 'support raw read_multi' do
70
+ with_activesupport do
71
+ memcached do
72
+ connect
73
+ @mc.write("abc", 5, :raw => true)
74
+ @mc.write("cba", 5, :raw => true)
75
+ if RAILS_VERSION =~ /2\.3/
76
+ assert_raise ArgumentError do
77
+ @mc.read_multi("abc", "cba")
78
+ end
79
+ else
80
+ assert_equal({'abc' => '5', 'cba' => '5' }, @mc.read_multi("abc", "cba"))
81
+ end
82
+
83
+ @dalli.write("abc", 5, :raw => true)
84
+ @dalli.write("cba", 5, :raw => true)
85
+ # XXX: API difference between m-c and dalli. Dalli is smarter about
86
+ # what it needs to unmarshal.
87
+ assert_equal({'abc' => '5', 'cba' => '5' }, @dalli.read_multi("abc", "cba"))
88
+ end
89
+ end
90
+ end
91
+
92
+ should 'support read, write and delete' do
93
+ with_activesupport do
94
+ memcached do
95
+ connect
96
+ x = rand_key
97
+ y = rand_key
98
+ assert_nil @mc.read(x)
99
+ assert_nil @dalli.read(y)
100
+ mres = @mc.write(x, 123)
101
+ dres = @dalli.write(y, 123)
102
+ assert_equal mres, dres
103
+
104
+ mres = @mc.read(x)
105
+ dres = @dalli.read(y)
106
+ assert_equal mres, dres
107
+ assert_equal 123, dres
108
+
109
+ mres = @mc.delete(x)
110
+ dres = @dalli.delete(y)
111
+ assert_equal mres, dres
112
+ assert_equal true, dres
113
+ end
114
+ end
115
+ end
116
+
117
+ should 'support increment/decrement commands' do
118
+ with_activesupport do
119
+ memcached do
120
+ connect
121
+ assert_equal true, @mc.write('counter', 0, :raw => true)
122
+ assert_equal 1, @mc.increment('counter')
123
+ assert_equal 2, @mc.increment('counter')
124
+ assert_equal 1, @mc.decrement('counter')
125
+ assert_equal "1", @mc.read('counter', :raw => true)
126
+
127
+ assert_equal true, @dalli.write('counter', 0, :raw => true)
128
+ assert_equal 1, @dalli.increment('counter')
129
+ assert_equal 2, @dalli.increment('counter')
130
+ assert_equal 1, @dalli.decrement('counter')
131
+ assert_equal "1", @dalli.read('counter', :raw => true)
132
+
133
+ assert_equal 0, @mc.increment('counterX')
134
+ assert_equal 0, @mc.increment('counterX')
135
+ assert_equal nil, @mc.read('counterX')
136
+
137
+ assert_equal 1, @dalli.increment('counterX')
138
+ assert_equal 2, @dalli.increment('counterX')
139
+ assert_equal 2, @dalli.read('counterX', :raw => true).to_i
140
+ end
141
+ end
142
+ end
143
+
144
+ should 'support other esoteric commands' do
145
+ with_activesupport do
146
+ memcached do
147
+ connect
148
+ ms = @mc.stats
149
+ ds = @dalli.stats
150
+ assert_equal ms.keys.sort, ds.keys.sort
151
+ assert_equal ms[ms.keys.first].keys.sort, ds[ds.keys.first].keys.sort
152
+
153
+ assert_equal true, @dalli.write(:foo, 'a')
154
+ assert_equal true, @mc.write(:foo, 'a')
155
+
156
+ assert_equal true, @mc.exist?(:foo)
157
+ assert_equal true, @dalli.exist?(:foo)
158
+
159
+ assert_equal false, @mc.exist?(:bar)
160
+ assert_equal false, @dalli.exist?(:bar)
161
+
162
+ @dalli.reset
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ def connect
169
+ @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => 'x')
170
+ @mc = ActiveSupport::Cache.lookup_store(:mem_cache_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => 'a')
171
+ @dalli.clear
172
+ end
173
+
174
+ def rand_key
175
+ rand(1_000_000_000)
176
+ end
177
+ end
@@ -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,398 @@
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 a live server' do
30
+
31
+ should "support get/set" do
32
+ memcached do |dc|
33
+ dc.flush
34
+
35
+ val1 = "1234567890"*105000
36
+ assert_error Dalli::DalliError, /too large/ do
37
+ dc.set('a', val1)
38
+ val2 = dc.get('a')
39
+ assert_equal val1, val2
40
+ end
41
+
42
+ val1 = "1234567890"*100000
43
+ dc.set('a', val1)
44
+ val2 = dc.get('a')
45
+ assert_equal val1, val2
46
+
47
+ assert_equal true, dc.set('a', nil)
48
+ assert_nil dc.get('a')
49
+ end
50
+ end
51
+
52
+ should "support the fetch operation" do
53
+ memcached do |dc|
54
+ dc.flush
55
+
56
+ expected = { 'blah' => 'blerg!' }
57
+ executed = false
58
+ value = dc.fetch('fetch_key') do
59
+ executed = true
60
+ expected
61
+ end
62
+ assert_equal expected, value
63
+ assert_equal true, executed
64
+
65
+ executed = false
66
+ value = dc.fetch('fetch_key') do
67
+ executed = true
68
+ expected
69
+ end
70
+ assert_equal expected, value
71
+ assert_equal false, executed
72
+ end
73
+ end
74
+
75
+ should "support the cas operation" do
76
+ memcached do |dc|
77
+ dc.flush
78
+
79
+ expected = { 'blah' => 'blerg!' }
80
+
81
+ resp = dc.cas('cas_key') do |value|
82
+ fail('Value should not exist')
83
+ end
84
+ assert_nil resp
85
+
86
+ mutated = { 'blah' => 'foo!' }
87
+ dc.set('cas_key', expected)
88
+ resp = dc.cas('cas_key') do |value|
89
+ assert_equal expected, value
90
+ mutated
91
+ end
92
+ assert_equal true, resp
93
+
94
+ resp = dc.get('cas_key')
95
+ assert_equal mutated, resp
96
+
97
+ # TODO Need to verify failure when value is mutated between get and add.
98
+ end
99
+ end
100
+
101
+ should "support multi-get" do
102
+ memcached do |dc|
103
+ dc.close
104
+ dc.flush
105
+ resp = dc.get_multi(%w(a b c d e f))
106
+ assert_equal({}, resp)
107
+
108
+ dc.set('a', 'foo')
109
+ dc.set('b', 123)
110
+ dc.set('c', %w(a b c))
111
+ resp = dc.get_multi(%w(a b c d e f))
112
+ assert_equal({ 'a' => 'foo', 'b' => 123, 'c' => %w(a b c) }, resp)
113
+
114
+ # Perform a huge multi-get with 10,000 elements.
115
+ arr = []
116
+ dc.multi do
117
+ 10_000.times do |idx|
118
+ dc.set idx, idx
119
+ arr << idx
120
+ end
121
+ end
122
+
123
+ result = dc.get_multi(arr)
124
+ assert_equal(10_000, result.size)
125
+ assert_equal(1000, result['1000'])
126
+ end
127
+ end
128
+
129
+ should 'support raw incr/decr' do
130
+ memcached do |client|
131
+ client.flush
132
+
133
+ assert_equal true, client.set('fakecounter', 0, 0, :raw => true)
134
+ assert_equal 1, client.incr('fakecounter', 1)
135
+ assert_equal 2, client.incr('fakecounter', 1)
136
+ assert_equal 3, client.incr('fakecounter', 1)
137
+ assert_equal 1, client.decr('fakecounter', 2)
138
+ assert_equal "1", client.get('fakecounter', :raw => true)
139
+
140
+ resp = client.incr('mycounter', 0)
141
+ assert_nil resp
142
+
143
+ resp = client.incr('mycounter', 1, 0, 2)
144
+ assert_equal 2, resp
145
+ resp = client.incr('mycounter', 1)
146
+ assert_equal 3, resp
147
+
148
+ resp = client.set('rawcounter', 10, 0, :raw => true)
149
+ assert_equal true, resp
150
+
151
+ resp = client.get('rawcounter', :raw => true)
152
+ assert_equal '10', resp
153
+
154
+ resp = client.incr('rawcounter', 1)
155
+ assert_equal 11, resp
156
+ end
157
+ end
158
+
159
+ should "support incr/decr operations" do
160
+ memcached do |dc|
161
+ dc.flush
162
+
163
+ resp = dc.decr('counter', 100, 5, 0)
164
+ assert_equal 0, resp
165
+
166
+ resp = dc.decr('counter', 10)
167
+ assert_equal 0, resp
168
+
169
+ resp = dc.incr('counter', 10)
170
+ assert_equal 10, resp
171
+
172
+ current = 10
173
+ 100.times do |x|
174
+ resp = dc.incr('counter', 10)
175
+ assert_equal current + ((x+1)*10), resp
176
+ end
177
+
178
+ resp = dc.decr('10billion', 0, 5, 10)
179
+ # go over the 32-bit mark to verify proper (un)packing
180
+ resp = dc.incr('10billion', 10_000_000_000)
181
+ assert_equal 10_000_000_010, resp
182
+
183
+ resp = dc.decr('10billion', 1)
184
+ assert_equal 10_000_000_009, resp
185
+
186
+ resp = dc.decr('10billion', 0)
187
+ assert_equal 10_000_000_009, resp
188
+
189
+ resp = dc.incr('10billion', 0)
190
+ assert_equal 10_000_000_009, resp
191
+
192
+ assert_nil dc.incr('DNE', 10)
193
+ assert_nil dc.decr('DNE', 10)
194
+
195
+ resp = dc.incr('big', 100, 5, 0xFFFFFFFFFFFFFFFE)
196
+ assert_equal 0xFFFFFFFFFFFFFFFE, resp
197
+ resp = dc.incr('big', 1)
198
+ assert_equal 0xFFFFFFFFFFFFFFFF, resp
199
+
200
+ # rollover the 64-bit value, we'll get something undefined.
201
+ resp = dc.incr('big', 1)
202
+ assert_not_equal 0x10000000000000000, resp
203
+ dc.reset
204
+ end
205
+ end
206
+
207
+ should 'support the append and prepend operations' do
208
+ memcached do |dc|
209
+ resp = dc.flush
210
+ assert_equal true, dc.set('456', 'xyz', 0, :raw => true)
211
+ assert_equal true, dc.prepend('456', '0')
212
+ assert_equal true, dc.append('456', '9')
213
+ assert_equal '0xyz9', dc.get('456', :raw => true)
214
+ assert_equal '0xyz9', dc.get('456')
215
+
216
+ assert_equal false, dc.append('nonexist', 'abc')
217
+ assert_equal false, dc.prepend('nonexist', 'abc')
218
+ end
219
+ end
220
+
221
+ should "pass a simple smoke test" do
222
+ memcached do |dc|
223
+ resp = dc.flush
224
+ assert_not_nil resp
225
+ assert_equal [true, true], resp
226
+
227
+ assert_equal true, dc.set(:foo, 'bar')
228
+ assert_equal 'bar', dc.get(:foo)
229
+
230
+ resp = dc.get('123')
231
+ assert_equal nil, resp
232
+
233
+ resp = dc.set('123', 'xyz')
234
+ assert_equal true, resp
235
+
236
+ resp = dc.get('123')
237
+ assert_equal 'xyz', resp
238
+
239
+ resp = dc.set('123', 'abc')
240
+ assert_equal true, resp
241
+
242
+ dc.prepend('123', '0')
243
+ dc.append('123', '0')
244
+
245
+ assert_raises Dalli::DalliError do
246
+ resp = dc.get('123')
247
+ end
248
+
249
+ dc.close
250
+ dc = nil
251
+
252
+ dc = Dalli::Client.new('localhost:19122')
253
+
254
+ resp = dc.set('456', 'xyz', 0, :raw => true)
255
+ assert_equal true, resp
256
+
257
+ resp = dc.prepend '456', '0'
258
+ assert_equal true, resp
259
+
260
+ resp = dc.append '456', '9'
261
+ assert_equal true, resp
262
+
263
+ resp = dc.get('456', :raw => true)
264
+ assert_equal '0xyz9', resp
265
+
266
+ resp = dc.stats
267
+ assert_equal Hash, resp.class
268
+
269
+ dc.close
270
+ end
271
+ end
272
+
273
+ should "support multithreaded access" do
274
+ memcached do |cache|
275
+ cache.flush
276
+ workers = []
277
+
278
+ cache.set('f', 'zzz')
279
+ assert_equal true, (cache.cas('f') do |value|
280
+ value << 'z'
281
+ end)
282
+ assert_equal 'zzzz', cache.get('f')
283
+
284
+ # Have a bunch of threads perform a bunch of operations at the same time.
285
+ # Verify the result of each operation to ensure the request and response
286
+ # are not intermingled between threads.
287
+ 10.times do
288
+ workers << Thread.new do
289
+ 100.times do
290
+ cache.set('a', 9)
291
+ cache.set('b', 11)
292
+ inc = cache.incr('cat', 10, 0, 10)
293
+ cache.set('f', 'zzz')
294
+ assert_not_nil(cache.cas('f') do |value|
295
+ value << 'z'
296
+ end)
297
+ assert_equal false, cache.add('a', 11)
298
+ assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
299
+ inc = cache.incr('cat', 10)
300
+ assert_equal 0, inc % 5
301
+ dec = cache.decr('cat', 5)
302
+ assert_equal 11, cache.get('b')
303
+ end
304
+ end
305
+ end
306
+
307
+ workers.each { |w| w.join }
308
+ cache.flush
309
+ end
310
+ end
311
+
312
+ should "handle namespaced keys" do
313
+ memcached do |dc|
314
+ dc = Dalli::Client.new('localhost:19122', :namespace => 'a')
315
+ dc.set('namespaced', 1)
316
+ dc2 = Dalli::Client.new('localhost:19122', :namespace => 'b')
317
+ dc2.set('namespaced', 2)
318
+ assert_equal 1, dc.get('namespaced')
319
+ assert_equal 2, dc2.get('namespaced')
320
+ end
321
+ end
322
+
323
+ should "handle namespaced keys in multi_get" do
324
+ memcached do |dc|
325
+ dc = Dalli::Client.new('localhost:19122', :namespace => 'a')
326
+ dc.set('a', 1)
327
+ dc.set('b', 2)
328
+ assert_equal({'a' => 1, 'b' => 2}, dc.get_multi('a', 'b'))
329
+ end
330
+ end
331
+
332
+ should "handle application marshalling issues" do
333
+ memcached do |dc|
334
+ old = Dalli.logger
335
+ Dalli.logger = Logger.new(nil)
336
+ begin
337
+ assert_equal false, dc.set('a', Proc.new { true })
338
+ ensure
339
+ Dalli.logger = old
340
+ end
341
+ end
342
+ end
343
+
344
+ context 'with compression' do
345
+ should 'allow large values' do
346
+ memcached do |dc|
347
+ dalli = Dalli::Client.new(dc.instance_variable_get(:@servers), :compression => true)
348
+
349
+ value = "0"*1024*1024
350
+ assert_raise Dalli::DalliError, /too large/ do
351
+ dc.set('verylarge', value)
352
+ end
353
+ dalli.set('verylarge', value)
354
+ end
355
+ end
356
+ end
357
+
358
+ context 'in low memory conditions' do
359
+
360
+ should 'handle error response correctly' do
361
+ memcached(19125, '-m 1 -M') do |dc|
362
+ failed = false
363
+ value = "1234567890"*100
364
+ 1_000.times do |idx|
365
+ begin
366
+ assert_equal true, dc.set(idx, value)
367
+ rescue Dalli::DalliError
368
+ failed = true
369
+ assert((800..900).include?(idx), "unexpected failure on iteration #{idx}")
370
+ break
371
+ end
372
+ end
373
+ assert failed, 'did not fail under low memory conditions'
374
+ end
375
+ end
376
+
377
+ should 'fit more values with compression' do
378
+ memcached(19126, '-m 1 -M') do |dc|
379
+ dalli = Dalli::Client.new('localhost:19126', :compression => true)
380
+ failed = false
381
+ value = "1234567890"*1000
382
+ 10_000.times do |idx|
383
+ begin
384
+ assert_equal true, dalli.set(idx, value)
385
+ rescue Dalli::DalliError
386
+ failed = true
387
+ assert((6000..7000).include?(idx), "unexpected failure on iteration #{idx}")
388
+ break
389
+ end
390
+ end
391
+ assert failed, 'did not fail under low memory conditions'
392
+ end
393
+ end
394
+
395
+ end
396
+
397
+ end
398
+ end