PageRenderTime 92ms CodeModel.GetById 2ms app.highlight 85ms RepoModel.GetById 1ms app.codeStats 0ms

/test/test_mem_cache.rb

https://github.com/xb/memcache-client
Ruby | 950 lines | 714 code | 220 blank | 16 comment | 5 complexity | 4c18216b85bba3d9aea9c785e61bff92 MD5 | raw file
  1# encoding: utf-8
  2require 'logger'
  3require 'stringio'
  4require 'test/unit'
  5require 'rubygems'
  6begin
  7  gem 'flexmock'
  8  require 'flexmock/test_unit'
  9rescue LoadError => e
 10  puts "Some tests require flexmock, please run `gem install flexmock`"
 11end
 12
 13$TESTING = true
 14
 15require File.dirname(__FILE__) + '/../lib/memcache'
 16
 17class MemCache
 18
 19  attr_writer :namespace
 20
 21end
 22
 23class FakeSocket
 24
 25  attr_reader :written, :data
 26
 27  def initialize
 28    @written = StringIO.new
 29    @data = StringIO.new
 30  end
 31
 32  def write(data)
 33    @written.write data
 34  end
 35
 36  def gets
 37    @data.gets
 38  end
 39
 40  def read(arg)
 41    @data.read arg
 42  end
 43
 44end
 45
 46class Test::Unit::TestCase
 47  def requirement(bool, msg)
 48    if bool
 49      yield
 50    else
 51      puts msg
 52      assert true
 53    end
 54  end
 55  
 56  def memcached_running?
 57    TCPSocket.new('localhost', 11211) rescue false
 58  end
 59  
 60  def xprofile(name, &block)
 61    a = Time.now
 62    block.call
 63    Time.now - a
 64  end
 65
 66  def profile(name, &block)
 67    require 'ruby-prof'
 68    a = Time.now
 69    result = RubyProf.profile(&block)
 70    time = Time.now - a
 71    printer = RubyProf::GraphHtmlPrinter.new(result)
 72    File.open("#{name}.html", 'w') do |f|
 73      printer.print(f, :min_percent=>1)
 74    end
 75    time
 76  end
 77  
 78end
 79
 80class FakeServer
 81
 82  attr_reader :host, :port, :socket, :weight, :multithread, :status
 83
 84  def initialize(socket = nil)
 85    @closed = false
 86    @host = 'example.com'
 87    @port = 11211
 88    @socket = socket || FakeSocket.new
 89    @weight = 1
 90    @multithread = false
 91    @status = "CONNECTED"
 92  end
 93
 94  def close
 95    # begin
 96    #   raise "Already closed"
 97    # rescue => e
 98    #   puts e.backtrace.join("\n")
 99    # end
100    @closed = true
101    @socket = nil
102    @status = "NOT CONNECTED"
103  end
104
105  def alive?
106    # puts "I'm #{@closed ? 'dead' : 'alive'}"
107    !@closed
108  end
109
110end
111
112class TestMemCache < Test::Unit::TestCase
113
114  def setup
115    @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace'
116  end
117
118  def test_performance
119    requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
120      host = Socket.gethostname
121
122      cache = MemCache.new(['localhost:11211',"#{host}:11211"])
123      cache.add('a', 1, 120)
124      with = xprofile 'get' do
125        1000.times do
126          cache.get('a')
127        end
128      end
129      puts ''
130      puts "1000 gets with socket timeout: #{with} sec"
131
132      cache = MemCache.new(['localhost:11211',"#{host}:11211"], :timeout => nil)
133      cache.add('a', 1, 120)
134      without = xprofile 'get' do
135        1000.times do
136          cache.get('a')
137        end
138      end
139      puts "1000 gets without socket timeout: #{without} sec"
140
141      assert without < with
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_initialize
337    cache = MemCache.new :namespace => 'my_namespace', :readonly => true
338
339    assert_equal 'my_namespace', cache.namespace
340    assert_equal true, cache.readonly?
341    assert_equal true, cache.servers.empty?
342  end
343
344  def test_initialize_compatible
345    cache = MemCache.new ['localhost:11211', 'localhost:11212'],
346            :namespace => 'my_namespace', :readonly => true
347
348    assert_equal 'my_namespace', cache.namespace
349    assert_equal true, cache.readonly?
350    assert_equal false, cache.servers.empty?
351  end
352
353  def test_initialize_compatible_no_hash
354    cache = MemCache.new ['localhost:11211', 'localhost:11212']
355
356    assert_equal nil, cache.namespace
357    assert_equal false, cache.readonly?
358    assert_equal false, cache.servers.empty?
359  end
360
361  def test_initialize_compatible_one_server
362    cache = MemCache.new 'localhost:11211'
363
364    assert_equal nil, cache.namespace
365    assert_equal false, cache.readonly?
366    assert_equal false, cache.servers.empty?
367  end
368
369  def test_initialize_compatible_bad_arg
370    e = assert_raise ArgumentError do
371      cache = MemCache.new Object.new
372    end
373
374    assert_equal 'first argument must be Array, Hash or String', e.message
375  end
376
377  def test_initialize_multiple_servers
378    cache = MemCache.new %w[localhost:11211 localhost:11212],
379                         :namespace => 'my_namespace', :readonly => true
380
381    assert_equal 'my_namespace', cache.namespace
382    assert_equal true, cache.readonly?
383    assert_equal false, cache.servers.empty?
384    assert !cache.instance_variable_get(:@continuum).empty?
385  end
386
387  def test_initialize_too_many_args
388    assert_raises ArgumentError do
389      MemCache.new 1, 2, 3
390    end
391  end
392
393  def test_decr
394    server = FakeServer.new
395    server.socket.data.write "5\r\n"
396    server.socket.data.rewind
397
398    @cache.servers = []
399    @cache.servers << server
400
401    value = @cache.decr 'key'
402
403    assert_equal "decr my_namespace:key 1\r\n",
404                 @cache.servers.first.socket.written.string
405
406    assert_equal 5, value
407  end
408
409  def test_decr_not_found
410    server = FakeServer.new
411    server.socket.data.write "NOT_FOUND\r\n"
412    server.socket.data.rewind
413
414    @cache.servers = []
415    @cache.servers << server
416
417    value = @cache.decr 'key'
418
419    assert_equal "decr my_namespace:key 1\r\n",
420                 @cache.servers.first.socket.written.string
421
422    assert_equal nil, value
423  end
424
425  def test_decr_space_padding
426    server = FakeServer.new
427    server.socket.data.write "5 \r\n"
428    server.socket.data.rewind
429
430    @cache.servers = []
431    @cache.servers << server
432
433    value = @cache.decr 'key'
434
435    assert_equal "decr my_namespace:key 1\r\n",
436                 @cache.servers.first.socket.written.string
437
438    assert_equal 5, value
439  end
440
441  def test_get
442    util_setup_fake_server
443
444    value = @cache.get 'key'
445
446    assert_equal "get my_namespace:key\r\n",
447                 @cache.servers.first.socket.written.string
448
449    assert_equal '0123456789', value
450  end
451
452  def test_get_bad_key
453    util_setup_fake_server
454    assert_raise ArgumentError do @cache.get 'k y' end
455
456    util_setup_fake_server
457    assert_raise ArgumentError do @cache.get 'k' * 250 end
458  end
459
460  def test_get_cache_get_IOError
461    socket = Object.new
462    def socket.write(arg) raise IOError, 'some io error'; end
463    server = FakeServer.new socket
464
465    @cache.servers = []
466    @cache.servers << server
467
468    e = assert_raise MemCache::MemCacheError do
469      @cache.get 'my_namespace:key'
470    end
471
472    assert_equal 'some io error', e.message
473  end
474
475  def test_get_cache_get_SystemCallError
476    socket = Object.new
477    def socket.write(arg) raise SystemCallError, 'some syscall error'; end
478    server = FakeServer.new socket
479
480    @cache.servers = []
481    @cache.servers << server
482
483    e = assert_raise MemCache::MemCacheError do
484      @cache.get 'my_namespace:key'
485    end
486
487    assert_equal 'unknown error - some syscall error', e.message
488  end
489
490  def test_get_no_connection
491    @cache.servers = 'localhost:1'
492    e = assert_raise MemCache::MemCacheError do
493      @cache.get 'key'
494    end
495
496    assert_match /^No connection to server/, e.message
497  end
498
499  def test_get_no_servers
500    @cache.servers = []
501    e = assert_raise MemCache::MemCacheError do
502      @cache.get 'key'
503    end
504
505    assert_equal 'No active servers', e.message
506  end
507
508  def test_get_multi
509    server = FakeServer.new
510    server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
511    server.socket.data.write "\004\b\"\0170123456789\r\n"
512    server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
513    server.socket.data.write "\004\b\"\0179876543210\r\n"
514    server.socket.data.write "END\r\n"
515    server.socket.data.rewind
516
517    @cache.servers = []
518    @cache.servers << server
519
520    values = @cache.get_multi 'key', 'keyb'
521
522    assert_equal "get my_namespace:key my_namespace:keyb\r\n",
523                 server.socket.written.string
524
525    expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
526
527    assert_equal expected.sort, values.sort
528  end
529
530  def test_get_raw
531    server = FakeServer.new
532    server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
533    server.socket.data.write "0123456789\r\n"
534    server.socket.data.write "END\r\n"
535    server.socket.data.rewind
536
537    @cache.servers = []
538    @cache.servers << server
539
540
541    value = @cache.get 'key', true
542
543    assert_equal "get my_namespace:key\r\n",
544                 @cache.servers.first.socket.written.string
545
546    assert_equal '0123456789', value
547  end
548
549  def test_get_server_for_key
550    server = @cache.get_server_for_key 'key'
551    assert_equal 'localhost', server.host
552    assert_equal 1, server.port
553  end
554
555  def test_get_server_for_key_multiple
556    s1 = util_setup_server @cache, 'one.example.com', ''
557    s2 = util_setup_server @cache, 'two.example.com', ''
558    @cache.servers = [s1, s2]
559
560    server = @cache.get_server_for_key 'keya'
561    assert_equal 'two.example.com', server.host
562    server = @cache.get_server_for_key 'keyb'
563    assert_equal 'two.example.com', server.host
564    server = @cache.get_server_for_key 'keyc'
565    assert_equal 'two.example.com', server.host
566    server = @cache.get_server_for_key 'keyd'
567    assert_equal 'one.example.com', server.host
568  end
569
570  def test_get_server_for_key_no_servers
571    @cache.servers = []
572
573    e = assert_raise MemCache::MemCacheError do
574      @cache.get_server_for_key 'key'
575    end
576
577    assert_equal 'No servers available', e.message
578  end
579
580  def test_get_server_for_key_spaces
581    e = assert_raise ArgumentError do
582      @cache.get_server_for_key 'space key'
583    end
584    assert_equal 'illegal character in key "space key"', e.message
585  end
586
587  def test_get_server_for_key_length
588    @cache.get_server_for_key 'x' * 250
589    long_key = 'x' * 251
590    e = assert_raise ArgumentError do
591      @cache.get_server_for_key long_key
592    end
593    assert_equal "key too long #{long_key.inspect}", e.message
594  end
595
596  def test_incr
597    server = FakeServer.new
598    server.socket.data.write "5\r\n"
599    server.socket.data.rewind
600
601    @cache.servers = []
602    @cache.servers << server
603
604    value = @cache.incr 'key'
605
606    assert_equal "incr my_namespace:key 1\r\n",
607                 @cache.servers.first.socket.written.string
608
609    assert_equal 5, value
610  end
611
612  def test_incr_not_found
613    server = FakeServer.new
614    server.socket.data.write "NOT_FOUND\r\n"
615    server.socket.data.rewind
616
617    @cache.servers = []
618    @cache.servers << server
619
620    value = @cache.incr 'key'
621
622    assert_equal "incr my_namespace:key 1\r\n",
623                 @cache.servers.first.socket.written.string
624
625    assert_equal nil, value
626  end
627
628  def test_incr_space_padding
629    server = FakeServer.new
630    server.socket.data.write "5 \r\n"
631    server.socket.data.rewind
632
633    @cache.servers = []
634    @cache.servers << server
635
636    value = @cache.incr 'key'
637
638    assert_equal "incr my_namespace:key 1\r\n",
639                 @cache.servers.first.socket.written.string
640
641    assert_equal 5, value
642  end
643
644  def test_make_cache_key
645    assert_equal 'my_namespace:key', @cache.make_cache_key('key')
646    @cache.namespace = nil
647    assert_equal 'key', @cache.make_cache_key('key')
648  end
649
650  def test_servers
651    server = FakeServer.new
652    @cache.servers = []
653    @cache.servers << server
654    assert_equal [server], @cache.servers
655  end
656
657  def test_set
658    server = FakeServer.new
659    server.socket.data.write "STORED\r\n"
660    server.socket.data.rewind
661    @cache.servers = []
662    @cache.servers << server
663
664    @cache.set 'key', 'value'
665
666    dumped = Marshal.dump('value')
667    expected = "set my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
668#    expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
669    assert_equal expected, server.socket.written.string
670  end
671
672  def test_set_expiry
673    server = FakeServer.new
674    server.socket.data.write "STORED\r\n"
675    server.socket.data.rewind
676    @cache.servers = []
677    @cache.servers << server
678
679    @cache.set 'key', 'value', 5
680
681    dumped = Marshal.dump('value')
682    expected = "set my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
683    assert_equal expected, server.socket.written.string
684  end
685
686  def test_set_raw
687    server = FakeServer.new
688    server.socket.data.write "STORED\r\n"
689    server.socket.data.rewind
690    @cache.servers = []
691    @cache.servers << server
692
693    @cache.set 'key', 'value', 0, true
694
695    expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
696    assert_equal expected, server.socket.written.string
697  end
698
699  def test_set_readonly
700    cache = MemCache.new :readonly => true
701
702    e = assert_raise MemCache::MemCacheError do
703      cache.set 'key', 'value'
704    end
705
706    assert_equal 'Update of readonly cache', e.message
707  end
708
709  def test_set_too_big
710    server = FakeServer.new
711
712    # Write two messages to the socket to test failover
713    server.socket.data.write "SERVER_ERROR\r\nSERVER_ERROR object too large for cache\r\n"
714    server.socket.data.rewind
715
716    @cache.servers = []
717    @cache.servers << server
718
719    e = assert_raise MemCache::MemCacheError do
720      @cache.set 'key', 'v'
721    end
722
723    assert_match /object too large for cache/, e.message
724  end
725
726  def test_add
727    server = FakeServer.new
728    server.socket.data.write "STORED\r\n"
729    server.socket.data.rewind
730    @cache.servers = []
731    @cache.servers << server
732
733    @cache.add 'key', 'value'
734    
735    dumped = Marshal.dump('value')
736
737    expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
738    assert_equal expected, server.socket.written.string
739  end
740
741  def test_add_exists
742    server = FakeServer.new
743    server.socket.data.write "NOT_STORED\r\n"
744    server.socket.data.rewind
745    @cache.servers = []
746    @cache.servers << server
747
748    @cache.add 'key', 'value'
749
750    dumped = Marshal.dump('value')
751    expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
752    assert_equal expected, server.socket.written.string
753  end
754
755  def test_add_expiry
756    server = FakeServer.new
757    server.socket.data.write "STORED\r\n"
758    server.socket.data.rewind
759    @cache.servers = []
760    @cache.servers << server
761
762    @cache.add 'key', 'value', 5
763
764    dumped = Marshal.dump('value')
765    expected = "add my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
766    assert_equal expected, server.socket.written.string
767  end
768
769  def test_add_raw
770    server = FakeServer.new
771    server.socket.data.write "STORED\r\n"
772    server.socket.data.rewind
773    @cache.servers = []
774    @cache.servers << server
775
776    @cache.add 'key', 'value', 0, true
777
778    expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
779    assert_equal expected, server.socket.written.string
780  end
781
782  def test_add_raw_int
783    server = FakeServer.new
784    server.socket.data.write "STORED\r\n"
785    server.socket.data.rewind
786    @cache.servers = []
787    @cache.servers << server
788
789    @cache.add 'key', 12, 0, true
790
791    expected = "add my_namespace:key 0 0 2\r\n12\r\n"
792    assert_equal expected, server.socket.written.string
793  end
794
795  def test_add_readonly
796    cache = MemCache.new :readonly => true
797
798    e = assert_raise MemCache::MemCacheError do
799      cache.add 'key', 'value'
800    end
801
802    assert_equal 'Update of readonly cache', e.message
803  end
804
805  def test_delete
806    server = FakeServer.new
807    @cache.servers = []
808    @cache.servers << server
809    
810    @cache.delete 'key'
811    
812    expected = "delete my_namespace:key 0\r\n"
813    assert_equal expected, server.socket.written.string
814  end
815
816  def test_delete_with_expiry
817    server = FakeServer.new
818    @cache.servers = []
819    @cache.servers << server
820    
821    @cache.delete 'key', 300
822    
823    expected = "delete my_namespace:key 300\r\n"
824    assert_equal expected, server.socket.written.string
825  end
826
827  def test_flush_all
828    @cache.servers = []
829    3.times { @cache.servers << FakeServer.new }
830
831    @cache.flush_all
832
833    expected = "flush_all\r\n"
834    @cache.servers.each do |server|
835      assert_equal expected, server.socket.written.string
836    end
837  end
838
839  def test_flush_all_failure
840    socket = FakeSocket.new
841
842    # Write two messages to the socket to test failover
843    socket.data.write "ERROR\r\nERROR\r\n"
844    socket.data.rewind
845
846    server = FakeServer.new socket
847
848    @cache.servers = []
849    @cache.servers << server
850
851    assert_raise MemCache::MemCacheError do
852      @cache.flush_all
853    end
854
855    assert_match /flush_all\r\n/, socket.written.string
856  end
857
858  def test_stats
859    socket = FakeSocket.new
860    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"
861    socket.data.rewind
862    server = FakeServer.new socket
863    def server.host() 'localhost'; end
864    def server.port() 11211; end
865
866    @cache.servers = []
867    @cache.servers << server
868
869    expected = {
870      'localhost:11211' => {
871        'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
872        'rusage_user' => 1.0003, 'dummy' => 'ok'
873      }
874    }
875    assert_equal expected, @cache.stats
876
877    assert_equal "stats\r\n", socket.written.string
878  end
879
880  def test_basic_threaded_operations_should_work
881    cache = MemCache.new :multithread => true,
882                         :namespace => 'my_namespace',
883                         :readonly => false
884
885    server = FakeServer.new
886    server.socket.data.write "STORED\r\n"
887    server.socket.data.rewind
888
889    cache.servers = []
890    cache.servers << server
891
892    assert cache.multithread
893
894    assert_nothing_raised do
895      cache.set "test", "test value"
896    end
897
898    output = server.socket.written.string
899    assert_match /set my_namespace:test/, output
900    assert_match /test value/, output
901  end
902
903  def test_basic_unthreaded_operations_should_work
904    cache = MemCache.new :multithread => false,
905                         :namespace => 'my_namespace',
906                         :readonly => false
907
908    server = FakeServer.new
909    server.socket.data.write "STORED\r\n"
910    server.socket.data.rewind
911
912    cache.servers = []
913    cache.servers << server
914
915    assert !cache.multithread
916
917    assert_nothing_raised do
918      cache.set "test", "test value"
919    end
920
921    output = server.socket.written.string
922    assert_match /set my_namespace:test/, output
923    assert_match /test value/, output
924  end
925
926  def util_setup_fake_server
927    server = FakeServer.new
928    server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
929    server.socket.data.write "\004\b\"\0170123456789\r\n"
930    server.socket.data.write "END\r\n"
931    server.socket.data.rewind
932
933    @cache.servers = []
934    @cache.servers << server
935
936    return server
937  end
938
939  def util_setup_server(memcache, host, responses)
940    server = MemCache::Server.new memcache, host
941    server.instance_variable_set :@sock, StringIO.new(responses)
942
943    @cache.servers = []
944    @cache.servers << server
945
946    return server
947  end
948
949end
950