kuende-fakeredis 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +19 -0
  4. data/Gemfile +13 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE +21 -0
  7. data/README.md +102 -0
  8. data/Rakefile +27 -0
  9. data/fakeredis.gemspec +24 -0
  10. data/gemfiles/redisrb-master.gemfile +14 -0
  11. data/lib/fake_redis.rb +1 -0
  12. data/lib/fakeredis.rb +6 -0
  13. data/lib/fakeredis/bitop_command.rb +56 -0
  14. data/lib/fakeredis/command_executor.rb +25 -0
  15. data/lib/fakeredis/expiring_hash.rb +70 -0
  16. data/lib/fakeredis/minitest.rb +24 -0
  17. data/lib/fakeredis/rspec.rb +24 -0
  18. data/lib/fakeredis/sort_method.rb +117 -0
  19. data/lib/fakeredis/sorted_set_argument_handler.rb +74 -0
  20. data/lib/fakeredis/sorted_set_store.rb +80 -0
  21. data/lib/fakeredis/transaction_commands.rb +83 -0
  22. data/lib/fakeredis/version.rb +3 -0
  23. data/lib/fakeredis/zset.rb +39 -0
  24. data/lib/redis/connection/memory.rb +1375 -0
  25. data/spec/bitop_command_spec.rb +209 -0
  26. data/spec/compatibility_spec.rb +9 -0
  27. data/spec/connection_spec.rb +85 -0
  28. data/spec/hashes_spec.rb +261 -0
  29. data/spec/keys_spec.rb +488 -0
  30. data/spec/lists_spec.rb +229 -0
  31. data/spec/memory_spec.rb +28 -0
  32. data/spec/server_spec.rb +100 -0
  33. data/spec/sets_spec.rb +280 -0
  34. data/spec/sort_method_spec.rb +74 -0
  35. data/spec/sorted_sets_spec.rb +578 -0
  36. data/spec/spec_helper.rb +29 -0
  37. data/spec/spec_helper_live_redis.rb +14 -0
  38. data/spec/strings_spec.rb +289 -0
  39. data/spec/subscription_spec.rb +107 -0
  40. data/spec/support/shared_examples/bitwise_operation.rb +59 -0
  41. data/spec/support/shared_examples/sortable.rb +69 -0
  42. data/spec/transactions_spec.rb +92 -0
  43. data/spec/upcase_method_name_spec.rb +18 -0
  44. metadata +148 -0
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ module FakeRedis
4
+ describe "#sort" do
5
+ before(:each) do
6
+ @client = Redis.new
7
+
8
+ @client.set('fake-redis-test:values_1', 'a')
9
+ @client.set('fake-redis-test:values_2', 'b')
10
+
11
+ @client.set('fake-redis-test:weight_1', '2')
12
+ @client.set('fake-redis-test:weight_2', '1')
13
+
14
+ @client.hset('fake-redis-test:hash_1', 'key', 'x')
15
+ @client.hset('fake-redis-test:hash_2', 'key', 'y')
16
+ end
17
+
18
+ context "WRONGTYPE Operation" do
19
+ it "should not allow #sort on Strings" do
20
+ @client.set("key1", "Hello")
21
+ expect {
22
+ @client.sort("key1")
23
+ }.to raise_error(Redis::CommandError)
24
+ end
25
+
26
+ it "should not allow #sort on Hashes" do
27
+ @client.hset("key1", "k1", "val1")
28
+ @client.hset("key1", "k2", "val2")
29
+ expect {
30
+ @client.sort("key1")
31
+ }.to raise_error(Redis::CommandError)
32
+ end
33
+ end
34
+
35
+ context "none" do
36
+ it "should return empty array" do
37
+ expect(@client.sort("key")).to eq []
38
+ end
39
+ end
40
+
41
+ context "list" do
42
+ before do
43
+ @key = "fake-redis-test:list_sort"
44
+
45
+ @client.rpush(@key, '1')
46
+ @client.rpush(@key, '2')
47
+ end
48
+
49
+ it_should_behave_like "a sortable"
50
+ end
51
+
52
+ context "set" do
53
+ before do
54
+ @key = "fake-redis-test:set_sort"
55
+
56
+ @client.sadd(@key, '1')
57
+ @client.sadd(@key, '2')
58
+ end
59
+
60
+ it_should_behave_like "a sortable"
61
+ end
62
+
63
+ context "zset" do
64
+ before do
65
+ @key = "fake-redis-test:zset_sort"
66
+
67
+ @client.zadd(@key, 100, '1')
68
+ @client.zadd(@key, 99, '2')
69
+ end
70
+
71
+ it_should_behave_like "a sortable"
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,578 @@
1
+ require 'spec_helper'
2
+
3
+ module FakeRedis
4
+ Infinity = 1.0/0.0
5
+
6
+ describe "SortedSetsMethods" do
7
+ before(:each) do
8
+ @client = Redis.new
9
+ end
10
+
11
+ it "should add a member to a sorted set, or update its score if it already exists" do
12
+ expect(@client.zadd("key", 1, "val")).to be(true)
13
+ expect(@client.zscore("key", "val")).to eq(1.0)
14
+
15
+ expect(@client.zadd("key", 2, "val")).to be(false)
16
+ expect(@client.zscore("key", "val")).to eq(2.0)
17
+
18
+ # These assertions only work in redis-rb v3.0.2 or higher
19
+ expect(@client.zadd("key2", "inf", "val")).to eq(true)
20
+ expect(@client.zscore("key2", "val")).to eq(Infinity)
21
+
22
+ expect(@client.zadd("key3", "+inf", "val")).to eq(true)
23
+ expect(@client.zscore("key3", "val")).to eq(Infinity)
24
+
25
+ expect(@client.zadd("key4", "-inf", "val")).to eq(true)
26
+ expect(@client.zscore("key4", "val")).to eq(-Infinity)
27
+ end
28
+
29
+ it "should return a nil score for value not in a sorted set or empty key" do
30
+ @client.zadd "key", 1, "val"
31
+
32
+ expect(@client.zscore("key", "val")).to eq(1.0)
33
+ expect(@client.zscore("key", "val2")).to be_nil
34
+ expect(@client.zscore("key2", "val")).to be_nil
35
+ end
36
+
37
+ it "should add multiple members to a sorted set, or update its score if it already exists" do
38
+ expect(@client.zadd("key", [1, "val", 2, "val2"])).to eq(2)
39
+ expect(@client.zscore("key", "val")).to eq(1)
40
+ expect(@client.zscore("key", "val2")).to eq(2)
41
+
42
+ expect(@client.zadd("key", [[5, "val"], [3, "val3"], [4, "val4"]])).to eq(2)
43
+ expect(@client.zscore("key", "val")).to eq(5)
44
+ expect(@client.zscore("key", "val2")).to eq(2)
45
+ expect(@client.zscore("key", "val3")).to eq(3)
46
+ expect(@client.zscore("key", "val4")).to eq(4)
47
+
48
+ expect(@client.zadd("key", [[5, "val5"], [3, "val6"]])).to eq(2)
49
+ expect(@client.zscore("key", "val5")).to eq(5)
50
+ expect(@client.zscore("key", "val6")).to eq(3)
51
+ end
52
+
53
+ it "should error with wrong number of arguments when adding members" do
54
+ expect { @client.zadd("key") }.to raise_error(ArgumentError, "wrong number of arguments")
55
+ expect { @client.zadd("key", 1) }.to raise_error(ArgumentError, "wrong number of arguments")
56
+ expect { @client.zadd("key", [1]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'zadd' command")
57
+ expect { @client.zadd("key", [1, "val", 2]) }.to raise_error(Redis::CommandError, "ERR syntax error")
58
+ expect { @client.zadd("key", [[1, "val"], [2]]) }.to raise_error(Redis::CommandError, "ERR syntax error")
59
+ end
60
+
61
+ it "should allow floats as scores when adding or updating" do
62
+ expect(@client.zadd("key", 4.321, "val")).to be(true)
63
+ expect(@client.zscore("key", "val")).to eq(4.321)
64
+
65
+ expect(@client.zadd("key", 54.3210, "val")).to be(false)
66
+ expect(@client.zscore("key", "val")).to eq(54.321)
67
+ end
68
+
69
+ it "should allow strings that can be parsed as float when adding or updating" do
70
+ expect(@client.zadd("key", "4.321", "val")).to be(true)
71
+ expect(@client.zscore("key", "val")).to eq(4.321)
72
+
73
+ expect(@client.zadd("key", "54.3210", "val")).to be(false)
74
+ expect(@client.zscore("key", "val")).to eq(54.321)
75
+ end
76
+
77
+ it "should error when the score is not a valid float" do
78
+ expect { @client.zadd("key", "score", "val") }.to raise_error(Redis::CommandError, "ERR value is not a valid float")
79
+ expect { @client.zadd("key", {}, "val") }.to raise_error(Redis::CommandError, "ERR value is not a valid float")
80
+ expect { @client.zadd("key", Time.now, "val") }.to raise_error(Redis::CommandError, "ERR value is not a valid float")
81
+ end
82
+
83
+ it "should remove members from sorted sets" do
84
+ expect(@client.zrem("key", "val")).to be(false)
85
+ expect(@client.zadd("key", 1, "val")).to be(true)
86
+ expect(@client.zrem("key", "val")).to be(true)
87
+ end
88
+
89
+ it "should remove multiple members from sorted sets" do
90
+ expect(@client.zrem("key2", %w(val))).to eq(0)
91
+ expect(@client.zrem("key2", %w(val val2 val3))).to eq(0)
92
+
93
+ @client.zadd("key2", 1, "val")
94
+ @client.zadd("key2", 1, "val2")
95
+ @client.zadd("key2", 1, "val3")
96
+
97
+ expect(@client.zrem("key2", %w(val val2 val3 val4))).to eq(3)
98
+ end
99
+
100
+ it "should remove sorted set's key when it is empty" do
101
+ @client.zadd("key", 1, "val")
102
+ @client.zrem("key", "val")
103
+ expect(@client.exists("key")).to eq(false)
104
+ end
105
+
106
+ it "should get the number of members in a sorted set" do
107
+ @client.zadd("key", 1, "val2")
108
+ @client.zadd("key", 2, "val1")
109
+ @client.zadd("key", 5, "val3")
110
+
111
+ expect(@client.zcard("key")).to eq(3)
112
+ end
113
+
114
+ it "should count the members in a sorted set with scores within the given values" do
115
+ @client.zadd("key", 1, "val1")
116
+ @client.zadd("key", 2, "val2")
117
+ @client.zadd("key", 3, "val3")
118
+
119
+ expect(@client.zcount("key", 2, 3)).to eq(2)
120
+ end
121
+
122
+ it "should increment the score of a member in a sorted set" do
123
+ @client.zadd("key", 1, "val1")
124
+ expect(@client.zincrby("key", 2, "val1")).to eq(3)
125
+ expect(@client.zscore("key", "val1")).to eq(3)
126
+ end
127
+
128
+ it "initializes the sorted set if the key wasnt already set" do
129
+ expect(@client.zincrby("key", 1, "val1")).to eq(1)
130
+ end
131
+
132
+ it "should convert the key to a string for zscore" do
133
+ @client.zadd("key", 1, 1)
134
+ expect(@client.zscore("key", 1)).to eq(1)
135
+ end
136
+
137
+ # These won't pass until redis-rb releases v3.0.2
138
+ it "should handle infinity values when incrementing a sorted set key" do
139
+ expect(@client.zincrby("bar", "+inf", "s2")).to eq(Infinity)
140
+ expect(@client.zincrby("bar", "-inf", "s1")).to eq(-Infinity)
141
+ end
142
+
143
+ it "should return a range of members in a sorted set, by index" do
144
+ @client.zadd("key", 1, "one")
145
+ @client.zadd("key", 2, "two")
146
+ @client.zadd("key", 3, "three")
147
+
148
+ expect(@client.zrange("key", 0, -1)).to eq(["one", "two", "three"])
149
+ expect(@client.zrange("key", 1, 2)).to eq(["two", "three"])
150
+ expect(@client.zrange("key", 0, -1, :withscores => true)).to eq([["one", 1], ["two", 2], ["three", 3]])
151
+ expect(@client.zrange("key", 1, 2, :with_scores => true)).to eq([["two", 2], ["three", 3]])
152
+ end
153
+
154
+ it "should sort zrange results logically" do
155
+ @client.zadd("key", 5, "val2")
156
+ @client.zadd("key", 5, "val3")
157
+ @client.zadd("key", 5, "val1")
158
+
159
+ expect(@client.zrange("key", 0, -1)).to eq(%w(val1 val2 val3))
160
+ expect(@client.zrange("key", 0, -1, :with_scores => true)).to eq([["val1", 5], ["val2", 5], ["val3", 5]])
161
+ end
162
+
163
+ it "should return a reversed range of members in a sorted set, by index" do
164
+ @client.zadd("key", 1, "one")
165
+ @client.zadd("key", 2, "two")
166
+ @client.zadd("key", 3, "three")
167
+
168
+ expect(@client.zrevrange("key", 0, -1)).to eq(["three", "two", "one"])
169
+ expect(@client.zrevrange("key", 1, 2)).to eq(["two", "one"])
170
+ expect(@client.zrevrange("key", 0, -1, :withscores => true)).to eq([["three", 3], ["two", 2], ["one", 1]])
171
+ expect(@client.zrevrange("key", 0, -1, :with_scores => true)).to eq([["three", 3], ["two", 2], ["one", 1]])
172
+ end
173
+
174
+ it "should return a range of members in a sorted set, by score" do
175
+ @client.zadd("key", 1, "one")
176
+ @client.zadd("key", 2, "two")
177
+ @client.zadd("key", 3, "three")
178
+
179
+ expect(@client.zrangebyscore("key", 0, 100)).to eq(["one", "two", "three"])
180
+ expect(@client.zrangebyscore("key", 1, 2)).to eq(["one", "two"])
181
+ expect(@client.zrangebyscore("key", 1, '(2')).to eq(['one'])
182
+ expect(@client.zrangebyscore("key", '(1', 2)).to eq(['two'])
183
+ expect(@client.zrangebyscore("key", '(1', '(2')).to eq([])
184
+ expect(@client.zrangebyscore("key", 0, 100, :withscores => true)).to eq([["one", 1], ["two", 2], ["three", 3]])
185
+ expect(@client.zrangebyscore("key", 1, 2, :with_scores => true)).to eq([["one", 1], ["two", 2]])
186
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [0, 1])).to eq(["one"])
187
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [0, -1])).to eq(["one", "two", "three"])
188
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [1, -1], :with_scores => true)).to eq([["two", 2], ["three", 3]])
189
+ expect(@client.zrangebyscore("key", '-inf', '+inf')).to eq(["one", "two", "three"])
190
+ expect(@client.zrangebyscore("key", 2, '+inf')).to eq(["two", "three"])
191
+ expect(@client.zrangebyscore("key", '-inf', 2)).to eq(['one', "two"])
192
+
193
+ expect(@client.zrangebyscore("badkey", 1, 2)).to eq([])
194
+ end
195
+
196
+ it "should return a reversed range of members in a sorted set, by score" do
197
+ @client.zadd("key", 1, "one")
198
+ @client.zadd("key", 2, "two")
199
+ @client.zadd("key", 3, "three")
200
+
201
+ expect(@client.zrevrangebyscore("key", 100, 0)).to eq(["three", "two", "one"])
202
+ expect(@client.zrevrangebyscore("key", 2, 1)).to eq(["two", "one"])
203
+ expect(@client.zrevrangebyscore("key", 1, 2)).to eq([])
204
+ expect(@client.zrevrangebyscore("key", 2, 1, :with_scores => true)).to eq([["two", 2.0], ["one", 1.0]])
205
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [0, 1])).to eq(["three"])
206
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [0, -1])).to eq(["three", "two", "one"])
207
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [1, -1], :with_scores => true)).to eq([["two", 2.0], ["one", 1.0]])
208
+ end
209
+
210
+ it "should determine the index of a member in a sorted set" do
211
+ @client.zadd("key", 1, "one")
212
+ @client.zadd("key", 2, "two")
213
+ @client.zadd("key", 3, "three")
214
+
215
+ expect(@client.zrank("key", "three")).to eq(2)
216
+ expect(@client.zrank("key", "four")).to be_nil
217
+ end
218
+
219
+ it "should determine the reversed index of a member in a sorted set" do
220
+ @client.zadd("key", 1, "one")
221
+ @client.zadd("key", 2, "two")
222
+ @client.zadd("key", 3, "three")
223
+
224
+ expect(@client.zrevrank("key", "three")).to eq(0)
225
+ expect(@client.zrevrank("key", "four")).to be_nil
226
+ end
227
+
228
+ it "should not raise errors for zrank() on accessing a non-existing key in a sorted set" do
229
+ expect(@client.zrank("no_such_key", "no_suck_id")).to be_nil
230
+ end
231
+
232
+ it "should not raise errors for zrevrank() on accessing a non-existing key in a sorted set" do
233
+ expect(@client.zrevrank("no_such_key", "no_suck_id")).to be_nil
234
+ end
235
+
236
+ describe "#zinterstore" do
237
+ before do
238
+ @client.zadd("key1", 1, "one")
239
+ @client.zadd("key1", 2, "two")
240
+ @client.zadd("key1", 3, "three")
241
+ @client.zadd("key2", 5, "two")
242
+ @client.zadd("key2", 7, "three")
243
+ @client.sadd("key3", 'one')
244
+ @client.sadd("key3", 'two')
245
+ end
246
+
247
+ it "should intersect two keys with custom scores" do
248
+ expect(@client.zinterstore("out", ["key1", "key2"])).to eq(2)
249
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['two', (2 + 5)], ['three', (3 + 7)]])
250
+ end
251
+
252
+ it "should intersect two keys with a default score" do
253
+ expect(@client.zinterstore("out", ["key1", "key3"])).to eq(2)
254
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['one', (1 + 1)], ['two', (2 + 1)]])
255
+ end
256
+
257
+ it "should intersect more than two keys" do
258
+ expect(@client.zinterstore("out", ["key1", "key2", "key3"])).to eq(1)
259
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['two', (2 + 5 + 1)]])
260
+ end
261
+
262
+ it "should not intersect an unknown key" do
263
+ expect(@client.zinterstore("out", ["key1", "no_key"])).to eq(0)
264
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([])
265
+ end
266
+
267
+ it "should intersect two keys by minimum values" do
268
+ expect(@client.zinterstore("out", ["key1", "key2"], :aggregate => :min)).to eq(2)
269
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 2], ["three", 3]])
270
+ end
271
+
272
+ it "should intersect two keys by maximum values" do
273
+ expect(@client.zinterstore("out", ["key1", "key2"], :aggregate => :max)).to eq(2)
274
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 5], ["three", 7]])
275
+ end
276
+
277
+ it "should intersect two keys by explicitly summing values" do
278
+ expect(@client.zinterstore("out", %w(key1 key2), :aggregate => :sum)).to eq(2)
279
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 + 5)], ["three", (3 + 7)]])
280
+ end
281
+
282
+ it "should intersect two keys with weighted values" do
283
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1])).to eq(2)
284
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 * 10 + 5)], ["three", (3 * 10 + 7)]])
285
+ end
286
+
287
+ it "should intersect two keys with weighted minimum values" do
288
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min)).to eq(2)
289
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 5], ["three", 7]])
290
+ end
291
+
292
+ it "should intersect two keys with weighted maximum values" do
293
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max)).to eq(2)
294
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 * 10)], ["three", (3 * 10)]])
295
+ end
296
+
297
+ it "should error without enough weights given" do
298
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => []) }.to raise_error(Redis::CommandError, "ERR syntax error")
299
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => [10]) }.to raise_error(Redis::CommandError, "ERR syntax error")
300
+ end
301
+
302
+ it "should error with too many weights given" do
303
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.to raise_error(Redis::CommandError, "ERR syntax error")
304
+ end
305
+
306
+ it "should error with an invalid aggregate" do
307
+ expect { @client.zinterstore("out", %w(key1 key2), :aggregate => :invalid) }.to raise_error(Redis::CommandError, "ERR syntax error")
308
+ end
309
+ end
310
+
311
+ context "zremrangebyscore" do
312
+ it "should remove items by score" do
313
+ @client.zadd("key", 1, "one")
314
+ @client.zadd("key", 2, "two")
315
+ @client.zadd("key", 3, "three")
316
+
317
+ expect(@client.zremrangebyscore("key", 0, 2)).to eq(2)
318
+ expect(@client.zcard("key")).to eq(1)
319
+ end
320
+
321
+ it "should remove items by score with infinity" do # Issue #50
322
+ @client.zadd("key", 10.0, "one")
323
+ @client.zadd("key", 20.0, "two")
324
+ @client.zadd("key", 30.0, "three")
325
+ expect(@client.zremrangebyscore("key", "-inf", "+inf")).to eq(3)
326
+ expect(@client.zcard("key")).to eq(0)
327
+ expect(@client.zscore("key", "one")).to be_nil
328
+ expect(@client.zscore("key", "two")).to be_nil
329
+ expect(@client.zscore("key", "three")).to be_nil
330
+ end
331
+
332
+ it "should return 0 if the key didn't exist" do
333
+ expect(@client.zremrangebyscore("key", 0, 2)).to eq(0)
334
+ end
335
+ end
336
+
337
+ context '#zremrangebyrank' do
338
+ it 'removes all elements with in the given range' do
339
+ @client.zadd("key", 1, "one")
340
+ @client.zadd("key", 2, "two")
341
+ @client.zadd("key", 3, "three")
342
+
343
+ expect(@client.zremrangebyrank("key", 0, 1)).to eq(2)
344
+ expect(@client.zcard('key')).to eq(1)
345
+ end
346
+
347
+ it 'handles out of range requests' do
348
+ @client.zadd("key", 1, "one")
349
+ @client.zadd("key", 2, "two")
350
+ @client.zadd("key", 3, "three")
351
+
352
+ expect(@client.zremrangebyrank("key", 25, -1)).to eq(0)
353
+ expect(@client.zcard('key')).to eq(3)
354
+ end
355
+
356
+ it "should return 0 if the key didn't exist" do
357
+ expect(@client.zremrangebyrank("key", 0, 1)).to eq(0)
358
+ end
359
+ end
360
+
361
+ describe "#zunionstore" do
362
+ before do
363
+ @client.zadd("key1", 1, "val1")
364
+ @client.zadd("key1", 2, "val2")
365
+ @client.zadd("key1", 3, "val3")
366
+ @client.zadd("key2", 5, "val2")
367
+ @client.zadd("key2", 7, "val3")
368
+ @client.sadd("key3", "val1")
369
+ @client.sadd("key3", "val2")
370
+ end
371
+
372
+ it "should union two keys with custom scores" do
373
+ expect(@client.zunionstore("out", %w(key1 key2))).to eq(3)
374
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]])
375
+ end
376
+
377
+ it "should union two keys with a default score" do
378
+ expect(@client.zunionstore("out", %w(key1 key3))).to eq(3)
379
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 + 1)], ["val2", (2 + 1)], ["val3", 3]])
380
+ end
381
+
382
+ it "should union more than two keys" do
383
+ expect(@client.zunionstore("out", %w(key1 key2 key3))).to eq(3)
384
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 + 1)], ["val2", (2 + 5 + 1)], ["val3", (3 + 7)]])
385
+ end
386
+
387
+ it "should union with an unknown key" do
388
+ expect(@client.zunionstore("out", %w(key1 no_key))).to eq(3)
389
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 2], ["val3", 3]])
390
+ end
391
+
392
+ it "should union two keys by minimum values" do
393
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :min)).to eq(3)
394
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 2], ["val3", 3]])
395
+ end
396
+
397
+ it "should union two keys by maximum values" do
398
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :max)).to eq(3)
399
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 5], ["val3", 7]])
400
+ end
401
+
402
+ it "should union two keys by explicitly summing values" do
403
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :sum)).to eq(3)
404
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]])
405
+ end
406
+
407
+ it "should union two keys with weighted values" do
408
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1])).to eq(3)
409
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 * 10)], ["val2", (2 * 10 + 5)], ["val3", (3 * 10 + 7)]])
410
+ end
411
+
412
+ it "should union two keys with weighted minimum values" do
413
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min)).to eq(3)
414
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val2", 5], ["val3", 7], ["val1", (1 * 10)]])
415
+ end
416
+
417
+ it "should union two keys with weighted maximum values" do
418
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max)).to eq(3)
419
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 * 10)], ["val2", (2 * 10)], ["val3", (3 * 10)]])
420
+ end
421
+
422
+ it "should error without enough weights given" do
423
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => []) }.to raise_error(Redis::CommandError, "ERR syntax error")
424
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => [10]) }.to raise_error(Redis::CommandError, "ERR syntax error")
425
+ end
426
+
427
+ it "should error with too many weights given" do
428
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.to raise_error(Redis::CommandError, "ERR syntax error")
429
+ end
430
+
431
+ it "should error with an invalid aggregate" do
432
+ expect { @client.zunionstore("out", %w(key1 key2), :aggregate => :invalid) }.to raise_error(Redis::CommandError, "ERR syntax error")
433
+ end
434
+ end
435
+
436
+ #it "should remove all members in a sorted set within the given indexes"
437
+
438
+ #it "should return a range of members in a sorted set, by index, with scores ordered from high to low"
439
+
440
+ #it "should return a range of members in a sorted set, by score, with scores ordered from high to low"
441
+
442
+ #it "should determine the index of a member in a sorted set, with scores ordered from high to low"
443
+
444
+ #it "should get the score associated with the given member in a sorted set"
445
+
446
+ #it "should add multiple sorted sets and store the resulting sorted set in a new key"
447
+
448
+ it "zrem should remove members add by zadd" do
449
+ @client.zadd("key1", 1, 3)
450
+ @client.zrem("key1", 3)
451
+ expect(@client.zscore("key1", 3)).to be_nil
452
+ end
453
+
454
+ describe "#zscan" do
455
+ before { 50.times { |x| @client.zadd("key", x, "key #{x}") } }
456
+
457
+ it 'with no arguments should return 10 numbers in ascending order' do
458
+ result = @client.zscan("key", 0)[1]
459
+ expect(result).to eq(result.sort { |x, y| x[1] <=> y[1] })
460
+ expect(result.count).to eq(10)
461
+ end
462
+
463
+ it 'with a count should return that number of members' do
464
+ expect(@client.zscan("key", 0, count: 2)).to eq(["2", [["key 0", 0.0], ["key 1", 1.0]]])
465
+ end
466
+
467
+ it 'with a count greater than the number of members, returns all the members in asc order' do
468
+ result = @client.zscan("key", 0, count: 1000)[1]
469
+ expect(result).to eq(result.sort { |x, y| x[1] <=> y[1] })
470
+ expect(result.size).to eq(50)
471
+ end
472
+
473
+ it 'with match, should return key-values where the key matches' do
474
+ @client.zadd("key", 1.0, "blah")
475
+ @client.zadd("key", 2.0, "bluh")
476
+ result = @client.zscan("key", 0, count: 100, match: "key*")[1]
477
+ expect(result).to_not include(["blah", 1.0])
478
+ expect(result).to_not include(["bluh", 2.0])
479
+ end
480
+ end
481
+
482
+ describe "#zscan_each" do
483
+ before { 50.times { |x| @client.zadd("key", x, "key #{x}") } }
484
+
485
+ it 'enumerates over the items in the sorted set' do
486
+ expect(@client.zscan_each("key").to_a).to eq(@client.zscan("key", 0, count: 50)[1])
487
+ end
488
+ end
489
+
490
+ describe '#zrangebylex' do
491
+ before { @client.zadd "myzset", [0, 'a', 0, 'b', 0, 'd', 0, 'c'] }
492
+
493
+ it "should return empty list for '+'..'-' range" do
494
+ ranged = @client.zrangebylex "myzset", "+", "-"
495
+ expect(ranged).to be_empty
496
+ end
497
+
498
+ it "should return all elements for '-'..'+' range" do
499
+ ranged = @client.zrangebylex "myzset", "-", "+"
500
+ expect(ranged).to eq %w(a b c d)
501
+ end
502
+
503
+ it "should include values starting with [ symbol" do
504
+ ranged = @client.zrangebylex "myzset", "-", "[c"
505
+ expect(ranged).to eq %w(a b c)
506
+ end
507
+
508
+ it "should exclude values with ( symbol" do
509
+ ranged = @client.zrangebylex "myzset", "-", "(c"
510
+ expect(ranged).to eq %w(a b)
511
+ end
512
+
513
+ it "should work with both [ and ( properly" do
514
+ ranged = @client.zrangebylex "myzset", "[aaa", "(d"
515
+ expect(ranged).to eq %w(b c)
516
+ end
517
+
518
+ it "should return empty array if key is not exist" do
519
+ ranged = @client.zrangebylex "puppies", "-", "+"
520
+ expect(ranged).to be_empty
521
+ end
522
+
523
+ it 'should raise error for invalid range when range is invalid' do
524
+ expect{ @client.zrangebylex "myzset", "-", "d" }.to raise_error(Redis::CommandError, "ERR min or max not valid string range item")
525
+ end
526
+
527
+ it "should limit and offset values as 4th argument" do
528
+ ranged = @client.zrangebylex "myzset", "-", "+", limit: [1, 3]
529
+ expect(ranged).to eq %w(b c d)
530
+ end
531
+ end
532
+
533
+ describe "#zrevrangebylex" do
534
+ before { @client.zadd "myzset", [0, 'a', 0, 'b', 0, 'd', 0, 'c'] }
535
+
536
+ it "should return empty list for '-'..'+' range" do
537
+ ranged = @client.zrevrangebylex "myzset", "-", "+"
538
+ expect(ranged).to be_empty
539
+ end
540
+
541
+ it "should return all elements for '+'..'-' range in descending order" do
542
+ ranged = @client.zrevrangebylex "myzset", "+", "-"
543
+ expect(ranged).to eq %w(d c b a)
544
+ end
545
+
546
+ it "should include values starting with [ symbol" do
547
+ ranged = @client.zrevrangebylex "myzset", "[c", "-"
548
+ expect(ranged).to eq %w(c b a)
549
+ end
550
+
551
+ it "should exclude values with ( symbol" do
552
+ ranged = @client.zrevrangebylex "myzset", "+", "(c"
553
+ expect(ranged).to eq %w(d)
554
+ end
555
+
556
+ it "should work with both [ and ( properly" do
557
+ ranged = @client.zrevrangebylex "myzset", "(d", "[aaa"
558
+ expect(ranged).to eq %w(c b)
559
+ end
560
+
561
+ it "should return empty array if key is not exist" do
562
+ ranged = @client.zrevrangebylex "puppies", "+", "-"
563
+ expect(ranged).to be_empty
564
+ end
565
+
566
+ it 'should raise error for invalid range when range is invalid' do
567
+ expect { @client.zrevrangebylex "myzset", "-", "d" }.to raise_error(Redis::CommandError, "ERR min or max not valid string range item")
568
+ end
569
+
570
+ it "should limit and offset values as 4th argument" do
571
+ pending "current stable (3.2.0) redis-rb doesn't support limit option"
572
+
573
+ ranged = @client.zrevrangebylex "myzset", "+", "-", limit: [0, 3]
574
+ expect(ranged).to eq %w(d c b)
575
+ end
576
+ end
577
+ end
578
+ end