PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/test/test_mem_cache.rb

https://github.com/timurvafin/memcache-client
Ruby | 744 lines | 688 code | 56 blank | 0 comment | 1 complexity | c5cf0b53ba8f9e035cc6a8a6b4c21a5f MD5 | raw file
  1. require 'stringio'
  2. require 'test/unit'
  3. require 'rubygems'
  4. require 'test/zentest_assertions'
  5. $TESTING = true
  6. require 'memcache'
  7. class MemCache
  8. attr_writer :namespace
  9. end
  10. class FakeSocket
  11. attr_reader :written, :data
  12. def initialize
  13. @written = StringIO.new
  14. @data = StringIO.new
  15. end
  16. def write(data)
  17. @written.write data
  18. end
  19. def gets
  20. @data.gets
  21. end
  22. def read(arg)
  23. @data.read arg
  24. end
  25. end
  26. class FakeServer
  27. attr_reader :host, :port, :socket
  28. def initialize(socket = nil)
  29. @closed = false
  30. @host = 'example.com'
  31. @port = 11211
  32. @socket = socket || FakeSocket.new
  33. end
  34. def close
  35. @closed = true
  36. end
  37. def alive?
  38. !@closed
  39. end
  40. end
  41. class TestMemCache < Test::Unit::TestCase
  42. def setup
  43. @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace'
  44. end
  45. def test_cache_get
  46. server = util_setup_fake_server
  47. assert_equal "\004\b\"\0170123456789",
  48. @cache.cache_get(server, 'my_namespace:key')
  49. assert_equal "get my_namespace:key\r\n",
  50. server.socket.written.string
  51. end
  52. def test_cache_get_EOF
  53. server = util_setup_fake_server
  54. server.socket.data.string = ''
  55. e = assert_raise MemCache::MemCacheError do
  56. @cache.cache_get server, 'my_namespace:key'
  57. end
  58. assert_equal "lost connection to example.com:11211", e.message
  59. end
  60. def test_cache_get_bad_state
  61. server = FakeServer.new
  62. server.socket.data.write "bogus response\r\n"
  63. server.socket.data.rewind
  64. @cache.servers = []
  65. @cache.servers << server
  66. e = assert_raise MemCache::MemCacheError do
  67. @cache.cache_get(server, 'my_namespace:key')
  68. end
  69. assert_equal "unexpected response \"bogus response\\r\\n\"", e.message
  70. deny server.alive?
  71. assert_equal "get my_namespace:key\r\n",
  72. server.socket.written.string
  73. end
  74. def test_cache_get_miss
  75. socket = FakeSocket.new
  76. socket.data.write "END\r\n"
  77. socket.data.rewind
  78. server = FakeServer.new socket
  79. assert_equal nil, @cache.cache_get(server, 'my_namespace:key')
  80. assert_equal "get my_namespace:key\r\n",
  81. socket.written.string
  82. end
  83. def test_cache_get_multi
  84. server = util_setup_fake_server
  85. server.socket.data.write "VALUE foo 0 7\r\n"
  86. server.socket.data.write "\004\b\"\bfoo\r\n"
  87. server.socket.data.write "VALUE bar 0 7\r\n"
  88. server.socket.data.write "\004\b\"\bbar\r\n"
  89. server.socket.data.write "END\r\n"
  90. server.socket.data.rewind
  91. result = @cache.cache_get_multi server, 'foo bar baz'
  92. assert_equal 2, result.length
  93. assert_equal "\004\b\"\bfoo", result['foo']
  94. assert_equal "\004\b\"\bbar", result['bar']
  95. end
  96. def test_cache_get_multi_EOF
  97. server = util_setup_fake_server
  98. server.socket.data.string = ''
  99. e = assert_raise MemCache::MemCacheError do
  100. @cache.cache_get_multi server, 'my_namespace:key'
  101. end
  102. assert_equal "lost connection to example.com:11211", e.message
  103. end
  104. def test_cache_get_multi_bad_state
  105. server = FakeServer.new
  106. server.socket.data.write "bogus response\r\n"
  107. server.socket.data.rewind
  108. @cache.servers = []
  109. @cache.servers << server
  110. e = assert_raise MemCache::MemCacheError do
  111. @cache.cache_get_multi server, 'my_namespace:key'
  112. end
  113. assert_equal "unexpected response \"bogus response\\r\\n\"", e.message
  114. deny server.alive?
  115. assert_equal "get my_namespace:key\r\n",
  116. server.socket.written.string
  117. end
  118. def test_crc32_ITU_T
  119. assert_equal 0, ''.crc32_ITU_T
  120. assert_equal 1260851911, 'my_namespace:key'.crc32_ITU_T
  121. end
  122. def test_initialize
  123. cache = MemCache.new :namespace => 'my_namespace', :readonly => true
  124. assert_equal 'my_namespace', cache.namespace
  125. assert_equal true, cache.readonly?
  126. assert_equal true, cache.servers.empty?
  127. end
  128. def test_initialize_compatible
  129. cache = MemCache.new ['localhost:11211', 'localhost:11212'],
  130. :namespace => 'my_namespace', :readonly => true
  131. assert_equal 'my_namespace', cache.namespace
  132. assert_equal true, cache.readonly?
  133. assert_equal false, cache.servers.empty?
  134. end
  135. def test_initialize_compatible_no_hash
  136. cache = MemCache.new ['localhost:11211', 'localhost:11212']
  137. assert_equal nil, cache.namespace
  138. assert_equal false, cache.readonly?
  139. assert_equal false, cache.servers.empty?
  140. end
  141. def test_initialize_compatible_one_server
  142. cache = MemCache.new 'localhost:11211'
  143. assert_equal nil, cache.namespace
  144. assert_equal false, cache.readonly?
  145. assert_equal false, cache.servers.empty?
  146. end
  147. def test_initialize_compatible_bad_arg
  148. e = assert_raise ArgumentError do
  149. cache = MemCache.new Object.new
  150. end
  151. assert_equal 'first argument must be Array, Hash or String', e.message
  152. end
  153. def test_initialize_multiple_servers
  154. cache = MemCache.new %w[localhost:11211 localhost:11212],
  155. :namespace => 'my_namespace', :readonly => true
  156. assert_equal 'my_namespace', cache.namespace
  157. assert_equal true, cache.readonly?
  158. assert_equal false, cache.servers.empty?
  159. deny_empty cache.instance_variable_get(:@buckets)
  160. end
  161. def test_initialize_too_many_args
  162. assert_raises ArgumentError do
  163. MemCache.new 1, 2, 3
  164. end
  165. end
  166. def test_decr
  167. server = FakeServer.new
  168. server.socket.data.write "5\r\n"
  169. server.socket.data.rewind
  170. @cache.servers = []
  171. @cache.servers << server
  172. value = @cache.decr 'key'
  173. assert_equal "decr my_namespace:key 1\r\n",
  174. @cache.servers.first.socket.written.string
  175. assert_equal 5, value
  176. end
  177. def test_decr_not_found
  178. server = FakeServer.new
  179. server.socket.data.write "NOT_FOUND\r\n"
  180. server.socket.data.rewind
  181. @cache.servers = []
  182. @cache.servers << server
  183. value = @cache.decr 'key'
  184. assert_equal "decr my_namespace:key 1\r\n",
  185. @cache.servers.first.socket.written.string
  186. assert_equal nil, value
  187. end
  188. def test_decr_space_padding
  189. server = FakeServer.new
  190. server.socket.data.write "5 \r\n"
  191. server.socket.data.rewind
  192. @cache.servers = []
  193. @cache.servers << server
  194. value = @cache.decr 'key'
  195. assert_equal "decr my_namespace:key 1\r\n",
  196. @cache.servers.first.socket.written.string
  197. assert_equal 5, value
  198. end
  199. def test_get
  200. util_setup_fake_server
  201. value = @cache.get 'key'
  202. assert_equal "get my_namespace:key\r\n",
  203. @cache.servers.first.socket.written.string
  204. assert_equal '0123456789', value
  205. end
  206. def test_get_bad_key
  207. util_setup_fake_server
  208. assert_raise ArgumentError do @cache.get 'k y' end
  209. util_setup_fake_server
  210. assert_raise ArgumentError do @cache.get 'k' * 250 end
  211. end
  212. def test_get_cache_get_IOError
  213. socket = Object.new
  214. def socket.write(arg) raise IOError, 'some io error'; end
  215. server = FakeServer.new socket
  216. @cache.servers = []
  217. @cache.servers << server
  218. e = assert_raise MemCache::MemCacheError do
  219. @cache.get 'my_namespace:key'
  220. end
  221. assert_equal 'some io error', e.message
  222. end
  223. def test_get_cache_get_SystemCallError
  224. socket = Object.new
  225. def socket.write(arg) raise SystemCallError, 'some syscall error'; end
  226. server = FakeServer.new socket
  227. @cache.servers = []
  228. @cache.servers << server
  229. e = assert_raise MemCache::MemCacheError do
  230. @cache.get 'my_namespace:key'
  231. end
  232. assert_equal 'unknown error - some syscall error', e.message
  233. end
  234. def test_get_no_connection
  235. @cache.servers = 'localhost:1'
  236. e = assert_raise MemCache::MemCacheError do
  237. @cache.get 'key'
  238. end
  239. assert_match /^No connection to server/, e.message
  240. end
  241. def test_get_no_servers
  242. @cache.servers = []
  243. e = assert_raise MemCache::MemCacheError do
  244. @cache.get 'key'
  245. end
  246. assert_equal 'No active servers', e.message
  247. end
  248. def test_get_multi
  249. server = FakeServer.new
  250. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  251. server.socket.data.write "\004\b\"\0170123456789\r\n"
  252. server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n"
  253. server.socket.data.write "\004\b\"\0179876543210\r\n"
  254. server.socket.data.write "END\r\n"
  255. server.socket.data.rewind
  256. @cache.servers = []
  257. @cache.servers << server
  258. values = @cache.get_multi 'key', 'keyb'
  259. assert_equal "get my_namespace:key my_namespace:keyb\r\n",
  260. server.socket.written.string
  261. expected = { 'key' => '0123456789', 'keyb' => '9876543210' }
  262. assert_equal expected.sort, values.sort
  263. end
  264. def test_get_raw
  265. server = FakeServer.new
  266. server.socket.data.write "VALUE my_namespace:key 0 10\r\n"
  267. server.socket.data.write "0123456789\r\n"
  268. server.socket.data.write "END\r\n"
  269. server.socket.data.rewind
  270. @cache.servers = []
  271. @cache.servers << server
  272. value = @cache.get 'key', true
  273. assert_equal "get my_namespace:key\r\n",
  274. @cache.servers.first.socket.written.string
  275. assert_equal '0123456789', value
  276. end
  277. def test_get_server_for_key
  278. server = @cache.get_server_for_key 'key'
  279. assert_equal 'localhost', server.host
  280. assert_equal 1, server.port
  281. end
  282. def test_get_server_for_key_multiple
  283. s1 = util_setup_server @cache, 'one.example.com', ''
  284. s2 = util_setup_server @cache, 'two.example.com', ''
  285. @cache.instance_variable_set :@servers, [s1, s2]
  286. @cache.instance_variable_set :@buckets, [s1, s2]
  287. server = @cache.get_server_for_key 'keya'
  288. assert_equal 'two.example.com', server.host
  289. server = @cache.get_server_for_key 'keyb'
  290. assert_equal 'one.example.com', server.host
  291. end
  292. def test_get_server_for_key_no_servers
  293. @cache.servers = []
  294. e = assert_raise MemCache::MemCacheError do
  295. @cache.get_server_for_key 'key'
  296. end
  297. assert_equal 'No servers available', e.message
  298. end
  299. def test_get_server_for_key_spaces
  300. e = assert_raise ArgumentError do
  301. @cache.get_server_for_key 'space key'
  302. end
  303. assert_equal 'illegal character in key "space key"', e.message
  304. end
  305. def test_get_server_for_key_length
  306. @cache.get_server_for_key 'x' * 250
  307. long_key = 'x' * 251
  308. e = assert_raise ArgumentError do
  309. @cache.get_server_for_key long_key
  310. end
  311. assert_equal "key too long #{long_key.inspect}", e.message
  312. end
  313. def test_incr
  314. server = FakeServer.new
  315. server.socket.data.write "5\r\n"
  316. server.socket.data.rewind
  317. @cache.servers = []
  318. @cache.servers << server
  319. value = @cache.incr 'key'
  320. assert_equal "incr my_namespace:key 1\r\n",
  321. @cache.servers.first.socket.written.string
  322. assert_equal 5, value
  323. end
  324. def test_incr_not_found
  325. server = FakeServer.new
  326. server.socket.data.write "NOT_FOUND\r\n"
  327. server.socket.data.rewind
  328. @cache.servers = []
  329. @cache.servers << server
  330. value = @cache.incr 'key'
  331. assert_equal "incr my_namespace:key 1\r\n",
  332. @cache.servers.first.socket.written.string
  333. assert_equal nil, value
  334. end
  335. def test_incr_space_padding
  336. server = FakeServer.new
  337. server.socket.data.write "5 \r\n"
  338. server.socket.data.rewind
  339. @cache.servers = []
  340. @cache.servers << server
  341. value = @cache.incr 'key'
  342. assert_equal "incr my_namespace:key 1\r\n",
  343. @cache.servers.first.socket.written.string
  344. assert_equal 5, value
  345. end
  346. def test_make_cache_key
  347. assert_equal 'my_namespace:key', @cache.make_cache_key('key')
  348. @cache.namespace = nil
  349. assert_equal 'key', @cache.make_cache_key('key')
  350. end
  351. def test_servers
  352. server = FakeServer.new
  353. @cache.servers = []
  354. @cache.servers << server
  355. assert_equal [server], @cache.servers
  356. end
  357. def test_servers_equals_type_error
  358. e = assert_raise TypeError do
  359. @cache.servers = [Object.new]
  360. end
  361. assert_equal 'cannot convert Object into MemCache::Server', e.message
  362. end
  363. def test_set
  364. server = FakeServer.new
  365. server.socket.data.write "STORED\r\n"
  366. server.socket.data.rewind
  367. @cache.servers = []
  368. @cache.servers << server
  369. @cache.set 'key', 'value'
  370. expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  371. assert_equal expected, server.socket.written.string
  372. end
  373. def test_set_expiry
  374. server = FakeServer.new
  375. server.socket.data.write "STORED\r\n"
  376. server.socket.data.rewind
  377. @cache.servers = []
  378. @cache.servers << server
  379. @cache.set 'key', 'value', 5
  380. expected = "set my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n"
  381. assert_equal expected, server.socket.written.string
  382. end
  383. def test_set_raw
  384. server = FakeServer.new
  385. server.socket.data.write "STORED\r\n"
  386. server.socket.data.rewind
  387. @cache.servers = []
  388. @cache.servers << server
  389. @cache.set 'key', 'value', 0, true
  390. expected = "set my_namespace:key 0 0 5\r\nvalue\r\n"
  391. assert_equal expected, server.socket.written.string
  392. end
  393. def test_set_readonly
  394. cache = MemCache.new :readonly => true
  395. e = assert_raise MemCache::MemCacheError do
  396. cache.set 'key', 'value'
  397. end
  398. assert_equal 'Update of readonly cache', e.message
  399. end
  400. def test_set_too_big
  401. server = FakeServer.new
  402. server.socket.data.write "SERVER_ERROR object too large for cache\r\n"
  403. server.socket.data.rewind
  404. @cache.servers = []
  405. @cache.servers << server
  406. e = assert_raise MemCache::MemCacheError do
  407. @cache.set 'key', 'v'
  408. end
  409. assert_equal 'object too large for cache', e.message
  410. end
  411. def test_add
  412. server = FakeServer.new
  413. server.socket.data.write "STORED\r\n"
  414. server.socket.data.rewind
  415. @cache.servers = []
  416. @cache.servers << server
  417. @cache.add 'key', 'value'
  418. expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  419. assert_equal expected, server.socket.written.string
  420. end
  421. def test_add_exists
  422. server = FakeServer.new
  423. server.socket.data.write "NOT_STORED\r\n"
  424. server.socket.data.rewind
  425. @cache.servers = []
  426. @cache.servers << server
  427. @cache.add 'key', 'value'
  428. expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n"
  429. assert_equal expected, server.socket.written.string
  430. end
  431. def test_add_expiry
  432. server = FakeServer.new
  433. server.socket.data.write "STORED\r\n"
  434. server.socket.data.rewind
  435. @cache.servers = []
  436. @cache.servers << server
  437. @cache.add 'key', 'value', 5
  438. expected = "add my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n"
  439. assert_equal expected, server.socket.written.string
  440. end
  441. def test_add_raw
  442. server = FakeServer.new
  443. server.socket.data.write "STORED\r\n"
  444. server.socket.data.rewind
  445. @cache.servers = []
  446. @cache.servers << server
  447. @cache.add 'key', 'value', 0, true
  448. expected = "add my_namespace:key 0 0 5\r\nvalue\r\n"
  449. assert_equal expected, server.socket.written.string
  450. end
  451. def test_add_readonly
  452. cache = MemCache.new :readonly => true
  453. e = assert_raise MemCache::MemCacheError do
  454. cache.add 'key', 'value'
  455. end
  456. assert_equal 'Update of readonly cache', e.message
  457. end
  458. def test_delete
  459. server = FakeServer.new
  460. @cache.servers = []
  461. @cache.servers << server
  462. @cache.delete 'key'
  463. expected = "delete my_namespace:key 0\r\n"
  464. assert_equal expected, server.socket.written.string
  465. end
  466. def test_delete_with_expiry
  467. server = FakeServer.new
  468. @cache.servers = []
  469. @cache.servers << server
  470. @cache.delete 'key', 300
  471. expected = "delete my_namespace:key 300\r\n"
  472. assert_equal expected, server.socket.written.string
  473. end
  474. def test_flush_all
  475. @cache.servers = []
  476. 3.times { @cache.servers << FakeServer.new }
  477. @cache.flush_all
  478. expected = "flush_all\r\n"
  479. @cache.servers.each do |server|
  480. assert_equal expected, server.socket.written.string
  481. end
  482. end
  483. def test_flush_all_failure
  484. socket = FakeSocket.new
  485. socket.data.write "ERROR\r\n"
  486. socket.data.rewind
  487. server = FakeServer.new socket
  488. def server.host() "localhost"; end
  489. def server.port() 11211; end
  490. @cache.servers = []
  491. @cache.servers << server
  492. assert_raise MemCache::MemCacheError do
  493. @cache.flush_all
  494. end
  495. assert_equal "flush_all\r\n", socket.written.string
  496. end
  497. def test_stats
  498. socket = FakeSocket.new
  499. 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"
  500. socket.data.rewind
  501. server = FakeServer.new socket
  502. def server.host() 'localhost'; end
  503. def server.port() 11211; end
  504. @cache.servers = []
  505. @cache.servers << server
  506. expected = {
  507. 'localhost:11211' => {
  508. 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3',
  509. 'rusage_user' => 1.0003, 'dummy' => 'ok'
  510. }
  511. }
  512. assert_equal expected, @cache.stats
  513. assert_equal "stats\r\n", socket.written.string
  514. end
  515. def test_basic_threaded_operations_should_work
  516. cache = MemCache.new :multithread => true,
  517. :namespace => 'my_namespace',
  518. :readonly => false
  519. server = util_setup_server cache, 'example.com', "OK\r\n"
  520. cache.instance_variable_set :@servers, [server]
  521. assert_nothing_raised do
  522. cache.set "test", "test value"
  523. end
  524. end
  525. def test_basic_unthreaded_operations_should_work
  526. cache = MemCache.new :multithread => false,
  527. :namespace => 'my_namespace',
  528. :readonly => false
  529. server = util_setup_server cache, 'example.com', "OK\r\n"
  530. cache.instance_variable_set :@servers, [server]
  531. assert_nothing_raised do
  532. cache.set "test", "test value"
  533. end
  534. end
  535. def util_setup_fake_server
  536. server = FakeServer.new
  537. server.socket.data.write "VALUE my_namespace:key 0 14\r\n"
  538. server.socket.data.write "\004\b\"\0170123456789\r\n"
  539. server.socket.data.write "END\r\n"
  540. server.socket.data.rewind
  541. @cache.servers = []
  542. @cache.servers << server
  543. return server
  544. end
  545. def util_setup_server(memcache, host, responses)
  546. server = MemCache::Server.new memcache, host
  547. server.instance_variable_set :@sock, StringIO.new(responses)
  548. @cache.servers = []
  549. @cache.servers << server
  550. return server
  551. end
  552. end