PageRenderTime 61ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/test/test_client.lua

http://github.com/nrk/redis-lua
Lua | 2645 lines | 2067 code | 536 blank | 42 comment | 135 complexity | 418ae1b497192bbfcbbdded8c45e1776 MD5 | raw file
  1. package.path = "../src/?.lua;src/?.lua;" .. package.path
  2. pcall(require, "luarocks.require")
  3. local unpack = _G.unpack or table.unpack
  4. local tsc = require "telescope"
  5. local redis = require "redis"
  6. local settings = {
  7. host = '127.0.0.1',
  8. port = 6379,
  9. database = 14,
  10. password = nil,
  11. }
  12. function table.merge(self, tbl2)
  13. local new_table = {}
  14. for k,v in pairs(self) do new_table[k] = v end
  15. for k,v in pairs(tbl2) do new_table[k] = v end
  16. return new_table
  17. end
  18. function table.keys(self)
  19. local keys = {}
  20. for k, _ in pairs(self) do table.insert(keys, k) end
  21. return keys
  22. end
  23. function table.values(self)
  24. local values = {}
  25. for _, v in pairs(self) do table.insert(values, v) end
  26. return values
  27. end
  28. function table.contains(self, value)
  29. for _, v in pairs(self) do
  30. if v == value then return true end
  31. end
  32. return false
  33. end
  34. function table.slice(self, first, length)
  35. -- TODO: must be improved
  36. local new_table = {}
  37. for i = first, first + length - 1 do
  38. table.insert(new_table, self[i])
  39. end
  40. return new_table
  41. end
  42. function table.compare(self, other)
  43. -- NOTE: the body of this function was taken and slightly adapted from
  44. -- Penlight (http://github.com/stevedonovan/Penlight)
  45. if #self ~= #other then return false end
  46. local visited = {}
  47. for i = 1, #self do
  48. local val, gotcha = self[i], nil
  49. for j = 1, #other do
  50. if not visited[j] then
  51. if (type(val) == 'table') then
  52. if (table.compare(val, other[j])) then
  53. gotcha = j
  54. break
  55. end
  56. else
  57. if val == other[j] then
  58. gotcha = j
  59. break
  60. end
  61. end
  62. end
  63. end
  64. if not gotcha then return false end
  65. visited[gotcha] = true
  66. end
  67. return true
  68. end
  69. function parse_version(version_str)
  70. local major, minor, patch, status = version_str:match('^(%d+)%.(%d+)%.(%d+)%-?(%w-)$')
  71. local info = {
  72. string = version_str,
  73. compare = function(self, other)
  74. if type(other) == 'string' then
  75. other = parse_version(other)
  76. end
  77. if self.unrecognized or other.unrecognized then
  78. error('Cannot compare versions')
  79. end
  80. for _, part in ipairs({ 'major', 'minor', 'patch' }) do
  81. if self[part] < other[part] then
  82. return -1
  83. end
  84. if self[part] > other[part] then
  85. return 1
  86. end
  87. end
  88. return 0
  89. end,
  90. is = function(self, op, other)
  91. local comparation = self:compare(other);
  92. if op == '<' then return comparation < 0 end
  93. if op == '<=' then return comparation <= 0 end
  94. if op == '=' then return comparation == 0 end
  95. if op == '>=' then return comparation >= 0 end
  96. if op == '>' then return comparation > 0 end
  97. error('Invalid comparison operator: '..op)
  98. end,
  99. }
  100. if major and minor and patch then
  101. info.major = tonumber(major)
  102. info.minor = tonumber(minor)
  103. info.patch = tonumber(patch)
  104. if status then
  105. info.status = status
  106. end
  107. else
  108. info.unrecognized = true
  109. end
  110. return info
  111. end
  112. local utils = {
  113. create_client = function(parameters)
  114. if parameters == nil then
  115. parameters = settings
  116. end
  117. local client = redis.connect(parameters.host, parameters.port)
  118. if parameters.password then client:auth(parameters.password) end
  119. if parameters.database then client:select(parameters.database) end
  120. client:flushdb()
  121. local info = client:info()
  122. local version = parse_version(info.redis_version or info.server.redis_version)
  123. if version:is('<', '1.2.0') then
  124. error("redis-lua does not support Redis < 1.2.0 (current: "..version.string..")")
  125. end
  126. return client, version
  127. end,
  128. rpush_return = function(client, key, values, wipe)
  129. if wipe then client:del(key) end
  130. for _, v in ipairs(values) do
  131. client:rpush(key, v)
  132. end
  133. return values
  134. end,
  135. sadd_return = function(client, key, values, wipe)
  136. if wipe then client:del(key) end
  137. for _, v in ipairs(values) do
  138. client:sadd(key, v)
  139. end
  140. return values
  141. end,
  142. zadd_return = function(client, key, values, wipe)
  143. if wipe then client:del(key) end
  144. for k, v in pairs(values) do
  145. client:zadd(key, v, k)
  146. end
  147. return values
  148. end,
  149. sleep = function(sec)
  150. socket.select(nil, nil, sec)
  151. end,
  152. }
  153. local shared = {
  154. kvs_table = function()
  155. return {
  156. foo = 'bar',
  157. hoge = 'piyo',
  158. foofoo = 'barbar',
  159. }
  160. end,
  161. kvs_ns_table = function()
  162. return {
  163. ['metavars:foo'] = 'bar',
  164. ['metavars:hoge'] = 'piyo',
  165. ['metavars:foofoo'] = 'barbar',
  166. }
  167. end,
  168. lang_table = function()
  169. return {
  170. italian = "ciao",
  171. english = "hello",
  172. japanese = "こんいちは!",
  173. }
  174. end,
  175. numbers = function()
  176. return { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }
  177. end,
  178. zset_sample = function()
  179. return { a = -10, b = 0, c = 10, d = 20, e = 20, f = 30 }
  180. end,
  181. }
  182. tsc.make_assertion("table_values", "'%s' to have the same values as '%s'", table.compare)
  183. tsc.make_assertion("response_queued", "to be queued", function(response)
  184. if type(response) == 'table' and response.queued == true then
  185. return true
  186. else
  187. return false
  188. end
  189. end)
  190. tsc.make_assertion("error_message", "result to be an error with the expected message", function(msg, f)
  191. local ok, err = pcall(f)
  192. return not ok and err:match(msg)
  193. end)
  194. -- ------------------------------------------------------------------------- --
  195. context("Client initialization", function()
  196. test("Can connect successfully", function()
  197. local client = redis.connect(settings.host, settings.port)
  198. assert_type(client, 'table')
  199. assert_true(table.contains(table.keys(client.network), 'socket'))
  200. client.network.socket:send("PING\r\n")
  201. assert_equal(client.network.socket:receive('*l'), '+PONG')
  202. end)
  203. test("Can handle connection failures", function()
  204. assert_error_message("could not connect to .*:%d+ %[connection refused%]", function()
  205. redis.connect(settings.host, settings.port + 100)
  206. end)
  207. end)
  208. test("Accepts an URI for connection parameters", function()
  209. local uri = 'redis://'..settings.host..':'..settings.port
  210. local client = redis.connect(uri)
  211. assert_type(client, 'table')
  212. end)
  213. test("Accepts a table for connection parameters", function()
  214. local client = redis.connect(settings)
  215. assert_type(client, 'table')
  216. end)
  217. test("Can use an already connected socket", function()
  218. local connection = require('socket').tcp()
  219. connection:connect(settings.host, settings.port)
  220. local client = redis.connect({ socket = connection })
  221. assert_type(client, 'table')
  222. assert_true(client:ping())
  223. end)
  224. test("Can specify a timeout for connecting", function()
  225. local time, timeout = os.time(), 2;
  226. assert_error_message("could not connect to .*:%d+ %[timeout%]", function()
  227. redis.connect({ host = '169.254.255.255', timeout = timeout })
  228. end)
  229. assert_equal(time + timeout, os.time())
  230. end)
  231. end)
  232. context("Client features", function()
  233. before(function()
  234. client = utils.create_client(settings)
  235. end)
  236. test("Send raw commands", function()
  237. assert_equal(client:raw_cmd("PING\r\n"), 'PONG')
  238. assert_true(client:raw_cmd("*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"))
  239. assert_equal(client:raw_cmd("GET foo\r\n"), 'bar')
  240. end)
  241. test("Tansform nil command arguments into empty strings", function()
  242. assert_true(client:set(nil, 'bar'))
  243. assert_equal(client:get(''), 'bar')
  244. end)
  245. test("Create a new unbound command object", function()
  246. local cmd = redis.command('doesnotexist')
  247. assert_nil(client.doesnotexist)
  248. assert_error(function() cmd(client) end)
  249. local cmd = redis.command('ping', {
  250. response = function(response) return response == 'PONG' end
  251. })
  252. assert_equal(cmd(client), true)
  253. end)
  254. test("Define commands at module level", function()
  255. redis.commands.doesnotexist = redis.command('doesnotexist')
  256. local client2 = utils.create_client(settings)
  257. redis.commands.doesnotexist = nil
  258. local client3 = utils.create_client(settings)
  259. assert_nil(client.doesnotexist)
  260. assert_not_nil(client2.doesnotexist)
  261. assert_nil(client3.doesnotexist)
  262. end)
  263. test("Define commands at module level (OLD)", function()
  264. redis.define_command('doesnotexist')
  265. local client2 = utils.create_client(settings)
  266. redis.undefine_command('doesnotexist')
  267. local client3 = utils.create_client(settings)
  268. assert_nil(client.doesnotexist)
  269. assert_not_nil(client2.doesnotexist)
  270. assert_nil(client3.doesnotexist)
  271. end)
  272. test("Define new commands at client instance level", function()
  273. client.doesnotexist = redis.command('doesnotexist')
  274. assert_not_nil(client.doesnotexist)
  275. assert_error(function() client:doesnotexist() end)
  276. client.doesnotexist = nil
  277. assert_nil(client.doesnotexist)
  278. client.ping = redis.command('ping')
  279. assert_not_nil(client.ping)
  280. assert_equal(client:ping(), 'PONG')
  281. client.ping = redis.command('ping', {
  282. request = client.requests.multibulk
  283. })
  284. assert_not_nil(client.ping)
  285. assert_equal(client:ping(), 'PONG')
  286. client.ping = redis.command('ping', {
  287. request = client.requests.multibulk,
  288. response = function(reply) return reply == 'PONG' end
  289. })
  290. assert_not_nil(client.ping)
  291. assert_true(client:ping())
  292. end)
  293. test("Define new commands at client instance level (OLD)", function()
  294. client:define_command('doesnotexist')
  295. assert_not_nil(client.doesnotexist)
  296. assert_error(function() client:doesnotexist() end)
  297. client:undefine_command('doesnotexist')
  298. assert_nil(client.doesnotexist)
  299. client:define_command('ping')
  300. assert_not_nil(client.ping)
  301. assert_equal(client:ping(), 'PONG')
  302. client:define_command('ping', {
  303. request = client.requests.multibulk
  304. })
  305. assert_not_nil(client.ping)
  306. assert_equal(client:ping(), 'PONG')
  307. client:define_command('ping', {
  308. request = client.requests.multibulk,
  309. response = function(reply) return reply == 'PONG' end
  310. })
  311. assert_not_nil(client.ping)
  312. assert_true(client:ping())
  313. end)
  314. test("Pipelining commands", function()
  315. local replies, count = client:pipeline(function(p)
  316. p:ping()
  317. p:exists('counter')
  318. p:incrby('counter', 10)
  319. p:incrby('counter', 30)
  320. p:exists('counter')
  321. p:get('counter')
  322. p:mset({ foo = 'bar', hoge = 'piyo'})
  323. p:del('foo', 'hoge')
  324. p:mget('does_not_exist', 'counter')
  325. p:info()
  326. p:get('nilkey')
  327. end)
  328. assert_type(replies, 'table')
  329. assert_equal(count, 11)
  330. assert_equal(#replies, 10)
  331. assert_true(replies[1])
  332. assert_type(replies[9], 'table')
  333. assert_equal(replies[9][2], '40')
  334. assert_type(replies[10], 'table')
  335. end)
  336. after(function()
  337. client:quit()
  338. end)
  339. end)
  340. context("Redis commands", function()
  341. before(function()
  342. client, version = utils.create_client(settings)
  343. end)
  344. after(function()
  345. client:quit()
  346. end)
  347. context("Connection related commands", function()
  348. test("PING (client:ping)", function()
  349. assert_true(client:ping())
  350. end)
  351. test("ECHO (client:echo)", function()
  352. local str_ascii, str_utf8 = "Can you hear me?", "聞こえますか?"
  353. assert_equal(client:echo(str_ascii), str_ascii)
  354. assert_equal(client:echo(str_utf8), str_utf8)
  355. end)
  356. test("SELECT (client:select)", function()
  357. if not settings.database then return end
  358. assert_true(client:select(0))
  359. assert_true(client:select(settings.database))
  360. assert_error(function() client:select(100) end)
  361. assert_error(function() client:select(-1) end)
  362. end)
  363. end)
  364. context("Commands operating on the key space", function()
  365. test("KEYS (client:keys)", function()
  366. local kvs_prefixed = shared.kvs_ns_table()
  367. local kvs_unprefixed = { aaa = 1, aba = 2, aca = 3 }
  368. local kvs_all = table.merge(kvs_prefixed, kvs_unprefixed)
  369. client:mset(kvs_all)
  370. assert_empty(client:keys('nokeys:*'))
  371. assert_table_values(
  372. table.values(client:keys('*')),
  373. table.keys(kvs_all)
  374. )
  375. assert_table_values(
  376. table.values(client:keys('metavars:*')),
  377. table.keys(kvs_prefixed)
  378. )
  379. assert_table_values(
  380. table.values(client:keys('a?a')),
  381. table.keys(kvs_unprefixed)
  382. )
  383. end)
  384. test("EXISTS (client:exists)", function()
  385. client:set('foo', 'bar')
  386. assert_true(client:exists('foo'))
  387. assert_false(client:exists('hoge'))
  388. end)
  389. test("DEL (client:del)", function()
  390. client:mset(shared.kvs_table())
  391. assert_equal(client:del('doesnotexist'), 0)
  392. assert_equal(client:del('foofoo'), 1)
  393. assert_equal(client:del('foo', 'hoge', 'doesnotexist'), 2)
  394. end)
  395. test("TYPE (client:type)", function()
  396. assert_equal(client:type('doesnotexist'), 'none')
  397. client:set('fooString', 'bar')
  398. assert_equal(client:type('fooString'), 'string')
  399. client:rpush('fooList', 'bar')
  400. assert_equal(client:type('fooList'), 'list')
  401. client:sadd('fooSet', 'bar')
  402. assert_equal(client:type('fooSet'), 'set')
  403. client:zadd('fooZSet', 0, 'bar')
  404. assert_equal(client:type('fooZSet'), 'zset')
  405. if version:is('>=', '2.0.0') then
  406. client:hset('fooHash', 'value', 'bar')
  407. assert_equal('hash', client:type('fooHash'))
  408. end
  409. end)
  410. test("RANDOMKEY (client:randomkey)", function()
  411. local kvs = shared.kvs_table()
  412. assert_nil(client:randomkey())
  413. client:mset(kvs)
  414. assert_true(table.contains(table.keys(kvs), client:randomkey()))
  415. end)
  416. test("RENAME (client:rename)", function()
  417. local kvs = shared.kvs_table()
  418. client:mset(kvs)
  419. assert_true(client:rename('hoge', 'hogehoge'))
  420. assert_false(client:exists('hoge'))
  421. assert_equal(client:get('hogehoge'), 'piyo')
  422. -- rename overwrites existing keys
  423. assert_true(client:rename('foo', 'foofoo'))
  424. assert_false(client:exists('foo'))
  425. assert_equal(client:get('foofoo'), 'bar')
  426. -- rename fails when the key does not exist
  427. assert_error(function()
  428. client:rename('doesnotexist', 'fuga')
  429. end)
  430. end)
  431. test("RENAMENX (client:renamenx)", function()
  432. local kvs = shared.kvs_table()
  433. client:mset(kvs)
  434. assert_true(client:renamenx('hoge', 'hogehoge'))
  435. assert_false(client:exists('hoge'))
  436. assert_equal(client:get('hogehoge'), 'piyo')
  437. -- rename overwrites existing keys
  438. assert_false(client:renamenx('foo', 'foofoo'))
  439. assert_true(client:exists('foo'))
  440. -- rename fails when the key does not exist
  441. assert_error(function()
  442. client:renamenx('doesnotexist', 'fuga')
  443. end)
  444. end)
  445. test("TTL (client:ttl)", function()
  446. client:set('foo', 'bar')
  447. assert_equal(client:ttl('foo'), -1)
  448. assert_true(client:expire('foo', 5))
  449. assert_lte(client:ttl('foo'), 5)
  450. end)
  451. test("PTTL (client:pttl)", function()
  452. if version:is('<', '2.5.0') then return end
  453. client:set('foo', 'bar')
  454. assert_equal(client:pttl('foo'), -1)
  455. local ttl = 5
  456. assert_true(client:expire('foo', ttl))
  457. assert_lte(client:pttl('foo'), 5 * 1000)
  458. assert_gte(client:pttl('foo'), 5 * 1000 - 500)
  459. end)
  460. test("EXPIRE (client:expire)", function()
  461. client:set('foo', 'bar')
  462. assert_true(client:expire('foo', 2))
  463. assert_true(client:exists('foo'))
  464. assert_lte(client:ttl('foo'), 2)
  465. utils.sleep(3)
  466. assert_false(client:exists('foo'))
  467. client:set('foo', 'bar')
  468. assert_true(client:expire('foo', 100))
  469. utils.sleep(3)
  470. assert_lte(client:ttl('foo'), 97)
  471. assert_true(client:expire('foo', -100))
  472. assert_false(client:exists('foo'))
  473. end)
  474. test("PEXPIRE (client:pexpire)", function()
  475. if version:is('<', '2.5.0') then return end
  476. local ttl = 1
  477. client:set('foo', 'bar')
  478. assert_true(client:pexpire('foo', ttl * 1000))
  479. assert_true(client:exists('foo'))
  480. assert_lte(client:pttl('foo'), ttl * 1000)
  481. assert_gte(client:pttl('foo'), ttl * 1000 - 500)
  482. utils.sleep(ttl)
  483. assert_false(client:exists('foo'))
  484. end)
  485. test("EXPIREAT (client:expireat)", function()
  486. client:set('foo', 'bar')
  487. assert_true(client:expireat('foo', os.time() + 2))
  488. assert_lte(client:ttl('foo'), 2)
  489. utils.sleep(3)
  490. assert_false(client:exists('foo'))
  491. client:set('foo', 'bar')
  492. assert_true(client:expireat('foo', os.time() - 100))
  493. assert_false(client:exists('foo'))
  494. end)
  495. test("PEXPIREAT (client:pexpireat)", function()
  496. if version:is('<', '2.5.0') then return end
  497. local ttl = 2
  498. client:set('foo', 'bar')
  499. assert_true(client:pexpireat('foo', os.time() + ttl * 1000))
  500. assert_lte(client:pttl('foo'), ttl * 1000)
  501. utils.sleep(ttl + 1)
  502. assert_false(client:exists('foo'))
  503. client:set('foo', 'bar')
  504. assert_true(client:pexpireat('foo', os.time() - 100 * 1000))
  505. assert_false(client:exists('foo'))
  506. end)
  507. test("MOVE (client:move)", function()
  508. if not settings.database then return end
  509. local other_db = settings.database + 1
  510. client:set('foo', 'bar')
  511. client:select(other_db)
  512. client:flushdb()
  513. client:select(settings.database)
  514. assert_true(client:move('foo', other_db))
  515. assert_false(client:move('foo', other_db))
  516. assert_false(client:move('doesnotexist', other_db))
  517. client:set('hoge', 'piyo')
  518. assert_error(function() client:move('hoge', 100) end)
  519. end)
  520. test("DBSIZE (client:dbsize)", function()
  521. assert_equal(client:dbsize(), 0)
  522. client:mset(shared.kvs_table())
  523. assert_greater_than(client:dbsize(), 0)
  524. end)
  525. test("PERSIST (client:persist)", function()
  526. if version:is('<', '2.1.0') then return end
  527. client:set('foo', 'bar')
  528. assert_true(client:expire('foo', 1))
  529. assert_equal(client:ttl('foo'), 1)
  530. assert_true(client:persist('foo'))
  531. assert_equal(client:ttl('foo'), -1)
  532. assert_false(client:persist('foo'))
  533. assert_false(client:persist('foobar'))
  534. end)
  535. test("SCAN (client:scan)", function()
  536. if version:is('<', '2.8.0') then return end
  537. client:mset(
  538. 'scan:1', '1',
  539. 'scan:2', '2',
  540. 'scan:3', '3',
  541. 'scan:4', '4'
  542. )
  543. local cursor, keys = unpack(client:scan(0, {
  544. match = 'scan:*', count = 10
  545. }))
  546. assert_type(cursor, 'string')
  547. assert_type(keys, 'table')
  548. assert_table_values(keys, {'scan:1','scan:2','scan:3','scan:4'})
  549. end)
  550. end)
  551. context("Commands operating on the key space - SORT", function()
  552. -- TODO: missing tests for params GET and BY
  553. before(function()
  554. -- TODO: code duplication!
  555. list01, list01_values = "list01", { "4","2","3","5","1" }
  556. for _,v in ipairs(list01_values) do client:rpush(list01,v) end
  557. list02, list02_values = "list02", { "1","10","2","20","3","30" }
  558. for _,v in ipairs(list02_values) do client:rpush(list02,v) end
  559. end)
  560. test("SORT (client:sort)", function()
  561. local sorted = client:sort(list01)
  562. assert_table_values(sorted, { "1","2","3","4","5" })
  563. end)
  564. test("SORT (client:sort) with parameter ASC/DESC", function()
  565. assert_table_values(client:sort(list01, { sort = 'asc'}), { "1","2","3","4","5" })
  566. assert_table_values(client:sort(list01, { sort = 'desc'}), { "5","4","3","2","1" })
  567. end)
  568. test("SORT (client:sort) with parameter LIMIT", function()
  569. assert_table_values(client:sort(list01, { limit = { 0,3 } }), { "1","2", "3" })
  570. assert_table_values(client:sort(list01, { limit = { 3,2 } }), { "4","5" })
  571. end)
  572. test("SORT (client:sort) with parameter ALPHA", function()
  573. assert_table_values(client:sort(list02, { alpha = false }), { "1","2","3","10","20","30" })
  574. assert_table_values(client:sort(list02, { alpha = true }), { "1","10","2","20","3","30" })
  575. end)
  576. test("SORT (client:sort) with parameter GET", function()
  577. client:rpush('uids', 1003)
  578. client:rpush('uids', 1001)
  579. client:rpush('uids', 1002)
  580. client:rpush('uids', 1000)
  581. local sortget = {
  582. ['uid:1000'] = 'foo', ['uid:1001'] = 'bar',
  583. ['uid:1002'] = 'hoge', ['uid:1003'] = 'piyo',
  584. }
  585. client:mset(sortget)
  586. assert_table_values(client:sort('uids', { get = 'uid:*' }), table.values(sortget))
  587. assert_table_values(client:sort('uids', { get = { 'uid:*' } }), table.values(sortget))
  588. end)
  589. test("SORT (client:sort) with multiple parameters", function()
  590. assert_table_values(client:sort(list02, {
  591. alpha = false,
  592. sort = 'desc',
  593. limit = { 1, 4 }
  594. }), { "20","10","3","2" })
  595. end)
  596. test("SORT (client:sort) with parameter STORE", function()
  597. assert_equal(client:sort(list01, { store = 'list01_ordered' }), 5)
  598. assert_true(client:exists('list01_ordered'))
  599. end)
  600. end)
  601. context("Commands operating on string values", function()
  602. test("SET (client:set)", function()
  603. assert_true(client:set('foo', 'bar'))
  604. assert_equal(client:get('foo'), 'bar')
  605. end)
  606. test("GET (client:get)", function()
  607. client:set('foo', 'bar')
  608. assert_equal(client:get('foo'), 'bar')
  609. assert_nil(client:get('hoge'))
  610. assert_error(function()
  611. client:rpush('metavars', 'foo')
  612. client:get('metavars')
  613. end)
  614. end)
  615. test("SETNX (client:setnx)", function()
  616. assert_true(client:setnx('foo', 'bar'))
  617. assert_false(client:setnx('foo', 'baz'))
  618. assert_equal(client:get('foo'), 'bar')
  619. end)
  620. test("SETEX (client:setex)", function()
  621. if version:is('<', '2.0.0') then return end
  622. assert_true(client:setex('foo', 10, 'bar'))
  623. assert_true(client:exists('foo'))
  624. assert_lte(client:ttl('foo'), 10)
  625. assert_true(client:setex('hoge', 1, 'piyo'))
  626. utils.sleep(2)
  627. assert_false(client:exists('hoge'))
  628. assert_error(function() client:setex('hoge', 2.5, 'piyo') end)
  629. assert_error(function() client:setex('hoge', 0, 'piyo') end)
  630. assert_error(function() client:setex('hoge', -10, 'piyo') end)
  631. end)
  632. test("PSETEX (client:psetex)", function()
  633. if version:is('<', '2.5.0') then return end
  634. local ttl = 10 * 1000
  635. assert_true(client:psetex('foo', ttl, 'bar'))
  636. assert_true(client:exists('foo'))
  637. assert_lte(client:pttl('foo'), ttl)
  638. assert_gte(client:pttl('foo'), ttl - 500)
  639. assert_true(client:psetex('hoge', 1 * 1000, 'piyo'))
  640. utils.sleep(2)
  641. assert_false(client:exists('hoge'))
  642. assert_error(function() client:psetex('hoge', 2.5, 'piyo') end)
  643. assert_error(function() client:psetex('hoge', 0, 'piyo') end)
  644. assert_error(function() client:psetex('hoge', -10, 'piyo') end)
  645. end)
  646. test("MSET (client:mset)", function()
  647. local kvs = shared.kvs_table()
  648. assert_true(client:mset(kvs))
  649. for k,v in pairs(kvs) do
  650. assert_equal(client:get(k), v)
  651. end
  652. assert_true(client:mset('a', '1', 'b', '2', 'c', '3'))
  653. assert_equal(client:get('a'), '1')
  654. assert_equal(client:get('b'), '2')
  655. assert_equal(client:get('c'), '3')
  656. end)
  657. test("MSETNX (client:msetnx)", function()
  658. assert_true(client:msetnx({ a = '1', b = '2' }))
  659. assert_false(client:msetnx({ c = '3', a = '100'}))
  660. assert_equal(client:get('a'), '1')
  661. assert_equal(client:get('b'), '2')
  662. end)
  663. test("MGET (client:mget)", function()
  664. local kvs = shared.kvs_table()
  665. local keys, values = table.keys(kvs), table.values(kvs)
  666. assert_true(client:mset(kvs))
  667. assert_table_values(client:mget(unpack(keys)), values)
  668. end)
  669. test("GETSET (client:getset)", function()
  670. assert_nil(client:getset('foo', 'bar'))
  671. assert_equal(client:getset('foo', 'barbar'), 'bar')
  672. assert_equal(client:getset('foo', 'baz'), 'barbar')
  673. end)
  674. test("INCR (client:incr)", function()
  675. assert_equal(client:incr('foo'), 1)
  676. assert_equal(client:incr('foo'), 2)
  677. assert_true(client:set('hoge', 'piyo'))
  678. if version:is('<', '2.0.0') then
  679. assert_equal(client:incr('hoge'), 1)
  680. else
  681. assert_error(function()
  682. client:incr('hoge')
  683. end)
  684. end
  685. end)
  686. test("INCRBY (client:incrby)", function()
  687. client:set('foo', 2)
  688. assert_equal(client:incrby('foo', 20), 22)
  689. assert_equal(client:incrby('foo', -12), 10)
  690. assert_equal(client:incrby('foo', -110), -100)
  691. end)
  692. test("INCRBYFLOAT (client:incrbyfloat)", function()
  693. if version:is('<', '2.5.0') then return end
  694. client:set('foo', 2)
  695. assert_equal(client:incrbyfloat('foo', 20.123), 22.123)
  696. assert_equal(client:incrbyfloat('foo', -12.123), 10)
  697. assert_equal(client:incrbyfloat('foo', -110.01), -100.01)
  698. end)
  699. test("DECR (client:decr)", function()
  700. assert_equal(client:decr('foo'), -1)
  701. assert_equal(client:decr('foo'), -2)
  702. assert_true(client:set('hoge', 'piyo'))
  703. if version:is('<', '2.0.0') then
  704. assert_equal(client:decr('hoge'), -1)
  705. else
  706. assert_error(function()
  707. client:decr('hoge')
  708. end)
  709. end
  710. end)
  711. test("DECRBY (client:decrby)", function()
  712. client:set('foo', -2)
  713. assert_equal(client:decrby('foo', 20), -22)
  714. assert_equal(client:decrby('foo', -12), -10)
  715. assert_equal(client:decrby('foo', -110), 100)
  716. end)
  717. test("APPEND (client:append)", function()
  718. if version:is('<', '2.0.0') then return end
  719. client:set('foo', 'bar')
  720. assert_equal(client:append('foo', '__'), 5)
  721. assert_equal(client:append('foo', 'bar'), 8)
  722. assert_equal(client:get('foo'), 'bar__bar')
  723. assert_equal(client:append('hoge', 'piyo'), 4)
  724. assert_equal(client:get('hoge'), 'piyo')
  725. assert_error(function()
  726. client:rpush('metavars', 'foo')
  727. client:append('metavars', 'bar')
  728. end)
  729. end)
  730. test("SUBSTR (client:substr)", function()
  731. if version:is('<', '2.0.0') then return end
  732. client:set('var', 'foobar')
  733. assert_equal(client:substr('var', 0, 2), 'foo')
  734. assert_equal(client:substr('var', 3, 5), 'bar')
  735. assert_equal(client:substr('var', -3, -1), 'bar')
  736. assert_equal(client:substr('var', 5, 0), '')
  737. client:set('numeric', 123456789)
  738. assert_equal(client:substr('numeric', 0, 4), '12345')
  739. assert_error(function()
  740. client:rpush('metavars', 'foo')
  741. client:substr('metavars', 0, 3)
  742. end)
  743. end)
  744. test("STRLEN (client:strlen)", function()
  745. if version:is('<', '2.1.0') then return end
  746. client:set('var', 'foobar')
  747. assert_equal(client:strlen('var'), 6)
  748. assert_equal(client:append('var', '___'), 9)
  749. assert_equal(client:strlen('var'), 9)
  750. assert_error(function()
  751. client:rpush('metavars', 'foo')
  752. qclient:strlen('metavars')
  753. end)
  754. end)
  755. test("SETRANGE (client:setrange)", function()
  756. if version:is('<', '2.1.0') then return end
  757. assert_equal(client:setrange('var', 0, 'foobar'), 6)
  758. assert_equal(client:get('var'), 'foobar')
  759. assert_equal(client:setrange('var', 3, 'foo'), 6)
  760. assert_equal(client:get('var'), 'foofoo')
  761. assert_equal(client:setrange('var', 10, 'barbar'), 16)
  762. assert_equal(client:get('var'), "foofoo\0\0\0\0barbar")
  763. assert_error(function()
  764. client:setrange('var', -1, 'bogus')
  765. end)
  766. assert_error(function()
  767. client:rpush('metavars', 'foo')
  768. client:setrange('metavars', 0, 'hoge')
  769. end)
  770. end)
  771. test("GETRANGE (client:getrange)", function()
  772. if version:is('<', '2.1.0') then return end
  773. client:set('var', 'foobar')
  774. assert_equal(client:getrange('var', 0, 2), 'foo')
  775. assert_equal(client:getrange('var', 3, 5), 'bar')
  776. assert_equal(client:getrange('var', -3, -1), 'bar')
  777. assert_equal(client:substr('var', 5, 0), '')
  778. client:set('numeric', 123456789)
  779. assert_equal(client:getrange('numeric', 0, 4), '12345')
  780. assert_error(function()
  781. client:rpush('metavars', 'foo')
  782. client:getrange('metavars', 0, 3)
  783. end)
  784. end)
  785. test("SETBIT (client:setbit)", function()
  786. if version:is('<', '2.1.0') then return end
  787. assert_equal(client:setbit('binary', 31, 1), 0)
  788. assert_equal(client:setbit('binary', 0, 1), 0)
  789. assert_equal(client:strlen('binary'), 4)
  790. assert_equal(client:get('binary'), "\128\0\0\1")
  791. assert_equal(client:setbit('binary', 0, 0), 1)
  792. assert_equal(client:setbit('binary', 0, 0), 0)
  793. assert_equal(client:get('binary'), "\0\0\0\1")
  794. assert_error(function()
  795. client:setbit('binary', -1, 1)
  796. end)
  797. assert_error(function()
  798. client:setbit('binary', 'invalid', 1)
  799. end)
  800. assert_error(function()
  801. client:setbit('binary', 'invalid', 1)
  802. end)
  803. assert_error(function()
  804. client:setbit('binary', 15, 255)
  805. end)
  806. assert_error(function()
  807. client:setbit('binary', 15, 'invalid')
  808. end)
  809. assert_error(function()
  810. client:rpush('metavars', 'foo')
  811. client:setbit('metavars', 0, 1)
  812. end)
  813. end)
  814. test("GETBIT (client:getbit)", function()
  815. if version:is('<', '2.1.0') then return end
  816. client:set('binary', "\128\0\0\1")
  817. assert_equal(client:getbit('binary', 0), 1)
  818. assert_equal(client:getbit('binary', 15), 0)
  819. assert_equal(client:getbit('binary', 31), 1)
  820. assert_equal(client:getbit('binary', 63), 0)
  821. assert_error(function()
  822. client:getbit('binary', -1)
  823. end)
  824. assert_error(function()
  825. client:getbit('binary', 'invalid')
  826. end)
  827. assert_error(function()
  828. client:rpush('metavars', 'foo')
  829. client:getbit('metavars', 0)
  830. end)
  831. end)
  832. test("BITOP (client:bitop)", function()
  833. if version:is('<', '2.5.10') then return end
  834. client:set('foo', 'a')
  835. client:set('bar', 'b')
  836. client:bitop('AND', 'foo&bar', 'foo', 'bar')
  837. client:bitop('OR', 'foo|bar', 'foo', 'bar')
  838. client:bitop('XOR', 'foo^bar', 'foo', 'bar')
  839. client:bitop('NOT', '-foo', 'foo')
  840. assert_equal(client:get('foo&bar'), '\96')
  841. assert_equal(client:get('foo|bar'), '\99')
  842. assert_equal(client:get('foo^bar'), '\3')
  843. assert_equal(client:get('-foo'), '\158')
  844. end)
  845. test("BITCOUNT (client:bitcount)", function()
  846. if version:is('<', '2.5.10') then return end
  847. client:set('foo', 'abcde')
  848. assert_equal(client:bitcount('foo', 1, 3), 10)
  849. assert_equal(client:bitcount('foo', 0, -1), 17)
  850. end)
  851. end)
  852. context("Commands operating on lists", function()
  853. test("RPUSH (client:rpush)", function()
  854. if version:is('<', '2.0.0') then
  855. assert_true(client:rpush('metavars', 'foo'))
  856. assert_true(client:rpush('metavars', 'hoge'))
  857. else
  858. assert_equal(client:rpush('metavars', 'foo'), 1)
  859. assert_equal(client:rpush('metavars', 'hoge'), 2)
  860. end
  861. assert_error(function()
  862. client:set('foo', 'bar')
  863. client:rpush('foo', 'baz')
  864. end)
  865. end)
  866. test("RPUSHX (client:rpushx)", function()
  867. if version:is('<', '2.1.0') then return end
  868. assert_equal(client:rpushx('numbers', 1), 0)
  869. assert_equal(client:rpush('numbers', 2), 1)
  870. assert_equal(client:rpushx('numbers', 3), 2)
  871. assert_equal(client:llen('numbers'), 2)
  872. assert_table_values(client:lrange('numbers', 0, -1), { '2', '3' })
  873. assert_error(function()
  874. client:set('foo', 'bar')
  875. client:rpushx('foo', 'baz')
  876. end)
  877. end)
  878. test("LPUSH (client:lpush)", function()
  879. if version:is('<', '2.0.0') then
  880. assert_true(client:lpush('metavars', 'foo'))
  881. assert_true(client:lpush('metavars', 'hoge'))
  882. else
  883. assert_equal(client:lpush('metavars', 'foo'), 1)
  884. assert_equal(client:lpush('metavars', 'hoge'), 2)
  885. end
  886. assert_error(function()
  887. client:set('foo', 'bar')
  888. client:lpush('foo', 'baz')
  889. end)
  890. end)
  891. test("LPUSHX (client:lpushx)", function()
  892. if version:is('<', '2.1.0') then return end
  893. assert_equal(client:lpushx('numbers', 1), 0)
  894. assert_equal(client:lpush('numbers', 2), 1)
  895. assert_equal(client:lpushx('numbers', 3), 2)
  896. assert_equal(client:llen('numbers'), 2)
  897. assert_table_values(client:lrange('numbers', 0, -1), { '3', '2' })
  898. assert_error(function()
  899. client:set('foo', 'bar')
  900. client:lpushx('foo', 'baz')
  901. end)
  902. end)
  903. test("LLEN (client:llen)", function()
  904. local kvs = shared.kvs_table()
  905. for _, v in pairs(kvs) do
  906. client:rpush('metavars', v)
  907. end
  908. assert_equal(client:llen('metavars'), 3)
  909. assert_equal(client:llen('doesnotexist'), 0)
  910. assert_error(function()
  911. client:set('foo', 'bar')
  912. client:llen('foo')
  913. end)
  914. end)
  915. test("LRANGE (client:lrange)", function()
  916. local numbers = utils.rpush_return(client, 'numbers', shared.numbers())
  917. assert_table_values(client:lrange('numbers', 0, 3), table.slice(numbers, 1, 4))
  918. assert_table_values(client:lrange('numbers', 4, 8), table.slice(numbers, 5, 5))
  919. assert_table_values(client:lrange('numbers', 0, 0), table.slice(numbers, 1, 1))
  920. assert_empty(client:lrange('numbers', 1, 0))
  921. assert_table_values(client:lrange('numbers', 0, -1), numbers)
  922. assert_table_values(client:lrange('numbers', 5, -5), { '5' })
  923. assert_empty(client:lrange('numbers', 7, -5))
  924. assert_table_values(client:lrange('numbers', -5, -2), table.slice(numbers, 6, 4))
  925. assert_table_values(client:lrange('numbers', -100, 100), numbers)
  926. end)
  927. test("LTRIM (client:ltrim)", function()
  928. local numbers = utils.rpush_return(client, 'numbers', shared.numbers(), true)
  929. assert_true(client:ltrim('numbers', 0, 2))
  930. assert_table_values(client:lrange('numbers', 0, -1), table.slice(numbers, 1, 3))
  931. local numbers = utils.rpush_return(client, 'numbers', shared.numbers(), true)
  932. assert_true(client:ltrim('numbers', 5, 9))
  933. assert_table_values(client:lrange('numbers', 0, -1), table.slice(numbers, 6, 5))
  934. local numbers = utils.rpush_return(client, 'numbers', shared.numbers(), true)
  935. assert_true(client:ltrim('numbers', 0, -6))
  936. assert_table_values(client:lrange('numbers', 0, -1), table.slice(numbers, 1, 5))
  937. local numbers = utils.rpush_return(client, 'numbers', shared.numbers(), true)
  938. assert_true(client:ltrim('numbers', -5, -3))
  939. assert_table_values(client:lrange('numbers', 0, -1), table.slice(numbers, 6, 3))
  940. local numbers = utils.rpush_return(client, 'numbers', shared.numbers(), true)
  941. assert_true(client:ltrim('numbers', -100, 100))
  942. assert_table_values(client:lrange('numbers', 0, -1), numbers)
  943. assert_error(function()
  944. client:set('foo', 'bar')
  945. client:ltrim('foo', 0, 1)
  946. end)
  947. end)
  948. test("LINDEX (client:lindex)", function()
  949. local numbers = utils.rpush_return(client, 'numbers', shared.numbers())
  950. assert_equal(client:lindex('numbers', 0), numbers[1])
  951. assert_equal(client:lindex('numbers', 5), numbers[6])
  952. assert_equal(client:lindex('numbers', 9), numbers[10])
  953. assert_nil(client:lindex('numbers', 100))
  954. assert_equal(client:lindex('numbers', -0), numbers[1])
  955. assert_equal(client:lindex('numbers', -1), numbers[10])
  956. assert_equal(client:lindex('numbers', -3), numbers[8])
  957. assert_nil(client:lindex('numbers', -100))
  958. assert_error(function()
  959. client:set('foo', 'bar')
  960. client:lindex('foo', 0)
  961. end)
  962. end)
  963. test("LSET (client:lset)", function()
  964. utils.rpush_return(client, 'numbers', shared.numbers())
  965. assert_true(client:lset('numbers', 5, -5))
  966. assert_equal(client:lindex('numbers', 5), '-5')
  967. assert_error(function()
  968. client:lset('numbers', 99, 99)
  969. end)
  970. assert_error(function()
  971. client:set('foo', 'bar')
  972. client:lset('foo', 0, 0)
  973. end)
  974. end)
  975. test("LREM (client:lrem)", function()
  976. local mixed = { '0', '_', '2', '_', '4', '_', '6', '_' }
  977. utils.rpush_return(client, 'mixed', mixed, true)
  978. assert_equal(client:lrem('mixed', 2, '_'), 2)
  979. assert_table_values(client:lrange('mixed', 0, -1), { '0', '2', '4', '_', '6', '_' })
  980. utils.rpush_return(client, 'mixed', mixed, true)
  981. assert_equal(client:lrem('mixed', 0, '_'), 4)
  982. assert_table_values(client:lrange('mixed', 0, -1), { '0', '2', '4', '6' })
  983. utils.rpush_return(client, 'mixed', mixed, true)
  984. assert_equal(client:lrem('mixed', -2, '_'), 2)
  985. assert_table_values(client:lrange('mixed', 0, -1), { '0', '_', '2', '_', '4', '6' })
  986. utils.rpush_return(client, 'mixed', mixed, true)
  987. assert_equal(client:lrem('mixed', 2, '|'), 0)
  988. assert_table_values(client:lrange('mixed', 0, -1), mixed)
  989. assert_equal(client:lrem('doesnotexist', 2, '_'), 0)
  990. assert_error(function()
  991. client:set('foo', 'bar')
  992. client:lrem('foo', 0, 0)
  993. end)
  994. end)
  995. test("LPOP (client:lpop)", function()
  996. local numbers = utils.rpush_return(client, 'numbers', { '0', '1', '2', '3', '4' })
  997. assert_equal(client:lpop('numbers'), numbers[1])
  998. assert_equal(client:lpop('numbers'), numbers[2])
  999. assert_equal(client:lpop('numbers'), numbers[3])
  1000. assert_table_values(client:lrange('numbers', 0, -1), { '3', '4' })
  1001. client:lpop('numbers')
  1002. client:lpop('numbers')
  1003. assert_nil(client:lpop('numbers'))
  1004. assert_nil(client:lpop('doesnotexist'))
  1005. assert_error(function()
  1006. client:set('foo', 'bar')
  1007. client:lpop('foo')
  1008. end)
  1009. end)
  1010. test("RPOP (client:rpop)", function()
  1011. local numbers = utils.rpush_return(client, 'numbers', { '0', '1', '2', '3', '4' })
  1012. assert_equal(client:rpop('numbers'), numbers[5])
  1013. assert_equal(client:rpop('numbers'), numbers[4])
  1014. assert_equal(client:rpop('numbers'), numbers[3])
  1015. assert_table_values(client:lrange('numbers', 0, -1), { '0', '1' })
  1016. client:rpop('numbers')
  1017. client:rpop('numbers')
  1018. assert_nil(client:rpop('numbers'))
  1019. assert_nil(client:rpop('doesnotexist'))
  1020. assert_error(function()
  1021. client:set('foo', 'bar')
  1022. client:rpop('foo')
  1023. end)
  1024. end)
  1025. test("RPOPLPUSH (client:rpoplpush)", function()
  1026. local numbers = utils.rpush_return(client, 'numbers', { '0', '1', '2' }, true)
  1027. assert_equal(client:llen('temporary'), 0)
  1028. assert_equal(client:rpoplpush('numbers', 'temporary'), '2')
  1029. assert_equal(client:rpoplpush('numbers', 'temporary'), '1')
  1030. assert_equal(client:rpoplpush('numbers', 'temporary'), '0')
  1031. assert_equal(client:llen('numbers'), 0)
  1032. assert_equal(client:llen('temporary'), 3)
  1033. local numbers = utils.rpush_return(client, 'numbers', { '0', '1', '2' }, true)
  1034. client:rpoplpush('numbers', 'numbers')
  1035. client:rpoplpush('numbers', 'numbers')
  1036. client:rpoplpush('numbers', 'numbers')
  1037. assert_table_values(client:lrange('numbers', 0, -1), numbers)
  1038. assert_nil(client:rpoplpush('doesnotexist1', 'doesnotexist2'))
  1039. assert_error(function()
  1040. client:set('foo', 'bar')
  1041. client:rpoplpush('foo', 'hoge')
  1042. end)
  1043. assert_error(function()
  1044. client:set('foo', 'bar')
  1045. client:rpoplpush('temporary', 'foo')
  1046. end)
  1047. end)
  1048. test("BLPOP (client:blpop)", function()
  1049. if version:is('<', '2.0.0') then return end
  1050. -- TODO: implement tests
  1051. end)
  1052. test("BRPOP (client:brpop)", function()
  1053. if version:is('<', '2.0.0') then return end
  1054. -- TODO: implement tests
  1055. end)
  1056. test("BRPOPLPUSH (client:brpoplpush)", function()
  1057. if version:is('<', '2.1.0') then return end
  1058. -- TODO: implement tests
  1059. end)
  1060. test("LINSERT (client:linsert)", function()
  1061. if version:is('<', '2.1.0') then return end
  1062. utils.rpush_return(client, 'numbers', shared.numbers(), true)
  1063. assert_equal(client:linsert('numbers', 'before', 0, -2), 11)
  1064. assert_equal(client:linsert('numbers', 'after', -2, -1), 12)
  1065. assert_table_values(client:lrange('numbers', 0, 3), { '-2', '-1', '0', '1' });
  1066. assert_equal(client:linsert('numbers', 'before', 100, 200), -1)
  1067. assert_equal(client:linsert('numbers', 'after', 100, 50), -1)
  1068. assert_error(function()
  1069. client:set('foo', 'bar')
  1070. client:linsert('foo', 0, 0)
  1071. end)
  1072. end)
  1073. end)
  1074. context("Commands operating on sets", function()
  1075. test("SADD (client:sadd)", function()
  1076. assert_equal(client:sadd('set', 0), 1)
  1077. assert_equal(client:sadd('set', 1), 1)
  1078. assert_equal(client:sadd('set', 0), 0)
  1079. assert_error(function()
  1080. client:set('foo', 'bar')
  1081. client:sadd('foo', 0)
  1082. end)
  1083. end)
  1084. test("SREM (client:srem)", function()
  1085. utils.sadd_return(client, 'set', { '0', '1', '2', '3', '4' })
  1086. assert_equal(client:srem('set', 0), 1)
  1087. assert_equal(client:srem('set', 4), 1)
  1088. assert_equal(client:srem('set', 10), 0)
  1089. assert_error(function()
  1090. client:set('foo', 'bar')
  1091. client:srem('foo', 0)
  1092. end)
  1093. end)
  1094. test("SPOP (client:spop)", function()
  1095. local set = utils.sadd_return(client, 'set', { '0', '1', '2', '3', '4' })
  1096. assert_true(table.contains(set, client:spop('set')))
  1097. assert_nil(client:spop('doesnotexist'))
  1098. assert_error(function()
  1099. client:set('foo', 'bar')
  1100. client:spop('foo')
  1101. end)
  1102. end)
  1103. test("SMOVE (client:smove)", function()
  1104. utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5' })
  1105. utils.sadd_return(client, 'setB', { '5', '6', '7', '8', '9', '10' })
  1106. assert_true(client:smove('setA', 'setB', 0))
  1107. assert_equal(client:srem('setA', 0), 0)
  1108. assert_equal(client:srem('setB', 0), 1)
  1109. assert_true(client:smove('setA', 'setB', 5))
  1110. assert_false(client:smove('setA', 'setB', 100))
  1111. assert_error(function()
  1112. client:set('foo', 'bar')
  1113. client:smove('foo', 'setB', 5)
  1114. end)
  1115. assert_error(function()
  1116. client:set('foo', 'bar')
  1117. client:smove('setA', 'foo', 5)
  1118. end)
  1119. end)
  1120. test("SCARD (client:scard)", function()
  1121. utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5' })
  1122. assert_equal(client:scard('setA'), 6)
  1123. -- empty set
  1124. client:sadd('setB', 0)
  1125. client:spop('setB')
  1126. assert_equal(client:scard('doesnotexist'), 0)
  1127. -- non-existent set
  1128. assert_equal(client:scard('doesnotexist'), 0)
  1129. assert_error(function()
  1130. client:set('foo', 'bar')
  1131. client:scard('foo')
  1132. end)
  1133. end)
  1134. test("SISMEMBER (client:sismember)", function()
  1135. utils.sadd_return(client, 'set', { '0', '1', '2', '3', '4', '5' })
  1136. assert_true(client:sismember('set', 3))
  1137. assert_false(client:sismember('set', 100))
  1138. assert_false(client:sismember('doesnotexist', 0))
  1139. assert_error(function()
  1140. client:set('foo', 'bar')
  1141. client:sismember('foo', 0)
  1142. end)
  1143. end)
  1144. test("SMEMBERS (client:smembers)", function()
  1145. local set = utils.sadd_return(client, 'set', { '0', '1', '2', '3', '4', '5' })
  1146. assert_table_values(client:smembers('set'), set)
  1147. if version:is('<', '2.0.0') then
  1148. assert_nil(client:smembers('doesnotexist'))
  1149. else
  1150. assert_table_values(client:smembers('doesnotexist'), {})
  1151. end
  1152. assert_error(function()
  1153. client:set('foo', 'bar')
  1154. client:smembers('foo')
  1155. end)
  1156. end)
  1157. test("SINTER (client:sinter)", function()
  1158. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1159. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1160. assert_table_values(client:sinter('setA'), setA)
  1161. assert_table_values(client:sinter('setA', 'setB'), { '3', '4', '6', '1' })
  1162. if version:is('<', '2.0.0') then
  1163. assert_nil(client:sinter('setA', 'doesnotexist'))
  1164. else
  1165. assert_table_values(client:sinter('setA', 'doesnotexist'), {})
  1166. end
  1167. assert_error(function()
  1168. client:set('foo', 'bar')
  1169. client:sinter('foo')
  1170. end)
  1171. assert_error(function()
  1172. client:set('foo', 'bar')
  1173. client:sinter('setA', 'foo')
  1174. end)
  1175. end)
  1176. test("SINTERSTORE (client:sinterstore)", function()
  1177. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1178. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1179. assert_equal(client:sinterstore('setC', 'setA'), #setA)
  1180. assert_table_values(client:smembers('setC'), setA)
  1181. client:del('setC')
  1182. -- this behaviour has changed in redis 2.0
  1183. assert_equal(client:sinterstore('setC', 'setA', 'setB'), 4)
  1184. assert_table_values(client:smembers('setC'), { '1', '3', '4', '6' })
  1185. client:del('setC')
  1186. assert_equal(client:sinterstore('setC', 'doesnotexist'), 0)
  1187. assert_false(client:exists('setC'))
  1188. -- existing keys are replaced by SINTERSTORE
  1189. client:set('foo', 'bar')
  1190. assert_equal(client:sinterstore('foo', 'setA'), #setA)
  1191. assert_error(function()
  1192. client:set('foo', 'bar')
  1193. client:sinterstore('setA', 'foo')
  1194. end)
  1195. end)
  1196. test("SUNION (client:sunion)", function()
  1197. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1198. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1199. assert_table_values(client:sunion('setA'), setA)
  1200. assert_table_values(
  1201. client:sunion('setA', 'setB'),
  1202. { '0', '1', '10', '2', '3', '4', '5', '6', '9' }
  1203. )
  1204. -- this behaviour has changed in redis 2.0
  1205. assert_table_values(client:sunion('setA', 'doesnotexist'), setA)
  1206. assert_error(function()
  1207. client:set('foo', 'bar')
  1208. client:sunion('foo')
  1209. end)
  1210. assert_error(function()
  1211. client:set('foo', 'bar')
  1212. client:sunion('setA', 'foo')
  1213. end)
  1214. end)
  1215. test("SUNIONSTORE (client:sunionstore)", function()
  1216. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1217. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1218. assert_equal(client:sunionstore('setC', 'setA'), #setA)
  1219. assert_table_values(client:smembers('setC'), setA)
  1220. client:del('setC')
  1221. assert_equal(client:sunionstore('setC', 'setA', 'setB'), 9)
  1222. assert_table_values(
  1223. client:smembers('setC'),
  1224. { '0' ,'1' , '10', '2', '3', '4', '5', '6', '9' }
  1225. )
  1226. client:del('setC')
  1227. assert_equal(client:sunionstore('setC', 'doesnotexist'), 0)
  1228. if version:is('<', '2.0.0') then
  1229. assert_true(client:exists('setC'))
  1230. else
  1231. assert_false(client:exists('setC'))
  1232. end
  1233. assert_equal(client:scard('setC'), 0)
  1234. -- existing keys are replaced by SUNIONSTORE
  1235. client:set('foo', 'bar')
  1236. assert_equal(client:sunionstore('foo', 'setA'), #setA)
  1237. assert_error(function()
  1238. client:set('foo', 'bar')
  1239. client:sunionstore('setA', 'foo')
  1240. end)
  1241. end)
  1242. test("SDIFF (client:sdiff)", function()
  1243. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1244. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1245. assert_table_values(client:sdiff('setA'), setA)
  1246. assert_table_values(client:sdiff('setA', 'setB'), { '5', '0', '2' })
  1247. assert_table_values(client:sdiff('setA', 'doesnotexist'), setA)
  1248. assert_error(function()
  1249. client:set('foo', 'bar')
  1250. client:sdiff('foo')
  1251. end)
  1252. assert_error(function()
  1253. client:set('foo', 'bar')
  1254. client:sdiff('setA', 'foo')
  1255. end)
  1256. end)
  1257. test("SDIFFSTORE (client:sdiffstore)", function()
  1258. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1259. local setB = utils.sadd_return(client, 'setB', { '1', '3', '4', '6', '9', '10' })
  1260. assert_equal(client:sdiffstore('setC', 'setA'), #setA)
  1261. assert_table_values(client:smembers('setC'), setA)
  1262. client:del('setC')
  1263. assert_equal(client:sdiffstore('setC', 'setA', 'setB'), 3)
  1264. assert_table_values(client:smembers('setC'), { '5', '0', '2' })
  1265. client:del('setC')
  1266. assert_equal(client:sdiffstore('setC', 'doesnotexist'), 0)
  1267. if version:is('<', '2.0.0') then
  1268. assert_true(client:exists('setC'))
  1269. else
  1270. assert_false(client:exists('setC'))
  1271. end
  1272. assert_equal(client:scard('setC'), 0)
  1273. -- existing keys are replaced by SDIFFSTORE
  1274. client:set('foo', 'bar')
  1275. assert_equal(client:sdiffstore('foo', 'setA'), #setA)
  1276. assert_error(function()
  1277. client:set('foo', 'bar')
  1278. client:sdiffstore('setA', 'foo')
  1279. end)
  1280. end)
  1281. test("SRANDMEMBER (client:srandmember)", function()
  1282. local setA = utils.sadd_return(client, 'setA', { '0', '1', '2', '3', '4', '5', '6' })
  1283. assert_true(table.contains(setA, client:srandmember('setA')))
  1284. assert_nil(client:srandmember('doesnotexist'))
  1285. assert_error(function()
  1286. client:set('foo', 'bar')
  1287. client:srandmember('foo')
  1288. end)
  1289. end)
  1290. test("SSCAN (client:sscan)", function()
  1291. if version:is('<', '2.8.0') then return end
  1292. local args = { 'member:1st', 'member:2nd', 'member:3rd', 'member:4th' }
  1293. client:sadd('key:set', unpack(args))
  1294. local cursor, members = unpack(client:sscan('key:set', 0))
  1295. assert_type(cursor, 'string')
  1296. assert_type(members, 'table')
  1297. assert_table_values(members, args)
  1298. local cursor, members = unpack(client:sscan('key:set', 0, {
  1299. match = 'member:*d', count = 10
  1300. }))
  1301. assert_type(cursor, 'string')
  1302. assert_type(members, 'table')
  1303. assert_table_values(members, { 'member:2nd', 'member:3rd' })
  1304. end)
  1305. end)
  1306. context("Commands operating on zsets", function()
  1307. test("ZADD (client:zadd)", function()
  1308. assert_equal(client:zadd('zset', 0, 'a'), 1)
  1309. assert_equal(client:zadd('zset', 1, 'b'), 1)
  1310. assert_equal(client:zadd('zset', -1, 'c'), 1)
  1311. assert_equal(client:zadd('zset', 2, 'b'), 0)
  1312. assert_equal(client:zadd('zset', -22, 'b'), 0)
  1313. assert_error(function()
  1314. client:set('foo', 'bar')
  1315. client:zadd('foo', 0, 'a')
  1316. end)
  1317. end)
  1318. test("ZINCRBY (client:zincrby)", function()
  1319. assert_equal(client:zincrby('doesnotexist', 1, 'foo'), 1)
  1320. assert_equal(client:type('doesnotexist'), 'zset')
  1321. utils.zadd_return(client, 'zset', shared.zset_sample())
  1322. assert_equal(client:zincrby('zset', 5, 'a'), -5)
  1323. assert_equal(client:zincrby('zset', 1, 'b'), 1)
  1324. assert_equal(client:zincrby('zset', 0, 'c'), 10)
  1325. assert_equal(client:zincrby('zset', -20, 'd'), 0)
  1326. assert_equal(client:zincrby('zset', 2, 'd'), 2)
  1327. assert_equal(client:zincrby('zset', -30, 'e'), -10)
  1328. assert_equal(client:zincrby('zset', 1, 'x'), 1)
  1329. assert_error(function()
  1330. client:set('foo', 'bar')
  1331. client:zincrby('foo', 1, 'a')
  1332. end)
  1333. end)
  1334. test("ZREM (client:zrem)", function()
  1335. utils.zadd_return(client, 'zset', shared.zset_sample())
  1336. assert_equal(client:zrem('zset', 'a'), 1)
  1337. assert_equal(client:zrem('zset', 'x'), 0)
  1338. assert_error(function()
  1339. client:set('foo', 'bar')
  1340. client:zrem('foo', 'bar')
  1341. end)
  1342. end)
  1343. test("ZRANGE (client:zrange)", function()
  1344. local zset = utils.zadd_return(client, 'zset', shared.zset_sample())
  1345. assert_table_values(client:zrange('zset', 0, 3), { 'a', 'b', 'c', 'd' })
  1346. assert_table_values(client:zrange('zset', 0, 0), { 'a' })
  1347. assert_empty(client:zrange('zset', 1, 0))
  1348. assert_table_values(client:zrange('zset', 0, -1), table.keys(zset))
  1349. assert_table_values(client:zrange('zset', 3, -3), { 'd' })
  1350. assert_empty(client:zrange('zset', 5, -3))
  1351. assert_table_values(client:zrange('zset', -100, 100), table.keys(zset))
  1352. assert_table_values(
  1353. client:zrange('zset', 0, 2, 'withscores'),
  1354. { { 'a', '-10' }, { 'b', '0' }, { 'c', '10' } }
  1355. )
  1356. assert_table_values(
  1357. client:zrange('zset', 0, 2, { withscores = true }),
  1358. { { 'a', '-10' }, { 'b', '0' }, { 'c', '10' } }
  1359. )
  1360. assert_error(function()
  1361. client:set('foo', 'bar')
  1362. client:zrange('foo', 0, -1)
  1363. end)
  1364. end)
  1365. test("ZREVRANGE (client:zrevrange)", function()
  1366. local zset = utils.zadd_return(client, 'zset', shared.zset_sample())
  1367. assert_table_values(client:zrevrange('zset', 0, 3), { 'f', 'e', 'd', 'c' })
  1368. assert_table_values(client:zrevrange('zset', 0, 0), { 'f' })
  1369. assert_empty(client:zrevrange('zset', 1, 0))
  1370. assert_table_values(client:zrevrange('zset', 0, -1), table.keys(zset))
  1371. assert_table_values(client:zrevrange('zset', 3, -3), { 'c' })
  1372. assert_empty(client:zrevrange('zset', 5, -3))
  1373. assert_table_values(client:zrevrange('zset', -100, 100), table.keys(zset))
  1374. assert_table_values(
  1375. client:zrevrange('zset', 0, 2, 'withscores'),
  1376. { { 'f', '30' }, { 'e', '20' }, { 'd', '20' } }
  1377. )
  1378. assert_table_values(
  1379. client:zrevrange('zset', 0, 2, { withscores = true }),
  1380. { { 'f', '30' }, { 'e', '20' }, { 'd', '20' } }
  1381. )
  1382. assert_error(function()
  1383. client:set('foo', 'bar')
  1384. client:zrevrange('foo', 0, -1)
  1385. end)
  1386. end)
  1387. test("ZRANGEBYSCORE (client:zrangebyscore)", function()
  1388. local zset = utils.zadd_return(client, 'zset', shared.zset_sample())
  1389. assert_table_values(client:zrangebyscore('zset', -10, -10), { 'a' })
  1390. assert_table_values(client:zrangebyscore('zset', 10, 30), { 'c', 'd', 'e', 'f' })
  1391. assert_table_values(client:zrangebyscore('zset', 20, 20), { 'd', 'e' })
  1392. assert_empty(client:zrangebyscore('zset', 30, 0))
  1393. assert_table_values(
  1394. client:zrangebyscore('zset', 10, 20, 'withscores'),
  1395. { { 'c', '10' }, { 'd', '20' }, { 'e', '20' } }
  1396. )
  1397. assert_table_values(
  1398. client:zrangebyscore('zset', 10, 20, { withscores = true }),
  1399. { { 'c', '10' }, { 'd', '20' }, { 'e', '20' } }
  1400. )
  1401. assert_table_values(
  1402. client:zrangebyscore('zset', 10, 20, { limit = { 1, 2 } }),
  1403. { 'd', 'e' }
  1404. )
  1405. assert_table_values(
  1406. client:zrangebyscore('zset', 10, 20, {
  1407. limit = { offset = 1, count = 2 }
  1408. }),
  1409. { 'd', 'e' }
  1410. )
  1411. assert_table_values(
  1412. client:zrangebyscore('zset', 10, 20, {
  1413. limit = { offset = 1, count = 2 },
  1414. withscores = true
  1415. }),
  1416. { { 'd', '20' }, { 'e', '20' } }
  1417. )
  1418. assert_error(function()
  1419. client:set('foo', 'bar')
  1420. client:zrangebyscore('foo', 0, -1)
  1421. end)
  1422. end)
  1423. test("ZREVRANGEBYSCORE (client:zrevrangebyscore)", function()
  1424. local zset = utils.zadd_return(client, 'zset', shared.zset_sample())
  1425. assert_table_values(client:zrevrangebyscore('zset', -10, -10), { 'a' })
  1426. assert_table_values(client:zrevrangebyscore('zset', 0, -10), { 'b', 'a' })
  1427. assert_table_values(client:zrevrangebyscore('zset', 20, 20), { 'e', 'd' })
  1428. assert_table_values(client:zrevrangebyscore('zset', 30, 0), { 'f', 'e', 'd', 'c', 'b' })
  1429. assert_table_values(
  1430. client:zrevrangebyscore('zset', 20, 10, 'withscores'),
  1431. { { 'e', '20' }, { 'd', '20' }, { 'c', '10' } }
  1432. )
  1433. assert_table_values(
  1434. client:zrevrangebyscore('zset', 20, 10, { limit = { 1, 2 } }),
  1435. { 'd', 'c' }
  1436. )
  1437. assert_table_values(
  1438. client:zrevrangebyscore('zset', 20, 10, {
  1439. limit = { offset = 1, count = 2 }
  1440. }),
  1441. { 'd', 'c' }
  1442. )
  1443. assert_table_values(
  1444. client:zrevrangebyscore('zset', 20, 10, {
  1445. limit = { offset = 1, count = 2 },
  1446. withscores = true
  1447. }),
  1448. { { 'd', '20' }, { 'c', '10' } }
  1449. )
  1450. assert_error(function()
  1451. client:set('foo', 'bar')
  1452. client:zrevrangebyscore('foo', 0, -1)
  1453. end)
  1454. end)
  1455. test("ZUNIONSTORE (client:zunionstore)", function()
  1456. if version:is('<', '2.0.0') then return end
  1457. utils.zadd_return(client, 'zseta', { a = 1, b = 2, c = 3 })
  1458. utils.zadd_return(client, 'zsetb', { b = 1, c = 2, d = 3 })
  1459. -- basic ZUNIONSTORE
  1460. assert_equal(client:zunionstore('zsetc', 2, 'zseta', 'zsetb'), 4)
  1461. assert_table_values(
  1462. client:zrange('zsetc', 0, -1, 'withscores'),
  1463. { { 'a', '1' }, { 'b', '3' }, { 'd', '3' }, { 'c', '5' } }
  1464. )
  1465. assert_equal(client:zunionstore('zsetc', 2, 'zseta', 'zsetbNull'), 3)
  1466. assert_table_values(
  1467. client:zrange('zsetc', 0, -1, 'withscores'),
  1468. { { 'a', '1' }, { 'b', '2' }, { 'c', '3' }}
  1469. )
  1470. assert_equal(client:zunionstore('zsetc', 2, 'zsetaNull', 'zsetb'), 3)
  1471. assert_table_values(
  1472. client:zrange('zsetc', 0, -1, 'withscores'),
  1473. { { 'b', '1' }, { 'c', '2' }, { 'd', '3' }}
  1474. )
  1475. assert_equal(client:zunionstore('zsetc', 2, 'zsetaNull', 'zsetbNull'), 0)
  1476. -- with WEIGHTS
  1477. local opts = { weights = { 2, 3 } }
  1478. assert_equal(client:zunionstore('zsetc', 2, 'zseta', 'zsetb', opts), 4)
  1479. assert_table_values(
  1480. client:zrange('zsetc', 0, -1, 'withscores'),
  1481. { { 'a', '2' }, { 'b', '7' }, { 'd', '9' }, { 'c', '12' } }
  1482. )
  1483. -- with AGGREGATE (min)
  1484. local opts = { aggregate = 'min' }
  1485. assert_equal(client:zunionstore('zsetc', 2, 'zseta', 'zsetb', opts), 4)
  1486. assert_table_values(
  1487. client:zrange('zsetc', 0, -1, 'withscores'),
  1488. { { 'a', '1' }, { 'b', '1' }, { 'c', '2' }, { 'd', '3' } }
  1489. )
  1490. -- with AGGREGATE (max)
  1491. local opts = { aggregate = 'max' }
  1492. assert_equal(client:zunionstore('zsetc', 2, 'zseta', 'zsetb', opts), 4)
  1493. assert_table_values(
  1494. client:zrange('zsetc', 0, -1, 'withscores'),
  1495. { { 'a', '1' }, { 'b', '2' }, { 'c', '3' }, { 'd', '3' } }
  1496. )
  1497. assert_error(function()
  1498. client:set('zsetFake', 'fake')
  1499. client:zunionstore('zsetc', 2, 'zseta', 'zsetFake')
  1500. end)
  1501. end)
  1502. test("ZINTERSTORE (client:zinterstore)", function()
  1503. if version:is('<', '2.0.0') then return end
  1504. utils.zadd_return(client, 'zseta', { a = 1, b = 2, c = 3 })
  1505. utils.zadd_return(client, 'zsetb', { b = 1, c = 2, d = 3 })
  1506. -- basic ZUNIONSTORE
  1507. assert_equal(client:zinterstore('zsetc', 2, 'zseta', 'zsetb'), 2)
  1508. assert_table_values(
  1509. client:zrange('zsetc', 0, -1, 'withscores'),
  1510. { { 'b', '3' }, { 'c', '5' } }
  1511. )
  1512. assert_equal(client:zinterstore('zsetc', 2, 'zseta', 'zsetbNull'), 0)
  1513. assert_equal(client:zinterstore('zsetc', 2, 'zsetaNull', 'zsetb'), 0)
  1514. assert_equal(client:zinterstore('zsetc', 2, 'zsetaNull', 'zsetbNull'), 0)
  1515. -- with WEIGHTS
  1516. local opts = { weights = { 2, 3 } }
  1517. assert_equal(client:zinterstore('zsetc', 2, 'zseta', 'zsetb', opts), 2)
  1518. assert_table_values(
  1519. client:zrange('zsetc', 0, -1, 'withscores'),
  1520. { { 'b', '7' }, { 'c', '12' } }
  1521. )
  1522. -- with AGGREGATE (min)
  1523. local opts = { aggregate = 'min' }
  1524. assert_equal(client:zinterstore('zsetc', 2, 'zseta', 'zsetb', opts), 2)
  1525. assert_table_values(
  1526. client:zrange('zsetc', 0, -1, 'withscores'),
  1527. { { 'b', '1' }, { 'c', '2' } }
  1528. )
  1529. -- with AGGREGATE (max)
  1530. local opts = { aggregate = 'max' }
  1531. assert_equal(client:zinterstore('zsetc', 2, 'zseta', 'zsetb', opts), 2)
  1532. assert_table_values(
  1533. client:zrange('zsetc', 0, -1, 'withscores'),
  1534. { { 'b', '2' }, { 'c', '3' } }
  1535. )
  1536. assert_error(function()
  1537. client:set('zsetFake', 'fake')
  1538. client:zinterstore('zsetc', 2, 'zseta', 'zsetFake')
  1539. end)
  1540. end)
  1541. test("ZCOUNT (client:zcount)", function()
  1542. if version:is('<', '2.0.0') then return end
  1543. utils.zadd_return(client, 'zset', shared.zset_sample())
  1544. assert_equal(client:zcount('zset', 50, 100), 0)
  1545. assert_equal(client:zcount('zset', -100, 100), 6)
  1546. assert_equal(client:zcount('zset', 10, 20), 3)
  1547. assert_equal(client:zcount('zset', '(10', 20), 2)
  1548. assert_equal(client:zcount('zset', 10, '(20'), 1)
  1549. assert_equal(client:zcount('zset', '(10', '(20'), 0)
  1550. assert_equal(client:zcount('zset', '(0', '(30'), 3)
  1551. assert_error(function()
  1552. client:set('foo', 'bar')
  1553. client:zcount('foo', 0, 0)
  1554. end)
  1555. end)
  1556. test("ZCARD (client:zcard)", function()
  1557. local zset = utils.zadd_return(client, 'zset', shared.zset_sample())
  1558. assert_equal(client:zcard('zset'), #table.keys(zset))
  1559. client:zrem('zset', 'a')
  1560. assert_equal(client:zcard('zset'), #table.keys(zset) - 1)
  1561. client:zadd('zsetB', 0, 'a')
  1562. client:zrem('zsetB', 'a')
  1563. assert_equal(client:zcard('zsetB'), 0)
  1564. assert_equal(client:zcard('doesnotexist'), 0)
  1565. assert_error(function()
  1566. client:set('foo', 'bar')
  1567. client:zcard('foo')
  1568. end)
  1569. end)
  1570. test("ZSCORE (client:zscore)", function()
  1571. utils.zadd_return(client, 'zset', shared.zset_sample())
  1572. assert_equal(client:zscore('zset', 'a'), '-10')
  1573. assert_equal(client:zscore('zset', 'c'), '10')
  1574. assert_equal(client:zscore('zset', 'e'), '20')
  1575. assert_nil(client:zscore('zset', 'x'))
  1576. assert_nil(client:zscore('doesnotexist', 'a'))
  1577. assert_error(function()
  1578. client:set('foo', 'bar')
  1579. client:zscore('foo', 'a')
  1580. end)
  1581. end)
  1582. test("ZREMRANGEBYSCORE (client:zremrangebyscore)", function()
  1583. utils.zadd_return(client, 'zset', shared.zset_sample())
  1584. assert_equal(client:zremrangebyscore('zset', -10, 0), 2)
  1585. assert_table_values(client:zrange('zset', 0, -1), { 'c', 'd', 'e', 'f' })
  1586. assert_equal(client:zremrangebyscore('zset', 10, 10), 1)
  1587. assert_table_values(client:zrange('zset', 0, -1), { 'd', 'e', 'f' })
  1588. assert_equal(client:zremrangebyscore('zset', 100, 100), 0)
  1589. assert_equal(client:zremrangebyscore('zset', 0, 100), 3)
  1590. assert_equal(client:zremrangebyscore('zset', 0, 100), 0)
  1591. assert_error(function()
  1592. client:set('foo', 'bar')
  1593. client:zremrangebyscore('foo', 0, 0)
  1594. end)
  1595. end)
  1596. test("ZRANK (client:zrank)", function()
  1597. if version:is('<', '2.0.0') then return end
  1598. utils.zadd_return(client, 'zset', shared.zset_sample())
  1599. assert_equal(client:zrank('zset', 'a'), 0)
  1600. assert_equal(client:zrank('zset', 'b'), 1)
  1601. assert_equal(client:zrank('zset', 'e'), 4)
  1602. client:zrem('zset', 'd')
  1603. assert_equal(client:zrank('zset', 'e'), 3)
  1604. assert_nil(client:zrank('zset', 'x'))
  1605. assert_error(function()
  1606. client:set('foo', 'bar')
  1607. client:zrank('foo', 'a')
  1608. end)
  1609. end)
  1610. test("ZREVRANK (client:zrevrank)", function()
  1611. if version:is('<', '2.0.0') then return end
  1612. utils.zadd_return(client, 'zset', shared.zset_sample())
  1613. assert_equal(client:zrevrank('zset', 'a'), 5)
  1614. assert_equal(client:zrevrank('zset', 'b'), 4)
  1615. assert_equal(client:zrevrank('zset', 'e'), 1)
  1616. client:zrem('zset', 'e')
  1617. assert_equal(client:zrevrank('zset', 'd'), 1)
  1618. assert_nil(client:zrevrank('zset', 'x'))
  1619. assert_error(function()
  1620. client:set('foo', 'bar')
  1621. client:zrevrank('foo', 'a')
  1622. end)
  1623. end)
  1624. test("ZREMRANGEBYRANK (client:zremrangebyrank)", function()
  1625. if version:is('<', '2.0.0') then return end
  1626. utils.zadd_return(client, 'zseta', shared.zset_sample())
  1627. assert_equal(client:zremrangebyrank('zseta', 0, 2), 3)
  1628. assert_table_values(client:zrange('zseta', 0, -1), { 'd', 'e', 'f' })
  1629. assert_equal(client:zremrangebyrank('zseta', 0, 0), 1)
  1630. assert_table_values(client:zrange('zseta', 0, -1), { 'e', 'f' })
  1631. utils.zadd_return(client, 'zsetb', shared.zset_sample())
  1632. assert_equal(client:zremrangebyrank('zsetb', -3, -1), 3)
  1633. assert_table_values(client:zrange('zsetb', 0, -1), { 'a', 'b', 'c' })
  1634. assert_equal(client:zremrangebyrank('zsetb', -1, -1), 1)
  1635. assert_table_values(client:zrange('zsetb', 0, -1), { 'a', 'b' })
  1636. assert_equal(client:zremrangebyrank('zsetb', -2, -1), 2)
  1637. assert_table_values(client:zrange('zsetb', 0, -1), { })
  1638. assert_false(client:exists('zsetb'))
  1639. assert_equal(client:zremrangebyrank('zsetc', 0, 0), 0)
  1640. assert_error(function()
  1641. client:set('foo', 'bar')
  1642. client:zremrangebyrank('foo', 0, 1)
  1643. end)
  1644. end)
  1645. test("ZSCAN (client:zscan)", function()
  1646. if version:is('<', '2.8.0') then return end
  1647. client:zadd('key:zset',
  1648. 1, 'member:1st', 2, 'member:2nd', 3, 'member:3rd', 4, 'member:4th'
  1649. )
  1650. local cursor, members = unpack(client:zscan('key:zset', 0))
  1651. assert_type(cursor, 'string')
  1652. assert_type(members, 'table')
  1653. assert_table_values(members, {
  1654. { 'member:1st', 1 }, { 'member:2nd', 2 },
  1655. { 'member:3rd', 3 }, { 'member:4th', 4 },
  1656. })
  1657. local cursor, members = unpack(client:zscan('key:zset', 0, {
  1658. match = 'member:*d', count = 10
  1659. }))
  1660. assert_type(cursor, 'string')
  1661. assert_type(members, 'table')
  1662. assert_table_values(members, { { 'member:2nd', 2 }, { 'member:3rd', 3 } })
  1663. end)
  1664. end)
  1665. context("Commands operating on hashes", function()
  1666. test("HSET (client:hset)", function()
  1667. if version:is('<', '2.0.0') then return end
  1668. assert_true(client:hset('metavars', 'foo', 'bar'))
  1669. assert_true(client:hset('metavars', 'hoge', 'piyo'))
  1670. assert_equal(client:hget('metavars', 'foo'), 'bar')
  1671. assert_equal(client:hget('metavars', 'hoge'), 'piyo')
  1672. assert_error(function()
  1673. client:set('test', 'foobar')
  1674. client:hset('test', 'hoge', 'piyo')
  1675. end)
  1676. end)
  1677. test("HGET (client:hget)", function()
  1678. if version:is('<', '2.0.0') then return end
  1679. assert_true(client:hset('metavars', 'foo', 'bar'))
  1680. assert_equal(client:hget('metavars', 'foo'), 'bar')
  1681. assert_nil(client:hget('metavars', 'hoge'))
  1682. assert_nil(client:hget('hashDoesNotExist', 'field'))
  1683. assert_error(function()
  1684. client:rpush('metavars', 'foo')
  1685. client:hget('metavars', 'foo')
  1686. end)
  1687. end)
  1688. test("HEXISTS (client:hexists)", function()
  1689. if version:is('<', '2.0.0') then return end
  1690. assert_true(client:hset('metavars', 'foo', 'bar'))
  1691. assert_true(client:hexists('metavars', 'foo'))
  1692. assert_false(client:hexists('metavars', 'hoge'))
  1693. assert_false(client:hexists('hashDoesNotExist', 'field'))
  1694. assert_error(function()
  1695. client:set('foo', 'bar')
  1696. client:hexists('foo')
  1697. end)
  1698. end)
  1699. test("HDEL (client:hdel)", function()
  1700. if version:is('<', '2.0.0') then return end
  1701. assert_true(client:hset('metavars', 'foo', 'bar'))
  1702. assert_true(client:hexists('metavars', 'foo'))
  1703. assert_equal(client:hdel('metavars', 'foo'), 1)
  1704. assert_false(client:hexists('metavars', 'foo'))
  1705. assert_equal(client:hdel('metavars', 'hoge'), 0)
  1706. assert_equal(client:hdel('hashDoesNotExist', 'field'), 0)
  1707. assert_error(function()
  1708. client:set('foo', 'bar')
  1709. client:hdel('foo', 'field')
  1710. end)
  1711. end)
  1712. test("HLEN (client:hlen)", function()
  1713. if version:is('<', '2.0.0') then return end
  1714. assert_true(client:hset('metavars', 'foo', 'bar'))
  1715. assert_true(client:hset('metavars', 'hoge', 'piyo'))
  1716. assert_true(client:hset('metavars', 'foofoo', 'barbar'))
  1717. assert_true(client:hset('metavars', 'hogehoge', 'piyopiyo'))
  1718. assert_equal(client:hlen('metavars'), 4)
  1719. client:hdel('metavars', 'foo')
  1720. assert_equal(client:hlen('metavars'), 3)
  1721. assert_equal(client:hlen('hashDoesNotExist'), 0)
  1722. assert_error(function()
  1723. client:set('foo', 'bar')
  1724. client:hlen('foo')
  1725. end)
  1726. end)
  1727. test("HSETNX (client:hsetnx)", function()
  1728. if version:is('<', '2.0.0') then return end
  1729. assert_true(client:hsetnx('metavars', 'foo', 'bar'))
  1730. assert_false(client:hsetnx('metavars', 'foo', 'barbar'))
  1731. assert_equal(client:hget('metavars', 'foo'), 'bar')
  1732. assert_error(function()
  1733. client:set('test', 'foobar')
  1734. client:hsetnx('test', 'hoge', 'piyo')
  1735. end)
  1736. end)
  1737. test("HMSET / HMGET (client:hmset, client:hmget)", function()
  1738. if version:is('<', '2.0.0') then return end
  1739. local hashKVs = { foo = 'bar', hoge = 'piyo' }
  1740. -- key => value pairs via table
  1741. assert_true(client:hmset('metavars', hashKVs))
  1742. local retval = client:hmget('metavars', table.keys(hashKVs))
  1743. assert_table_values(retval, table.values(hashKVs))
  1744. -- key => value pairs via function arguments
  1745. client:del('metavars')
  1746. assert_true(client:hmset('metavars', 'foo', 'bar', 'hoge', 'piyo'))
  1747. assert_table_values(retval, table.values(hashKVs))
  1748. end)
  1749. test("HINCRBY (client:hincrby)", function()
  1750. if version:is('<', '2.0.0') then return end
  1751. assert_equal(client:hincrby('hash', 'counter', 10), 10)
  1752. assert_equal(client:hincrby('hash', 'counter', 10), 20)
  1753. assert_equal(client:hincrby('hash', 'counter', -20), 0)
  1754. assert_error(function()
  1755. client:hset('hash', 'field', 'string_value')
  1756. client:hincrby('hash', 'field', 10)
  1757. end)
  1758. assert_error(function()
  1759. client:set('foo', 'bar')
  1760. client:hincrby('foo', 'bar', 1)
  1761. end)
  1762. end)
  1763. test("HINCRBYFLOAT (client:hincrbyfloat)", function()
  1764. if version:is('<', '2.5.0') then return end
  1765. assert_equal(client:hincrbyfloat('hash', 'counter', 10.1), 10.1)
  1766. assert_equal(client:hincrbyfloat('hash', 'counter', 10.4), 20.5)
  1767. assert_equal(client:hincrbyfloat('hash', 'counter', -20.000), 0.5)
  1768. assert_error(function()
  1769. client:hset('hash', 'field', 'string_value')
  1770. client:hincrbyfloat('hash', 'field', 10.10)
  1771. end)
  1772. assert_error(function()
  1773. client:set('foo', 'bar')
  1774. client:hincrbyfloat('foo', 'bar', 1.10)
  1775. end)
  1776. end)
  1777. test("HKEYS (client:hkeys)", function()
  1778. if version:is('<', '2.0.0') then return end
  1779. local hashKVs = { foo = 'bar', hoge = 'piyo' }
  1780. assert_true(client:hmset('metavars', hashKVs))
  1781. assert_table_values(client:hkeys('metavars'), table.keys(hashKVs))
  1782. assert_table_values(client:hkeys('hashDoesNotExist'), { })
  1783. assert_error(function()
  1784. client:set('foo', 'bar')
  1785. client:hkeys('foo')
  1786. end)
  1787. end)
  1788. test("HVALS (client:hvals)", function()
  1789. if version:is('<', '2.0.0') then return end
  1790. local hashKVs = { foo = 'bar', hoge = 'piyo' }
  1791. assert_true(client:hmset('metavars', hashKVs))
  1792. assert_table_values(client:hvals('metavars'), table.values(hashKVs))
  1793. assert_table_values(client:hvals('hashDoesNotExist'), { })
  1794. assert_error(function()
  1795. client:set('foo', 'bar')
  1796. client:hvals('foo')
  1797. end)
  1798. end)
  1799. test("HGETALL (client:hgetall)", function()
  1800. if version:is('<', '2.0.0') then return end
  1801. local hashKVs = { foo = 'bar', hoge = 'piyo' }
  1802. assert_true(client:hmset('metavars', hashKVs))
  1803. assert_true(table.compare(client:hgetall('metavars'), hashKVs))
  1804. assert_true(table.compare(client:hgetall('hashDoesNotExist'), { }))
  1805. assert_error(function()
  1806. client:set('foo', 'bar')
  1807. client:hgetall('foo')
  1808. end)
  1809. end)
  1810. test("HSCAN (client:hscan)", function()
  1811. if version:is('<', '2.8.0') then return end
  1812. local args = {
  1813. ['field:1st'] = 2, ['field:2nd'] = 2,
  1814. ['field:3rd'] = 3, ['field:4th'] = 4,
  1815. }
  1816. client:hmset('key:hash', args)
  1817. local cursor, kvs = unpack(client:hscan('key:hash', 0))
  1818. assert_type(cursor, 'string')
  1819. assert_type(kvs, 'table')
  1820. assert_true(table.compare(kvs, args))
  1821. local cursor, kvs = unpack(client:hscan('key:hash', 0, {
  1822. match = 'field:*d', count = 10
  1823. }))
  1824. assert_type(cursor, 'string')
  1825. assert_type(kvs, 'table')
  1826. assert_table_values(kvs, { ['field:2nd'] = 2, ['field:3rd'] = 3 })
  1827. end)
  1828. end)
  1829. context("Remote server control commands", function()
  1830. test("INFO (client:info)", function()
  1831. local info = client:info()
  1832. assert_type(info, 'table')
  1833. assert_not_nil(info.redis_version or info.server.redis_version)
  1834. end)
  1835. test("CONFIG GET (client:config)", function()
  1836. if version:is('<', '2.0.0') then return end
  1837. local config = client:config('get', '*')
  1838. assert_type(config, 'table')
  1839. assert_not_nil(config['list-max-ziplist-entries'])
  1840. if version:is('>=', '2.4.0') then
  1841. assert_not_nil(config.loglevel)
  1842. end
  1843. local config = client:config('get', '*max-*-entries*')
  1844. assert_type(config, 'table')
  1845. assert_not_nil(config['list-max-ziplist-entries'])
  1846. if version:is('>=', '2.4.0') then
  1847. assert_nil(config.loglevel)
  1848. end
  1849. end)
  1850. test("CONFIG SET (client:config)", function()
  1851. if version:is('<', '2.4.0') then return end
  1852. local new, previous = 'notice', client:config('get', 'loglevel').loglevel
  1853. assert_type(previous, 'string')
  1854. assert_true(client:config('set', 'loglevel', new))
  1855. assert_equal(client:config('get', 'loglevel').loglevel, new)
  1856. assert_true(client:config('set', 'loglevel', previous))
  1857. end)
  1858. test("CONFIG RESETSTAT (client:config)", function()
  1859. assert_true(client:config('resetstat'))
  1860. end)
  1861. test("SLOWLOG RESET (client:slowlog)", function()
  1862. if version:is('<', '2.2.12') then return end
  1863. assert_true(client:slowlog('reset'))
  1864. end)
  1865. test("SLOWLOG GET (client:slowlog)", function()
  1866. if version:is('<', '2.2.12') then return end
  1867. local previous = client:config('get', 'slowlog-log-slower-than')['slowlog-log-slower-than']
  1868. client:config('set', 'slowlog-log-slower-than', 0)
  1869. client:set('foo', 'bar')
  1870. client:del('foo')
  1871. local log = client:slowlog('get')
  1872. assert_type(log, 'table')
  1873. assert_greater_than(#log, 0)
  1874. assert_type(log[1], 'table')
  1875. assert_greater_than(log[1].id, 0)
  1876. assert_greater_than(log[1].timestamp, 0)
  1877. assert_greater_than(log[1].duration, 0)
  1878. assert_type(log[1].command, 'table')
  1879. local log = client:slowlog('get', 1)
  1880. assert_type(log, 'table')
  1881. assert_equal(#log, 1)
  1882. client:config('set', 'slowlog-log-slower-than', previous or 10000)
  1883. end)
  1884. test("TIME (client:time)", function()
  1885. if version:is('<', '2.5.0') then return end
  1886. local redis_time = client:time()
  1887. assert_type(redis_time, 'table')
  1888. assert_not_nil(redis_time[1])
  1889. assert_not_nil(redis_time[2])
  1890. end)
  1891. test("CLIENT (client:client)", function()
  1892. if version:is('<', '2.4.0') then return end
  1893. -- TODO: implement tests
  1894. end)
  1895. test("LASTSAVE (client:lastsave)", function()
  1896. assert_not_nil(client:lastsave())
  1897. end)
  1898. test("FLUSHDB (client:flushdb)", function()
  1899. assert_true(client:flushdb())
  1900. end)
  1901. end)
  1902. context("Transactions", function()
  1903. test("MULTI / EXEC (client:multi, client:exec)", function()
  1904. if version:is('<', '2.0.0') then return end
  1905. assert_true(client:multi())
  1906. assert_response_queued(client:ping())
  1907. assert_response_queued(client:echo('hello'))
  1908. assert_response_queued(client:echo('redis'))
  1909. assert_table_values(client:exec(), { 'PONG', 'hello', 'redis' })
  1910. assert_true(client:multi())
  1911. assert_table_values(client:exec(), {})
  1912. -- should raise an error when trying to EXEC without having previously issued MULTI
  1913. assert_error(function() client:exec() end)
  1914. end)
  1915. test("DISCARD (client:discard)", function()
  1916. if version:is('<', '2.0.0') then return end
  1917. assert_true(client:multi())
  1918. assert_response_queued(client:set('foo', 'bar'))
  1919. assert_response_queued(client:set('hoge', 'piyo'))
  1920. assert_true(client:discard())
  1921. -- should raise an error when trying to EXEC after a DISCARD
  1922. assert_error(function() client:exec() end)
  1923. assert_false(client:exists('foo'))
  1924. assert_false(client:exists('hoge'))
  1925. end)
  1926. test("WATCH", function()
  1927. if version:is('<', '2.1.0') then return end
  1928. local client2 = utils.create_client(settings)
  1929. assert_true(client:set('foo', 'bar'))
  1930. assert_true(client:watch('foo'))
  1931. assert_true(client:multi())
  1932. assert_response_queued(client:get('foo'))
  1933. assert_true(client2:set('foo', 'hijacked'))
  1934. assert_nil(client:exec())
  1935. end)
  1936. test("UNWATCH", function()
  1937. if version:is('<', '2.1.0') then return end
  1938. local client2 = utils.create_client(settings)
  1939. assert_true(client:set('foo', 'bar'))
  1940. assert_true(client:watch('foo'))
  1941. assert_true(client:unwatch())
  1942. assert_true(client:multi())
  1943. assert_response_queued(client:get('foo'))
  1944. assert_true(client2:set('foo', 'hijacked'))
  1945. assert_table_values(client:exec(), { 'hijacked' })
  1946. end)
  1947. test("MULTI / EXEC / DISCARD abstraction", function()
  1948. if version:is('<', '2.0.0') then return end
  1949. local replies, processed
  1950. replies, processed = client:transaction(function(t)
  1951. -- empty transaction
  1952. end)
  1953. assert_table_values(replies, { })
  1954. assert_equal(processed, 0)
  1955. replies, processed = client:transaction(function(t)
  1956. t:discard()
  1957. end)
  1958. assert_table_values(replies, { })
  1959. assert_equal(processed, 0)
  1960. replies, processed = client:transaction(function(t)
  1961. assert_response_queued(t:set('foo', 'bar'))
  1962. assert_true(t:discard())
  1963. assert_response_queued(t:ping())
  1964. assert_response_queued(t:echo('hello'))
  1965. assert_response_queued(t:echo('redis'))
  1966. assert_response_queued(t:exists('foo'))
  1967. end)
  1968. assert_table_values(replies, { true, 'hello', 'redis', false })
  1969. assert_equal(processed, 4)
  1970. -- clean up transaction after client-side errors
  1971. assert_error(function()
  1972. client:transaction(function(t)
  1973. t:lpush('metavars', 'foo')
  1974. error('whoops!')
  1975. t:lpush('metavars', 'hoge')
  1976. end)
  1977. end)
  1978. assert_false(client:exists('metavars'))
  1979. end)
  1980. test("WATCH / MULTI / EXEC abstraction", function()
  1981. if version:is('<', '2.1.0') then return end
  1982. local redis2 = utils.create_client(settings)
  1983. local watch_keys = { 'foo' }
  1984. local replies, processed = client:transaction(watch_keys, function(t)
  1985. -- empty transaction
  1986. end)
  1987. assert_table_values(replies, { })
  1988. assert_equal(processed, 0)
  1989. assert_error(function()
  1990. client:transaction(watch_keys, function(t)
  1991. t:set('foo', 'bar')
  1992. redis2:set('foo', 'hijacked')
  1993. t:get('foo')
  1994. end)
  1995. end)
  1996. end)
  1997. test("WATCH / MULTI / EXEC with check-and-set (CAS) abstraction", function()
  1998. if version:is('<', '2.1.0') then return end
  1999. local opts, replies, processed
  2000. opts = { cas = 'foo' }
  2001. replies, processed = client:transaction(opts, function(t)
  2002. -- empty transaction (with missing call to t:multi())
  2003. end)
  2004. assert_table_values(replies, { })
  2005. assert_equal(processed, 0)
  2006. opts = { watch = 'foo', cas = true }
  2007. replies, processed = client:transaction(opts, function(t)
  2008. t:multi()
  2009. -- empty transaction
  2010. end)
  2011. assert_table_values(replies, { })
  2012. assert_equal(processed, 0)
  2013. local redis2 = utils.create_client(settings)
  2014. local n = 5
  2015. opts = { watch = 'foobarr', cas = true, retry = 5 }
  2016. replies, processed = client:transaction(opts, function(t)
  2017. t:set('foobar', 'bazaar')
  2018. local val = t:get('foobar')
  2019. t:multi()
  2020. assert_response_queued(t:set('discardable', 'bar'))
  2021. assert_equal(t:commands_queued(), 1)
  2022. assert_true(t:discard())
  2023. assert_response_queued(t:ping())
  2024. assert_equal(t:commands_queued(), 1)
  2025. assert_response_queued(t:echo('hello'))
  2026. assert_response_queued(t:echo('redis'))
  2027. assert_equal(t:commands_queued(), 3)
  2028. if n>0 then
  2029. n = n-1
  2030. redis2:set("foobarr", n)
  2031. end
  2032. assert_response_queued(t:exists('foo'))
  2033. assert_response_queued(t:get('foobar'))
  2034. assert_response_queued(t:get('foobarr'))
  2035. end)
  2036. assert_table_values(replies, { true, 'hello', 'redis', false, "bazaar", '0' })
  2037. assert_equal(processed, 6)
  2038. end)
  2039. test("Abstraction options", function()
  2040. -- TODO: more in-depth tests (proxy calls to WATCH)
  2041. local opts, replies, processed
  2042. local tx_empty = function(t) end
  2043. local tx_cas_empty = function(t) t:multi() end
  2044. replies, processed = client:transaction(tx_empty)
  2045. assert_table_values(replies, { })
  2046. assert_error(function()
  2047. client:transaction(opts, tx_empty)
  2048. end)
  2049. opts = 'foo'
  2050. replies, processed = client:transaction(opts, tx_empty)
  2051. assert_table_values(replies, { })
  2052. assert_equal(processed, 0)
  2053. opts = { 'foo', 'bar' }
  2054. replies, processed = client:transaction(opts, tx_empty)
  2055. assert_equal(processed, 0)
  2056. opts = { watch = 'foo' }
  2057. replies, processed = client:transaction(opts, tx_empty)
  2058. assert_equal(processed, 0)
  2059. opts = { watch = { 'foo', 'bar' } }
  2060. replies, processed = client:transaction(opts, tx_empty)
  2061. assert_equal(processed, 0)
  2062. opts = { cas = true }
  2063. replies, processed = client:transaction(opts, tx_cas_empty)
  2064. assert_equal(processed, 0)
  2065. opts = { 'foo', 'bar', cas = true }
  2066. replies, processed = client:transaction(opts, tx_cas_empty)
  2067. assert_equal(processed, 0)
  2068. opts = { 'foo', nil, 'bar', cas = true }
  2069. replies, processed = client:transaction(opts, tx_cas_empty)
  2070. assert_equal(processed, 0)
  2071. opts = { watch = { 'foo', 'bar' }, cas = true }
  2072. replies, processed = client:transaction(opts, tx_cas_empty)
  2073. assert_equal(processed, 0)
  2074. opts = { nil, cas = true }
  2075. replies, processed = client:transaction(opts, tx_cas_empty)
  2076. assert_equal(processed, 0)
  2077. end)
  2078. end)
  2079. context("Pub/Sub", function()
  2080. test('PUBLISH (client:publish)', function()
  2081. assert_equal(client:publish('redis-lua-publish', 'test'), 0)
  2082. end)
  2083. test('SUBSCRIBE (client:subscribe)', function()
  2084. client:subscribe('redis-lua-publish')
  2085. -- we have one subscriber
  2086. data = 'data' .. tostring(math.random(1000))
  2087. publisher = utils.create_client(settings)
  2088. assert_equal(publisher:publish('redis-lua-publish', data), 1)
  2089. -- we have data
  2090. response = client:subscribe('redis-lua-publish')
  2091. -- {"message","redis-lua-publish","testXXX"}
  2092. assert_true(table.contains(response, 'message'))
  2093. assert_true(table.contains(response, 'redis-lua-publish'))
  2094. assert_true(table.contains(response, data))
  2095. client:unsubscribe('redis-lua-publish')
  2096. end)
  2097. end)
  2098. context("Scripting", function()
  2099. test('EVAL (client:eval)', function()
  2100. if version:is('<', '2.5.0') then return end
  2101. end)
  2102. test('EVALSHA (client:evalsha)', function()
  2103. if version:is('<', '2.5.0') then return end
  2104. end)
  2105. test('SCRIPT (client:script)', function()
  2106. if version:is('<', '2.5.0') then return end
  2107. end)
  2108. end)
  2109. end)