PageRenderTime 140ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/test/test_mem_cache.rb

https://github.com/bcg/memcache-client
Ruby | 989 lines | 745 code | 227 blank | 17 comment | 5 complexity | 705852088ba6955ba3571d9f64f71b5b 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_multithread_error
  258. server = FakeServer.new
  259. # Write two messages to the socket to test failover
  260. server.socket.data.write "bogus response\r\nbogus response\r\n"
  261. server.socket.data.rewind
  262. @cache.servers = []
  263. @cache.servers << server
  264. assert_nothing_raised do
  265. @cache.set 'a', 1
  266. end
  267. passed = true
  268. Thread.new do
  269. begin
  270. @cache.set 'b', 2
  271. passed = false
  272. rescue MemCache::MemCacheError => me
  273. passed = me.message =~ /multiple threads/
  274. end
  275. end
  276. assert passed
  277. end
  278. def test_initialize
  279. cache = MemCache.new :namespace => 'my_namespace', :readonly => true
  280. assert_equal 'my_namespace', cache.namespace
  281. assert_equal true, cache.readonly?
  282. assert_equal true, cache.servers.empty?
  283. end
  284. def test_initialize_compatible
  285. cache = MemCache.new ['localhost:11211', 'localhost:11212'],
  286. :namespace => 'my_namespace', :readonly => true
  287. assert_equal 'my_namespace', cache.namespace
  288. assert_equal true, cache.readonly?
  289. assert_equal false, cache.servers.empty?
  290. end
  291. def test_initialize_compatible_no_hash
  292. cache = MemCache.new ['localhost:11211', 'localhost:11212']
  293. assert_equal nil, cache.namespace
  294. assert_equal false, cache.readonly?
  295. assert_equal false, cache.servers.empty?
  296. end
  297. def test_initialize_compatible_one_server
  298. cache = MemCache.new 'localhost:11211'
  299. assert_equal nil, cache.namespace
  300. assert_equal false, cache.readonly?
  301. assert_equal false, cache.servers.empty?
  302. end
  303. def test_initialize_compatible_bad_arg
  304. e = assert_raise ArgumentError do
  305. cache = MemCache.new Object.new
  306. end
  307. assert_equal 'first argument must be Array, Hash or String', e.message
  308. end
  309. def test_initialize_multiple_servers
  310. cache = MemCache.new %w[localhost:11211 localhost:11212],
  311. :namespace => 'my_namespace', :readonly => true
  312. assert_equal 'my_namespace', cache.namespace
  313. assert_equal true, cache.readonly?
  314. assert_equal false, cache.servers.empty?
  315. assert !cache.instance_variable_get(:@continuum).empty?
  316. end
  317. def test_initialize_too_many_args
  318. assert_raises ArgumentError do
  319. MemCache.new 1, 2, 3
  320. end
  321. end
  322. def test_decr
  323. server = FakeServer.new
  324. server.socket.data.write "5\r\n"
  325. server.socket.data.rewind
  326. @cache.servers = []
  327. @cache.servers << server
  328. value = @cache.decr 'key'
  329. assert_equal "decr my_namespace:key 1\r\n",
  330. @cache.servers.first.socket.written.string
  331. assert_equal 5, value
  332. end
  333. def test_decr_not_found
  334. server = FakeServer.new
  335. server.socket.data.write "NOT_FOUND\r\n"
  336. server.socket.data.rewind
  337. @cache.servers = []
  338. @cache.servers << server
  339. value = @cache.decr 'key'
  340. assert_equal "decr my_namespace:key 1\r\n",
  341. @cache.servers.first.socket.written.string
  342. assert_equal nil, value
  343. end
  344. def test_decr_space_padding
  345. server = FakeServer.new
  346. server.socket.data.write "5 \r\n"
  347. server.socket.data.rewind
  348. @cache.servers = []
  349. @cache.servers << server
  350. value = @cache.decr 'key'
  351. assert_equal "decr my_namespace:key 1\r\n",
  352. @cache.servers.first.socket.written.string
  353. assert_equal 5, value
  354. end
  355. def test_get
  356. util_setup_fake_server
  357. value = @cache.get 'key'
  358. assert_equal "get my_namespace:key\r\n",
  359. @cache.servers.first.socket.written.string
  360. assert_equal '0123456789', value
  361. end
  362. def test_get_bad_key
  363. util_setup_fake_server
  364. assert_raise ArgumentError do @cache.get 'k y' end
  365. util_setup_fake_server
  366. assert_raise ArgumentError do @cache.get 'k' * 250 end
  367. end
  368. def test_get_cache_get_IOError
  369. socket = Object.new
  370. def socket.write(arg) raise IOError, 'some io error'; end
  371. server = FakeServer.new socket
  372. @cache.servers = []
  373. @cache.servers << server
  374. e = assert_raise MemCache::MemCacheError do
  375. @cache.get 'my_namespace:key'
  376. end
  377. assert_equal 'some io error', e.message
  378. end
  379. def test_get_cache_get_SystemCallError
  380. socket = Object.new
  381. def socket.write(arg) raise SystemCallError, 'some syscall error'; end
  382. server = FakeServer.new socket
  383. @cache.servers = []
  384. @cache.servers << server
  385. e = assert_raise MemCache::MemCacheError do
  386. @cache.get 'my_namespace:key'
  387. end
  388. assert_equal 'unknown error - some syscall error', e.message
  389. end
  390. def test_get_no_connection
  391. @cache.servers = 'localhost:1'
  392. e = assert_raise MemCache::MemCacheError do
  393. @cache.get 'key'
  394. end
  395. assert_match /^No connection to server/, e.message
  396. end
  397. def test_get_no_servers
  398. @cache.servers = []
  399. e = assert_raise MemCache::MemCacheError do
  400. @cache.get 'key'
  401. end
  402. assert_equal 'No active servers', e.message
  403. end
  404. def test_get_multi
  405. server = FakeServer.new
  406. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  407. server.socket.data.write "\004\b\"\0170123456789\r\n"
  408. server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
  409. server.socket.data.write "\004\b\"\0179876543210\r\n"
  410. server.socket.data.write "END\r\n"
  411. server.socket.data.rewind
  412. @cache.servers = []
  413. @cache.servers << server
  414. values = @cache.get_multi 'key', 'keyb'
  415. assert_equal "get my_namespace:key my_namespace:keyb\r\n",
  416. server.socket.written.string
  417. expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
  418. assert_equal expected.sort, values.sort
  419. end
  420. def test_get_raw
  421. server = FakeServer.new
  422. server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
  423. server.socket.data.write "0123456789\r\n"
  424. server.socket.data.write "END\r\n"
  425. server.socket.data.rewind
  426. @cache.servers = []
  427. @cache.servers << server
  428. value = @cache.get 'key', true
  429. assert_equal "get my_namespace:key\r\n",
  430. @cache.servers.first.socket.written.string
  431. assert_equal '0123456789', value
  432. end
  433. def test_get_server_for_key
  434. server = @cache.get_server_for_key 'key'
  435. assert_equal 'localhost', server.host
  436. assert_equal 1, server.port
  437. end
  438. def test_get_server_for_key_multiple
  439. s1 = util_setup_server @cache, 'one.example.com', ''
  440. s2 = util_setup_server @cache, 'two.example.com', ''
  441. @cache.servers = [s1, s2]
  442. server = @cache.get_server_for_key 'keya'
  443. assert_equal 'two.example.com', server.host
  444. server = @cache.get_server_for_key 'keyb'
  445. assert_equal 'two.example.com', server.host
  446. server = @cache.get_server_for_key 'keyc'
  447. assert_equal 'two.example.com', server.host
  448. server = @cache.get_server_for_key 'keyd'
  449. assert_equal 'one.example.com', server.host
  450. end
  451. def test_get_server_for_key_no_servers
  452. @cache.servers = []
  453. e = assert_raise MemCache::MemCacheError do
  454. @cache.get_server_for_key 'key'
  455. end
  456. assert_equal 'No servers available', e.message
  457. end
  458. def test_get_server_for_key_spaces
  459. e = assert_raise ArgumentError do
  460. @cache.get_server_for_key 'space key'
  461. end
  462. assert_equal 'illegal character in key "space key"', e.message
  463. end
  464. def test_get_server_for_key_length
  465. @cache.get_server_for_key 'x' * 250
  466. long_key = 'x' * 251
  467. e = assert_raise ArgumentError do
  468. @cache.get_server_for_key long_key
  469. end
  470. assert_equal "key too long #{long_key.inspect}", e.message
  471. end
  472. def test_incr
  473. server = FakeServer.new
  474. server.socket.data.write "5\r\n"
  475. server.socket.data.rewind
  476. @cache.servers = []
  477. @cache.servers << server
  478. value = @cache.incr 'key'
  479. assert_equal "incr my_namespace:key 1\r\n",
  480. @cache.servers.first.socket.written.string
  481. assert_equal 5, value
  482. end
  483. def test_incr_not_found
  484. server = FakeServer.new
  485. server.socket.data.write "NOT_FOUND\r\n"
  486. server.socket.data.rewind
  487. @cache.servers = []
  488. @cache.servers << server
  489. value = @cache.incr 'key'
  490. assert_equal "incr my_namespace:key 1\r\n",
  491. @cache.servers.first.socket.written.string
  492. assert_equal nil, value
  493. end
  494. def test_incr_space_padding
  495. server = FakeServer.new
  496. server.socket.data.write "5 \r\n"
  497. server.socket.data.rewind
  498. @cache.servers = []
  499. @cache.servers << server
  500. value = @cache.incr 'key'
  501. assert_equal "incr my_namespace:key 1\r\n",
  502. @cache.servers.first.socket.written.string
  503. assert_equal 5, value
  504. end
  505. def test_make_cache_key
  506. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  507. @cache.namespace = nil
  508. assert_equal 'key', @cache.make_cache_key('key')
  509. end
  510. def test_servers
  511. server = FakeServer.new
  512. @cache.servers = []
  513. @cache.servers << server
  514. assert_equal [server], @cache.servers
  515. end
  516. def test_set
  517. server = FakeServer.new
  518. server.socket.data.write "STORED\r\n"
  519. server.socket.data.rewind
  520. @cache.servers = []
  521. @cache.servers << server
  522. @cache.set 'key', 'value'
  523. dumped = Marshal.dump('value')
  524. expected = "set my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  525. # expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  526. assert_equal expected, server.socket.written.string
  527. end
  528. def test_set_expiry
  529. server = FakeServer.new
  530. server.socket.data.write "STORED\r\n"
  531. server.socket.data.rewind
  532. @cache.servers = []
  533. @cache.servers << server
  534. @cache.set 'key', 'value', 5
  535. dumped = Marshal.dump('value')
  536. expected = "set my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  537. assert_equal expected, server.socket.written.string
  538. end
  539. def test_set_raw
  540. server = FakeServer.new
  541. server.socket.data.write "STORED\r\n"
  542. server.socket.data.rewind
  543. @cache.servers = []
  544. @cache.servers << server
  545. @cache.set 'key', 'value', 0, true
  546. expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
  547. assert_equal expected, server.socket.written.string
  548. end
  549. def test_set_nonblock
  550. server = FakeServer.new
  551. server.socket.data.write "NEVER READ"
  552. server.socket.data.rewind
  553. @cache.servers = []
  554. @cache.servers << server
  555. @cache.set 'key', 'value', 0, true, true
  556. expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
  557. assert_equal expected, server.socket.written.string
  558. assert_equal "NEVER READ", server.socket.gets
  559. end
  560. def test_set_readonly
  561. cache = MemCache.new :readonly => true
  562. e = assert_raise MemCache::MemCacheError do
  563. cache.set 'key', 'value'
  564. end
  565. assert_equal 'Update of readonly cache', e.message
  566. end
  567. def test_set_too_big
  568. server = FakeServer.new
  569. # Write two messages to the socket to test failover
  570. server.socket.data.write "SERVER_ERROR\r\nSERVER_ERROR object too large for cache\r\n"
  571. server.socket.data.rewind
  572. @cache.servers = []
  573. @cache.servers << server
  574. e = assert_raise MemCache::MemCacheError do
  575. @cache.set 'key', 'v'
  576. end
  577. assert_match /object too large for cache/, e.message
  578. end
  579. def test_add
  580. server = FakeServer.new
  581. server.socket.data.write "STORED\r\n"
  582. server.socket.data.rewind
  583. @cache.servers = []
  584. @cache.servers << server
  585. @cache.add 'key', 'value'
  586. dumped = Marshal.dump('value')
  587. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  588. assert_equal expected, server.socket.written.string
  589. end
  590. def test_add_exists
  591. server = FakeServer.new
  592. server.socket.data.write "NOT_STORED\r\n"
  593. server.socket.data.rewind
  594. @cache.servers = []
  595. @cache.servers << server
  596. @cache.add 'key', 'value'
  597. dumped = Marshal.dump('value')
  598. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  599. assert_equal expected, server.socket.written.string
  600. end
  601. def test_add_expiry
  602. server = FakeServer.new
  603. server.socket.data.write "STORED\r\n"
  604. server.socket.data.rewind
  605. @cache.servers = []
  606. @cache.servers << server
  607. @cache.add 'key', 'value', 5
  608. dumped = Marshal.dump('value')
  609. expected = "add my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  610. assert_equal expected, server.socket.written.string
  611. end
  612. def test_add_raw
  613. server = FakeServer.new
  614. server.socket.data.write "STORED\r\n"
  615. server.socket.data.rewind
  616. @cache.servers = []
  617. @cache.servers << server
  618. @cache.add 'key', 'value', 0, true
  619. expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
  620. assert_equal expected, server.socket.written.string
  621. end
  622. def test_add_raw_int
  623. server = FakeServer.new
  624. server.socket.data.write "STORED\r\n"
  625. server.socket.data.rewind
  626. @cache.servers = []
  627. @cache.servers << server
  628. @cache.add 'key', 12, 0, true
  629. expected = "add my_namespace:key 0 0 2\r\n12\r\n"
  630. assert_equal expected, server.socket.written.string
  631. end
  632. def test_add_readonly
  633. cache = MemCache.new :readonly => true
  634. e = assert_raise MemCache::MemCacheError do
  635. cache.add 'key', 'value'
  636. end
  637. assert_equal 'Update of readonly cache', e.message
  638. end
  639. def test_delete
  640. server = FakeServer.new
  641. @cache.servers = []
  642. @cache.servers << server
  643. @cache.delete 'key'
  644. expected = "delete my_namespace:key 0\r\n"
  645. assert_equal expected, server.socket.written.string
  646. end
  647. def test_delete_with_expiry
  648. server = FakeServer.new
  649. @cache.servers = []
  650. @cache.servers << server
  651. @cache.delete 'key', 300
  652. expected = "delete my_namespace:key 300\r\n"
  653. assert_equal expected, server.socket.written.string
  654. end
  655. def test_flush_all
  656. @cache.servers = []
  657. 3.times { @cache.servers << FakeServer.new }
  658. @cache.flush_all
  659. expected = "flush_all\r\n"
  660. @cache.servers.each do |server|
  661. assert_equal expected, server.socket.written.string
  662. end
  663. end
  664. def test_flush_all_failure
  665. socket = FakeSocket.new
  666. # Write two messages to the socket to test failover
  667. socket.data.write "ERROR\r\nERROR\r\n"
  668. socket.data.rewind
  669. server = FakeServer.new socket
  670. @cache.servers = []
  671. @cache.servers << server
  672. assert_raise MemCache::MemCacheError do
  673. @cache.flush_all
  674. end
  675. assert_match /flush_all\r\n/, socket.written.string
  676. end
  677. def test_stats
  678. socket = FakeSocket.new
  679. 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"
  680. socket.data.rewind
  681. server = FakeServer.new socket
  682. def server.host() 'localhost'; end
  683. def server.port() 11211; end
  684. @cache.servers = []
  685. @cache.servers << server
  686. expected = {
  687. 'localhost:11211' => {
  688. 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
  689. 'rusage_user' => 1.0003, 'dummy' => 'ok'
  690. }
  691. }
  692. assert_equal expected, @cache.stats
  693. assert_equal "stats\r\n", socket.written.string
  694. end
  695. def test_basic_threaded_operations_should_work
  696. cache = MemCache.new :multithread => true,
  697. :namespace => 'my_namespace',
  698. :readonly => false
  699. server = FakeServer.new
  700. server.socket.data.write "STORED\r\n"
  701. server.socket.data.rewind
  702. cache.servers = []
  703. cache.servers << server
  704. assert cache.multithread
  705. assert_nothing_raised do
  706. cache.set "test", "test value"
  707. end
  708. output = server.socket.written.string
  709. assert_match /set my_namespace:test/, output
  710. assert_match /test value/, output
  711. end
  712. def test_basic_unthreaded_operations_should_work
  713. cache = MemCache.new :multithread => false,
  714. :namespace => 'my_namespace',
  715. :readonly => false
  716. server = FakeServer.new
  717. server.socket.data.write "STORED\r\n"
  718. server.socket.data.rewind
  719. cache.servers = []
  720. cache.servers << server
  721. assert !cache.multithread
  722. assert_nothing_raised do
  723. cache.set "test", "test value"
  724. end
  725. output = server.socket.written.string
  726. assert_match /set my_namespace:test/, output
  727. assert_match /test value/, output
  728. end
  729. def util_setup_fake_server
  730. server = FakeServer.new
  731. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  732. server.socket.data.write "\004\b\"\0170123456789\r\n"
  733. server.socket.data.write "END\r\n"
  734. server.socket.data.rewind
  735. @cache.servers = []
  736. @cache.servers << server
  737. return server
  738. end
  739. def util_setup_server(memcache, host, responses)
  740. server = MemCache::Server.new memcache, host
  741. server.instance_variable_set :@sock, StringIO.new(responses)
  742. @cache.servers = []
  743. @cache.servers << server
  744. return server
  745. end
  746. end