redis 3.3.5 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis/Gemfile +8 -1
  4. data/.travis.yml +34 -62
  5. data/CHANGELOG.md +45 -2
  6. data/Gemfile +5 -1
  7. data/README.md +32 -76
  8. data/benchmarking/logging.rb +1 -1
  9. data/bin/build +71 -0
  10. data/bors.toml +14 -0
  11. data/lib/redis/client.rb +38 -20
  12. data/lib/redis/cluster/command.rb +81 -0
  13. data/lib/redis/cluster/command_loader.rb +32 -0
  14. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  15. data/lib/redis/cluster/node.rb +104 -0
  16. data/lib/redis/cluster/node_key.rb +35 -0
  17. data/lib/redis/cluster/node_loader.rb +35 -0
  18. data/lib/redis/cluster/option.rb +76 -0
  19. data/lib/redis/cluster/slot.rb +69 -0
  20. data/lib/redis/cluster/slot_loader.rb +47 -0
  21. data/lib/redis/cluster.rb +285 -0
  22. data/lib/redis/connection/command_helper.rb +2 -8
  23. data/lib/redis/connection/hiredis.rb +2 -2
  24. data/lib/redis/connection/ruby.rb +13 -30
  25. data/lib/redis/connection/synchrony.rb +12 -4
  26. data/lib/redis/connection.rb +2 -2
  27. data/lib/redis/distributed.rb +29 -8
  28. data/lib/redis/errors.rb +46 -0
  29. data/lib/redis/hash_ring.rb +20 -64
  30. data/lib/redis/pipeline.rb +9 -7
  31. data/lib/redis/version.rb +1 -1
  32. data/lib/redis.rb +287 -52
  33. data/makefile +74 -0
  34. data/redis.gemspec +9 -10
  35. data/test/bitpos_test.rb +13 -19
  36. data/test/blocking_commands_test.rb +3 -5
  37. data/test/client_test.rb +18 -1
  38. data/test/cluster_abnormal_state_test.rb +38 -0
  39. data/test/cluster_blocking_commands_test.rb +15 -0
  40. data/test/cluster_client_internals_test.rb +77 -0
  41. data/test/cluster_client_key_hash_tags_test.rb +88 -0
  42. data/test/cluster_client_options_test.rb +147 -0
  43. data/test/cluster_client_pipelining_test.rb +59 -0
  44. data/test/cluster_client_replicas_test.rb +36 -0
  45. data/test/cluster_client_slots_test.rb +94 -0
  46. data/test/cluster_client_transactions_test.rb +71 -0
  47. data/test/cluster_commands_on_cluster_test.rb +165 -0
  48. data/test/cluster_commands_on_connection_test.rb +40 -0
  49. data/test/cluster_commands_on_geo_test.rb +74 -0
  50. data/test/cluster_commands_on_hashes_test.rb +11 -0
  51. data/test/cluster_commands_on_hyper_log_log_test.rb +17 -0
  52. data/test/cluster_commands_on_keys_test.rb +134 -0
  53. data/test/cluster_commands_on_lists_test.rb +15 -0
  54. data/test/cluster_commands_on_pub_sub_test.rb +101 -0
  55. data/test/cluster_commands_on_scripting_test.rb +56 -0
  56. data/test/cluster_commands_on_server_test.rb +221 -0
  57. data/test/cluster_commands_on_sets_test.rb +39 -0
  58. data/test/cluster_commands_on_sorted_sets_test.rb +35 -0
  59. data/test/cluster_commands_on_streams_test.rb +196 -0
  60. data/test/cluster_commands_on_strings_test.rb +15 -0
  61. data/test/cluster_commands_on_transactions_test.rb +41 -0
  62. data/test/cluster_commands_on_value_types_test.rb +14 -0
  63. data/test/command_map_test.rb +3 -5
  64. data/test/commands_on_geo_test.rb +116 -0
  65. data/test/commands_on_hashes_test.rb +2 -16
  66. data/test/commands_on_hyper_log_log_test.rb +3 -17
  67. data/test/commands_on_lists_test.rb +2 -15
  68. data/test/commands_on_sets_test.rb +2 -72
  69. data/test/commands_on_sorted_sets_test.rb +2 -132
  70. data/test/commands_on_strings_test.rb +2 -96
  71. data/test/commands_on_value_types_test.rb +80 -6
  72. data/test/connection_handling_test.rb +5 -7
  73. data/test/distributed_blocking_commands_test.rb +10 -4
  74. data/test/distributed_commands_on_hashes_test.rb +16 -5
  75. data/test/distributed_commands_on_hyper_log_log_test.rb +8 -15
  76. data/test/distributed_commands_on_lists_test.rb +4 -7
  77. data/test/distributed_commands_on_sets_test.rb +58 -36
  78. data/test/distributed_commands_on_sorted_sets_test.rb +51 -10
  79. data/test/distributed_commands_on_strings_test.rb +30 -10
  80. data/test/distributed_commands_on_value_types_test.rb +38 -4
  81. data/test/distributed_commands_requiring_clustering_test.rb +1 -3
  82. data/test/distributed_connection_handling_test.rb +1 -3
  83. data/test/distributed_internals_test.rb +8 -19
  84. data/test/distributed_key_tags_test.rb +4 -6
  85. data/test/distributed_persistence_control_commands_test.rb +1 -3
  86. data/test/distributed_publish_subscribe_test.rb +1 -3
  87. data/test/distributed_remote_server_control_commands_test.rb +1 -3
  88. data/test/distributed_scripting_test.rb +1 -3
  89. data/test/distributed_sorting_test.rb +1 -3
  90. data/test/distributed_test.rb +12 -14
  91. data/test/distributed_transactions_test.rb +1 -3
  92. data/test/encoding_test.rb +4 -8
  93. data/test/error_replies_test.rb +2 -4
  94. data/test/fork_safety_test.rb +1 -6
  95. data/test/helper.rb +179 -66
  96. data/test/helper_test.rb +1 -3
  97. data/test/internals_test.rb +47 -56
  98. data/test/lint/blocking_commands.rb +40 -16
  99. data/test/lint/hashes.rb +41 -0
  100. data/test/lint/hyper_log_log.rb +15 -1
  101. data/test/lint/lists.rb +16 -0
  102. data/test/lint/sets.rb +142 -0
  103. data/test/lint/sorted_sets.rb +183 -2
  104. data/test/lint/strings.rb +108 -20
  105. data/test/lint/value_types.rb +8 -0
  106. data/test/persistence_control_commands_test.rb +1 -3
  107. data/test/pipelining_commands_test.rb +12 -8
  108. data/test/publish_subscribe_test.rb +1 -3
  109. data/test/remote_server_control_commands_test.rb +60 -3
  110. data/test/scanning_test.rb +1 -7
  111. data/test/scripting_test.rb +1 -3
  112. data/test/sentinel_command_test.rb +1 -3
  113. data/test/sentinel_test.rb +1 -3
  114. data/test/sorting_test.rb +1 -3
  115. data/test/ssl_test.rb +45 -49
  116. data/test/support/cluster/orchestrator.rb +199 -0
  117. data/test/support/connection/hiredis.rb +1 -1
  118. data/test/support/connection/ruby.rb +1 -1
  119. data/test/support/connection/synchrony.rb +1 -1
  120. data/test/support/redis_mock.rb +1 -1
  121. data/test/synchrony_driver.rb +6 -9
  122. data/test/thread_safety_test.rb +1 -3
  123. data/test/transactions_test.rb +11 -3
  124. data/test/unknown_commands_test.rb +1 -3
  125. data/test/url_param_test.rb +44 -46
  126. metadata +109 -16
  127. data/Rakefile +0 -87
data/test/lint/hashes.rb CHANGED
@@ -30,6 +30,21 @@ module Lint
30
30
  assert_equal nil, r.hget("foo", "f1")
31
31
  end
32
32
 
33
+ def test_splat_hdel
34
+ target_version "2.3.9" do
35
+ r.hset("foo", "f1", "s1")
36
+ r.hset("foo", "f2", "s2")
37
+
38
+ assert_equal "s1", r.hget("foo", "f1")
39
+ assert_equal "s2", r.hget("foo", "f2")
40
+
41
+ assert_equal 2, r.hdel("foo", "f1", "f2")
42
+
43
+ assert_equal nil, r.hget("foo", "f1")
44
+ assert_equal nil, r.hget("foo", "f2")
45
+ end
46
+ end
47
+
33
48
  def test_variadic_hdel
34
49
  target_version "2.3.9" do
35
50
  r.hset("foo", "f1", "s1")
@@ -129,6 +144,17 @@ module Lint
129
144
  assert({"f1" => "s1", "f2" => "s2"} == r.mapped_hmget("foo", "f1", "f2"))
130
145
  end
131
146
 
147
+ def test_mapped_hmget_in_a_pipeline_returns_hash
148
+ r.hset("foo", "f1", "s1")
149
+ r.hset("foo", "f2", "s2")
150
+
151
+ result = r.pipelined do
152
+ r.mapped_hmget("foo", "f1", "f2")
153
+ end
154
+
155
+ assert_equal result[0], { "f1" => "s1", "f2" => "s2" }
156
+ end
157
+
132
158
  def test_hincrby
133
159
  r.hincrby("foo", "f1", 1)
134
160
 
@@ -158,5 +184,20 @@ module Lint
158
184
  assert_equal "1.9", r.hget("foo", "f1")
159
185
  end
160
186
  end
187
+
188
+ def test_hstrlen
189
+ target_version('3.2.0') do
190
+ redis.hmset('foo', 'f1', 'HelloWorld', 'f2', 99, 'f3', -256)
191
+ assert_equal 10, r.hstrlen('foo', 'f1')
192
+ assert_equal 2, r.hstrlen('foo', 'f2')
193
+ assert_equal 4, r.hstrlen('foo', 'f3')
194
+ end
195
+ end
196
+
197
+ def test_hscan
198
+ redis.hmset('foo', 'f1', 'Jack', 'f2', 33)
199
+ expected = ['0', [%w[f1 Jack], %w[f2 33]]]
200
+ assert_equal expected, redis.hscan('foo', 0)
201
+ end
161
202
  end
162
203
  end
@@ -55,6 +55,20 @@ module Lint
55
55
  end
56
56
  end
57
57
 
58
- end
58
+ def test_pfmerge
59
+ target_version '2.8.9' do
60
+ r.pfadd 'foo', 's1'
61
+ r.pfadd 'bar', 's2'
62
+
63
+ assert_equal true, r.pfmerge('res', 'foo', 'bar')
64
+ assert_equal 2, r.pfcount('res')
65
+ end
66
+ end
59
67
 
68
+ def test_variadic_pfmerge_expanded
69
+ redis.pfadd('{1}foo', %w[foo bar zap a])
70
+ redis.pfadd('{1}bar', %w[a b c foo])
71
+ assert_equal true, redis.pfmerge('{1}baz', '{1}foo', '{1}bar')
72
+ end
73
+ end
60
74
  end
data/test/lint/lists.rb CHANGED
@@ -139,5 +139,21 @@ module Lint
139
139
  r.linsert "foo", :anywhere, "s3", "s2"
140
140
  end
141
141
  end
142
+
143
+ def test_rpoplpush
144
+ r.rpush 'foo', 's1'
145
+ r.rpush 'foo', 's2'
146
+
147
+ assert_equal 's2', r.rpoplpush('foo', 'bar')
148
+ assert_equal ['s2'], r.lrange('bar', 0, -1)
149
+ assert_equal 's1', r.rpoplpush('foo', 'bar')
150
+ assert_equal %w[s1 s2], r.lrange('bar', 0, -1)
151
+ end
152
+
153
+ def test_variadic_rpoplpush_expand
154
+ redis.rpush('{1}foo', %w[a b c])
155
+ redis.rpush('{1}bar', %w[d e f])
156
+ assert_equal 'c', redis.rpoplpush('{1}foo', '{1}bar')
157
+ end
142
158
  end
143
159
  end
data/test/lint/sets.rb CHANGED
@@ -136,5 +136,147 @@ module Lint
136
136
 
137
137
  assert_equal 4, r.scard("foo")
138
138
  end
139
+
140
+ def test_smove
141
+ r.sadd 'foo', 's1'
142
+ r.sadd 'bar', 's2'
143
+
144
+ assert r.smove('foo', 'bar', 's1')
145
+ assert r.sismember('bar', 's1')
146
+ end
147
+
148
+ def test_sinter
149
+ r.sadd 'foo', 's1'
150
+ r.sadd 'foo', 's2'
151
+ r.sadd 'bar', 's2'
152
+
153
+ assert_equal ['s2'], r.sinter('foo', 'bar')
154
+ end
155
+
156
+ def test_variadic_smove_expand
157
+ r.sadd('{1}foo', 's1')
158
+ r.sadd('{1}foo', 's2')
159
+ r.sadd('{1}foo', 's3')
160
+ r.sadd('{1}bar', 's3')
161
+ r.sadd('{1}bar', 's4')
162
+ r.sadd('{1}bar', 's5')
163
+ assert_equal true, r.smove('{1}foo', '{1}bar', 's2')
164
+ end
165
+
166
+ def test_variadic_sinter_expand
167
+ r.sadd('{1}foo', 's1')
168
+ r.sadd('{1}foo', 's2')
169
+ r.sadd('{1}foo', 's3')
170
+ r.sadd('{1}bar', 's3')
171
+ r.sadd('{1}bar', 's4')
172
+ r.sadd('{1}bar', 's5')
173
+ assert_equal %w[s3], r.sinter('{1}foo', '{1}bar')
174
+ end
175
+
176
+ def test_sinterstore
177
+ r.sadd 'foo', 's1'
178
+ r.sadd 'foo', 's2'
179
+ r.sadd 'bar', 's2'
180
+
181
+ r.sinterstore('baz', 'foo', 'bar')
182
+
183
+ assert_equal ['s2'], r.smembers('baz')
184
+ end
185
+
186
+ def test_variadic_sinterstore_expand
187
+ r.sadd('{1}foo', 's1')
188
+ r.sadd('{1}foo', 's2')
189
+ r.sadd('{1}foo', 's3')
190
+ r.sadd('{1}bar', 's3')
191
+ r.sadd('{1}bar', 's4')
192
+ r.sadd('{1}bar', 's5')
193
+ assert_equal 1, r.sinterstore('{1}baz', '{1}foo', '{1}bar')
194
+ end
195
+
196
+ def test_sunion
197
+ r.sadd 'foo', 's1'
198
+ r.sadd 'foo', 's2'
199
+ r.sadd 'bar', 's2'
200
+ r.sadd 'bar', 's3'
201
+
202
+ assert_equal %w[s1 s2 s3], r.sunion('foo', 'bar').sort
203
+ end
204
+
205
+ def test_variadic_sunion_expand
206
+ r.sadd('{1}foo', 's1')
207
+ r.sadd('{1}foo', 's2')
208
+ r.sadd('{1}foo', 's3')
209
+ r.sadd('{1}bar', 's3')
210
+ r.sadd('{1}bar', 's4')
211
+ r.sadd('{1}bar', 's5')
212
+ assert_equal %w[s1 s2 s3 s4 s5], r.sunion('{1}foo', '{1}bar').sort
213
+ end
214
+
215
+ def test_sunionstore
216
+ r.sadd 'foo', 's1'
217
+ r.sadd 'foo', 's2'
218
+ r.sadd 'bar', 's2'
219
+ r.sadd 'bar', 's3'
220
+
221
+ r.sunionstore('baz', 'foo', 'bar')
222
+
223
+ assert_equal %w[s1 s2 s3], r.smembers('baz').sort
224
+ end
225
+
226
+ def test_variadic_sunionstore_expand
227
+ r.sadd('{1}foo', 's1')
228
+ r.sadd('{1}foo', 's2')
229
+ r.sadd('{1}foo', 's3')
230
+ r.sadd('{1}bar', 's3')
231
+ r.sadd('{1}bar', 's4')
232
+ r.sadd('{1}bar', 's5')
233
+ assert_equal 5, r.sunionstore('{1}baz', '{1}foo', '{1}bar')
234
+ end
235
+
236
+ def test_sdiff
237
+ r.sadd 'foo', 's1'
238
+ r.sadd 'foo', 's2'
239
+ r.sadd 'bar', 's2'
240
+ r.sadd 'bar', 's3'
241
+
242
+ assert_equal ['s1'], r.sdiff('foo', 'bar')
243
+ assert_equal ['s3'], r.sdiff('bar', 'foo')
244
+ end
245
+
246
+ def test_variadic_sdiff_expand
247
+ r.sadd('{1}foo', 's1')
248
+ r.sadd('{1}foo', 's2')
249
+ r.sadd('{1}foo', 's3')
250
+ r.sadd('{1}bar', 's3')
251
+ r.sadd('{1}bar', 's4')
252
+ r.sadd('{1}bar', 's5')
253
+ assert_equal %w[s1 s2], r.sdiff('{1}foo', '{1}bar').sort
254
+ end
255
+
256
+ def test_sdiffstore
257
+ r.sadd 'foo', 's1'
258
+ r.sadd 'foo', 's2'
259
+ r.sadd 'bar', 's2'
260
+ r.sadd 'bar', 's3'
261
+
262
+ r.sdiffstore('baz', 'foo', 'bar')
263
+
264
+ assert_equal ['s1'], r.smembers('baz')
265
+ end
266
+
267
+ def test_variadic_sdiffstore_expand
268
+ r.sadd('{1}foo', 's1')
269
+ r.sadd('{1}foo', 's2')
270
+ r.sadd('{1}foo', 's3')
271
+ r.sadd('{1}bar', 's3')
272
+ r.sadd('{1}bar', 's4')
273
+ r.sadd('{1}bar', 's5')
274
+ assert_equal 2, r.sdiffstore('{1}baz', '{1}foo', '{1}bar')
275
+ end
276
+
277
+ def test_sscan
278
+ r.sadd('foo', %w[1 2 3 foo foobar feelsgood])
279
+ assert_equal %w[0 feelsgood foo foobar], r.sscan('foo', 0, match: 'f*').flatten.sort
280
+ end
139
281
  end
140
282
  end
@@ -41,7 +41,8 @@ module Lint
41
41
  assert_equal 11.0, r.zadd("foo", 10, "s1", :incr => true)
42
42
  assert_equal(-Infinity, r.zadd("bar", "-inf", "s1", :incr => true))
43
43
  assert_equal(+Infinity, r.zadd("bar", "+inf", "s2", :incr => true))
44
- r.del "foo", "bar"
44
+ r.del 'foo'
45
+ r.del 'bar'
45
46
 
46
47
  # Incompatible options combination
47
48
  assert_raise(Redis::CommandError) { r.zadd("foo", 1, "s1", :xx => true, :nx => true) }
@@ -104,7 +105,8 @@ module Lint
104
105
  assert_equal(-Infinity, r.zadd("bar", ["-inf", "s1"], :incr => true))
105
106
  assert_equal(+Infinity, r.zadd("bar", ["+inf", "s2"], :incr => true))
106
107
  assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1", 2, "s2"], :incr => true) }
107
- r.del "foo", "bar"
108
+ r.del 'foo'
109
+ r.del 'bar'
108
110
 
109
111
  # Incompatible options combination
110
112
  assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1"], :xx => true, :nx => true) }
@@ -312,5 +314,184 @@ module Lint
312
314
  assert_equal 3, r.zremrangebyscore("foo", 2, 4)
313
315
  assert_equal ["s1"], r.zrange("foo", 0, -1)
314
316
  end
317
+
318
+ def test_zpopmax
319
+ target_version('4.9.0') do
320
+ r.zadd('foo', %w[0 a 1 b 2 c])
321
+ assert_equal %w[c 2], r.zpopmax('foo')
322
+ end
323
+ end
324
+
325
+ def test_zpopmin
326
+ target_version('4.9.0') do
327
+ r.zadd('foo', %w[0 a 1 b 2 c])
328
+ assert_equal %w[a 0], r.zpopmin('foo')
329
+ end
330
+ end
331
+
332
+ def test_zremrangebylex
333
+ r.zadd('foo', %w[0 a 0 b 0 c 0 d 0 e 0 f 0 g])
334
+ assert_equal 5, r.zremrangebylex('foo', '(b', '[g')
335
+ end
336
+
337
+ def test_zlexcount
338
+ target_version '2.8.9' do
339
+ r.zadd 'foo', 0, 'aaren'
340
+ r.zadd 'foo', 0, 'abagael'
341
+ r.zadd 'foo', 0, 'abby'
342
+ r.zadd 'foo', 0, 'abbygail'
343
+
344
+ assert_equal 4, r.zlexcount('foo', '[a', "[a\xff")
345
+ assert_equal 4, r.zlexcount('foo', '[aa', "[ab\xff")
346
+ assert_equal 3, r.zlexcount('foo', '(aaren', "[ab\xff")
347
+ assert_equal 2, r.zlexcount('foo', '[aba', '(abbygail')
348
+ assert_equal 1, r.zlexcount('foo', '(aaren', '(abby')
349
+ end
350
+ end
351
+
352
+ def test_zrangebylex
353
+ target_version '2.8.9' do
354
+ r.zadd 'foo', 0, 'aaren'
355
+ r.zadd 'foo', 0, 'abagael'
356
+ r.zadd 'foo', 0, 'abby'
357
+ r.zadd 'foo', 0, 'abbygail'
358
+
359
+ assert_equal %w[aaren abagael abby abbygail], r.zrangebylex('foo', '[a', "[a\xff")
360
+ assert_equal %w[aaren abagael], r.zrangebylex('foo', '[a', "[a\xff", limit: [0, 2])
361
+ assert_equal %w[abby abbygail], r.zrangebylex('foo', '(abb', "(abb\xff")
362
+ assert_equal %w[abbygail], r.zrangebylex('foo', '(abby', "(abby\xff")
363
+ end
364
+ end
365
+
366
+ def test_zrevrangebylex
367
+ target_version '2.9.9' do
368
+ r.zadd 'foo', 0, 'aaren'
369
+ r.zadd 'foo', 0, 'abagael'
370
+ r.zadd 'foo', 0, 'abby'
371
+ r.zadd 'foo', 0, 'abbygail'
372
+
373
+ assert_equal %w[abbygail abby abagael aaren], r.zrevrangebylex('foo', "[a\xff", '[a')
374
+ assert_equal %w[abbygail abby], r.zrevrangebylex('foo', "[a\xff", '[a', limit: [0, 2])
375
+ assert_equal %w[abbygail abby], r.zrevrangebylex('foo', "(abb\xff", '(abb')
376
+ assert_equal %w[abbygail], r.zrevrangebylex('foo', "(abby\xff", '(abby')
377
+ end
378
+ end
379
+
380
+ def test_zcount
381
+ r.zadd 'foo', 1, 's1'
382
+ r.zadd 'foo', 2, 's2'
383
+ r.zadd 'foo', 3, 's3'
384
+
385
+ assert_equal 2, r.zcount('foo', 2, 3)
386
+ end
387
+
388
+ def test_zunionstore
389
+ r.zadd 'foo', 1, 's1'
390
+ r.zadd 'bar', 2, 's2'
391
+ r.zadd 'foo', 3, 's3'
392
+ r.zadd 'bar', 4, 's4'
393
+
394
+ assert_equal 4, r.zunionstore('foobar', %w[foo bar])
395
+ assert_equal %w[s1 s2 s3 s4], r.zrange('foobar', 0, -1)
396
+ end
397
+
398
+ def test_zunionstore_with_weights
399
+ r.zadd 'foo', 1, 's1'
400
+ r.zadd 'foo', 3, 's3'
401
+ r.zadd 'bar', 20, 's2'
402
+ r.zadd 'bar', 40, 's4'
403
+
404
+ assert_equal 4, r.zunionstore('foobar', %w[foo bar])
405
+ assert_equal %w[s1 s3 s2 s4], r.zrange('foobar', 0, -1)
406
+
407
+ assert_equal 4, r.zunionstore('foobar', %w[foo bar], weights: [10, 1])
408
+ assert_equal %w[s1 s2 s3 s4], r.zrange('foobar', 0, -1)
409
+ end
410
+
411
+ def test_zunionstore_with_aggregate
412
+ r.zadd 'foo', 1, 's1'
413
+ r.zadd 'foo', 2, 's2'
414
+ r.zadd 'bar', 4, 's2'
415
+ r.zadd 'bar', 3, 's3'
416
+
417
+ assert_equal 3, r.zunionstore('foobar', %w[foo bar])
418
+ assert_equal %w[s1 s3 s2], r.zrange('foobar', 0, -1)
419
+
420
+ assert_equal 3, r.zunionstore('foobar', %w[foo bar], aggregate: :min)
421
+ assert_equal %w[s1 s2 s3], r.zrange('foobar', 0, -1)
422
+
423
+ assert_equal 3, r.zunionstore('foobar', %w[foo bar], aggregate: :max)
424
+ assert_equal %w[s1 s3 s2], r.zrange('foobar', 0, -1)
425
+ end
426
+
427
+ def test_zunionstore_expand
428
+ r.zadd('{1}foo', %w[0 a 1 b 2 c])
429
+ r.zadd('{1}bar', %w[0 c 1 d 2 e])
430
+ assert_equal 5, r.zunionstore('{1}baz', %w[{1}foo {1}bar])
431
+ end
432
+
433
+ def test_zinterstore
434
+ r.zadd 'foo', 1, 's1'
435
+ r.zadd 'bar', 2, 's1'
436
+ r.zadd 'foo', 3, 's3'
437
+ r.zadd 'bar', 4, 's4'
438
+
439
+ assert_equal 1, r.zinterstore('foobar', %w[foo bar])
440
+ assert_equal ['s1'], r.zrange('foobar', 0, -1)
441
+ end
442
+
443
+ def test_zinterstore_with_weights
444
+ r.zadd 'foo', 1, 's1'
445
+ r.zadd 'foo', 2, 's2'
446
+ r.zadd 'foo', 3, 's3'
447
+ r.zadd 'bar', 20, 's2'
448
+ r.zadd 'bar', 30, 's3'
449
+ r.zadd 'bar', 40, 's4'
450
+
451
+ assert_equal 2, r.zinterstore('foobar', %w[foo bar])
452
+ assert_equal %w[s2 s3], r.zrange('foobar', 0, -1)
453
+
454
+ assert_equal 2, r.zinterstore('foobar', %w[foo bar], weights: [10, 1])
455
+ assert_equal %w[s2 s3], r.zrange('foobar', 0, -1)
456
+
457
+ assert_equal 40.0, r.zscore('foobar', 's2')
458
+ assert_equal 60.0, r.zscore('foobar', 's3')
459
+ end
460
+
461
+ def test_zinterstore_with_aggregate
462
+ r.zadd 'foo', 1, 's1'
463
+ r.zadd 'foo', 2, 's2'
464
+ r.zadd 'foo', 3, 's3'
465
+ r.zadd 'bar', 20, 's2'
466
+ r.zadd 'bar', 30, 's3'
467
+ r.zadd 'bar', 40, 's4'
468
+
469
+ assert_equal 2, r.zinterstore('foobar', %w[foo bar])
470
+ assert_equal %w[s2 s3], r.zrange('foobar', 0, -1)
471
+ assert_equal 22.0, r.zscore('foobar', 's2')
472
+ assert_equal 33.0, r.zscore('foobar', 's3')
473
+
474
+ assert_equal 2, r.zinterstore('foobar', %w[foo bar], aggregate: :min)
475
+ assert_equal %w[s2 s3], r.zrange('foobar', 0, -1)
476
+ assert_equal 2.0, r.zscore('foobar', 's2')
477
+ assert_equal 3.0, r.zscore('foobar', 's3')
478
+
479
+ assert_equal 2, r.zinterstore('foobar', %w[foo bar], aggregate: :max)
480
+ assert_equal %w[s2 s3], r.zrange('foobar', 0, -1)
481
+ assert_equal 20.0, r.zscore('foobar', 's2')
482
+ assert_equal 30.0, r.zscore('foobar', 's3')
483
+ end
484
+
485
+ def test_zinterstore_expand
486
+ r.zadd '{1}foo', %w[0 s1 1 s2 2 s3]
487
+ r.zadd '{1}bar', %w[0 s3 1 s4 2 s5]
488
+ assert_equal 1, r.zinterstore('{1}baz', %w[{1}foo {1}bar], weights: [2.0, 3.0])
489
+ end
490
+
491
+ def test_zscan
492
+ r.zadd('foo', %w[0 a 1 b 2 c])
493
+ expected = ['0', [['a', 0.0], ['b', 1.0], ['c', 2.0]]]
494
+ assert_equal expected, r.zscan('foo', 0)
495
+ end
315
496
  end
316
497
  end
data/test/lint/strings.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  module Lint
2
2
 
3
3
  module Strings
4
+ def mock(*args, &block)
5
+ redis_mock(*args, &block)
6
+ end
4
7
 
5
8
  def test_set_and_get
6
9
  r.set("foo", "s1")
@@ -8,18 +11,6 @@ module Lint
8
11
  assert_equal "s1", r.get("foo")
9
12
  end
10
13
 
11
- def test_set_and_get_with_brackets
12
- r["foo"] = "s1"
13
-
14
- assert_equal "s1", r["foo"]
15
- end
16
-
17
- def test_set_and_get_with_brackets_and_symbol
18
- r[:foo] = "s1"
19
-
20
- assert_equal "s1", r[:foo]
21
- end
22
-
23
14
  def test_set_and_get_with_newline_characters
24
15
  r.set("foo", "1\n")
25
16
 
@@ -35,14 +26,12 @@ module Lint
35
26
  end
36
27
 
37
28
  def test_set_and_get_with_ascii_characters
38
- if defined?(Encoding)
39
- with_external_encoding("ASCII-8BIT") do
40
- (0..255).each do |i|
41
- str = "#{i.chr}---#{i.chr}"
42
- r.set("foo", str)
43
-
44
- assert_equal str, r.get("foo")
45
- end
29
+ with_external_encoding("ASCII-8BIT") do
30
+ (0..255).each do |i|
31
+ str = "#{i.chr}---#{i.chr}"
32
+ r.set("foo", str)
33
+
34
+ assert_equal str, r.get("foo")
46
35
  end
47
36
  end
48
37
  end
@@ -256,5 +245,104 @@ module Lint
256
245
 
257
246
  assert_equal 5, r.strlen("foo")
258
247
  end
248
+
249
+ def test_bitfield
250
+ target_version('3.2.0') do
251
+ mock(bitfield: ->(*_) { "*2\r\n:1\r\n:0\r\n" }) do |redis|
252
+ assert_equal [1, 0], redis.bitfield('foo', 'INCRBY', 'i5', 100, 1, 'GET', 'u4', 0)
253
+ end
254
+ end
255
+ end
256
+
257
+ def test_mget
258
+ r.set('{1}foo', 's1')
259
+ r.set('{1}bar', 's2')
260
+
261
+ assert_equal %w[s1 s2], r.mget('{1}foo', '{1}bar')
262
+ assert_equal ['s1', 's2', nil], r.mget('{1}foo', '{1}bar', '{1}baz')
263
+ end
264
+
265
+ def test_mget_mapped
266
+ r.set('{1}foo', 's1')
267
+ r.set('{1}bar', 's2')
268
+
269
+ response = r.mapped_mget('{1}foo', '{1}bar')
270
+
271
+ assert_equal 's1', response['{1}foo']
272
+ assert_equal 's2', response['{1}bar']
273
+
274
+ response = r.mapped_mget('{1}foo', '{1}bar', '{1}baz')
275
+
276
+ assert_equal 's1', response['{1}foo']
277
+ assert_equal 's2', response['{1}bar']
278
+ assert_equal nil, response['{1}baz']
279
+ end
280
+
281
+ def test_mapped_mget_in_a_pipeline_returns_hash
282
+ r.set('{1}foo', 's1')
283
+ r.set('{1}bar', 's2')
284
+
285
+ result = r.pipelined do
286
+ r.mapped_mget('{1}foo', '{1}bar')
287
+ end
288
+
289
+ assert_equal({ '{1}foo' => 's1', '{1}bar' => 's2' }, result[0])
290
+ end
291
+
292
+ def test_mset
293
+ r.mset('{1}foo', 's1', '{1}bar', 's2')
294
+
295
+ assert_equal 's1', r.get('{1}foo')
296
+ assert_equal 's2', r.get('{1}bar')
297
+ end
298
+
299
+ def test_mset_mapped
300
+ r.mapped_mset('{1}foo' => 's1', '{1}bar' => 's2')
301
+
302
+ assert_equal 's1', r.get('{1}foo')
303
+ assert_equal 's2', r.get('{1}bar')
304
+ end
305
+
306
+ def test_msetnx
307
+ r.set('{1}foo', 's1')
308
+ assert_equal false, r.msetnx('{1}foo', 's2', '{1}bar', 's3')
309
+ assert_equal 's1', r.get('{1}foo')
310
+ assert_equal nil, r.get('{1}bar')
311
+
312
+ r.del('{1}foo')
313
+ assert_equal true, r.msetnx('{1}foo', 's2', '{1}bar', 's3')
314
+ assert_equal 's2', r.get('{1}foo')
315
+ assert_equal 's3', r.get('{1}bar')
316
+ end
317
+
318
+ def test_msetnx_mapped
319
+ r.set('{1}foo', 's1')
320
+ assert_equal false, r.mapped_msetnx('{1}foo' => 's2', '{1}bar' => 's3')
321
+ assert_equal 's1', r.get('{1}foo')
322
+ assert_equal nil, r.get('{1}bar')
323
+
324
+ r.del('{1}foo')
325
+ assert_equal true, r.mapped_msetnx('{1}foo' => 's2', '{1}bar' => 's3')
326
+ assert_equal 's2', r.get('{1}foo')
327
+ assert_equal 's3', r.get('{1}bar')
328
+ end
329
+
330
+ def test_bitop
331
+ with_external_encoding('UTF-8') do
332
+ target_version '2.5.10' do
333
+ r.set('foo{1}', 'a')
334
+ r.set('bar{1}', 'b')
335
+
336
+ r.bitop(:and, 'foo&bar{1}', 'foo{1}', 'bar{1}')
337
+ assert_equal "\x60", r.get('foo&bar{1}')
338
+ r.bitop(:or, 'foo|bar{1}', 'foo{1}', 'bar{1}')
339
+ assert_equal "\x63", r.get('foo|bar{1}')
340
+ r.bitop(:xor, 'foo^bar{1}', 'foo{1}', 'bar{1}')
341
+ assert_equal "\x03", r.get('foo^bar{1}')
342
+ r.bitop(:not, '~foo{1}', 'foo{1}')
343
+ assert_equal "\x9E", r.get('~foo{1}')
344
+ end
345
+ end
346
+ end
259
347
  end
260
348
  end
@@ -93,6 +93,14 @@ module Lint
93
93
  assert r.restore("bar", 1000, w)
94
94
  assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1)
95
95
  assert [0, 1].include? r.ttl("bar")
96
+
97
+ r.set("bar", "somethingelse")
98
+ assert_raises(Redis::CommandError) { r.restore("bar", 1000, w) } # ensure by default replace is false
99
+ assert_raises(Redis::CommandError) { r.restore("bar", 1000, w, :replace => false) }
100
+ assert_equal "somethingelse", r.get("bar")
101
+ assert r.restore("bar", 1000, w, :replace => true)
102
+ assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1)
103
+ assert [0, 1].include? r.ttl("bar")
96
104
  end
97
105
  end
98
106
 
@@ -1,6 +1,4 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
1
+ require_relative "helper"
4
2
 
5
3
  class TestPersistenceControlCommands < Test::Unit::TestCase
6
4
 
@@ -1,6 +1,4 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
1
+ require_relative "helper"
4
2
 
5
3
  class TestPipeliningCommands < Test::Unit::TestCase
6
4
 
@@ -130,15 +128,21 @@ class TestPipeliningCommands < Test::Unit::TestCase
130
128
  end
131
129
  end
132
130
 
131
+ def test_futures_raise_when_command_errors_and_needs_transformation
132
+ assert_raise(Redis::CommandError) do
133
+ r.pipelined do
134
+ @result = r.zrange("a", "b", 5, :with_scores => true)
135
+ end
136
+ end
137
+ end
138
+
133
139
  def test_futures_can_be_identified
134
140
  r.pipelined do
135
141
  @result = r.sadd("foo", 1)
136
142
  end
137
143
 
138
144
  assert_equal true, @result.is_a?(Redis::Future)
139
- if defined?(::BasicObject)
140
- assert_equal true, @result.is_a?(::BasicObject)
141
- end
145
+ assert_equal true, @result.is_a?(::BasicObject)
142
146
  assert_equal Redis::Future, @result.class
143
147
  end
144
148
 
@@ -225,7 +229,7 @@ class TestPipeliningCommands < Test::Unit::TestCase
225
229
  p2.select 2
226
230
  end
227
231
 
228
- assert_equal 2, r.client.db
232
+ assert_equal 2, r._client.db
229
233
  end
230
234
 
231
235
  def test_nested_pipeline_select_client_db
@@ -237,6 +241,6 @@ class TestPipeliningCommands < Test::Unit::TestCase
237
241
  end
238
242
  end
239
243
 
240
- assert_equal 3, r.client.db
244
+ assert_equal 3, r._client.db
241
245
  end
242
246
  end