PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/bundle/ruby/1.8/gems/memcache-client-1.7.6/test/test_mem_cache.rb

https://github.com/alecslupu/Free-RPG-Engine-FaceBook-Game-App
Ruby | 1220 lines | 933 code | 271 blank | 16 comment | 7 complexity | 19966e5d4d66d16919047694af8a3719 MD5 | raw file
Possible License(s): BSD-3-Clause
  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. Thread.abort_on_exception = true
  13. $TESTING = true
  14. require File.dirname(__FILE__) + '/../lib/memcache' if not defined?(MemCache)
  15. class MemCache
  16. attr_writer :namespace
  17. attr_writer :autofix_keys
  18. end
  19. class FakeSocket
  20. attr_reader :written, :data
  21. def initialize
  22. @written = StringIO.new
  23. @data = StringIO.new
  24. end
  25. def write(data)
  26. @written.write data
  27. end
  28. def gets
  29. @data.gets
  30. end
  31. def read(arg)
  32. @data.read arg
  33. end
  34. end
  35. class Test::Unit::TestCase
  36. def requirement(bool, msg)
  37. if bool
  38. yield
  39. else
  40. puts msg
  41. assert true
  42. end
  43. end
  44. def memcached_running?
  45. TCPSocket.new('localhost', 11211) rescue false
  46. end
  47. def xprofile(name, &block)
  48. a = Time.now
  49. block.call
  50. Time.now - a
  51. end
  52. def profile(name, &block)
  53. require 'ruby-prof'
  54. a = Time.now
  55. result = RubyProf.profile(&block)
  56. time = Time.now - a
  57. printer = RubyProf::GraphHtmlPrinter.new(result)
  58. File.open("#{name}.html", 'w') do |f|
  59. printer.print(f, :min_percent=>1)
  60. end
  61. time
  62. end
  63. end
  64. class FakeServer
  65. attr_accessor :host, :port, :socket, :weight, :multithread, :status
  66. def initialize(socket = nil)
  67. @closed = false
  68. @host = 'example.com'
  69. @port = 11211
  70. @socket = socket || FakeSocket.new
  71. @weight = 1
  72. @multithread = true
  73. @status = "CONNECTED"
  74. end
  75. def close
  76. # begin
  77. # raise "Already closed"
  78. # rescue => e
  79. # puts e.backtrace.join("\n")
  80. # end
  81. @closed = true
  82. @socket = nil
  83. @status = "NOT CONNECTED"
  84. end
  85. def alive?
  86. # puts "I'm #{@closed ? 'dead' : 'alive'}"
  87. !@closed
  88. end
  89. end
  90. class TestMemCache < Test::Unit::TestCase
  91. def setup
  92. @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace'
  93. end
  94. def test_performance
  95. requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
  96. cache = MemCache.new(['localhost:11211',"127.0.0.1:11211"])
  97. cache.flush_all
  98. cache.add('a', 1, 120)
  99. with = xprofile 'get' do
  100. 1000.times do
  101. cache.get('a')
  102. end
  103. end
  104. puts ''
  105. puts "1000 gets with socket timeout: #{with} sec"
  106. cache = MemCache.new(['localhost:11211',"127.0.0.1:11211"], :timeout => nil)
  107. cache.add('a', 1, 120)
  108. without = xprofile 'get' do
  109. 1000.times do
  110. cache.get('a')
  111. end
  112. end
  113. puts "1000 gets without socket timeout: #{without} sec"
  114. end
  115. end
  116. def test_consistent_hashing
  117. requirement(self.respond_to?(:flexmock), 'Flexmock is required to run this test') do
  118. flexmock(MemCache::Server).new_instances.should_receive(:alive?).and_return(true)
  119. # Setup a continuum of two servers
  120. @cache.servers = ['mike1', 'mike2', 'mike3']
  121. keys = []
  122. 1000.times do |idx|
  123. keys << idx.to_s
  124. end
  125. before_continuum = keys.map {|key| @cache.get_server_for_key(key) }
  126. @cache.servers = ['mike1', 'mike2', 'mike3', 'mike4']
  127. after_continuum = keys.map {|key| @cache.get_server_for_key(key) }
  128. same_count = before_continuum.zip(after_continuum).find_all {|a| a[0].host == a[1].host }.size
  129. # With continuum, we should see about 75% of the keys map to the same server
  130. # With modulo, we would see about 25%.
  131. assert same_count > 700
  132. end
  133. end
  134. def test_get_multi_with_server_failure
  135. @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace', :logger => nil #Logger.new(STDOUT)
  136. s1 = FakeServer.new
  137. s2 = FakeServer.new
  138. # Write two messages to the socket to test failover
  139. s1.socket.data.write "VALUE my_namespace:a 0 14\r\n\004\b\"\0170123456789\r\nEND\r\n"
  140. s1.socket.data.rewind
  141. s2.socket.data.write "bogus response\r\nbogus response\r\n"
  142. s2.socket.data.rewind
  143. @cache.servers = [s1, s2]
  144. assert s1.alive?
  145. assert s2.alive?
  146. # a maps to s1, the rest map to s2
  147. value = @cache.get_multi(['foo', 'bar', 'a', 'b', 'c'])
  148. assert_equal({'a'=>'0123456789'}, value)
  149. assert s1.alive?
  150. assert !s2.alive?
  151. end
  152. def test_cache_get_with_failover
  153. @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace', :logger => nil#Logger.new(STDOUT)
  154. s1 = FakeServer.new
  155. s2 = FakeServer.new
  156. # Write two messages to the socket to test failover
  157. s1.socket.data.write "VALUE foo 0 14\r\n\004\b\"\0170123456789\r\n"
  158. s1.socket.data.rewind
  159. s2.socket.data.write "bogus response\r\nbogus response\r\n"
  160. s2.socket.data.rewind
  161. @cache.instance_variable_set(:@failover, true)
  162. @cache.servers = [s1, s2]
  163. assert s1.alive?
  164. assert s2.alive?
  165. @cache.get('foo')
  166. assert s1.alive?
  167. assert !s2.alive?
  168. end
  169. def test_cache_get_without_failover
  170. s1 = FakeServer.new
  171. s2 = FakeServer.new
  172. s1.socket.data.write "VALUE foo 0 14\r\n\004\b\"\0170123456789\r\n"
  173. s1.socket.data.rewind
  174. s2.socket.data.write "bogus response\r\nbogus response\r\n"
  175. s2.socket.data.rewind
  176. @cache.instance_variable_set(:@failover, false)
  177. @cache.servers = [s1, s2]
  178. assert s1.alive?
  179. assert s2.alive?
  180. e = assert_raise MemCache::MemCacheError do
  181. @cache.get('foo')
  182. end
  183. assert s1.alive?
  184. assert !s2.alive?
  185. assert_equal "No servers available", e.message
  186. end
  187. def test_cache_get
  188. server = util_setup_fake_server
  189. assert_equal "\004\b\"\0170123456789",
  190. @cache.cache_get(server, 'my_namespace:key')
  191. assert_equal "get my_namespace:key\r\n",
  192. server.socket.written.string
  193. end
  194. def test_cache_get_EOF
  195. server = util_setup_fake_server
  196. server.socket.data.string = ''
  197. e = assert_raise IndexError do
  198. @cache.cache_get server, 'my_namespace:key'
  199. end
  200. assert_equal "No connection to server (NOT CONNECTED)", e.message
  201. end
  202. def test_cache_get_bad_state
  203. server = FakeServer.new
  204. # Write two messages to the socket to test failover
  205. server.socket.data.write "bogus response\r\nbogus response\r\n"
  206. server.socket.data.rewind
  207. @cache.servers = []
  208. @cache.servers << server
  209. e = assert_raise IndexError do
  210. @cache.cache_get(server, 'my_namespace:key')
  211. end
  212. assert_match(/#{Regexp.quote 'No connection to server (NOT CONNECTED)'}/, e.message)
  213. assert !server.alive?
  214. end
  215. def test_cache_get_miss
  216. socket = FakeSocket.new
  217. socket.data.write "END\r\n"
  218. socket.data.rewind
  219. server = FakeServer.new socket
  220. assert_equal nil, @cache.cache_get(server, 'my_namespace:key')
  221. assert_equal "get my_namespace:key\r\n",
  222. socket.written.string
  223. end
  224. def test_cache_get_multi
  225. server = util_setup_fake_server
  226. server.socket.data.write "VALUE foo 0 7\r\n"
  227. server.socket.data.write "\004\b\"\bfoo\r\n"
  228. server.socket.data.write "VALUE bar 0 7\r\n"
  229. server.socket.data.write "\004\b\"\bbar\r\n"
  230. server.socket.data.write "END\r\n"
  231. server.socket.data.rewind
  232. result = @cache.cache_get_multi server, 'foo bar baz'
  233. assert_equal 2, result.length
  234. assert_equal "\004\b\"\bfoo", result['foo']
  235. assert_equal "\004\b\"\bbar", result['bar']
  236. end
  237. def test_cache_get_multi_EOF
  238. server = util_setup_fake_server
  239. server.socket.data.string = ''
  240. e = assert_raise IndexError do
  241. @cache.cache_get_multi server, 'my_namespace:key'
  242. end
  243. assert_equal "No connection to server (NOT CONNECTED)", e.message
  244. end
  245. def test_cache_get_multi_bad_state
  246. server = FakeServer.new
  247. # Write two messages to the socket to test failover
  248. server.socket.data.write "bogus response\r\nbogus response\r\n"
  249. server.socket.data.rewind
  250. @cache.servers = []
  251. @cache.servers << server
  252. e = assert_raise IndexError do
  253. @cache.cache_get_multi server, 'my_namespace:key'
  254. end
  255. assert_match(/#{Regexp.quote 'No connection to server (NOT CONNECTED)'}/, e.message)
  256. assert !server.alive?
  257. end
  258. def test_multithread_error
  259. server = FakeServer.new
  260. server.multithread = false
  261. @cache = MemCache.new(['localhost:1'], :multithread => false)
  262. server.socket.data.write "bogus response\r\nbogus response\r\n"
  263. server.socket.data.rewind
  264. @cache.servers = []
  265. @cache.servers << server
  266. assert_nothing_raised do
  267. @cache.set 'a', 1
  268. end
  269. passed = true
  270. Thread.new do
  271. begin
  272. @cache.set 'b', 2
  273. passed = false
  274. rescue MemCache::MemCacheError => me
  275. passed = me.message =~ /multiple threads/
  276. end
  277. end
  278. assert passed
  279. end
  280. def test_initialize
  281. cache = MemCache.new :namespace => 'my_namespace', :readonly => true
  282. assert_equal 'my_namespace', cache.namespace
  283. assert_equal true, cache.readonly?
  284. assert_equal true, cache.servers.empty?
  285. end
  286. def test_initialize_compatible
  287. cache = MemCache.new ['localhost:11211', 'localhost:11212'],
  288. :namespace => 'my_namespace', :readonly => true
  289. assert_equal 'my_namespace', cache.namespace
  290. assert_equal true, cache.readonly?
  291. assert_equal false, cache.servers.empty?
  292. end
  293. def test_initialize_compatible_no_hash
  294. cache = MemCache.new ['localhost:11211', 'localhost:11212']
  295. assert_equal nil, cache.namespace
  296. assert_equal false, cache.readonly?
  297. assert_equal false, cache.servers.empty?
  298. end
  299. def test_initialize_compatible_one_server
  300. cache = MemCache.new 'localhost:11211'
  301. assert_equal nil, cache.namespace
  302. assert_equal false, cache.readonly?
  303. assert_equal false, cache.servers.empty?
  304. end
  305. def test_initialize_compatible_bad_arg
  306. e = assert_raise ArgumentError do
  307. cache = MemCache.new Object.new
  308. end
  309. assert_equal 'first argument must be Array, Hash or String', e.message
  310. end
  311. def test_initialize_multiple_servers
  312. cache = MemCache.new %w[localhost:11211 localhost:11212],
  313. :namespace => 'my_namespace', :readonly => true
  314. assert_equal 'my_namespace', cache.namespace
  315. assert_equal true, cache.readonly?
  316. assert_equal false, cache.servers.empty?
  317. assert !cache.instance_variable_get(:@continuum).empty?
  318. end
  319. def test_initialize_too_many_args
  320. assert_raises ArgumentError do
  321. MemCache.new 1, 2, 3
  322. end
  323. end
  324. def test_decr
  325. server = FakeServer.new
  326. server.socket.data.write "5\r\n"
  327. server.socket.data.rewind
  328. @cache.servers = []
  329. @cache.servers << server
  330. value = @cache.decr 'key'
  331. assert_equal "decr my_namespace:key 1\r\n",
  332. @cache.servers.first.socket.written.string
  333. assert_equal 5, value
  334. end
  335. def test_decr_not_found
  336. server = FakeServer.new
  337. server.socket.data.write "NOT_FOUND\r\n"
  338. server.socket.data.rewind
  339. @cache.servers = []
  340. @cache.servers << server
  341. value = @cache.decr 'key'
  342. assert_equal "decr my_namespace:key 1\r\n",
  343. @cache.servers.first.socket.written.string
  344. assert_equal nil, value
  345. end
  346. def test_decr_space_padding
  347. server = FakeServer.new
  348. server.socket.data.write "5 \r\n"
  349. server.socket.data.rewind
  350. @cache.servers = []
  351. @cache.servers << server
  352. value = @cache.decr 'key'
  353. assert_equal "decr my_namespace:key 1\r\n",
  354. @cache.servers.first.socket.written.string
  355. assert_equal 5, value
  356. end
  357. def test_get
  358. util_setup_fake_server
  359. value = @cache.get 'key'
  360. assert_equal "get my_namespace:key\r\n",
  361. @cache.servers.first.socket.written.string
  362. assert_equal '0123456789', value
  363. end
  364. def test_fetch_without_a_block
  365. server = FakeServer.new
  366. server.socket.data.write "END\r\n"
  367. server.socket.data.rewind
  368. @cache.servers = [server]
  369. flexmock(@cache).should_receive(:get).with('key', false).and_return(nil)
  370. value = @cache.fetch('key', 1)
  371. assert_equal nil, value
  372. end
  373. def test_fetch_miss
  374. server = FakeServer.new
  375. server.socket.data.write "END\r\n"
  376. server.socket.data.rewind
  377. @cache.servers = [server]
  378. flexmock(@cache).should_receive(:get).with('key', false).and_return(nil)
  379. flexmock(@cache).should_receive(:add).with('key', 'value', 1, false)
  380. value = @cache.fetch('key', 1) { 'value' }
  381. assert_equal 'value', value
  382. end
  383. def test_fetch_hit
  384. server = FakeServer.new
  385. server.socket.data.write "END\r\n"
  386. server.socket.data.rewind
  387. @cache.servers = [server]
  388. flexmock(@cache).should_receive(:get).with('key', false).and_return('value')
  389. flexmock(@cache).should_receive(:add).never
  390. value = @cache.fetch('key', 1) { raise 'Should not be called.' }
  391. assert_equal 'value', value
  392. end
  393. def test_get_bad_key
  394. util_setup_fake_server
  395. assert_raise ArgumentError do @cache.get 'k y' end
  396. util_setup_fake_server
  397. assert_raise ArgumentError do @cache.get 'k' * 250 end
  398. end
  399. def test_get_cache_get_IOError
  400. socket = Object.new
  401. def socket.write(arg) raise IOError, 'some io error'; end
  402. server = FakeServer.new socket
  403. @cache.servers = []
  404. @cache.servers << server
  405. e = assert_raise MemCache::MemCacheError do
  406. @cache.get 'my_namespace:key'
  407. end
  408. assert_equal 'some io error', e.message
  409. end
  410. def test_get_cache_get_SystemCallError
  411. socket = Object.new
  412. def socket.write(arg) raise SystemCallError, 'some syscall error'; end
  413. server = FakeServer.new socket
  414. @cache.servers = []
  415. @cache.servers << server
  416. e = assert_raise MemCache::MemCacheError do
  417. @cache.get 'my_namespace:key'
  418. end
  419. assert_equal 'unknown error - some syscall error', e.message
  420. end
  421. def test_get_no_connection
  422. @cache.servers = 'localhost:1'
  423. e = assert_raise MemCache::MemCacheError do
  424. @cache.get 'key'
  425. end
  426. assert_match(/^No connection to server/, e.message)
  427. end
  428. def test_get_no_servers
  429. @cache.servers = []
  430. e = assert_raise MemCache::MemCacheError do
  431. @cache.get 'key'
  432. end
  433. assert_equal 'No active servers', e.message
  434. end
  435. def test_get_multi
  436. server = FakeServer.new
  437. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  438. server.socket.data.write "\004\b\"\0170123456789\r\n"
  439. server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
  440. server.socket.data.write "\004\b\"\0179876543210\r\n"
  441. server.socket.data.write "END\r\n"
  442. server.socket.data.rewind
  443. @cache.servers = []
  444. @cache.servers << server
  445. values = @cache.get_multi 'key', 'keyb'
  446. assert_equal "get my_namespace:key my_namespace:keyb\r\n",
  447. server.socket.written.string
  448. expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
  449. assert_equal expected.sort, values.sort
  450. end
  451. def test_get_raw
  452. server = FakeServer.new
  453. server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
  454. server.socket.data.write "0123456789\r\n"
  455. server.socket.data.write "END\r\n"
  456. server.socket.data.rewind
  457. @cache.servers = []
  458. @cache.servers << server
  459. value = @cache.get 'key', true
  460. assert_equal "get my_namespace:key\r\n",
  461. @cache.servers.first.socket.written.string
  462. assert_equal '0123456789', value
  463. end
  464. def test_get_server_for_key
  465. server = @cache.get_server_for_key 'key'
  466. assert_equal 'localhost', server.host
  467. assert_equal 1, server.port
  468. end
  469. def test_get_server_for_key_multiple
  470. s1 = util_setup_server @cache, 'one.example.com', ''
  471. s2 = util_setup_server @cache, 'two.example.com', ''
  472. @cache.servers = [s1, s2]
  473. server = @cache.get_server_for_key 'keya'
  474. assert_equal 'two.example.com', server.host
  475. server = @cache.get_server_for_key 'keyb'
  476. assert_equal 'two.example.com', server.host
  477. server = @cache.get_server_for_key 'keyc'
  478. assert_equal 'two.example.com', server.host
  479. server = @cache.get_server_for_key 'keyd'
  480. assert_equal 'one.example.com', server.host
  481. end
  482. def test_get_server_for_key_no_servers
  483. @cache.servers = []
  484. e = assert_raise MemCache::MemCacheError do
  485. @cache.get_server_for_key 'key'
  486. end
  487. assert_equal 'No servers available', e.message
  488. end
  489. def test_get_server_for_key_spaces
  490. e = assert_raise ArgumentError do
  491. @cache.get_server_for_key 'space key'
  492. end
  493. assert_equal 'illegal character in key "space key"', e.message
  494. end
  495. def test_get_server_for_key_length
  496. @cache.get_server_for_key 'x' * 250
  497. long_key = 'x' * 251
  498. e = assert_raise ArgumentError do
  499. @cache.get_server_for_key long_key
  500. end
  501. assert_equal "key too long #{long_key.inspect}", e.message
  502. end
  503. def test_incr
  504. server = FakeServer.new
  505. server.socket.data.write "5\r\n"
  506. server.socket.data.rewind
  507. @cache.servers = []
  508. @cache.servers << server
  509. value = @cache.incr 'key'
  510. assert_equal "incr my_namespace:key 1\r\n",
  511. @cache.servers.first.socket.written.string
  512. assert_equal 5, value
  513. end
  514. def test_incr_not_found
  515. server = FakeServer.new
  516. server.socket.data.write "NOT_FOUND\r\n"
  517. server.socket.data.rewind
  518. @cache.servers = []
  519. @cache.servers << server
  520. value = @cache.incr 'key'
  521. assert_equal "incr my_namespace:key 1\r\n",
  522. @cache.servers.first.socket.written.string
  523. assert_equal nil, value
  524. end
  525. def test_incr_space_padding
  526. server = FakeServer.new
  527. server.socket.data.write "5 \r\n"
  528. server.socket.data.rewind
  529. @cache.servers = []
  530. @cache.servers << server
  531. value = @cache.incr 'key'
  532. assert_equal "incr my_namespace:key 1\r\n",
  533. @cache.servers.first.socket.written.string
  534. assert_equal 5, value
  535. end
  536. def test_make_cache_key
  537. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  538. @cache.namespace = nil
  539. assert_equal 'key', @cache.make_cache_key('key')
  540. end
  541. def test_make_cache_key_without_autofix
  542. @cache.autofix_keys = false
  543. key = "keys with more than two hundred and fifty characters can cause problems, because they get truncated and start colliding with each other. It's not a common occurrence, but when it happens is very hard to debug. the autofix option takes care of that for you"
  544. hash = Digest::SHA1.hexdigest(key)
  545. @cache.namespace = nil
  546. assert_equal key, @cache.make_cache_key(key)
  547. @cache.autofix_keys = true
  548. @cache.namespace = "my_namespace"
  549. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  550. @cache.namespace = nil
  551. assert_equal 'key', @cache.make_cache_key('key')
  552. key = "keys with more than two hundred and fifty characters can cause problems, because they get truncated and start colliding with each other. It's not a common occurrence, but when it happens is very hard to debug. the autofix option takes care of that for you"
  553. hash = Digest::SHA1.hexdigest(key)
  554. @cache.namespace = "my_namespace"
  555. assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
  556. @cache.namespace = nil
  557. assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
  558. key = "a short key with spaces"
  559. hash = Digest::SHA1.hexdigest(key)
  560. @cache.namespace = "my_namespace"
  561. assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
  562. @cache.namespace = nil
  563. assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
  564. end
  565. def test_servers
  566. server = FakeServer.new
  567. @cache.servers = []
  568. @cache.servers << server
  569. assert_equal [server], @cache.servers
  570. end
  571. def test_set
  572. server = FakeServer.new
  573. server.socket.data.write "STORED\r\n"
  574. server.socket.data.rewind
  575. @cache.servers = []
  576. @cache.servers << server
  577. @cache.set 'key', 'value'
  578. dumped = Marshal.dump('value')
  579. expected = "set my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  580. # expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  581. assert_equal expected, server.socket.written.string
  582. end
  583. def test_set_expiry
  584. server = FakeServer.new
  585. server.socket.data.write "STORED\r\n"
  586. server.socket.data.rewind
  587. @cache.servers = []
  588. @cache.servers << server
  589. @cache.set 'key', 'value', 5
  590. dumped = Marshal.dump('value')
  591. expected = "set my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  592. assert_equal expected, server.socket.written.string
  593. end
  594. def test_set_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. @cache.set 'key', 'value', 0, true
  601. expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
  602. assert_equal expected, server.socket.written.string
  603. end
  604. def test_set_readonly
  605. cache = MemCache.new :readonly => true
  606. e = assert_raise MemCache::MemCacheError do
  607. cache.set 'key', 'value'
  608. end
  609. assert_equal 'Update of readonly cache', e.message
  610. end
  611. def test_check_size_on
  612. cache = MemCache.new :check_size => true
  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. e = assert_raise MemCache::MemCacheError do
  619. cache.set 'key', 'v' * 1048577
  620. end
  621. assert_equal 'Value too large, memcached can only store 1MB of data per key', e.message
  622. end
  623. def test_check_size_off
  624. cache = MemCache.new :check_size => false
  625. server = FakeServer.new
  626. server.socket.data.write "STORED\r\n"
  627. server.socket.data.rewind
  628. cache.servers = []
  629. cache.servers << server
  630. assert_nothing_raised do
  631. cache.set 'key', 'v' * 1048577
  632. end
  633. end
  634. def test_set_too_big
  635. server = FakeServer.new
  636. # Write two messages to the socket to test failover
  637. server.socket.data.write "SERVER_ERROR\r\nSERVER_ERROR object too large for cache\r\n"
  638. server.socket.data.rewind
  639. @cache.servers = []
  640. @cache.servers << server
  641. e = assert_raise MemCache::MemCacheError do
  642. @cache.set 'key', 'v'
  643. end
  644. assert_match(/object too large for cache/, e.message)
  645. end
  646. def test_prepend
  647. server = FakeServer.new
  648. server.socket.data.write "STORED\r\n"
  649. server.socket.data.rewind
  650. @cache.servers = []
  651. @cache.servers << server
  652. @cache.prepend 'key', 'value'
  653. dumped = Marshal.dump('value')
  654. expected = "prepend my_namespace:key 0 0 5\r\nvalue\r\n"
  655. assert_equal expected, server.socket.written.string
  656. end
  657. def test_append
  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. @cache.append 'key', 'value'
  664. expected = "append my_namespace:key 0 0 5\r\nvalue\r\n"
  665. assert_equal expected, server.socket.written.string
  666. end
  667. def test_replace
  668. server = FakeServer.new
  669. server.socket.data.write "STORED\r\n"
  670. server.socket.data.rewind
  671. @cache.servers = []
  672. @cache.servers << server
  673. @cache.replace 'key', 'value', 150
  674. dumped = Marshal.dump('value')
  675. expected = "replace my_namespace:key 0 150 #{dumped.length}\r\n#{dumped}\r\n"
  676. assert_equal expected, server.socket.written.string
  677. end
  678. def test_add
  679. server = FakeServer.new
  680. server.socket.data.write "STORED\r\n"
  681. server.socket.data.rewind
  682. @cache.servers = []
  683. @cache.servers << server
  684. @cache.add 'key', 'value'
  685. dumped = Marshal.dump('value')
  686. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  687. assert_equal expected, server.socket.written.string
  688. end
  689. def test_add_exists
  690. server = FakeServer.new
  691. server.socket.data.write "NOT_STORED\r\n"
  692. server.socket.data.rewind
  693. @cache.servers = []
  694. @cache.servers << server
  695. @cache.add 'key', 'value'
  696. dumped = Marshal.dump('value')
  697. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  698. assert_equal expected, server.socket.written.string
  699. end
  700. def test_add_expiry
  701. server = FakeServer.new
  702. server.socket.data.write "STORED\r\n"
  703. server.socket.data.rewind
  704. @cache.servers = []
  705. @cache.servers << server
  706. @cache.add 'key', 'value', 5
  707. dumped = Marshal.dump('value')
  708. expected = "add my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  709. assert_equal expected, server.socket.written.string
  710. end
  711. def test_add_raw
  712. server = FakeServer.new
  713. server.socket.data.write "STORED\r\n"
  714. server.socket.data.rewind
  715. @cache.servers = []
  716. @cache.servers << server
  717. @cache.add 'key', 'value', 0, true
  718. expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
  719. assert_equal expected, server.socket.written.string
  720. end
  721. def test_add_raw_int
  722. server = FakeServer.new
  723. server.socket.data.write "STORED\r\n"
  724. server.socket.data.rewind
  725. @cache.servers = []
  726. @cache.servers << server
  727. @cache.add 'key', 12, 0, true
  728. expected = "add my_namespace:key 0 0 2\r\n12\r\n"
  729. assert_equal expected, server.socket.written.string
  730. end
  731. def test_add_readonly
  732. cache = MemCache.new :readonly => true
  733. e = assert_raise MemCache::MemCacheError do
  734. cache.add 'key', 'value'
  735. end
  736. assert_equal 'Update of readonly cache', e.message
  737. end
  738. def test_delete
  739. server = FakeServer.new
  740. @cache.servers = []
  741. @cache.servers << server
  742. @cache.delete 'key'
  743. expected = "delete my_namespace:key 0\r\n"
  744. assert_equal expected, server.socket.written.string
  745. end
  746. def test_delete_with_expiry
  747. server = FakeServer.new
  748. @cache.servers = []
  749. @cache.servers << server
  750. @cache.delete 'key', 300
  751. expected = "delete my_namespace:key 300\r\n"
  752. assert_equal expected, server.socket.written.string
  753. end
  754. def test_flush_all
  755. @cache.servers = []
  756. 3.times { @cache.servers << FakeServer.new }
  757. @cache.flush_all
  758. expected = "flush_all\r\n"
  759. @cache.servers.each do |server|
  760. assert_equal expected, server.socket.written.string
  761. end
  762. end
  763. def test_flush_all_with_delay
  764. @cache.servers = []
  765. 3.times { @cache.servers << FakeServer.new }
  766. @cache.flush_all(10)
  767. @cache.servers.each_with_index do |server, idx|
  768. expected = "flush_all #{idx*10}\r\n"
  769. assert_equal expected, server.socket.written.string
  770. end
  771. end
  772. def test_flush_all_failure
  773. socket = FakeSocket.new
  774. # Write two messages to the socket to test failover
  775. socket.data.write "ERROR\r\nERROR\r\n"
  776. socket.data.rewind
  777. server = FakeServer.new socket
  778. @cache.servers = []
  779. @cache.servers << server
  780. assert_raise MemCache::MemCacheError do
  781. @cache.flush_all
  782. end
  783. assert_match(/flush_all\r\n/, socket.written.string)
  784. end
  785. def test_flush_all_for_real
  786. requirement(memcached_running?, 'A real memcached server must be running for testing flush_all') do
  787. cache = MemCache.new "localhost:11211", :namespace => "test_flush_all"
  788. k, v = "1234", "test"
  789. assert_nil cache.get(k)
  790. cache.set(k, v)
  791. assert_equal v, cache.get(k)
  792. cache.flush_all
  793. assert_nil cache.get(k)
  794. end
  795. end
  796. def test_stats
  797. socket = FakeSocket.new
  798. 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"
  799. socket.data.rewind
  800. server = FakeServer.new socket
  801. def server.host() 'localhost'; end
  802. def server.port() 11211; end
  803. @cache.servers = []
  804. @cache.servers << server
  805. expected = {
  806. 'localhost:11211' => {
  807. 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
  808. 'rusage_user' => 1.0003, 'dummy' => 'ok'
  809. }
  810. }
  811. assert_equal expected, @cache.stats
  812. assert_equal "stats\r\n", socket.written.string
  813. end
  814. def test_basic_threaded_operations_should_work
  815. cache = MemCache.new :multithread => true,
  816. :namespace => 'my_namespace',
  817. :readonly => false
  818. server = FakeServer.new
  819. server.socket.data.write "STORED\r\n"
  820. server.socket.data.rewind
  821. cache.servers = []
  822. cache.servers << server
  823. assert cache.multithread
  824. assert_nothing_raised do
  825. cache.set "test", "test value"
  826. end
  827. output = server.socket.written.string
  828. assert_match(/set my_namespace:test/, output)
  829. assert_match(/test value/, output)
  830. end
  831. def test_namespace_separator
  832. cache = MemCache.new :namespace => 'ns', :namespace_separator => ''
  833. server = FakeServer.new
  834. server.socket.data.write "STORED\r\n"
  835. server.socket.data.rewind
  836. cache.servers = []
  837. cache.servers << server
  838. assert_nothing_raised do
  839. cache.set "test", "test value"
  840. end
  841. output = server.socket.written.string
  842. assert_match(/set nstest/, output)
  843. assert_match(/test value/, output)
  844. end
  845. def test_basic_unthreaded_operations_should_work
  846. cache = MemCache.new :multithread => false,
  847. :namespace => 'my_namespace',
  848. :readonly => false
  849. server = FakeServer.new
  850. server.socket.data.write "STORED\r\n"
  851. server.socket.data.rewind
  852. cache.servers = []
  853. cache.servers << server
  854. assert !cache.multithread
  855. assert_nothing_raised do
  856. cache.set "test", "test value"
  857. end
  858. output = server.socket.written.string
  859. assert_match(/set my_namespace:test/, output)
  860. assert_match(/test value/, output)
  861. end
  862. def util_setup_fake_server
  863. server = FakeServer.new
  864. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  865. server.socket.data.write "\004\b\"\0170123456789\r\n"
  866. server.socket.data.write "END\r\n"
  867. server.socket.data.rewind
  868. @cache.servers = []
  869. @cache.servers << server
  870. return server
  871. end
  872. def util_setup_server(memcache, host, responses)
  873. server = MemCache::Server.new memcache, host
  874. server.instance_variable_set :@sock, StringIO.new(responses)
  875. @cache.servers = []
  876. @cache.servers << server
  877. return server
  878. end
  879. def test_crazy_multithreaded_access
  880. requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
  881. # Use a null logger to verify logging doesn't blow up at runtime
  882. cache = MemCache.new(['localhost:11211', '127.0.0.1:11211'], :logger => Logger.new('/dev/null'))
  883. cache.flush_all
  884. workers = []
  885. cache.set('f', 'zzz')
  886. assert_equal "STORED\r\n", (cache.cas('f') do |value|
  887. value << 'z'
  888. end)
  889. assert_equal 'zzzz', cache.get('f')
  890. # Have a bunch of threads perform a bunch of operations at the same time.
  891. # Verify the result of each operation to ensure the request and response
  892. # are not intermingled between threads.
  893. 10.times do
  894. workers << Thread.new do
  895. 100.times do
  896. cache.set('a', 9)
  897. cache.set('b', 11)
  898. cache.add('c', 10, 0, true)
  899. cache.set('d', 'a', 100, true)
  900. cache.set('e', 'x', 100, true)
  901. cache.set('f', 'zzz')
  902. assert_not_nil(cache.cas('f') do |value|
  903. value << 'z'
  904. end)
  905. cache.append('d', 'b')
  906. cache.prepend('e', 'y')
  907. assert_equal "NOT_STORED\r\n", cache.add('a', 11)
  908. assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
  909. inc = cache.incr('c', 10)
  910. assert_equal 0, inc % 5
  911. assert inc > 14
  912. assert cache.decr('c', 5) > 14
  913. assert_equal 11, cache.get('b')
  914. d = cache.get('d', true)
  915. assert_match(/\Aab*\Z/, d)
  916. e = cache.get('e', true)
  917. assert_match(/\Ay*x\Z/, e)
  918. end
  919. end
  920. end
  921. workers.each { |w| w.join }
  922. cache.flush_all
  923. end
  924. end
  925. end