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