ninjudd-memcache 0.9.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.
@@ -0,0 +1,739 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'test/zentest_assertions'
5
+
6
+ $TESTING = true
7
+
8
+ require 'memcache'
9
+
10
+ class MemCache
11
+
12
+ attr_writer :namespace
13
+
14
+ end
15
+
16
+ class FakeSocket
17
+
18
+ attr_reader :written, :data
19
+
20
+ def initialize
21
+ @written = StringIO.new
22
+ @data = StringIO.new
23
+ end
24
+
25
+ def write(data)
26
+ @written.write data
27
+ end
28
+
29
+ def gets
30
+ @data.gets
31
+ end
32
+
33
+ def read(arg)
34
+ @data.read arg
35
+ end
36
+
37
+ end
38
+
39
+ class FakeServer
40
+
41
+ attr_reader :host, :port, :socket
42
+
43
+ def initialize(socket = nil)
44
+ @closed = false
45
+ @host = 'example.com'
46
+ @port = 11211
47
+ @socket = socket || FakeSocket.new
48
+ end
49
+
50
+ def close
51
+ @closed = true
52
+ end
53
+
54
+ def alive?
55
+ !@closed
56
+ end
57
+
58
+ end
59
+
60
+ class TestMemCache < Test::Unit::TestCase
61
+
62
+ def setup
63
+ @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace'
64
+ end
65
+
66
+ def test_cache_get
67
+ server = util_setup_fake_server
68
+
69
+ assert_equal "\004\b\"\0170123456789",
70
+ @cache.cache_get(server, 'my_namespace:key')
71
+
72
+ assert_equal "get my_namespace:key\r\n",
73
+ server.socket.written.string
74
+ end
75
+
76
+ def test_cache_get_EOF
77
+ server = util_setup_fake_server
78
+ server.socket.data.string = ''
79
+
80
+ e = assert_raise MemCache::MemCacheError do
81
+ @cache.cache_get server, 'my_namespace:key'
82
+ end
83
+
84
+ assert_equal "lost connection to example.com:11211", e.message
85
+ end
86
+
87
+ def test_cache_get_bad_state
88
+ server = FakeServer.new
89
+ server.socket.data.write "bogus response\r\n"
90
+ server.socket.data.rewind
91
+
92
+ @cache.servers = []
93
+ @cache.servers << server
94
+
95
+ e = assert_raise MemCache::MemCacheError do
96
+ @cache.cache_get(server, 'my_namespace:key')
97
+ end
98
+
99
+ assert_equal "unexpected response \"bogus response\\r\\n\"", e.message
100
+
101
+ deny server.alive?
102
+
103
+ assert_equal "get my_namespace:key\r\n",
104
+ server.socket.written.string
105
+ end
106
+
107
+ def test_cache_get_miss
108
+ socket = FakeSocket.new
109
+ socket.data.write "END\r\n"
110
+ socket.data.rewind
111
+ server = FakeServer.new socket
112
+
113
+ assert_equal nil, @cache.cache_get(server, 'my_namespace:key')
114
+
115
+ assert_equal "get my_namespace:key\r\n",
116
+ socket.written.string
117
+ end
118
+
119
+ def test_cache_get_multi
120
+ server = util_setup_fake_server
121
+ server.socket.data.write "VALUE foo 0 7\r\n"
122
+ server.socket.data.write "\004\b\"\bfoo\r\n"
123
+ server.socket.data.write "VALUE bar 0 7\r\n"
124
+ server.socket.data.write "\004\b\"\bbar\r\n"
125
+ server.socket.data.write "END\r\n"
126
+ server.socket.data.rewind
127
+
128
+ result = @cache.cache_get_multi server, 'foo bar baz'
129
+
130
+ assert_equal 2, result.length
131
+ assert_equal "\004\b\"\bfoo", result['foo']
132
+ assert_equal "\004\b\"\bbar", result['bar']
133
+ end
134
+
135
+ def test_cache_get_multi_EOF
136
+ server = util_setup_fake_server
137
+ server.socket.data.string = ''
138
+
139
+ e = assert_raise MemCache::MemCacheError do
140
+ @cache.cache_get_multi server, 'my_namespace:key'
141
+ end
142
+
143
+ assert_equal "lost connection to example.com:11211", e.message
144
+ end
145
+
146
+ def test_cache_get_multi_bad_state
147
+ server = FakeServer.new
148
+ server.socket.data.write "bogus response\r\n"
149
+ server.socket.data.rewind
150
+
151
+ @cache.servers = []
152
+ @cache.servers << server
153
+
154
+ e = assert_raise MemCache::MemCacheError do
155
+ @cache.cache_get_multi server, 'my_namespace:key'
156
+ end
157
+
158
+ assert_equal "unexpected response \"bogus response\\r\\n\"", e.message
159
+
160
+ deny server.alive?
161
+
162
+ assert_equal "get my_namespace:key\r\n",
163
+ server.socket.written.string
164
+ end
165
+
166
+ def test_initialize
167
+ cache = MemCache.new :namespace => 'my_namespace', :readonly => true
168
+
169
+ assert_equal 'my_namespace', cache.namespace
170
+ assert_equal true, cache.readonly?
171
+ assert_equal true, cache.servers.empty?
172
+ end
173
+
174
+ def test_initialize_compatible
175
+ cache = MemCache.new ['localhost:11211', 'localhost:11212'],
176
+ :namespace => 'my_namespace', :readonly => true
177
+
178
+ assert_equal 'my_namespace', cache.namespace
179
+ assert_equal true, cache.readonly?
180
+ assert_equal false, cache.servers.empty?
181
+ end
182
+
183
+ def test_initialize_compatible_no_hash
184
+ cache = MemCache.new ['localhost:11211', 'localhost:11212']
185
+
186
+ assert_equal nil, cache.namespace
187
+ assert_equal false, cache.readonly?
188
+ assert_equal false, cache.servers.empty?
189
+ end
190
+
191
+ def test_initialize_compatible_one_server
192
+ cache = MemCache.new 'localhost:11211'
193
+
194
+ assert_equal nil, cache.namespace
195
+ assert_equal false, cache.readonly?
196
+ assert_equal false, cache.servers.empty?
197
+ end
198
+
199
+ def test_initialize_compatible_bad_arg
200
+ e = assert_raise ArgumentError do
201
+ cache = MemCache.new Object.new
202
+ end
203
+
204
+ assert_equal 'first argument must be Array, Hash or String', e.message
205
+ end
206
+
207
+ def test_initialize_multiple_servers
208
+ cache = MemCache.new %w[localhost:11211 localhost:11212],
209
+ :namespace => 'my_namespace', :readonly => true
210
+
211
+ assert_equal 'my_namespace', cache.namespace
212
+ assert_equal true, cache.readonly?
213
+ assert_equal false, cache.servers.empty?
214
+ deny_empty cache.instance_variable_get(:@buckets)
215
+ end
216
+
217
+ def test_initialize_too_many_args
218
+ assert_raises ArgumentError do
219
+ MemCache.new 1, 2, 3
220
+ end
221
+ end
222
+
223
+ def test_decr
224
+ server = FakeServer.new
225
+ server.socket.data.write "5\r\n"
226
+ server.socket.data.rewind
227
+
228
+ @cache.servers = []
229
+ @cache.servers << server
230
+
231
+ value = @cache.decr 'key'
232
+
233
+ assert_equal "decr my_namespace:key 1\r\n",
234
+ @cache.servers.first.socket.written.string
235
+
236
+ assert_equal 5, value
237
+ end
238
+
239
+ def test_decr_not_found
240
+ server = FakeServer.new
241
+ server.socket.data.write "NOT_FOUND\r\n"
242
+ server.socket.data.rewind
243
+
244
+ @cache.servers = []
245
+ @cache.servers << server
246
+
247
+ value = @cache.decr 'key'
248
+
249
+ assert_equal "decr my_namespace:key 1\r\n",
250
+ @cache.servers.first.socket.written.string
251
+
252
+ assert_equal nil, value
253
+ end
254
+
255
+ def test_decr_space_padding
256
+ server = FakeServer.new
257
+ server.socket.data.write "5 \r\n"
258
+ server.socket.data.rewind
259
+
260
+ @cache.servers = []
261
+ @cache.servers << server
262
+
263
+ value = @cache.decr 'key'
264
+
265
+ assert_equal "decr my_namespace:key 1\r\n",
266
+ @cache.servers.first.socket.written.string
267
+
268
+ assert_equal 5, value
269
+ end
270
+
271
+ def test_get
272
+ util_setup_fake_server
273
+
274
+ value = @cache.get 'key'
275
+
276
+ assert_equal "get my_namespace:key\r\n",
277
+ @cache.servers.first.socket.written.string
278
+
279
+ assert_equal '0123456789', value
280
+ end
281
+
282
+ def test_get_bad_key
283
+ util_setup_fake_server
284
+ assert_raise ArgumentError do @cache.get 'k y' end
285
+
286
+ util_setup_fake_server
287
+ assert_raise ArgumentError do @cache.get 'k' * 250 end
288
+ end
289
+
290
+ def test_get_cache_get_IOError
291
+ socket = Object.new
292
+ def socket.write(arg) raise IOError, 'some io error'; end
293
+ server = FakeServer.new socket
294
+
295
+ @cache.servers = []
296
+ @cache.servers << server
297
+
298
+ e = assert_raise MemCache::MemCacheError do
299
+ @cache.get 'my_namespace:key'
300
+ end
301
+
302
+ assert_equal 'some io error', e.message
303
+ end
304
+
305
+ def test_get_cache_get_SystemCallError
306
+ socket = Object.new
307
+ def socket.write(arg) raise SystemCallError, 'some syscall error'; end
308
+ server = FakeServer.new socket
309
+
310
+ @cache.servers = []
311
+ @cache.servers << server
312
+
313
+ e = assert_raise MemCache::MemCacheError do
314
+ @cache.get 'my_namespace:key'
315
+ end
316
+
317
+ assert_equal 'unknown error - some syscall error', e.message
318
+ end
319
+
320
+ def test_get_no_connection
321
+ @cache.servers = 'localhost:1'
322
+ e = assert_raise MemCache::MemCacheError do
323
+ @cache.get 'key'
324
+ end
325
+
326
+ assert_match /^No connection to server/, e.message
327
+ end
328
+
329
+ def test_get_no_servers
330
+ @cache.servers = []
331
+ e = assert_raise MemCache::MemCacheError do
332
+ @cache.get 'key'
333
+ end
334
+
335
+ assert_equal 'No active servers', e.message
336
+ end
337
+
338
+ def test_get_multi
339
+ server = FakeServer.new
340
+ server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
341
+ server.socket.data.write "\004\b\"\0170123456789\r\n"
342
+ server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
343
+ server.socket.data.write "\004\b\"\0179876543210\r\n"
344
+ server.socket.data.write "END\r\n"
345
+ server.socket.data.rewind
346
+
347
+ @cache.servers = []
348
+ @cache.servers << server
349
+
350
+ values = @cache.get_multi 'key', 'keyb'
351
+
352
+ assert_equal "get my_namespace:key my_namespace:keyb\r\n",
353
+ server.socket.written.string
354
+
355
+ expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
356
+
357
+ assert_equal expected.sort, values.sort
358
+ end
359
+
360
+ def test_get_raw
361
+ server = FakeServer.new
362
+ server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
363
+ server.socket.data.write "0123456789\r\n"
364
+ server.socket.data.write "END\r\n"
365
+ server.socket.data.rewind
366
+
367
+ @cache.servers = []
368
+ @cache.servers << server
369
+
370
+
371
+ value = @cache.get 'key', true
372
+
373
+ assert_equal "get my_namespace:key\r\n",
374
+ @cache.servers.first.socket.written.string
375
+
376
+ assert_equal '0123456789', value
377
+ end
378
+
379
+ def test_get_server_for_key
380
+ server = @cache.get_server_for_key 'key'
381
+ assert_equal 'localhost', server.host
382
+ assert_equal 1, server.port
383
+ end
384
+
385
+ def test_get_server_for_key_multiple
386
+ s1 = util_setup_server @cache, 'one.example.com', ''
387
+ s2 = util_setup_server @cache, 'two.example.com', ''
388
+ @cache.instance_variable_set :@servers, [s1, s2]
389
+ @cache.instance_variable_set :@buckets, [s1, s2]
390
+
391
+ server = @cache.get_server_for_key 'keya'
392
+ assert_equal 'two.example.com', server.host
393
+ server = @cache.get_server_for_key 'keyb'
394
+ assert_equal 'one.example.com', server.host
395
+ end
396
+
397
+ def test_get_server_for_key_no_servers
398
+ @cache.servers = []
399
+
400
+ e = assert_raise MemCache::MemCacheError do
401
+ @cache.get_server_for_key 'key'
402
+ end
403
+
404
+ assert_equal 'No servers available', e.message
405
+ end
406
+
407
+ def test_get_server_for_key_spaces
408
+ e = assert_raise ArgumentError do
409
+ @cache.get_server_for_key 'space key'
410
+ end
411
+ assert_equal 'illegal character in key "space key"', e.message
412
+ end
413
+
414
+ def test_get_server_for_key_length
415
+ @cache.get_server_for_key 'x' * 250
416
+ long_key = 'x' * 251
417
+ e = assert_raise ArgumentError do
418
+ @cache.get_server_for_key long_key
419
+ end
420
+ assert_equal "key too long #{long_key.inspect}", e.message
421
+ end
422
+
423
+ def test_incr
424
+ server = FakeServer.new
425
+ server.socket.data.write "5\r\n"
426
+ server.socket.data.rewind
427
+
428
+ @cache.servers = []
429
+ @cache.servers << server
430
+
431
+ value = @cache.incr 'key'
432
+
433
+ assert_equal "incr my_namespace:key 1\r\n",
434
+ @cache.servers.first.socket.written.string
435
+
436
+ assert_equal 5, value
437
+ end
438
+
439
+ def test_incr_not_found
440
+ server = FakeServer.new
441
+ server.socket.data.write "NOT_FOUND\r\n"
442
+ server.socket.data.rewind
443
+
444
+ @cache.servers = []
445
+ @cache.servers << server
446
+
447
+ value = @cache.incr 'key'
448
+
449
+ assert_equal "incr my_namespace:key 1\r\n",
450
+ @cache.servers.first.socket.written.string
451
+
452
+ assert_equal nil, value
453
+ end
454
+
455
+ def test_incr_space_padding
456
+ server = FakeServer.new
457
+ server.socket.data.write "5 \r\n"
458
+ server.socket.data.rewind
459
+
460
+ @cache.servers = []
461
+ @cache.servers << server
462
+
463
+ value = @cache.incr 'key'
464
+
465
+ assert_equal "incr my_namespace:key 1\r\n",
466
+ @cache.servers.first.socket.written.string
467
+
468
+ assert_equal 5, value
469
+ end
470
+
471
+ def test_make_cache_key
472
+ assert_equal 'my_namespace:key', @cache.make_cache_key('key')
473
+ @cache.namespace = nil
474
+ assert_equal 'key', @cache.make_cache_key('key')
475
+ end
476
+
477
+ def test_servers
478
+ server = FakeServer.new
479
+ @cache.servers = []
480
+ @cache.servers << server
481
+ assert_equal [server], @cache.servers
482
+ end
483
+
484
+ def test_servers_equals_type_error
485
+ e = assert_raise TypeError do
486
+ @cache.servers = [Object.new]
487
+ end
488
+
489
+ assert_equal 'cannot convert Object into MemCache::Server', e.message
490
+ end
491
+
492
+ def test_set
493
+ server = FakeServer.new
494
+ server.socket.data.write "STORED\r\n"
495
+ server.socket.data.rewind
496
+ @cache.servers = []
497
+ @cache.servers << server
498
+
499
+ @cache.set 'key', 'value'
500
+
501
+ expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
502
+ assert_equal expected, server.socket.written.string
503
+ end
504
+
505
+ def test_set_expiry
506
+ server = FakeServer.new
507
+ server.socket.data.write "STORED\r\n"
508
+ server.socket.data.rewind
509
+ @cache.servers = []
510
+ @cache.servers << server
511
+
512
+ @cache.set 'key', 'value', 5
513
+
514
+ expected = "set my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n"
515
+ assert_equal expected, server.socket.written.string
516
+ end
517
+
518
+ def test_set_raw
519
+ server = FakeServer.new
520
+ server.socket.data.write "STORED\r\n"
521
+ server.socket.data.rewind
522
+ @cache.servers = []
523
+ @cache.servers << server
524
+
525
+ @cache.set 'key', 'value', 0, true
526
+
527
+ expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
528
+ assert_equal expected, server.socket.written.string
529
+ end
530
+
531
+ def test_set_readonly
532
+ cache = MemCache.new :readonly => true
533
+
534
+ e = assert_raise MemCache::MemCacheError do
535
+ cache.set 'key', 'value'
536
+ end
537
+
538
+ assert_equal 'Update of readonly cache', e.message
539
+ end
540
+
541
+ def test_set_too_big
542
+ server = FakeServer.new
543
+ server.socket.data.write "SERVER_ERROR object too large for cache\r\n"
544
+ server.socket.data.rewind
545
+ @cache.servers = []
546
+ @cache.servers << server
547
+
548
+ e = assert_raise MemCache::MemCacheError do
549
+ @cache.set 'key', 'v'
550
+ end
551
+
552
+ assert_equal 'object too large for cache', e.message
553
+ end
554
+
555
+ def test_add
556
+ server = FakeServer.new
557
+ server.socket.data.write "STORED\r\n"
558
+ server.socket.data.rewind
559
+ @cache.servers = []
560
+ @cache.servers << server
561
+
562
+ @cache.add 'key', 'value'
563
+
564
+ expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
565
+ assert_equal expected, server.socket.written.string
566
+ end
567
+
568
+ def test_add_exists
569
+ server = FakeServer.new
570
+ server.socket.data.write "NOT_STORED\r\n"
571
+ server.socket.data.rewind
572
+ @cache.servers = []
573
+ @cache.servers << server
574
+
575
+ @cache.add 'key', 'value'
576
+
577
+ expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
578
+ assert_equal expected, server.socket.written.string
579
+ end
580
+
581
+ def test_add_expiry
582
+ server = FakeServer.new
583
+ server.socket.data.write "STORED\r\n"
584
+ server.socket.data.rewind
585
+ @cache.servers = []
586
+ @cache.servers << server
587
+
588
+ @cache.add 'key', 'value', 5
589
+
590
+ expected = "add my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n"
591
+ assert_equal expected, server.socket.written.string
592
+ end
593
+
594
+ def test_add_raw
595
+ server = FakeServer.new
596
+ server.socket.data.write "STORED\r\n"
597
+ server.socket.data.rewind
598
+ @cache.servers = []
599
+ @cache.servers << server
600
+
601
+ @cache.add 'key', 'value', 0, true
602
+
603
+ expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
604
+ assert_equal expected, server.socket.written.string
605
+ end
606
+
607
+ def test_add_readonly
608
+ cache = MemCache.new :readonly => true
609
+
610
+ e = assert_raise MemCache::MemCacheError do
611
+ cache.add 'key', 'value'
612
+ end
613
+
614
+ assert_equal 'Update of readonly cache', e.message
615
+ end
616
+
617
+ def test_delete
618
+ server = FakeServer.new
619
+ @cache.servers = []
620
+ @cache.servers << server
621
+
622
+ @cache.delete 'key'
623
+
624
+ expected = "delete my_namespace:key 0\r\n"
625
+ assert_equal expected, server.socket.written.string
626
+ end
627
+
628
+ def test_delete_with_expiry
629
+ server = FakeServer.new
630
+ @cache.servers = []
631
+ @cache.servers << server
632
+
633
+ @cache.delete 'key', 300
634
+
635
+ expected = "delete my_namespace:key 300\r\n"
636
+ assert_equal expected, server.socket.written.string
637
+ end
638
+
639
+ def test_flush_all
640
+ @cache.servers = []
641
+ 3.times { @cache.servers << FakeServer.new }
642
+
643
+ @cache.flush_all
644
+
645
+ expected = "flush_all\r\n"
646
+ @cache.servers.each do |server|
647
+ assert_equal expected, server.socket.written.string
648
+ end
649
+ end
650
+
651
+ def test_flush_all_failure
652
+ socket = FakeSocket.new
653
+ socket.data.write "ERROR\r\n"
654
+ socket.data.rewind
655
+ server = FakeServer.new socket
656
+ def server.host() "localhost"; end
657
+ def server.port() 11211; end
658
+
659
+ @cache.servers = []
660
+ @cache.servers << server
661
+
662
+ assert_raise MemCache::MemCacheError do
663
+ @cache.flush_all
664
+ end
665
+
666
+ assert_equal "flush_all\r\n", socket.written.string
667
+ end
668
+
669
+ def test_stats
670
+ socket = FakeSocket.new
671
+ 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"
672
+ socket.data.rewind
673
+ server = FakeServer.new socket
674
+ def server.host() 'localhost'; end
675
+ def server.port() 11211; end
676
+
677
+ @cache.servers = []
678
+ @cache.servers << server
679
+
680
+ expected = {
681
+ 'localhost:11211' => {
682
+ 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
683
+ 'rusage_user' => 1.0003, 'dummy' => 'ok'
684
+ }
685
+ }
686
+ assert_equal expected, @cache.stats
687
+
688
+ assert_equal "stats\r\n", socket.written.string
689
+ end
690
+
691
+ def test_basic_threaded_operations_should_work
692
+ cache = MemCache.new :multithread => true,
693
+ :namespace => 'my_namespace',
694
+ :readonly => false
695
+ server = util_setup_server cache, 'example.com', "OK\r\n"
696
+ cache.instance_variable_set :@servers, [server]
697
+
698
+ assert_nothing_raised do
699
+ cache.set "test", "test value"
700
+ end
701
+ end
702
+
703
+ def test_basic_unthreaded_operations_should_work
704
+ cache = MemCache.new :multithread => false,
705
+ :namespace => 'my_namespace',
706
+ :readonly => false
707
+ server = util_setup_server cache, 'example.com', "OK\r\n"
708
+ cache.instance_variable_set :@servers, [server]
709
+
710
+ assert_nothing_raised do
711
+ cache.set "test", "test value"
712
+ end
713
+ end
714
+
715
+ def util_setup_fake_server
716
+ server = FakeServer.new
717
+ server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
718
+ server.socket.data.write "\004\b\"\0170123456789\r\n"
719
+ server.socket.data.write "END\r\n"
720
+ server.socket.data.rewind
721
+
722
+ @cache.servers = []
723
+ @cache.servers << server
724
+
725
+ return server
726
+ end
727
+
728
+ def util_setup_server(memcache, host, responses)
729
+ server = MemCache::Server.new memcache, host
730
+ server.instance_variable_set :@sock, StringIO.new(responses)
731
+
732
+ @cache.servers = []
733
+ @cache.servers << server
734
+
735
+ return server
736
+ end
737
+
738
+ end
739
+