PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/External.LCA_RESTRICTED/Languages/Ruby/ruby19/lib/ruby/gems/1.9.1/gems/memcache-client-1.8.5/test/test_mem_cache.rb

http://github.com/IronLanguages/main
Ruby | 1258 lines | 962 code | 279 blank | 17 comment | 6 complexity | bccdcaf6059962d6ba6188e094e54772 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. # encoding: utf-8
  2. require 'rubygems'
  3. require 'logger'
  4. require 'stringio'
  5. require 'test/unit'
  6. $TESTING = true
  7. require 'memcache'
  8. begin
  9. gem 'flexmock'
  10. require 'flexmock/test_unit'
  11. rescue LoadError => e
  12. puts "Some tests require flexmock, please run `gem install flexmock`"
  13. end
  14. Thread.abort_on_exception = true
  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_multi_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 "VALUE my_namespace:keyb 0 10\r\n"
  456. server.socket.data.write "9876543210\r\n"
  457. server.socket.data.write "END\r\n"
  458. server.socket.data.rewind
  459. @cache.servers = []
  460. @cache.servers << server
  461. values = @cache.get_multi 'key', 'keyb', :raw => true
  462. assert_equal "get my_namespace:key my_namespace:keyb\r\n",
  463. server.socket.written.string
  464. expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
  465. assert_equal expected.sort, values.sort
  466. end
  467. def test_get_raw
  468. server = FakeServer.new
  469. server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
  470. server.socket.data.write "0123456789\r\n"
  471. server.socket.data.write "END\r\n"
  472. server.socket.data.rewind
  473. @cache.servers = []
  474. @cache.servers << server
  475. value = @cache.get 'key', true
  476. assert_equal "get my_namespace:key\r\n",
  477. @cache.servers.first.socket.written.string
  478. assert_equal '0123456789', value
  479. end
  480. def test_get_server_for_key
  481. server = @cache.get_server_for_key 'key'
  482. assert_equal 'localhost', server.host
  483. assert_equal 1, server.port
  484. end
  485. def test_get_server_for_key_multiple
  486. s1 = util_setup_server @cache, 'one.example.com', ''
  487. s2 = util_setup_server @cache, 'two.example.com', ''
  488. @cache.servers = [s1, s2]
  489. server = @cache.get_server_for_key 'keya'
  490. assert_equal 'two.example.com', server.host
  491. server = @cache.get_server_for_key 'keyb'
  492. assert_equal 'two.example.com', server.host
  493. server = @cache.get_server_for_key 'keyc'
  494. assert_equal 'two.example.com', server.host
  495. server = @cache.get_server_for_key 'keyd'
  496. assert_equal 'one.example.com', server.host
  497. end
  498. def test_get_server_for_key_no_servers
  499. @cache.servers = []
  500. e = assert_raise MemCache::MemCacheError do
  501. @cache.get_server_for_key 'key'
  502. end
  503. assert_equal 'No servers available', e.message
  504. end
  505. def test_get_server_for_key_spaces
  506. e = assert_raise ArgumentError do
  507. @cache.get_server_for_key 'space key'
  508. end
  509. assert_equal 'illegal character in key "space key"', e.message
  510. end
  511. def test_get_server_for_blank_key
  512. e = assert_raise ArgumentError do
  513. @cache.get_server_for_key ''
  514. end
  515. assert_equal 'key cannot be blank', e.message
  516. end
  517. def test_get_server_for_key_length
  518. @cache.get_server_for_key 'x' * 250
  519. long_key = 'x' * 251
  520. e = assert_raise ArgumentError do
  521. @cache.get_server_for_key long_key
  522. end
  523. assert_equal "key too long #{long_key.inspect}", e.message
  524. end
  525. def test_incr
  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_incr_not_found
  537. server = FakeServer.new
  538. server.socket.data.write "NOT_FOUND\r\n"
  539. server.socket.data.rewind
  540. @cache.servers = []
  541. @cache.servers << server
  542. value = @cache.incr 'key'
  543. assert_equal "incr my_namespace:key 1\r\n",
  544. @cache.servers.first.socket.written.string
  545. assert_equal nil, value
  546. end
  547. def test_incr_space_padding
  548. server = FakeServer.new
  549. server.socket.data.write "5 \r\n"
  550. server.socket.data.rewind
  551. @cache.servers = []
  552. @cache.servers << server
  553. value = @cache.incr 'key'
  554. assert_equal "incr my_namespace:key 1\r\n",
  555. @cache.servers.first.socket.written.string
  556. assert_equal 5, value
  557. end
  558. def test_make_cache_key
  559. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  560. @cache.namespace = nil
  561. assert_equal 'key', @cache.make_cache_key('key')
  562. end
  563. def test_make_cache_key_without_autofix
  564. @cache.autofix_keys = false
  565. 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"
  566. hash = Digest::SHA1.hexdigest(key)
  567. @cache.namespace = nil
  568. assert_equal key, @cache.make_cache_key(key)
  569. end
  570. def test_make_cache_key_with_autofix
  571. @cache.autofix_keys = true
  572. @cache.namespace = "my_namespace"
  573. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  574. @cache.namespace = nil
  575. assert_equal 'key', @cache.make_cache_key('key')
  576. 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"
  577. hash = Digest::SHA1.hexdigest(key)
  578. @cache.namespace = "my_namespace"
  579. assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
  580. @cache.namespace = nil
  581. assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
  582. key = "a short key with spaces"
  583. hash = Digest::SHA1.hexdigest(key)
  584. @cache.namespace = "my_namespace"
  585. assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
  586. @cache.namespace = nil
  587. assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
  588. # namespace + separator + key > 250
  589. key = 'k' * 240
  590. hash = Digest::SHA1.hexdigest(key)
  591. @cache.namespace = 'n' * 10
  592. assert_equal "#{@cache.namespace}:#{hash}-autofixed", @cache.make_cache_key(key)
  593. end
  594. def test_servers
  595. server = FakeServer.new
  596. @cache.servers = []
  597. @cache.servers << server
  598. assert_equal [server], @cache.servers
  599. end
  600. def test_set
  601. server = FakeServer.new
  602. server.socket.data.write "STORED\r\n"
  603. server.socket.data.rewind
  604. @cache.servers = []
  605. @cache.servers << server
  606. @cache.set 'key', 'value'
  607. dumped = Marshal.dump('value')
  608. expected = "set my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  609. # expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  610. assert_equal expected, server.socket.written.string
  611. end
  612. def test_set_expiry
  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.set 'key', 'value', 5
  619. dumped = Marshal.dump('value')
  620. expected = "set my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  621. assert_equal expected, server.socket.written.string
  622. end
  623. def test_set_raw
  624. server = FakeServer.new
  625. server.socket.data.write "STORED\r\n"
  626. server.socket.data.rewind
  627. @cache.servers = []
  628. @cache.servers << server
  629. @cache.set 'key', 'value', 0, true
  630. expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
  631. assert_equal expected, server.socket.written.string
  632. end
  633. def test_set_readonly
  634. cache = MemCache.new :readonly => true
  635. e = assert_raise MemCache::MemCacheError do
  636. cache.set 'key', 'value'
  637. end
  638. assert_equal 'Update of readonly cache', e.message
  639. end
  640. def test_check_size_on
  641. cache = MemCache.new :check_size => true
  642. server = FakeServer.new
  643. server.socket.data.write "STORED\r\n"
  644. server.socket.data.rewind
  645. cache.servers = []
  646. cache.servers << server
  647. e = assert_raise MemCache::MemCacheError do
  648. cache.set 'key', 'v' * 1048577
  649. end
  650. assert_equal 'Value too large, memcached can only store 1MB of data per key', e.message
  651. end
  652. def test_check_size_off
  653. cache = MemCache.new :check_size => false
  654. server = FakeServer.new
  655. server.socket.data.write "STORED\r\n"
  656. server.socket.data.rewind
  657. cache.servers = []
  658. cache.servers << server
  659. assert_nothing_raised do
  660. cache.set 'key', 'v' * 1048577
  661. end
  662. end
  663. def test_set_too_big
  664. server = FakeServer.new
  665. # Write two messages to the socket to test failover
  666. server.socket.data.write "SERVER_ERROR\r\nSERVER_ERROR object too large for cache\r\n"
  667. server.socket.data.rewind
  668. @cache.servers = []
  669. @cache.servers << server
  670. e = assert_raise MemCache::MemCacheError do
  671. @cache.set 'key', 'v'
  672. end
  673. assert_match(/object too large for cache/, e.message)
  674. end
  675. def test_prepend
  676. server = FakeServer.new
  677. server.socket.data.write "STORED\r\n"
  678. server.socket.data.rewind
  679. @cache.servers = []
  680. @cache.servers << server
  681. @cache.prepend 'key', 'value'
  682. dumped = Marshal.dump('value')
  683. expected = "prepend my_namespace:key 0 0 5\r\nvalue\r\n"
  684. assert_equal expected, server.socket.written.string
  685. end
  686. def test_append
  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. @cache.append 'key', 'value'
  693. expected = "append my_namespace:key 0 0 5\r\nvalue\r\n"
  694. assert_equal expected, server.socket.written.string
  695. end
  696. def test_replace
  697. server = FakeServer.new
  698. server.socket.data.write "STORED\r\n"
  699. server.socket.data.rewind
  700. @cache.servers = []
  701. @cache.servers << server
  702. @cache.replace 'key', 'value', 150
  703. dumped = Marshal.dump('value')
  704. expected = "replace my_namespace:key 0 150 #{dumped.length}\r\n#{dumped}\r\n"
  705. assert_equal expected, server.socket.written.string
  706. end
  707. def test_add
  708. server = FakeServer.new
  709. server.socket.data.write "STORED\r\n"
  710. server.socket.data.rewind
  711. @cache.servers = []
  712. @cache.servers << server
  713. @cache.add 'key', 'value'
  714. dumped = Marshal.dump('value')
  715. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  716. assert_equal expected, server.socket.written.string
  717. end
  718. def test_add_exists
  719. server = FakeServer.new
  720. server.socket.data.write "NOT_STORED\r\n"
  721. server.socket.data.rewind
  722. @cache.servers = []
  723. @cache.servers << server
  724. @cache.add 'key', 'value'
  725. dumped = Marshal.dump('value')
  726. expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
  727. assert_equal expected, server.socket.written.string
  728. end
  729. def test_add_expiry
  730. server = FakeServer.new
  731. server.socket.data.write "STORED\r\n"
  732. server.socket.data.rewind
  733. @cache.servers = []
  734. @cache.servers << server
  735. @cache.add 'key', 'value', 5
  736. dumped = Marshal.dump('value')
  737. expected = "add my_namespace:key 0 5 #{dumped.length}\r\n#{dumped}\r\n"
  738. assert_equal expected, server.socket.written.string
  739. end
  740. def test_add_raw
  741. server = FakeServer.new
  742. server.socket.data.write "STORED\r\n"
  743. server.socket.data.rewind
  744. @cache.servers = []
  745. @cache.servers << server
  746. @cache.add 'key', 'value', 0, true
  747. expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
  748. assert_equal expected, server.socket.written.string
  749. end
  750. def test_add_raw_int
  751. server = FakeServer.new
  752. server.socket.data.write "STORED\r\n"
  753. server.socket.data.rewind
  754. @cache.servers = []
  755. @cache.servers << server
  756. @cache.add 'key', 12, 0, true
  757. expected = "add my_namespace:key 0 0 2\r\n12\r\n"
  758. assert_equal expected, server.socket.written.string
  759. end
  760. def test_add_readonly
  761. cache = MemCache.new :readonly => true
  762. e = assert_raise MemCache::MemCacheError do
  763. cache.add 'key', 'value'
  764. end
  765. assert_equal 'Update of readonly cache', e.message
  766. end
  767. def test_delete
  768. server = FakeServer.new
  769. @cache.servers = []
  770. @cache.servers << server
  771. @cache.delete 'key'
  772. expected = "delete my_namespace:key\r\n"
  773. assert_equal expected, server.socket.written.string
  774. end
  775. def test_delete_with_expiry
  776. server = FakeServer.new
  777. @cache.servers = []
  778. @cache.servers << server
  779. @cache.delete 'key', 300
  780. expected = "delete my_namespace:key\r\n"
  781. assert_equal expected, server.socket.written.string
  782. end
  783. def test_flush_all
  784. @cache.servers = []
  785. 3.times { @cache.servers << FakeServer.new }
  786. @cache.flush_all
  787. expected = "flush_all\r\n"
  788. @cache.servers.each do |server|
  789. assert_equal expected, server.socket.written.string
  790. end
  791. end
  792. def test_flush_all_with_delay
  793. @cache.servers = []
  794. 3.times { @cache.servers << FakeServer.new }
  795. @cache.flush_all(10)
  796. @cache.servers.each_with_index do |server, idx|
  797. expected = "flush_all #{idx*10}\r\n"
  798. assert_equal expected, server.socket.written.string
  799. end
  800. end
  801. def test_flush_all_failure
  802. socket = FakeSocket.new
  803. # Write two messages to the socket to test failover
  804. socket.data.write "ERROR\r\nERROR\r\n"
  805. socket.data.rewind
  806. server = FakeServer.new socket
  807. @cache.servers = []
  808. @cache.servers << server
  809. assert_raise MemCache::MemCacheError do
  810. @cache.flush_all
  811. end
  812. assert_match(/flush_all\r\n/, socket.written.string)
  813. end
  814. def test_flush_all_for_real
  815. requirement(memcached_running?, 'A real memcached server must be running for testing flush_all') do
  816. cache = MemCache.new "localhost:11211", :namespace => "test_flush_all"
  817. k, v = "1234", "test"
  818. assert_nil cache.get(k)
  819. cache.set(k, v)
  820. assert_equal v, cache.get(k)
  821. cache.flush_all
  822. assert_nil cache.get(k)
  823. end
  824. end
  825. def test_stats
  826. socket = FakeSocket.new
  827. 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"
  828. socket.data.rewind
  829. server = FakeServer.new socket
  830. def server.host() 'localhost'; end
  831. def server.port() 11211; end
  832. @cache.servers = []
  833. @cache.servers << server
  834. expected = {
  835. 'localhost:11211' => {
  836. 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
  837. 'rusage_user' => 1.0003, 'dummy' => 'ok'
  838. }
  839. }
  840. assert_equal expected, @cache.stats
  841. assert_equal "stats\r\n", socket.written.string
  842. end
  843. def test_basic_threaded_operations_should_work
  844. cache = MemCache.new :multithread => true,
  845. :namespace => 'my_namespace',
  846. :readonly => false
  847. server = FakeServer.new
  848. server.socket.data.write "STORED\r\n"
  849. server.socket.data.rewind
  850. cache.servers = []
  851. cache.servers << server
  852. assert cache.multithread
  853. assert_nothing_raised do
  854. cache.set "test", "test value"
  855. end
  856. output = server.socket.written.string
  857. assert_match(/set my_namespace:test/, output)
  858. assert_match(/test value/, output)
  859. end
  860. def test_namespace_separator
  861. cache = MemCache.new :namespace => 'ns', :namespace_separator => ''
  862. server = FakeServer.new
  863. server.socket.data.write "STORED\r\n"
  864. server.socket.data.rewind
  865. cache.servers = []
  866. cache.servers << server
  867. assert_nothing_raised do
  868. cache.set "test", "test value"
  869. end
  870. output = server.socket.written.string
  871. assert_match(/set nstest/, output)
  872. assert_match(/test value/, output)
  873. end
  874. def test_basic_unthreaded_operations_should_work
  875. cache = MemCache.new :multithread => false,
  876. :namespace => 'my_namespace',
  877. :readonly => false
  878. server = FakeServer.new
  879. server.socket.data.write "STORED\r\n"
  880. server.socket.data.rewind
  881. cache.servers = []
  882. cache.servers << server
  883. assert !cache.multithread
  884. assert_nothing_raised do
  885. cache.set "test", "test value"
  886. end
  887. output = server.socket.written.string
  888. assert_match(/set my_namespace:test/, output)
  889. assert_match(/test value/, output)
  890. end
  891. def util_setup_fake_server
  892. server = FakeServer.new
  893. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  894. server.socket.data.write "\004\b\"\0170123456789\r\n"
  895. server.socket.data.write "END\r\n"
  896. server.socket.data.rewind
  897. @cache.servers = []
  898. @cache.servers << server
  899. return server
  900. end
  901. def util_setup_server(memcache, host, responses)
  902. server = MemCache::Server.new memcache, host
  903. server.instance_variable_set :@sock, StringIO.new(responses)
  904. @cache.servers = []
  905. @cache.servers << server
  906. return server
  907. end
  908. def test_crazy_multithreaded_access
  909. requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
  910. # Use a null logger to verify logging doesn't blow up at runtime
  911. cache = MemCache.new(['localhost:11211', '127.0.0.1:11211'], :logger => Logger.new('/dev/null'))
  912. cache.flush_all
  913. assert_equal true, cache.multithread
  914. workers = []
  915. cache.set('f', 'zzz')
  916. assert_equal "STORED\r\n", (cache.cas('f') do |value|
  917. value << 'z'
  918. end)
  919. assert_equal 'zzzz', cache.get('f')
  920. # Have a bunch of threads perform a bunch of operations at the same time.
  921. # Verify the result of each operation to ensure the request and response
  922. # are not intermingled between threads.
  923. 10.times do
  924. workers << Thread.new do
  925. 100.times do
  926. cache.set('a', 9)
  927. cache.set('b', 11)
  928. cache.add('c', 10, 0, true)
  929. cache.set('d', 'a', 100, true)
  930. cache.set('e', 'x', 100, true)
  931. cache.set('f', 'zzz')
  932. assert_not_nil(cache.cas('f') do |value|
  933. value << 'z'
  934. end)
  935. cache.append('d', 'b')
  936. cache.prepend('e', 'y')
  937. assert_equal "NOT_STORED\r\n", cache.add('a', 11)
  938. assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
  939. inc = cache.incr('c', 10)
  940. assert_equal 0, inc % 5
  941. assert inc > 14
  942. assert cache.decr('c', 5) > 14
  943. assert_equal 11, cache.get('b')
  944. d = cache.get('d', true)
  945. assert_match(/\Aab*\Z/, d)
  946. e = cache.get('e', true)
  947. assert_match(/\Ay*x\Z/, e)
  948. end
  949. end
  950. end
  951. workers.each { |w| w.join }
  952. cache.flush_all
  953. end
  954. end
  955. end