jjp-memcache-client 1.8.7

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,110 @@
1
+ # encoding: ascii-8bit
2
+ require 'test/unit'
3
+ require 'memcache'
4
+
5
+ class TestEventMachine < Test::Unit::TestCase
6
+
7
+ def test_concurrent_fibers
8
+ return puts("Skipping EventMachine test, not Ruby 1.9") if RUBY_VERSION < '1.9'
9
+ return puts("Skipping EventMachine test, no live server") if !live_server?
10
+
11
+ require 'eventmachine'
12
+ require 'memcache/event_machine'
13
+ ex = nil
14
+ m = MemCache.new(['127.0.0.1:11211', 'localhost:11211'])
15
+ within_em(3) do
16
+ begin
17
+ key1 = 'foo'
18
+ key2 = 'bar'*50
19
+ key3 = '£∞'*45
20
+ value1 = 'abc'
21
+ value2 = 'xyz'*1000
22
+ value3 = '∞§¶•ª'*1000
23
+
24
+ 100.times do
25
+ assert_equal "STORED\r\n", m.set(key1, value1)
26
+ assert_equal "STORED\r\n", m.set(key2, value2)
27
+ assert_equal "STORED\r\n", m.set(key3, value3)
28
+ m.get(key1)
29
+ m.get(key2)
30
+ m.get(key3)
31
+ assert m.delete(key1)
32
+ assert_equal "STORED\r\n", m.set(key1, value2)
33
+ m.get(key1)
34
+ assert_equal "STORED\r\n", m.set(key2, value3)
35
+ m.get(key2)
36
+ assert_equal "STORED\r\n", m.set(key3, value1)
37
+ m.get(key3)
38
+ h = m.get_multi(key1, key2, key3)
39
+ assert h
40
+ assert_equal Hash, h.class
41
+ assert h.size > 0
42
+ end
43
+ rescue Exception => exp
44
+ puts exp.message
45
+ ex = exp
46
+ ensure
47
+ EM.stop
48
+ end
49
+ end
50
+ raise ex if ex
51
+ end
52
+
53
+ def test_live_server
54
+ return puts("Skipping EventMachine test, not Ruby 1.9") if RUBY_VERSION < '1.9'
55
+ return puts("Skipping EventMachine test, no live server") if !live_server?
56
+
57
+ require 'eventmachine'
58
+ require 'memcache/event_machine'
59
+ ex = nil
60
+ within_em do
61
+ begin
62
+ m = MemCache.new(['127.0.0.1:11211', 'localhost:11211'])
63
+ key1 = 'foo'
64
+ key2 = 'bar'*50
65
+ key3 = '£∞'*50
66
+ value1 = 'abc'
67
+ value2 = 'xyz'*1000
68
+ value3 = '∞§¶•ª'*1000
69
+
70
+ 1000.times do
71
+ assert_equal "STORED\r\n", m.set(key1, value1)
72
+ assert_equal "STORED\r\n", m.set(key2, value2)
73
+ assert_equal "STORED\r\n", m.set(key3, value3)
74
+ assert_equal value1, m.get(key1)
75
+ assert_equal value2, m.get(key2)
76
+ assert_equal value3, m.get(key3)
77
+ assert_equal "DELETED\r\n", m.delete(key1)
78
+ assert_equal "STORED\r\n", m.set(key1, value2)
79
+ assert_equal value2, m.get(key1)
80
+ assert_equal "STORED\r\n", m.set(key2, value3)
81
+ assert_equal value3, m.get(key2)
82
+ assert_equal "STORED\r\n", m.set(key3, value1)
83
+ assert_equal value1, m.get(key3)
84
+ assert_equal({ key1 => value2, key2 => value3, key3 => value1 },
85
+ m.get_multi(key1, key2, key3))
86
+ end
87
+ rescue Exception => exp
88
+ puts exp.message
89
+ ex = exp
90
+ ensure
91
+ EM.stop
92
+ end
93
+ end
94
+ raise ex if ex
95
+ end
96
+
97
+ private
98
+
99
+ def within_em(count=1, &block)
100
+ EM.run do
101
+ count.times do
102
+ Fiber.new(&block).resume
103
+ end
104
+ end
105
+ end
106
+
107
+ def live_server?
108
+ TCPSocket.new('localhost', 11211) rescue nil
109
+ end
110
+ end
@@ -0,0 +1,1323 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'logger'
4
+ require 'stringio'
5
+ require 'test/unit'
6
+ $TESTING = true
7
+ require 'memcache'
8
+
9
+ begin
10
+ gem 'flexmock'
11
+ require 'flexmock/test_unit'
12
+ rescue LoadError => e
13
+ puts "Some tests require flexmock, please run `gem install flexmock`"
14
+ end
15
+
16
+ Thread.abort_on_exception = true
17
+
18
+ class MemCache
19
+
20
+ attr_writer :namespace
21
+ attr_writer :autofix_keys
22
+
23
+ end
24
+
25
+ class FakeSocket
26
+
27
+ attr_reader :written, :data
28
+
29
+ def initialize
30
+ @written = StringIO.new
31
+ @data = StringIO.new
32
+ end
33
+
34
+ def write(data)
35
+ @written.write data
36
+ end
37
+
38
+ def gets
39
+ @data.gets
40
+ end
41
+
42
+ def read(arg)
43
+ @data.read arg
44
+ end
45
+
46
+ end
47
+
48
+ class Test::Unit::TestCase
49
+ def requirement(bool, msg)
50
+ if bool
51
+ yield
52
+ else
53
+ puts msg
54
+ assert true
55
+ end
56
+ end
57
+
58
+ def memcached_running?
59
+ TCPSocket.new('localhost', 11211) rescue false
60
+ end
61
+
62
+ def xprofile(name, &block)
63
+ a = Time.now
64
+ block.call
65
+ Time.now - a
66
+ end
67
+
68
+ def profile(name, &block)
69
+ require 'ruby-prof'
70
+ a = Time.now
71
+ result = RubyProf.profile(&block)
72
+ time = Time.now - a
73
+ printer = RubyProf::GraphHtmlPrinter.new(result)
74
+ File.open("#{name}.html", 'w') do |f|
75
+ printer.print(f, :min_percent=>1)
76
+ end
77
+ time
78
+ end
79
+
80
+ end
81
+
82
+ class FakeServer
83
+
84
+ attr_accessor :host, :port, :socket, :weight, :multithread, :status
85
+
86
+ def initialize(socket = nil)
87
+ @closed = false
88
+ @host = 'example.com'
89
+ @port = 11211
90
+ @socket = socket || FakeSocket.new
91
+ @weight = 1
92
+ @multithread = true
93
+ @status = "CONNECTED"
94
+ end
95
+
96
+ def close
97
+ # begin
98
+ # raise "Already closed"
99
+ # rescue => e
100
+ # puts e.backtrace.join("\n")
101
+ # end
102
+ @closed = true
103
+ @socket = nil
104
+ @status = "NOT CONNECTED"
105
+ end
106
+
107
+ def alive?
108
+ # puts "I'm #{@closed ? 'dead' : 'alive'}"
109
+ !@closed
110
+ end
111
+
112
+ end
113
+
114
+ class TestMemCache < Test::Unit::TestCase
115
+
116
+ def setup
117
+ @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace'
118
+ end
119
+
120
+ def test_performance
121
+ requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
122
+
123
+ cache = MemCache.new(['localhost:11211',"127.0.0.1:11211"])
124
+ cache.flush_all
125
+ cache.add('a', 1, 120)
126
+ with = xprofile 'get' do
127
+ 1000.times do
128
+ cache.get('a')
129
+ end
130
+ end
131
+ puts ''
132
+ puts "1000 gets with socket timeout: #{with} sec"
133
+
134
+ cache = MemCache.new(['localhost:11211',"127.0.0.1:11211"], :timeout => nil)
135
+ cache.add('a', 1, 120)
136
+ without = xprofile 'get' do
137
+ 1000.times do
138
+ cache.get('a')
139
+ end
140
+ end
141
+ puts "1000 gets without socket timeout: #{without} sec"
142
+ end
143
+ end
144
+
145
+ def test_consistent_hashing
146
+ requirement(self.respond_to?(:flexmock), 'Flexmock is required to run this test') do
147
+
148
+ flexmock(MemCache::Server).new_instances.should_receive(:alive?).and_return(true)
149
+
150
+ # Setup a continuum of two servers
151
+ @cache.servers = ['mike1', 'mike2', 'mike3']
152
+
153
+ keys = []
154
+ 1000.times do |idx|
155
+ keys << idx.to_s
156
+ end
157
+
158
+ before_continuum = keys.map {|key| @cache.get_server_for_key(key) }
159
+
160
+ @cache.servers = ['mike1', 'mike2', 'mike3', 'mike4']
161
+
162
+ after_continuum = keys.map {|key| @cache.get_server_for_key(key) }
163
+
164
+ same_count = before_continuum.zip(after_continuum).find_all {|a| a[0].host == a[1].host }.size
165
+
166
+ # With continuum, we should see about 75% of the keys map to the same server
167
+ # With modulo, we would see about 25%.
168
+ assert same_count > 700
169
+ end
170
+ end
171
+
172
+ def test_get_multi_with_server_failure
173
+ @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace', :logger => nil #Logger.new(STDOUT)
174
+ s1 = FakeServer.new
175
+ s2 = FakeServer.new
176
+
177
+ # Write two messages to the socket to test failover
178
+ s1.socket.data.write "VALUE my_namespace:a 0 14\r\n\004\b\"\0170123456789\r\nEND\r\n"
179
+ s1.socket.data.rewind
180
+ s2.socket.data.write "bogus response\r\nbogus response\r\n"
181
+ s2.socket.data.rewind
182
+
183
+ @cache.servers = [s1, s2]
184
+
185
+ assert s1.alive?
186
+ assert s2.alive?
187
+ # a maps to s1, the rest map to s2
188
+ value = @cache.get_multi(['foo', 'bar', 'a', 'b', 'c'])
189
+ assert_equal({'a'=>'0123456789'}, value)
190
+ assert s1.alive?
191
+ assert !s2.alive?
192
+ end
193
+
194
+ def test_cache_get_with_failover
195
+ @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace', :logger => nil#Logger.new(STDOUT)
196
+ s1 = FakeServer.new
197
+ s2 = FakeServer.new
198
+
199
+ # Write two messages to the socket to test failover
200
+ s1.socket.data.write "VALUE foo 0 14\r\n\004\b\"\0170123456789\r\n"
201
+ s1.socket.data.rewind
202
+ s2.socket.data.write "bogus response\r\nbogus response\r\n"
203
+ s2.socket.data.rewind
204
+
205
+ @cache.instance_variable_set(:@failover, true)
206
+ @cache.servers = [s1, s2]
207
+
208
+ assert s1.alive?
209
+ assert s2.alive?
210
+ @cache.get('foo')
211
+ assert s1.alive?
212
+ assert !s2.alive?
213
+ end
214
+
215
+ def test_cache_get_without_failover
216
+ s1 = FakeServer.new
217
+ s2 = FakeServer.new
218
+
219
+ s1.socket.data.write "VALUE foo 0 14\r\n\004\b\"\0170123456789\r\n"
220
+ s1.socket.data.rewind
221
+ s2.socket.data.write "bogus response\r\nbogus response\r\n"
222
+ s2.socket.data.rewind
223
+
224
+ @cache.instance_variable_set(:@failover, false)
225
+ @cache.servers = [s1, s2]
226
+
227
+ assert s1.alive?
228
+ assert s2.alive?
229
+ e = assert_raise MemCache::MemCacheError do
230
+ @cache.get('foo')
231
+ end
232
+ assert s1.alive?
233
+ assert !s2.alive?
234
+
235
+ assert_equal "No servers available", e.message
236
+ end
237
+
238
+ def test_cache_get
239
+ server = util_setup_fake_server
240
+
241
+ assert_equal "\004\b\"\0170123456789",
242
+ @cache.cache_get(server, 'my_namespace:key')
243
+
244
+ assert_equal "get my_namespace:key\r\n",
245
+ server.socket.written.string
246
+ end
247
+
248
+ def test_cache_get_EOF
249
+ server = util_setup_fake_server
250
+ server.socket.data.string = ''
251
+
252
+ e = assert_raise IndexError do
253
+ @cache.cache_get server, 'my_namespace:key'
254
+ end
255
+
256
+ assert_equal "No connection to server (NOT CONNECTED)", e.message
257
+ end
258
+
259
+ def test_cache_get_bad_state
260
+ server = FakeServer.new
261
+
262
+ # Write two messages to the socket to test failover
263
+ server.socket.data.write "bogus response\r\nbogus response\r\n"
264
+ server.socket.data.rewind
265
+
266
+ @cache.servers = []
267
+ @cache.servers << server
268
+
269
+ e = assert_raise IndexError do
270
+ @cache.cache_get(server, 'my_namespace:key')
271
+ end
272
+
273
+ assert_match(/#{Regexp.quote 'No connection to server (NOT CONNECTED)'}/, e.message)
274
+
275
+ assert !server.alive?
276
+ end
277
+
278
+ def test_cache_get_miss
279
+ socket = FakeSocket.new
280
+ socket.data.write "END\r\n"
281
+ socket.data.rewind
282
+ server = FakeServer.new socket
283
+
284
+ assert_equal nil, @cache.cache_get(server, 'my_namespace:key')
285
+
286
+ assert_equal "get my_namespace:key\r\n",
287
+ socket.written.string
288
+ end
289
+
290
+ def test_cache_get_multi
291
+ server = util_setup_fake_server
292
+ server.socket.data.write "VALUE foo 0 7\r\n"
293
+ server.socket.data.write "\004\b\"\bfoo\r\n"
294
+ server.socket.data.write "VALUE bar 0 7\r\n"
295
+ server.socket.data.write "\004\b\"\bbar\r\n"
296
+ server.socket.data.write "END\r\n"
297
+ server.socket.data.rewind
298
+
299
+ result = @cache.cache_get_multi server, 'foo bar baz'
300
+
301
+ assert_equal 2, result.length
302
+ assert_equal "\004\b\"\bfoo", result['foo']
303
+ assert_equal "\004\b\"\bbar", result['bar']
304
+ end
305
+
306
+ def test_cache_get_multi_EOF
307
+ server = util_setup_fake_server
308
+ server.socket.data.string = ''
309
+
310
+ e = assert_raise IndexError do
311
+ @cache.cache_get_multi server, 'my_namespace:key'
312
+ end
313
+
314
+ assert_equal "No connection to server (NOT CONNECTED)", e.message
315
+ end
316
+
317
+ def test_cache_get_multi_bad_state
318
+ server = FakeServer.new
319
+
320
+ # Write two messages to the socket to test failover
321
+ server.socket.data.write "bogus response\r\nbogus response\r\n"
322
+ server.socket.data.rewind
323
+
324
+ @cache.servers = []
325
+ @cache.servers << server
326
+
327
+ e = assert_raise IndexError do
328
+ @cache.cache_get_multi server, 'my_namespace:key'
329
+ end
330
+
331
+ assert_match(/#{Regexp.quote 'No connection to server (NOT CONNECTED)'}/, e.message)
332
+
333
+ assert !server.alive?
334
+ end
335
+
336
+ def test_multithread_error
337
+ server = FakeServer.new
338
+ server.multithread = false
339
+
340
+ @cache = MemCache.new(['localhost:1'], :multithread => false)
341
+
342
+ server.socket.data.write "bogus response\r\nbogus response\r\n"
343
+ server.socket.data.rewind
344
+
345
+ @cache.servers = []
346
+ @cache.servers << server
347
+
348
+ assert_nothing_raised do
349
+ @cache.set 'a', 1
350
+ end
351
+
352
+ passed = true
353
+ Thread.new do
354
+ begin
355
+ @cache.set 'b', 2
356
+ passed = false
357
+ rescue MemCache::MemCacheError => me
358
+ passed = me.message =~ /multiple threads/
359
+ end
360
+ end
361
+ assert passed
362
+ end
363
+
364
+ def test_initialize
365
+ cache = MemCache.new :namespace => 'my_namespace', :readonly => true
366
+
367
+ assert_equal 'my_namespace', cache.namespace
368
+ assert_equal true, cache.readonly?
369
+ assert_equal true, cache.servers.empty?
370
+ end
371
+
372
+ def test_initialize_compatible
373
+ cache = MemCache.new ['localhost:11211', 'localhost:11212'],
374
+ :namespace => 'my_namespace', :readonly => true
375
+
376
+ assert_equal 'my_namespace', cache.namespace
377
+ assert_equal true, cache.readonly?
378
+ assert_equal false, cache.servers.empty?
379
+ end
380
+
381
+ def test_initialize_compatible_no_hash
382
+ cache = MemCache.new ['localhost:11211', 'localhost:11212']
383
+
384
+ assert_equal nil, cache.namespace
385
+ assert_equal false, cache.readonly?
386
+ assert_equal false, cache.servers.empty?
387
+ end
388
+
389
+ def test_initialize_compatible_one_server
390
+ cache = MemCache.new 'localhost:11211'
391
+
392
+ assert_equal nil, cache.namespace
393
+ assert_equal false, cache.readonly?
394
+ assert_equal false, cache.servers.empty?
395
+ end
396
+
397
+ def test_initialize_compatible_bad_arg
398
+ e = assert_raise ArgumentError do
399
+ cache = MemCache.new Object.new
400
+ end
401
+
402
+ assert_equal 'first argument must be Array, Hash or String', e.message
403
+ end
404
+
405
+ def test_initialize_multiple_servers
406
+ cache = MemCache.new %w[localhost:11211 localhost:11212],
407
+ :namespace => 'my_namespace', :readonly => true
408
+
409
+ assert_equal 'my_namespace', cache.namespace
410
+ assert_equal true, cache.readonly?
411
+ assert_equal false, cache.servers.empty?
412
+ assert !cache.instance_variable_get(:@continuum).empty?
413
+ end
414
+
415
+ def test_initialize_too_many_args
416
+ assert_raises ArgumentError do
417
+ MemCache.new 1, 2, 3
418
+ end
419
+ end
420
+
421
+ def test_decr
422
+ server = FakeServer.new
423
+ server.socket.data.write "5\r\n"
424
+ server.socket.data.rewind
425
+
426
+ @cache.servers = []
427
+ @cache.servers << server
428
+
429
+ value = @cache.decr 'key'
430
+
431
+ assert_equal "decr my_namespace:key 1\r\n",
432
+ @cache.servers.first.socket.written.string
433
+
434
+ assert_equal 5, value
435
+ end
436
+
437
+ def test_decr_not_found
438
+ server = FakeServer.new
439
+ server.socket.data.write "NOT_FOUND\r\n"
440
+ server.socket.data.rewind
441
+
442
+ @cache.servers = []
443
+ @cache.servers << server
444
+
445
+ value = @cache.decr 'key'
446
+
447
+ assert_equal "decr my_namespace:key 1\r\n",
448
+ @cache.servers.first.socket.written.string
449
+
450
+ assert_equal nil, value
451
+ end
452
+
453
+ def test_decr_space_padding
454
+ server = FakeServer.new
455
+ server.socket.data.write "5 \r\n"
456
+ server.socket.data.rewind
457
+
458
+ @cache.servers = []
459
+ @cache.servers << server
460
+
461
+ value = @cache.decr 'key'
462
+
463
+ assert_equal "decr my_namespace:key 1\r\n",
464
+ @cache.servers.first.socket.written.string
465
+
466
+ assert_equal 5, value
467
+ end
468
+
469
+ def test_get
470
+ util_setup_fake_server
471
+
472
+ value = @cache.get 'key'
473
+
474
+ assert_equal "get my_namespace:key\r\n",
475
+ @cache.servers.first.socket.written.string
476
+
477
+ assert_equal '0123456789', value
478
+ end
479
+
480
+ def test_fetch_without_a_block
481
+ server = FakeServer.new
482
+ server.socket.data.write "END\r\n"
483
+ server.socket.data.rewind
484
+
485
+ @cache.servers = [server]
486
+
487
+ flexmock(@cache).should_receive(:get).with('key', false).and_return(nil)
488
+
489
+ value = @cache.fetch('key', 1)
490
+ assert_equal nil, value
491
+ end
492
+
493
+ def test_fetch_miss
494
+ server = FakeServer.new
495
+ server.socket.data.write "END\r\n"
496
+ server.socket.data.rewind
497
+
498
+ @cache.servers = [server]
499
+
500
+ flexmock(@cache).should_receive(:get).with('key', false).and_return(nil)
501
+ flexmock(@cache).should_receive(:add).with('key', 'value', 1, false)
502
+
503
+ value = @cache.fetch('key', 1) { 'value' }
504
+
505
+ assert_equal 'value', value
506
+ end
507
+
508
+ def test_fetch_hit
509
+ server = FakeServer.new
510
+ server.socket.data.write "END\r\n"
511
+ server.socket.data.rewind
512
+
513
+ @cache.servers = [server]
514
+
515
+ flexmock(@cache).should_receive(:get).with('key', false).and_return('value')
516
+ flexmock(@cache).should_receive(:add).never
517
+
518
+ value = @cache.fetch('key', 1) { raise 'Should not be called.' }
519
+
520
+ assert_equal 'value', value
521
+ end
522
+
523
+ def test_get_bad_key
524
+ util_setup_fake_server
525
+ assert_raise ArgumentError do @cache.get 'k y' end
526
+
527
+ util_setup_fake_server
528
+ assert_raise ArgumentError do @cache.get 'k' * 250 end
529
+ end
530
+
531
+ def test_get_cache_get_IOError
532
+ socket = Object.new
533
+ def socket.write(arg) raise IOError, 'some io error'; end
534
+ server = FakeServer.new socket
535
+
536
+ @cache.servers = []
537
+ @cache.servers << server
538
+
539
+ e = assert_raise MemCache::MemCacheError do
540
+ @cache.get 'my_namespace:key'
541
+ end
542
+
543
+ assert_equal 'some io error', e.message
544
+ end
545
+
546
+ def test_get_cache_get_SystemCallError
547
+ socket = Object.new
548
+ def socket.write(arg) raise SystemCallError, 'some syscall error'; end
549
+ server = FakeServer.new socket
550
+
551
+ @cache.servers = []
552
+ @cache.servers << server
553
+
554
+ e = assert_raise MemCache::MemCacheError do
555
+ @cache.get 'my_namespace:key'
556
+ end
557
+
558
+ assert_equal 'unknown error - some syscall error', e.message.downcase
559
+ end
560
+
561
+ def test_get_no_connection
562
+ @cache.servers = 'localhost:1'
563
+ e = assert_raise MemCache::MemCacheError do
564
+ @cache.get 'key'
565
+ end
566
+
567
+ assert_match(/^No connection to server/, e.message)
568
+ end
569
+
570
+ def test_get_no_servers
571
+ @cache.servers = []
572
+ e = assert_raise MemCache::MemCacheError do
573
+ @cache.get 'key'
574
+ end
575
+
576
+ assert_equal 'No active servers', e.message
577
+ end
578
+
579
+ def test_get_multi
580
+ server = FakeServer.new
581
+ server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
582
+ server.socket.data.write "\004\b\"\0170123456789\r\n"
583
+ server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
584
+ server.socket.data.write "\004\b\"\0179876543210\r\n"
585
+ server.socket.data.write "END\r\n"
586
+ server.socket.data.rewind
587
+
588
+ @cache.servers = []
589
+ @cache.servers << server
590
+
591
+ values = @cache.get_multi 'key', 'keyb'
592
+
593
+ assert_equal "get my_namespace:key my_namespace:keyb\r\n",
594
+ server.socket.written.string
595
+
596
+ expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
597
+
598
+ assert_equal expected.sort, values.sort
599
+ end
600
+
601
+ def test_get_multi_raw
602
+ server = FakeServer.new
603
+ server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
604
+ server.socket.data.write "0123456789\r\n"
605
+ server.socket.data.write "VALUE my_namespace:keyb 0 10\r\n"
606
+ server.socket.data.write "9876543210\r\n"
607
+ server.socket.data.write "END\r\n"
608
+ server.socket.data.rewind
609
+
610
+ @cache.servers = []
611
+ @cache.servers << server
612
+
613
+ values = @cache.get_multi 'key', 'keyb', :raw => true
614
+
615
+ assert_equal "get my_namespace:key my_namespace:keyb\r\n",
616
+ server.socket.written.string
617
+
618
+ expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
619
+
620
+ assert_equal expected.sort, values.sort
621
+ end
622
+
623
+ def test_get_raw
624
+ server = FakeServer.new
625
+ server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
626
+ server.socket.data.write "0123456789\r\n"
627
+ server.socket.data.write "END\r\n"
628
+ server.socket.data.rewind
629
+
630
+ @cache.servers = []
631
+ @cache.servers << server
632
+
633
+
634
+ value = @cache.get 'key', true
635
+
636
+ assert_equal "get my_namespace:key\r\n",
637
+ @cache.servers.first.socket.written.string
638
+
639
+ assert_equal '0123456789', value
640
+ end
641
+
642
+ def test_get_server_for_key
643
+ server = @cache.get_server_for_key 'key'
644
+ assert_equal 'localhost', server.host
645
+ assert_equal 1, server.port
646
+ end
647
+
648
+ def test_get_server_for_key_multiple
649
+ s1 = util_setup_server @cache, 'one.example.com', ''
650
+ s2 = util_setup_server @cache, 'two.example.com', ''
651
+ @cache.servers = [s1, s2]
652
+
653
+ server = @cache.get_server_for_key 'keya'
654
+ assert_equal 'two.example.com', server.host
655
+ server = @cache.get_server_for_key 'keyb'
656
+ assert_equal 'two.example.com', server.host
657
+ server = @cache.get_server_for_key 'keyc'
658
+ assert_equal 'two.example.com', server.host
659
+ server = @cache.get_server_for_key 'keyd'
660
+ assert_equal 'one.example.com', server.host
661
+ end
662
+
663
+ def test_get_server_for_key_no_servers
664
+ @cache.servers = []
665
+
666
+ e = assert_raise MemCache::MemCacheError do
667
+ @cache.get_server_for_key 'key'
668
+ end
669
+
670
+ assert_equal 'No servers available', e.message
671
+ end
672
+
673
+ def test_get_server_for_key_spaces
674
+ e = assert_raise ArgumentError do
675
+ @cache.get_server_for_key 'space key'
676
+ end
677
+ assert_equal 'illegal character in key "space key"', e.message
678
+ end
679
+
680
+ def test_get_server_for_blank_key
681
+ e = assert_raise ArgumentError do
682
+ @cache.get_server_for_key ''
683
+ end
684
+ assert_equal 'key cannot be blank', e.message
685
+ end
686
+
687
+ def test_get_server_for_key_length
688
+ @cache.get_server_for_key 'x' * 250
689
+ long_key = 'x' * 251
690
+ e = assert_raise ArgumentError do
691
+ @cache.get_server_for_key long_key
692
+ end
693
+ assert_equal "key too long #{long_key.inspect}", e.message
694
+ end
695
+
696
+ def test_incr
697
+ server = FakeServer.new
698
+ server.socket.data.write "5\r\n"
699
+ server.socket.data.rewind
700
+
701
+ @cache.servers = []
702
+ @cache.servers << server
703
+
704
+ value = @cache.incr 'key'
705
+
706
+ assert_equal "incr my_namespace:key 1\r\n",
707
+ @cache.servers.first.socket.written.string
708
+
709
+ assert_equal 5, value
710
+ end
711
+
712
+ def test_incr_not_found
713
+ server = FakeServer.new
714
+ server.socket.data.write "NOT_FOUND\r\n"
715
+ server.socket.data.rewind
716
+
717
+ @cache.servers = []
718
+ @cache.servers << server
719
+
720
+ value = @cache.incr 'key'
721
+
722
+ assert_equal "incr my_namespace:key 1\r\n",
723
+ @cache.servers.first.socket.written.string
724
+
725
+ assert_equal nil, value
726
+ end
727
+
728
+ def test_incr_space_padding
729
+ server = FakeServer.new
730
+ server.socket.data.write "5 \r\n"
731
+ server.socket.data.rewind
732
+
733
+ @cache.servers = []
734
+ @cache.servers << server
735
+
736
+ value = @cache.incr 'key'
737
+
738
+ assert_equal "incr my_namespace:key 1\r\n",
739
+ @cache.servers.first.socket.written.string
740
+
741
+ assert_equal 5, value
742
+ end
743
+
744
+ def test_make_cache_key
745
+ assert_equal 'my_namespace:key', @cache.make_cache_key('key')
746
+ @cache.namespace = nil
747
+ assert_equal 'key', @cache.make_cache_key('key')
748
+ end
749
+
750
+ def test_make_cache_key_without_autofix
751
+ @cache.autofix_keys = false
752
+
753
+ key = "keys with more than two hundred and fifty characters can cause problems, because they get truncated and start colliding with each other. It's not a common occurrence, but when it happens is very hard to debug. the autofix option takes care of that for you"
754
+ hash = Digest::SHA1.hexdigest(key)
755
+ @cache.namespace = nil
756
+ assert_equal key, @cache.make_cache_key(key)
757
+ end
758
+
759
+ def test_make_cache_key_with_autofix
760
+ @cache.autofix_keys = true
761
+
762
+ @cache.namespace = "my_namespace"
763
+ assert_equal 'my_namespace:key', @cache.make_cache_key('key')
764
+ @cache.namespace = nil
765
+ assert_equal 'key', @cache.make_cache_key('key')
766
+
767
+ key = "keys with more than two hundred and fifty characters can cause problems, because they get truncated and start colliding with each other. It's not a common occurrence, but when it happens is very hard to debug. the autofix option takes care of that for you"
768
+ hash = Digest::SHA1.hexdigest(key)
769
+ @cache.namespace = "my_namespace"
770
+ assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
771
+ @cache.namespace = nil
772
+ assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
773
+
774
+ key = "a short key with spaces"
775
+ hash = Digest::SHA1.hexdigest(key)
776
+ @cache.namespace = "my_namespace"
777
+ assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
778
+ @cache.namespace = nil
779
+ assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
780
+
781
+ # namespace + separator + key > 250
782
+ key = 'k' * 240
783
+ hash = Digest::SHA1.hexdigest(key)
784
+ @cache.namespace = 'n' * 10
785
+ assert_equal "#{@cache.namespace}:#{hash}-autofixed", @cache.make_cache_key(key)
786
+ end
787
+
788
+ def test_servers
789
+ server = FakeServer.new
790
+ @cache.servers = []
791
+ @cache.servers << server
792
+ assert_equal [server], @cache.servers
793
+ end
794
+
795
+ def test_set
796
+ server = FakeServer.new
797
+ server.socket.data.write "STORED\r\n"
798
+ server.socket.data.rewind
799
+ @cache.servers = []
800
+ @cache.servers << server
801
+
802
+ @cache.set 'key', 'value'
803
+
804
+ dumped = Marshal.dump('value')
805
+ expected = "set my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
806
+ assert_equal expected, server.socket.written.string
807
+ end
808
+
809
+ def test_set_utf8
810
+ server = FakeServer.new
811
+ server.socket.data.write "STORED\r\n"
812
+ server.socket.data.rewind
813
+ @cache.servers = []
814
+ @cache.servers << server
815
+
816
+ @cache.set 'key', 'value 启'
817
+
818
+ dumped = Marshal.dump('value 启')
819
+
820
+ expected = "set my_namespace:key 0 0 #{dumped.bytesize}\r\n"
821
+ expected << dumped
822
+ expected << "\r\n"
823
+ assert_equal expected, server.socket.written.string
824
+ end
825
+
826
+ def test_set_expiry
827
+ server = FakeServer.new
828
+ server.socket.data.write "STORED\r\n"
829
+ server.socket.data.rewind
830
+ @cache.servers = []
831
+ @cache.servers << server
832
+
833
+ @cache.set 'key', 'value', 5
834
+
835
+ dumped = Marshal.dump('value')
836
+ expected = "set my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
837
+ assert_equal expected, server.socket.written.string
838
+ end
839
+
840
+ def test_set_raw
841
+ server = FakeServer.new
842
+ server.socket.data.write "STORED\r\n"
843
+ server.socket.data.rewind
844
+ @cache.servers = []
845
+ @cache.servers << server
846
+
847
+ @cache.set 'key', 'value', 0, true
848
+
849
+ expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
850
+ assert_equal expected, server.socket.written.string
851
+ end
852
+
853
+ def test_set_utf8_raw
854
+ server = FakeServer.new
855
+ server.socket.data.write "STORED\r\n"
856
+ server.socket.data.rewind
857
+ @cache.servers = []
858
+ @cache.servers << server
859
+
860
+ val = 'value 启'
861
+ @cache.set 'key', val, 0, true
862
+
863
+ expected = "set my_namespace:key 0 0 #{val.bytesize}\r\n#{val}\r\n"
864
+ assert_equal expected, server.socket.written.string
865
+ end
866
+
867
+ def test_set_readonly
868
+ cache = MemCache.new :readonly => true
869
+
870
+ e = assert_raise MemCache::MemCacheError do
871
+ cache.set 'key', 'value'
872
+ end
873
+
874
+ assert_equal 'Update of readonly cache', e.message
875
+ end
876
+
877
+ def test_check_size_on
878
+ cache = MemCache.new :check_size => true
879
+
880
+ server = FakeServer.new
881
+ server.socket.data.write "STORED\r\n"
882
+ server.socket.data.rewind
883
+
884
+ cache.servers = []
885
+ cache.servers << server
886
+
887
+ e = assert_raise MemCache::MemCacheError do
888
+ cache.set 'key', 'v' * 1048577
889
+ end
890
+
891
+ assert_equal 'Value too large, memcached can only store 1MB of data per key', e.message
892
+ end
893
+
894
+ def test_check_size_off
895
+ cache = MemCache.new :check_size => false
896
+
897
+ server = FakeServer.new
898
+ server.socket.data.write "STORED\r\n"
899
+ server.socket.data.rewind
900
+
901
+ cache.servers = []
902
+ cache.servers << server
903
+
904
+ assert_nothing_raised do
905
+ cache.set 'key', 'v' * 1048577
906
+ end
907
+ end
908
+
909
+ def test_set_too_big
910
+ server = FakeServer.new
911
+
912
+ # Write two messages to the socket to test failover
913
+ server.socket.data.write "SERVER_ERROR\r\nSERVER_ERROR object too large for cache\r\n"
914
+ server.socket.data.rewind
915
+
916
+ @cache.servers = []
917
+ @cache.servers << server
918
+
919
+ e = assert_raise MemCache::MemCacheError do
920
+ @cache.set 'key', 'v'
921
+ end
922
+
923
+ assert_match(/object too large for cache/, e.message)
924
+ end
925
+
926
+ def test_prepend
927
+ server = FakeServer.new
928
+ server.socket.data.write "STORED\r\n"
929
+ server.socket.data.rewind
930
+ @cache.servers = []
931
+ @cache.servers << server
932
+
933
+ @cache.prepend 'key', 'value'
934
+
935
+ dumped = Marshal.dump('value')
936
+
937
+ expected = "prepend my_namespace:key 0 0 5\r\nvalue\r\n"
938
+ assert_equal expected, server.socket.written.string
939
+ end
940
+
941
+ def test_append
942
+ server = FakeServer.new
943
+ server.socket.data.write "STORED\r\n"
944
+ server.socket.data.rewind
945
+ @cache.servers = []
946
+ @cache.servers << server
947
+
948
+ @cache.append 'key', 'value'
949
+
950
+ expected = "append my_namespace:key 0 0 5\r\nvalue\r\n"
951
+ assert_equal expected, server.socket.written.string
952
+ end
953
+
954
+ def test_replace
955
+ server = FakeServer.new
956
+ server.socket.data.write "STORED\r\n"
957
+ server.socket.data.rewind
958
+ @cache.servers = []
959
+ @cache.servers << server
960
+
961
+ @cache.replace 'key', 'value', 150
962
+
963
+ dumped = Marshal.dump('value')
964
+
965
+ expected = "replace my_namespace:key 0 150 #{dumped.length}\r\n#{dumped}\r\n"
966
+ assert_equal expected, server.socket.written.string
967
+ end
968
+
969
+ def test_add
970
+ server = FakeServer.new
971
+ server.socket.data.write "STORED\r\n"
972
+ server.socket.data.rewind
973
+ @cache.servers = []
974
+ @cache.servers << server
975
+
976
+ @cache.add 'key', 'value'
977
+
978
+ dumped = Marshal.dump('value')
979
+
980
+ expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
981
+ assert_equal expected, server.socket.written.string
982
+ end
983
+
984
+ def test_add_exists
985
+ server = FakeServer.new
986
+ server.socket.data.write "NOT_STORED\r\n"
987
+ server.socket.data.rewind
988
+ @cache.servers = []
989
+ @cache.servers << server
990
+
991
+ @cache.add 'key', 'value'
992
+
993
+ dumped = Marshal.dump('value')
994
+ expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
995
+ assert_equal expected, server.socket.written.string
996
+ end
997
+
998
+ def test_add_expiry
999
+ server = FakeServer.new
1000
+ server.socket.data.write "STORED\r\n"
1001
+ server.socket.data.rewind
1002
+ @cache.servers = []
1003
+ @cache.servers << server
1004
+
1005
+ @cache.add 'key', 'value', 5
1006
+
1007
+ dumped = Marshal.dump('value')
1008
+ expected = "add my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
1009
+ assert_equal expected, server.socket.written.string
1010
+ end
1011
+
1012
+ def test_add_raw
1013
+ server = FakeServer.new
1014
+ server.socket.data.write "STORED\r\n"
1015
+ server.socket.data.rewind
1016
+ @cache.servers = []
1017
+ @cache.servers << server
1018
+
1019
+ @cache.add 'key', 'value', 0, true
1020
+
1021
+ expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
1022
+ assert_equal expected, server.socket.written.string
1023
+ end
1024
+
1025
+ def test_add_raw_int
1026
+ server = FakeServer.new
1027
+ server.socket.data.write "STORED\r\n"
1028
+ server.socket.data.rewind
1029
+ @cache.servers = []
1030
+ @cache.servers << server
1031
+
1032
+ @cache.add 'key', 12, 0, true
1033
+
1034
+ expected = "add my_namespace:key 0 0 2\r\n12\r\n"
1035
+ assert_equal expected, server.socket.written.string
1036
+ end
1037
+
1038
+ def test_add_readonly
1039
+ cache = MemCache.new :readonly => true
1040
+
1041
+ e = assert_raise MemCache::MemCacheError do
1042
+ cache.add 'key', 'value'
1043
+ end
1044
+
1045
+ assert_equal 'Update of readonly cache', e.message
1046
+ end
1047
+
1048
+ def test_delete
1049
+ server = FakeServer.new
1050
+ @cache.servers = []
1051
+ @cache.servers << server
1052
+
1053
+ @cache.delete 'key'
1054
+
1055
+ expected = "delete my_namespace:key\r\n"
1056
+ assert_equal expected, server.socket.written.string
1057
+ end
1058
+
1059
+ def test_delete_with_expiry
1060
+ server = FakeServer.new
1061
+ @cache.servers = []
1062
+ @cache.servers << server
1063
+
1064
+ @cache.delete 'key', 300
1065
+
1066
+ expected = "delete my_namespace:key\r\n"
1067
+ assert_equal expected, server.socket.written.string
1068
+ end
1069
+
1070
+ def test_flush_all
1071
+ @cache.servers = []
1072
+ 3.times { @cache.servers << FakeServer.new }
1073
+
1074
+ @cache.flush_all
1075
+
1076
+ expected = "flush_all\r\n"
1077
+ @cache.servers.each do |server|
1078
+ assert_equal expected, server.socket.written.string
1079
+ end
1080
+ end
1081
+
1082
+ def test_flush_all_with_delay
1083
+ @cache.servers = []
1084
+ 3.times { @cache.servers << FakeServer.new }
1085
+
1086
+ @cache.flush_all(10)
1087
+
1088
+ @cache.servers.each_with_index do |server, idx|
1089
+ expected = "flush_all #{idx*10}\r\n"
1090
+ assert_equal expected, server.socket.written.string
1091
+ end
1092
+ end
1093
+
1094
+ def test_flush_all_failure
1095
+ socket = FakeSocket.new
1096
+
1097
+ # Write two messages to the socket to test failover
1098
+ socket.data.write "ERROR\r\nERROR\r\n"
1099
+ socket.data.rewind
1100
+
1101
+ server = FakeServer.new socket
1102
+
1103
+ @cache.servers = []
1104
+ @cache.servers << server
1105
+
1106
+ assert_raise MemCache::MemCacheError do
1107
+ @cache.flush_all
1108
+ end
1109
+
1110
+ assert_match(/flush_all\r\n/, socket.written.string)
1111
+ end
1112
+
1113
+ def test_flush_all_for_real
1114
+ requirement(memcached_running?, 'A real memcached server must be running for testing flush_all') do
1115
+ cache = MemCache.new "localhost:11211", :namespace => "test_flush_all"
1116
+ k, v = "1234", "test"
1117
+ assert_nil cache.get(k)
1118
+ cache.set(k, v)
1119
+ assert_equal v, cache.get(k)
1120
+ cache.flush_all
1121
+ assert_nil cache.get(k)
1122
+ end
1123
+ end
1124
+
1125
+ def test_stats
1126
+ socket = FakeSocket.new
1127
+ socket.data.write "STAT pid 20188\r\nSTAT total_items 32\r\nSTAT version 1.2.3\r\nSTAT rusage_user 1:300\r\nSTAT dummy ok\r\nEND\r\n"
1128
+ socket.data.rewind
1129
+ server = FakeServer.new socket
1130
+ def server.host() 'localhost'; end
1131
+ def server.port() 11211; end
1132
+
1133
+ @cache.servers = []
1134
+ @cache.servers << server
1135
+
1136
+ expected = {
1137
+ 'localhost:11211' => {
1138
+ 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
1139
+ 'rusage_user' => 1.0003, 'dummy' => 'ok'
1140
+ }
1141
+ }
1142
+ assert_equal expected, @cache.stats
1143
+
1144
+ assert_equal "stats\r\n", socket.written.string
1145
+ end
1146
+
1147
+ def test_basic_threaded_operations_should_work
1148
+ cache = MemCache.new :multithread => true,
1149
+ :namespace => 'my_namespace',
1150
+ :readonly => false
1151
+
1152
+ server = FakeServer.new
1153
+ server.socket.data.write "STORED\r\n"
1154
+ server.socket.data.rewind
1155
+
1156
+ cache.servers = []
1157
+ cache.servers << server
1158
+
1159
+ assert cache.multithread
1160
+
1161
+ assert_nothing_raised do
1162
+ cache.set "test", "test value"
1163
+ end
1164
+
1165
+ output = server.socket.written.string
1166
+ assert_match(/set my_namespace:test/, output)
1167
+ assert_match(/test value/, output)
1168
+ end
1169
+
1170
+ def test_namespace_separator
1171
+ cache = MemCache.new :namespace => 'ns', :namespace_separator => ''
1172
+
1173
+ server = FakeServer.new
1174
+ server.socket.data.write "STORED\r\n"
1175
+ server.socket.data.rewind
1176
+
1177
+ cache.servers = []
1178
+ cache.servers << server
1179
+
1180
+ assert_nothing_raised do
1181
+ cache.set "test", "test value"
1182
+ end
1183
+
1184
+ output = server.socket.written.string
1185
+ assert_match(/set nstest/, output)
1186
+ assert_match(/test value/, output)
1187
+ end
1188
+
1189
+ def test_basic_unthreaded_operations_should_work
1190
+ cache = MemCache.new :multithread => false,
1191
+ :namespace => 'my_namespace',
1192
+ :readonly => false
1193
+
1194
+ server = FakeServer.new
1195
+ server.socket.data.write "STORED\r\n"
1196
+ server.socket.data.rewind
1197
+
1198
+ cache.servers = []
1199
+ cache.servers << server
1200
+
1201
+ assert !cache.multithread
1202
+
1203
+ assert_nothing_raised do
1204
+ cache.set "test", "test value"
1205
+ end
1206
+
1207
+ output = server.socket.written.string
1208
+ assert_match(/set my_namespace:test/, output)
1209
+ assert_match(/test value/, output)
1210
+ end
1211
+
1212
+ def util_setup_fake_server
1213
+ server = FakeServer.new
1214
+ server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
1215
+ server.socket.data.write "\004\b\"\0170123456789\r\n"
1216
+ server.socket.data.write "END\r\n"
1217
+ server.socket.data.rewind
1218
+
1219
+ @cache.servers = []
1220
+ @cache.servers << server
1221
+
1222
+ return server
1223
+ end
1224
+
1225
+ def util_setup_server(memcache, host, responses)
1226
+ server = MemCache::Server.new memcache, host
1227
+ server.instance_variable_set :@sock, StringIO.new(responses)
1228
+
1229
+ @cache.servers = []
1230
+ @cache.servers << server
1231
+
1232
+ return server
1233
+ end
1234
+
1235
+ def test_crazy_multithreaded_access
1236
+ requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
1237
+
1238
+ # Use a null logger to verify logging doesn't blow up at runtime
1239
+ cache = MemCache.new(['localhost:11211', '127.0.0.1:11211'], :logger => Logger.new('/dev/null'))
1240
+ cache.flush_all
1241
+ assert_equal true, cache.multithread
1242
+ workers = []
1243
+
1244
+ cache.set('f', 'zzz')
1245
+ assert_equal "STORED\r\n", (cache.cas('f') do |value|
1246
+ value << 'z'
1247
+ end)
1248
+ assert_equal 'zzzz', cache.get('f')
1249
+
1250
+ # Have a bunch of threads perform a bunch of operations at the same time.
1251
+ # Verify the result of each operation to ensure the request and response
1252
+ # are not intermingled between threads.
1253
+ 10.times do
1254
+ workers << Thread.new do
1255
+ 100.times do
1256
+ cache.set('a', 9)
1257
+ cache.set('b', 11)
1258
+ cache.add('c', 10, 0, true)
1259
+ cache.set('d', 'a', 100, true)
1260
+ cache.set('e', 'x', 100, true)
1261
+ cache.set('f', 'zzz')
1262
+ cache.set('g', '1ብbሲg')
1263
+ cache.set('Ẽ뷽cc벼g', 'batman')
1264
+ assert_not_nil(cache.cas('f') do |value|
1265
+ value << 'z'
1266
+ end)
1267
+ cache.append('d', 'b')
1268
+ cache.prepend('e', 'y')
1269
+ assert_equal "NOT_STORED\r\n", cache.add('a', 11)
1270
+ assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
1271
+ inc = cache.incr('c', 10)
1272
+ assert_equal 0, inc % 5
1273
+ assert inc > 14
1274
+ assert cache.decr('c', 5) > 14
1275
+ assert_equal 11, cache.get('b')
1276
+ assert_equal '1ብbሲg', cache.get('g')
1277
+ assert_equal 'batman', cache.get('Ẽ뷽cc벼g')
1278
+ d = cache.get('d', true)
1279
+ assert_match(/\Aab*\Z/, d)
1280
+ e = cache.get('e', true)
1281
+ assert_match(/\Ay*x\Z/, e)
1282
+ end
1283
+ end
1284
+ end
1285
+
1286
+ workers.each { |w| w.join }
1287
+ cache.flush_all
1288
+ end
1289
+ end
1290
+
1291
+ def test_large_value
1292
+ requirement(memcached_running?, 'A memcached server must be running for live testing') do
1293
+ m = MemCache.new 'localhost'
1294
+ value = '1234567890'*500000
1295
+ assert_raises MemCache::MemCacheError do
1296
+ m.set('large_value', value)
1297
+ end
1298
+ value = '1234567890'*50000
1299
+ m.set('large_value', value)
1300
+ assert_equal value, m.get('large_value')
1301
+ end
1302
+ end
1303
+
1304
+ def test_custom_encoding
1305
+ requirement(memcached_running?, 'A memcached server must be running for live testing') do
1306
+ key = "£"
1307
+ array = [180,250,184,213]
1308
+ value = array.pack('c*')
1309
+ value.force_encoding('big5')
1310
+ assert_equal array, value.bytes.to_a
1311
+
1312
+ m = MemCache.new 'localhost'
1313
+ m.set(key, value)
1314
+ result = m.get(key)
1315
+ assert_equal(value, result)
1316
+ assert_equal(value.encoding.name, result.encoding.name)
1317
+ # m.set(key, value, true)
1318
+ # assert_equal(value, m.get(key))
1319
+ end
1320
+ end
1321
+
1322
+ end
1323
+