redis 3.3.5 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
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