fakeredis 0.5.0 → 0.8.0

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 (44) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +14 -5
  4. data/LICENSE +1 -1
  5. data/README.md +42 -24
  6. data/fakeredis.gemspec +1 -1
  7. data/lib/fakeredis.rb +28 -0
  8. data/lib/fakeredis/bitop_command.rb +56 -0
  9. data/lib/fakeredis/command_executor.rb +6 -9
  10. data/lib/fakeredis/expiring_hash.rb +3 -5
  11. data/lib/fakeredis/geo_commands.rb +142 -0
  12. data/lib/fakeredis/geo_set.rb +84 -0
  13. data/lib/fakeredis/minitest.rb +24 -0
  14. data/lib/fakeredis/rspec.rb +1 -0
  15. data/lib/fakeredis/sort_method.rb +3 -3
  16. data/lib/fakeredis/sorted_set_store.rb +1 -1
  17. data/lib/fakeredis/transaction_commands.rb +2 -2
  18. data/lib/fakeredis/version.rb +1 -1
  19. data/lib/fakeredis/zset.rb +8 -2
  20. data/lib/redis/connection/memory.rb +650 -82
  21. data/spec/bitop_command_spec.rb +209 -0
  22. data/spec/command_executor_spec.rb +15 -0
  23. data/spec/compatibility_spec.rb +1 -1
  24. data/spec/connection_spec.rb +21 -21
  25. data/spec/fakeredis_spec.rb +73 -0
  26. data/spec/geo_set_spec.rb +164 -0
  27. data/spec/hashes_spec.rb +138 -57
  28. data/spec/hyper_log_logs_spec.rb +50 -0
  29. data/spec/keys_spec.rb +232 -90
  30. data/spec/lists_spec.rb +91 -35
  31. data/spec/memory_spec.rb +80 -7
  32. data/spec/server_spec.rb +38 -24
  33. data/spec/sets_spec.rb +112 -46
  34. data/spec/sort_method_spec.rb +6 -0
  35. data/spec/sorted_sets_spec.rb +482 -150
  36. data/spec/spec_helper.rb +9 -18
  37. data/spec/spec_helper_live_redis.rb +4 -4
  38. data/spec/strings_spec.rb +113 -79
  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 +20 -16
  42. data/spec/transactions_spec.rb +34 -13
  43. data/spec/upcase_method_name_spec.rb +2 -2
  44. metadata +23 -6
data/spec/sets_spec.rb CHANGED
@@ -7,30 +7,34 @@ module FakeRedis
7
7
  end
8
8
 
9
9
  it "should add a member to a set" do
10
- @client.sadd("key", "value").should be == true
11
- @client.sadd("key", "value").should be == false
10
+ expect(@client.sadd("key", "value")).to eq(true)
11
+ expect(@client.sadd("key", "value")).to eq(false)
12
12
 
13
- @client.smembers("key").should be == ["value"]
13
+ expect(@client.smembers("key")).to eq(["value"])
14
14
  end
15
15
 
16
16
  it "should raise error if command arguments count is not enough" do
17
17
  expect { @client.sadd("key", []) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sadd' command")
18
18
  expect { @client.sinter(*[]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sinter' command")
19
+ expect { @client.sinter([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sinter' command")
20
+ expect { @client.sunion(*[]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sunion' command")
21
+ expect { @client.sunion([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sunion' command")
22
+ expect { @client.srem("key", []) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'srem' command")
19
23
 
20
- @client.smembers("key").should be_empty
24
+ expect(@client.smembers("key")).to be_empty
21
25
  end
22
26
 
23
27
  it "should add multiple members to a set" do
24
- @client.sadd("key", %w(value other something more)).should be == 4
25
- @client.sadd("key", %w(and additional values)).should be == 3
26
- @client.smembers("key").should =~ ["value", "other", "something", "more", "and", "additional", "values"]
28
+ expect(@client.sadd("key", %w(value other something more))).to eq(4)
29
+ expect(@client.sadd("key", %w(and additional values))).to eq(3)
30
+ expect(@client.smembers("key")).to match_array(["value", "other", "something", "more", "and", "additional", "values"])
27
31
  end
28
32
 
29
33
  it "should get the number of members in a set" do
30
34
  @client.sadd("key", "val1")
31
35
  @client.sadd("key", "val2")
32
36
 
33
- @client.scard("key").should be == 2
37
+ expect(@client.scard("key")).to eq(2)
34
38
  end
35
39
 
36
40
  it "should subtract multiple sets" do
@@ -43,14 +47,16 @@ module FakeRedis
43
47
  @client.sadd("key3", "c")
44
48
  @client.sadd("key3", "e")
45
49
 
46
- @client.sdiff("key1", "key2", "key3").should =~ ["b", "d"]
50
+ expect(@client.sdiff("key1", "key2", "key3")).to match_array(["b", "d"])
51
+ expect(@client.sdiff("key1", ["key2", "key3"])).to match_array(["b", "d"])
47
52
  end
48
53
 
49
54
  it "should subtract from a nonexistent set" do
50
55
  @client.sadd("key2", "a")
51
56
  @client.sadd("key2", "b")
52
57
 
53
- @client.sdiff("key1", "key2").should == []
58
+ expect(@client.sdiff("key1", "key2")).to eq([])
59
+ expect(@client.sdiff(["key1", "key2"])).to eq([])
54
60
  end
55
61
 
56
62
  it "should subtract multiple sets and store the resulting set in a key" do
@@ -63,8 +69,10 @@ module FakeRedis
63
69
  @client.sadd("key3", "c")
64
70
  @client.sadd("key3", "e")
65
71
  @client.sdiffstore("key", "key1", "key2", "key3")
72
+ @client.sdiffstore("new_key", "key1", ["key2", "key3"])
66
73
 
67
- @client.smembers("key").should =~ ["b", "d"]
74
+ expect(@client.smembers("key")).to match_array(["b", "d"])
75
+ expect(@client.smembers("new_key")).to match_array(["b", "d"])
68
76
  end
69
77
 
70
78
  it "should intersect multiple sets" do
@@ -77,7 +85,8 @@ module FakeRedis
77
85
  @client.sadd("key3", "c")
78
86
  @client.sadd("key3", "e")
79
87
 
80
- @client.sinter("key1", "key2", "key3").should be == ["c"]
88
+ expect(@client.sinter("key1", "key2", "key3")).to eq(["c"])
89
+ expect(@client.sinter(["key1", "key2", "key3"])).to eq(["c"])
81
90
  end
82
91
 
83
92
  it "should intersect multiple sets and store the resulting set in a key" do
@@ -90,15 +99,18 @@ module FakeRedis
90
99
  @client.sadd("key3", "c")
91
100
  @client.sadd("key3", "e")
92
101
  @client.sinterstore("key", "key1", "key2", "key3")
93
- @client.smembers("key").should be == ["c"]
102
+ @client.sinterstore("new_key", ["key1", "key2", "key3"])
103
+
104
+ expect(@client.smembers("key")).to eq(["c"])
105
+ expect(@client.smembers("new_key")).to eq(["c"])
94
106
  end
95
107
 
96
108
  it "should determine if a given value is a member of a set" do
97
109
  @client.sadd("key1", "a")
98
110
 
99
- @client.sismember("key1", "a").should be == true
100
- @client.sismember("key1", "b").should be == false
101
- @client.sismember("key2", "a").should be == false
111
+ expect(@client.sismember("key1", "a")).to eq(true)
112
+ expect(@client.sismember("key1", "b")).to eq(false)
113
+ expect(@client.sismember("key2", "a")).to eq(false)
102
114
  end
103
115
 
104
116
  it "should get all the members in a set" do
@@ -107,51 +119,67 @@ module FakeRedis
107
119
  @client.sadd("key", "c")
108
120
  @client.sadd("key", "d")
109
121
 
110
- @client.smembers("key").should =~ ["a", "b", "c", "d"]
122
+ expect(@client.smembers("key")).to match_array(["a", "b", "c", "d"])
111
123
  end
112
124
 
113
125
  it "should move a member from one set to another" do
114
126
  @client.sadd("key1", "a")
115
127
  @client.sadd("key1", "b")
116
128
  @client.sadd("key2", "c")
117
- @client.smove("key1", "key2", "a").should be == true
118
- @client.smove("key1", "key2", "a").should be == false
129
+ expect(@client.smove("key1", "key2", "a")).to eq(true)
130
+ expect(@client.smove("key1", "key2", "a")).to eq(false)
119
131
 
120
- @client.smembers("key1").should be == ["b"]
121
- @client.smembers("key2").should =~ ["c", "a"]
132
+ expect(@client.smembers("key1")).to eq(["b"])
133
+ expect(@client.smembers("key2")).to match_array(["c", "a"])
122
134
  end
123
135
 
124
136
  it "should remove and return a random member from a set" do
125
137
  @client.sadd("key1", "a")
126
138
  @client.sadd("key1", "b")
127
139
 
128
- ["a", "b"].include?(@client.spop("key1")).should be true
129
- ["a", "b"].include?(@client.spop("key1")).should be true
130
- @client.spop("key1").should be_nil
140
+ expect(["a", "b"].include?(@client.spop("key1"))).to be true
141
+ expect(["a", "b"].include?(@client.spop("key1"))).to be true
142
+ expect(@client.spop("key1")).to be_nil
131
143
  end
132
144
 
133
145
  it "should get a random member from a set" do
134
146
  @client.sadd("key1", "a")
135
147
  @client.sadd("key1", "b")
136
148
 
137
- ["a", "b"].include?(@client.spop("key1")).should be true
149
+ expect(["a", "b"].include?(@client.spop("key1"))).to be true
150
+ end
151
+
152
+ it "should pop multiple members from a set" do
153
+ @client.sadd("key1", "a")
154
+ @client.sadd("key1", "b")
155
+ @client.sadd("key1", "c")
156
+
157
+ vals = @client.spop("key1", 2)
158
+ expect(vals.count).to eq(2)
159
+ vals.each { |v| expect(["a", "b", "c"].include?(v)).to be true }
160
+
161
+ new_vals = @client.spop("key1", 2)
162
+ expect(new_vals.count).to eq(1)
163
+ expect(["a", "b", "c"].include?(new_vals.first)).to be true
164
+
165
+ expect(["a", "b", "c"]).to eq((vals + new_vals).sort)
138
166
  end
139
167
 
140
168
  it "should remove a member from a set" do
141
169
  @client.sadd("key1", "a")
142
170
  @client.sadd("key1", "b")
143
- @client.srem("key1", "a").should be == true
144
- @client.srem("key1", "a").should be == false
171
+ expect(@client.srem("key1", "a")).to eq(true)
172
+ expect(@client.srem("key1", "a")).to eq(false)
145
173
 
146
- @client.smembers("key1").should be == ["b"]
174
+ expect(@client.smembers("key1")).to eq(["b"])
147
175
  end
148
176
 
149
177
  it "should remove multiple members from a set" do
150
178
  @client.sadd("key1", "a")
151
179
  @client.sadd("key1", "b")
152
180
 
153
- @client.srem("key1", [ "a", "b"]).should == 2
154
- @client.smembers("key1").should be_empty
181
+ expect(@client.srem("key1", [ "a", "b"])).to eq(2)
182
+ expect(@client.smembers("key1")).to be_empty
155
183
  end
156
184
 
157
185
  it "should remove the set's key once it's empty" do
@@ -160,7 +188,7 @@ module FakeRedis
160
188
  @client.srem("key1", "b")
161
189
  @client.srem("key1", "a")
162
190
 
163
- @client.exists("key1").should be == false
191
+ expect(@client.exists("key1")).to eq(false)
164
192
  end
165
193
 
166
194
  it "should add multiple sets" do
@@ -173,7 +201,7 @@ module FakeRedis
173
201
  @client.sadd("key3", "c")
174
202
  @client.sadd("key3", "e")
175
203
 
176
- @client.sunion("key1", "key2", "key3").should =~ ["a", "b", "c", "d", "e"]
204
+ expect(@client.sunion("key1", "key2", "key3")).to match_array(["a", "b", "c", "d", "e"])
177
205
  end
178
206
 
179
207
  it "should add multiple sets and store the resulting set in a key" do
@@ -187,7 +215,7 @@ module FakeRedis
187
215
  @client.sadd("key3", "e")
188
216
  @client.sunionstore("key", "key1", "key2", "key3")
189
217
 
190
- @client.smembers("key").should =~ ["a", "b", "c", "d", "e"]
218
+ expect(@client.smembers("key")).to match_array(["a", "b", "c", "d", "e"])
191
219
  end
192
220
  end
193
221
 
@@ -207,7 +235,7 @@ module FakeRedis
207
235
  it 'is a random element from the set' do
208
236
  random_element = @client.srandmember("key1")
209
237
 
210
- ['a', 'b', 'c'].include?(random_element).should be true
238
+ expect(['a', 'b', 'c'].include?(random_element)).to be true
211
239
  end
212
240
  end
213
241
 
@@ -215,7 +243,7 @@ module FakeRedis
215
243
  it 'is an array of one random element from the set' do
216
244
  random_elements = @client.srandmember("key1", 1)
217
245
 
218
- [['a'], ['b'], ['c']].include?(@client.srandmember("key1", 1)).should be true
246
+ expect([['a'], ['b'], ['c']].include?(random_elements)).to be true
219
247
  end
220
248
  end
221
249
 
@@ -223,10 +251,10 @@ module FakeRedis
223
251
  it 'is an array of two unique, random elements from the set' do
224
252
  random_elements = @client.srandmember("key1", 2)
225
253
 
226
- random_elements.count.should == 2
227
- random_elements.uniq.count.should == 2
254
+ expect(random_elements.count).to eq(2)
255
+ expect(random_elements.uniq.count).to eq(2)
228
256
  random_elements.all? do |element|
229
- ['a', 'b', 'c'].include?(element).should be true
257
+ expect(['a', 'b', 'c'].include?(element)).to be true
230
258
  end
231
259
  end
232
260
  end
@@ -235,10 +263,10 @@ module FakeRedis
235
263
  it 'is an array of 100 random elements from the set, some of which are repeated' do
236
264
  random_elements = @client.srandmember("key1", -100)
237
265
 
238
- random_elements.count.should == 100
239
- random_elements.uniq.count.should <= 3
266
+ expect(random_elements.count).to eq(100)
267
+ expect(random_elements.uniq.count).to be <= 3
240
268
  random_elements.all? do |element|
241
- ['a', 'b', 'c'].include?(element).should be true
269
+ expect(['a', 'b', 'c'].include?(element)).to be true
242
270
  end
243
271
  end
244
272
  end
@@ -247,9 +275,9 @@ module FakeRedis
247
275
  it 'is an array of all of the elements from the set, none of which are repeated' do
248
276
  random_elements = @client.srandmember("key1", 100)
249
277
 
250
- random_elements.count.should == 3
251
- random_elements.uniq.count.should == 3
252
- random_elements.should =~ ['a', 'b', 'c']
278
+ expect(random_elements.count).to eq(3)
279
+ expect(random_elements.uniq.count).to eq(3)
280
+ expect(random_elements).to match_array(['a', 'b', 'c'])
253
281
  end
254
282
  end
255
283
  end
@@ -258,11 +286,49 @@ module FakeRedis
258
286
  before { @client.del("key1") }
259
287
 
260
288
  it 'is nil without the extra parameter' do
261
- @client.srandmember("key1").should be_nil
289
+ expect(@client.srandmember("key1")).to be_nil
262
290
  end
263
291
 
264
292
  it 'is an empty array with an extra parameter' do
265
- @client.srandmember("key1", 1).should == []
293
+ expect(@client.srandmember("key1", 1)).to eq([])
294
+ end
295
+ end
296
+
297
+ describe "#sscan" do
298
+ it 'with no arguments and few items, returns all items' do
299
+ @client.sadd('set', ['name', 'Jack', 'age', '33'])
300
+ result = @client.sscan('set', 0)
301
+
302
+ expect(result[0]).to eq('0')
303
+ expect(result[1]).to eq(['name', 'Jack', 'age', '33'])
304
+ end
305
+
306
+ it 'with a count should return that number of members or more' do
307
+ @client.sadd('set', ['a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5', 'f', '6', 'g', '7'])
308
+ result = @client.sscan('set', 0, count: 3)
309
+ expect(result[0]).to eq('3')
310
+ expect(result[1]).to eq([ 'a', '1', 'b'])
311
+ end
312
+
313
+ it 'returns items starting at the provided cursor' do
314
+ @client.sadd('set', ['a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5', 'f', '6', 'g', '7'])
315
+ result = @client.sscan('set', 2, count: 3)
316
+ expect(result[0]).to eq('5')
317
+ expect(result[1]).to eq(['b', '2', 'c'])
318
+ end
319
+
320
+ it 'with match, returns items matching the given pattern' do
321
+ @client.sadd('set', ['aa', '1', 'b', '2', 'cc', '3', 'd', '4', 'ee', '5', 'f', '6', 'gg', '7'])
322
+ result = @client.sscan('set', 2, count: 7, match: '??')
323
+ expect(result[0]).to eq('9')
324
+ expect(result[1]).to eq(['cc','ee'])
325
+ end
326
+
327
+ it 'returns an empty result if the key is not found' do
328
+ result = @client.sscan('set', 0)
329
+
330
+ expect(result[0]).to eq('0')
331
+ expect(result[1]).to eq([])
266
332
  end
267
333
  end
268
334
  end
@@ -32,6 +32,12 @@ module FakeRedis
32
32
  end
33
33
  end
34
34
 
35
+ context "none" do
36
+ it "should return empty array" do
37
+ expect(@client.sort("key")).to eq []
38
+ end
39
+ end
40
+
35
41
  context "list" do
36
42
  before do
37
43
  @key = "fake-redis-test:list_sort"
@@ -9,84 +9,126 @@ module FakeRedis
9
9
  end
10
10
 
11
11
  it "should add a member to a sorted set, or update its score if it already exists" do
12
- @client.zadd("key", 1, "val").should be(true)
13
- @client.zscore("key", "val").should be == 1.0
12
+ expect(@client.zadd("key", 1, "val")).to be(true)
13
+ expect(@client.zscore("key", "val")).to eq(1.0)
14
14
 
15
- @client.zadd("key", 2, "val").should be(false)
16
- @client.zscore("key", "val").should be == 2.0
15
+ expect(@client.zadd("key", 2, "val")).to be(false)
16
+ expect(@client.zscore("key", "val")).to eq(2.0)
17
17
 
18
18
  # These assertions only work in redis-rb v3.0.2 or higher
19
- @client.zadd("key2", "inf", "val").should be == true
20
- @client.zscore("key2", "val").should be == Infinity
19
+ expect(@client.zadd("key2", "inf", "val")).to eq(true)
20
+ expect(@client.zscore("key2", "val")).to eq(Infinity)
21
21
 
22
- @client.zadd("key3", "+inf", "val").should be == true
23
- @client.zscore("key3", "val").should be == Infinity
22
+ expect(@client.zadd("key3", "+inf", "val")).to eq(true)
23
+ expect(@client.zscore("key3", "val")).to eq(Infinity)
24
24
 
25
- @client.zadd("key4", "-inf", "val").should be == true
26
- @client.zscore("key4", "val").should be == -Infinity
25
+ expect(@client.zadd("key4", "-inf", "val")).to eq(true)
26
+ expect(@client.zscore("key4", "val")).to eq(-Infinity)
27
27
  end
28
28
 
29
29
  it "should return a nil score for value not in a sorted set or empty key" do
30
30
  @client.zadd "key", 1, "val"
31
31
 
32
- @client.zscore("key", "val").should be == 1.0
33
- @client.zscore("key", "val2").should be_nil
34
- @client.zscore("key2", "val").should be_nil
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
35
  end
36
36
 
37
37
  it "should add multiple members to a sorted set, or update its score if it already exists" do
38
- @client.zadd("key", [1, "val", 2, "val2"]).should be == 2
39
- @client.zscore("key", "val").should be == 1
40
- @client.zscore("key", "val2").should be == 2
41
-
42
- @client.zadd("key", [[5, "val"], [3, "val3"], [4, "val4"]]).should be == 2
43
- @client.zscore("key", "val").should be == 5
44
- @client.zscore("key", "val2").should be == 2
45
- @client.zscore("key", "val3").should be == 3
46
- @client.zscore("key", "val4").should be == 4
47
-
48
- @client.zadd("key", [[5, "val5"], [3, "val6"]]).should be == 2
49
- @client.zscore("key", "val5").should be == 5
50
- @client.zscore("key", "val6").should be == 3
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
51
  end
52
52
 
53
53
  it "should error with wrong number of arguments when adding members" do
54
- lambda { @client.zadd("key") }.should raise_error(ArgumentError, "wrong number of arguments")
55
- lambda { @client.zadd("key", 1) }.should raise_error(ArgumentError, "wrong number of arguments")
56
- lambda { @client.zadd("key", [1]) }.should raise_error(Redis::CommandError, "ERR wrong number of arguments for 'zadd' command")
57
- lambda { @client.zadd("key", [1, "val", 2]) }.should raise_error(Redis::CommandError, "ERR syntax error")
58
- lambda { @client.zadd("key", [[1, "val"], [2]]) }.should raise_error(Redis::CommandError, "ERR syntax error")
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
59
  end
60
60
 
61
61
  it "should allow floats as scores when adding or updating" do
62
- @client.zadd("key", 4.321, "val").should be(true)
63
- @client.zscore("key", "val").should be == 4.321
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
64
68
 
65
- @client.zadd("key", 54.3210, "val").should be(false)
66
- @client.zscore("key", "val").should be == 54.321
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")
67
81
  end
68
82
 
69
83
  it "should remove members from sorted sets" do
70
- @client.zrem("key", "val").should be(false)
71
- @client.zadd("key", 1, "val").should be(true)
72
- @client.zrem("key", "val").should be(true)
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)
73
87
  end
74
88
 
75
89
  it "should remove multiple members from sorted sets" do
76
- @client.zrem("key2", %w(val)).should be == 0
77
- @client.zrem("key2", %w(val val2 val3)).should be == 0
90
+ expect(@client.zrem("key2", %w(val))).to eq(0)
91
+ expect(@client.zrem("key2", %w(val val2 val3))).to eq(0)
78
92
 
79
93
  @client.zadd("key2", 1, "val")
80
94
  @client.zadd("key2", 1, "val2")
81
95
  @client.zadd("key2", 1, "val3")
82
96
 
83
- @client.zrem("key2", %w(val val2 val3 val4)).should be == 3
97
+ expect(@client.zrem("key2", %w(val val2 val3 val4))).to eq(3)
84
98
  end
85
99
 
86
100
  it "should remove sorted set's key when it is empty" do
87
101
  @client.zadd("key", 1, "val")
88
102
  @client.zrem("key", "val")
89
- @client.exists("key").should be == false
103
+ expect(@client.exists("key")).to eq(false)
104
+ end
105
+
106
+ it "should pop members with the highest scores from sorted set" do
107
+ @client.zadd("key", [1, "val1", 2, "val2", 3, "val3"])
108
+ expect(@client.zpopmax("key")).to eq(["val3", 3.0])
109
+ expect(@client.zpopmax("key", 3)).to eq([["val2", 2.0], ["val1", 1.0]])
110
+ expect(@client.zpopmax("nonexistent")).to eq(nil)
111
+ end
112
+
113
+ it "should pop members with the lowest scores from sorted set" do
114
+ @client.zadd("key", [1, "val1", 2, "val2", 3, "val3"])
115
+ expect(@client.zpopmin("key")).to eq(["val1", 1.0])
116
+ expect(@client.zpopmin("key", 3)).to eq([["val2", 2.0], ["val3", 3.0]])
117
+ expect(@client.zpopmin("nonexistent")).to eq(nil)
118
+ end
119
+
120
+ it "should pop members with the highest score from first sorted set that is non-empty" do
121
+ @client.zadd("key1", [1, "val1", 2, "val2"])
122
+ @client.zadd("key2", [3, "val3"])
123
+ expect(@client.bzpopmax("nonexistent", "key1", "key2", 0)).to eq(["key1", "val2", 2.0])
124
+ expect(@client.bzpopmax("nonexistent")).to eq(nil)
125
+ end
126
+
127
+ it "should pop members with the lowest score from first sorted set that is non-empty" do
128
+ @client.zadd("key1", [1, "val1", 2, "val2"])
129
+ @client.zadd("key2", [3, "val3"])
130
+ expect(@client.bzpopmin("nonexistent", "key1", "key2", 0)).to eq(["key1", "val1", 1.0])
131
+ expect(@client.bzpopmin("nonexistent")).to eq(nil)
90
132
  end
91
133
 
92
134
  it "should get the number of members in a sorted set" do
@@ -94,7 +136,7 @@ module FakeRedis
94
136
  @client.zadd("key", 2, "val1")
95
137
  @client.zadd("key", 5, "val3")
96
138
 
97
- @client.zcard("key").should be == 3
139
+ expect(@client.zcard("key")).to eq(3)
98
140
  end
99
141
 
100
142
  it "should count the members in a sorted set with scores within the given values" do
@@ -102,28 +144,28 @@ module FakeRedis
102
144
  @client.zadd("key", 2, "val2")
103
145
  @client.zadd("key", 3, "val3")
104
146
 
105
- @client.zcount("key", 2, 3).should be == 2
147
+ expect(@client.zcount("key", 2, 3)).to eq(2)
106
148
  end
107
149
 
108
150
  it "should increment the score of a member in a sorted set" do
109
151
  @client.zadd("key", 1, "val1")
110
- @client.zincrby("key", 2, "val1").should be == 3
111
- @client.zscore("key", "val1").should be == 3
152
+ expect(@client.zincrby("key", 2, "val1")).to eq(3)
153
+ expect(@client.zscore("key", "val1")).to eq(3)
112
154
  end
113
155
 
114
156
  it "initializes the sorted set if the key wasnt already set" do
115
- @client.zincrby("key", 1, "val1").should be == 1
157
+ expect(@client.zincrby("key", 1, "val1")).to eq(1)
116
158
  end
117
159
 
118
160
  it "should convert the key to a string for zscore" do
119
161
  @client.zadd("key", 1, 1)
120
- @client.zscore("key", 1).should be == 1
162
+ expect(@client.zscore("key", 1)).to eq(1)
121
163
  end
122
164
 
123
165
  # These won't pass until redis-rb releases v3.0.2
124
166
  it "should handle infinity values when incrementing a sorted set key" do
125
- @client.zincrby("bar", "+inf", "s2").should be == Infinity
126
- @client.zincrby("bar", "-inf", "s1").should be == -Infinity
167
+ expect(@client.zincrby("bar", "+inf", "s2")).to eq(Infinity)
168
+ expect(@client.zincrby("bar", "-inf", "s1")).to eq(-Infinity)
127
169
  end
128
170
 
129
171
  it "should return a range of members in a sorted set, by index" do
@@ -131,10 +173,11 @@ module FakeRedis
131
173
  @client.zadd("key", 2, "two")
132
174
  @client.zadd("key", 3, "three")
133
175
 
134
- @client.zrange("key", 0, -1).should be == ["one", "two", "three"]
135
- @client.zrange("key", 1, 2).should be == ["two", "three"]
136
- @client.zrange("key", 0, -1, :withscores => true).should be == [["one", 1], ["two", 2], ["three", 3]]
137
- @client.zrange("key", 1, 2, :with_scores => true).should be == [["two", 2], ["three", 3]]
176
+ expect(@client.zrange("key", 0, -1)).to eq(["one", "two", "three"])
177
+ expect(@client.zrange("key", 1, 2)).to eq(["two", "three"])
178
+ expect(@client.zrange("key", -50, -2)).to eq(["one", "two"])
179
+ expect(@client.zrange("key", 0, -1, :withscores => true)).to eq([["one", 1], ["two", 2], ["three", 3]])
180
+ expect(@client.zrange("key", 1, 2, :with_scores => true)).to eq([["two", 2], ["three", 3]])
138
181
  end
139
182
 
140
183
  it "should sort zrange results logically" do
@@ -142,8 +185,8 @@ module FakeRedis
142
185
  @client.zadd("key", 5, "val3")
143
186
  @client.zadd("key", 5, "val1")
144
187
 
145
- @client.zrange("key", 0, -1).should be == %w(val1 val2 val3)
146
- @client.zrange("key", 0, -1, :with_scores => true).should be == [["val1", 5], ["val2", 5], ["val3", 5]]
188
+ expect(@client.zrange("key", 0, -1)).to eq(%w(val1 val2 val3))
189
+ expect(@client.zrange("key", 0, -1, :with_scores => true)).to eq([["val1", 5], ["val2", 5], ["val3", 5]])
147
190
  end
148
191
 
149
192
  it "should return a reversed range of members in a sorted set, by index" do
@@ -151,10 +194,10 @@ module FakeRedis
151
194
  @client.zadd("key", 2, "two")
152
195
  @client.zadd("key", 3, "three")
153
196
 
154
- @client.zrevrange("key", 0, -1).should be == ["three", "two", "one"]
155
- @client.zrevrange("key", 1, 2).should be == ["two", "one"]
156
- @client.zrevrange("key", 0, -1, :withscores => true).should be == [["three", 3], ["two", 2], ["one", 1]]
157
- @client.zrevrange("key", 0, -1, :with_scores => true).should be == [["three", 3], ["two", 2], ["one", 1]]
197
+ expect(@client.zrevrange("key", 0, -1)).to eq(["three", "two", "one"])
198
+ expect(@client.zrevrange("key", 1, 2)).to eq(["two", "one"])
199
+ expect(@client.zrevrange("key", 0, -1, :withscores => true)).to eq([["three", 3], ["two", 2], ["one", 1]])
200
+ expect(@client.zrevrange("key", 0, -1, :with_scores => true)).to eq([["three", 3], ["two", 2], ["one", 1]])
158
201
  end
159
202
 
160
203
  it "should return a range of members in a sorted set, by score" do
@@ -162,21 +205,21 @@ module FakeRedis
162
205
  @client.zadd("key", 2, "two")
163
206
  @client.zadd("key", 3, "three")
164
207
 
165
- @client.zrangebyscore("key", 0, 100).should be == ["one", "two", "three"]
166
- @client.zrangebyscore("key", 1, 2).should be == ["one", "two"]
167
- @client.zrangebyscore("key", 1, '(2').should be == ['one']
168
- @client.zrangebyscore("key", '(1', 2).should be == ['two']
169
- @client.zrangebyscore("key", '(1', '(2').should be == []
170
- @client.zrangebyscore("key", 0, 100, :withscores => true).should be == [["one", 1], ["two", 2], ["three", 3]]
171
- @client.zrangebyscore("key", 1, 2, :with_scores => true).should be == [["one", 1], ["two", 2]]
172
- @client.zrangebyscore("key", 0, 100, :limit => [0, 1]).should be == ["one"]
173
- @client.zrangebyscore("key", 0, 100, :limit => [0, -1]).should be == ["one", "two", "three"]
174
- @client.zrangebyscore("key", 0, 100, :limit => [1, -1], :with_scores => true).should be == [["two", 2], ["three", 3]]
175
- @client.zrangebyscore("key", '-inf', '+inf').should be == ["one", "two", "three"]
176
- @client.zrangebyscore("key", 2, '+inf').should be == ["two", "three"]
177
- @client.zrangebyscore("key", '-inf', 2).should be == ['one', "two"]
178
-
179
- @client.zrangebyscore("badkey", 1, 2).should be == []
208
+ expect(@client.zrangebyscore("key", 0, 100)).to eq(["one", "two", "three"])
209
+ expect(@client.zrangebyscore("key", 1, 2)).to eq(["one", "two"])
210
+ expect(@client.zrangebyscore("key", 1, '(2')).to eq(['one'])
211
+ expect(@client.zrangebyscore("key", '(1', 2)).to eq(['two'])
212
+ expect(@client.zrangebyscore("key", '(1', '(2')).to eq([])
213
+ expect(@client.zrangebyscore("key", 0, 100, :withscores => true)).to eq([["one", 1], ["two", 2], ["three", 3]])
214
+ expect(@client.zrangebyscore("key", 1, 2, :with_scores => true)).to eq([["one", 1], ["two", 2]])
215
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [0, 1])).to eq(["one"])
216
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [0, -1])).to eq(["one", "two", "three"])
217
+ expect(@client.zrangebyscore("key", 0, 100, :limit => [1, -1], :with_scores => true)).to eq([["two", 2], ["three", 3]])
218
+ expect(@client.zrangebyscore("key", '-inf', '+inf')).to eq(["one", "two", "three"])
219
+ expect(@client.zrangebyscore("key", 2, '+inf')).to eq(["two", "three"])
220
+ expect(@client.zrangebyscore("key", '-inf', 2)).to eq(['one', "two"])
221
+
222
+ expect(@client.zrangebyscore("badkey", 1, 2)).to eq([])
180
223
  end
181
224
 
182
225
  it "should return a reversed range of members in a sorted set, by score" do
@@ -184,13 +227,13 @@ module FakeRedis
184
227
  @client.zadd("key", 2, "two")
185
228
  @client.zadd("key", 3, "three")
186
229
 
187
- @client.zrevrangebyscore("key", 100, 0).should be == ["three", "two", "one"]
188
- @client.zrevrangebyscore("key", 2, 1).should be == ["two", "one"]
189
- @client.zrevrangebyscore("key", 1, 2).should be == []
190
- @client.zrevrangebyscore("key", 2, 1, :with_scores => true).should be == [["two", 2.0], ["one", 1.0]]
191
- @client.zrevrangebyscore("key", 100, 0, :limit => [0, 1]).should be == ["three"]
192
- @client.zrevrangebyscore("key", 100, 0, :limit => [0, -1]).should be == ["three", "two", "one"]
193
- @client.zrevrangebyscore("key", 100, 0, :limit => [1, -1], :with_scores => true).should be == [["two", 2.0], ["one", 1.0]]
230
+ expect(@client.zrevrangebyscore("key", 100, 0)).to eq(["three", "two", "one"])
231
+ expect(@client.zrevrangebyscore("key", 2, 1)).to eq(["two", "one"])
232
+ expect(@client.zrevrangebyscore("key", 1, 2)).to eq([])
233
+ expect(@client.zrevrangebyscore("key", 2, 1, :with_scores => true)).to eq([["two", 2.0], ["one", 1.0]])
234
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [0, 1])).to eq(["three"])
235
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [0, -1])).to eq(["three", "two", "one"])
236
+ expect(@client.zrevrangebyscore("key", 100, 0, :limit => [1, -1], :with_scores => true)).to eq([["two", 2.0], ["one", 1.0]])
194
237
  end
195
238
 
196
239
  it "should determine the index of a member in a sorted set" do
@@ -198,8 +241,8 @@ module FakeRedis
198
241
  @client.zadd("key", 2, "two")
199
242
  @client.zadd("key", 3, "three")
200
243
 
201
- @client.zrank("key", "three").should be == 2
202
- @client.zrank("key", "four").should be_nil
244
+ expect(@client.zrank("key", "three")).to eq(2)
245
+ expect(@client.zrank("key", "four")).to be_nil
203
246
  end
204
247
 
205
248
  it "should determine the reversed index of a member in a sorted set" do
@@ -207,16 +250,16 @@ module FakeRedis
207
250
  @client.zadd("key", 2, "two")
208
251
  @client.zadd("key", 3, "three")
209
252
 
210
- @client.zrevrank("key", "three").should be == 0
211
- @client.zrevrank("key", "four").should be_nil
253
+ expect(@client.zrevrank("key", "three")).to eq(0)
254
+ expect(@client.zrevrank("key", "four")).to be_nil
212
255
  end
213
256
 
214
257
  it "should not raise errors for zrank() on accessing a non-existing key in a sorted set" do
215
- @client.zrank("no_such_key", "no_suck_id").should be_nil
258
+ expect(@client.zrank("no_such_key", "no_suck_id")).to be_nil
216
259
  end
217
260
 
218
261
  it "should not raise errors for zrevrank() on accessing a non-existing key in a sorted set" do
219
- @client.zrevrank("no_such_key", "no_suck_id").should be_nil
262
+ expect(@client.zrevrank("no_such_key", "no_suck_id")).to be_nil
220
263
  end
221
264
 
222
265
  describe "#zinterstore" do
@@ -231,66 +274,82 @@ module FakeRedis
231
274
  end
232
275
 
233
276
  it "should intersect two keys with custom scores" do
234
- @client.zinterstore("out", ["key1", "key2"]).should be == 2
235
- @client.zrange("out", 0, -1, :with_scores => true).should be == [['two', (2 + 5)], ['three', (3 + 7)]]
277
+ expect(@client.zinterstore("out", ["key1", "key2"])).to eq(2)
278
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['two', (2 + 5)], ['three', (3 + 7)]])
236
279
  end
237
280
 
238
281
  it "should intersect two keys with a default score" do
239
- @client.zinterstore("out", ["key1", "key3"]).should be == 2
240
- @client.zrange("out", 0, -1, :with_scores => true).should be == [['one', (1 + 1)], ['two', (2 + 1)]]
282
+ expect(@client.zinterstore("out", ["key1", "key3"])).to eq(2)
283
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['one', (1 + 1)], ['two', (2 + 1)]])
241
284
  end
242
285
 
243
286
  it "should intersect more than two keys" do
244
- @client.zinterstore("out", ["key1", "key2", "key3"]).should be == 1
245
- @client.zrange("out", 0, -1, :with_scores => true).should be == [['two', (2 + 5 + 1)]]
287
+ expect(@client.zinterstore("out", ["key1", "key2", "key3"])).to eq(1)
288
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([['two', (2 + 5 + 1)]])
246
289
  end
247
290
 
248
291
  it "should not intersect an unknown key" do
249
- @client.zinterstore("out", ["key1", "no_key"]).should be == 0
250
- @client.zrange("out", 0, -1, :with_scores => true).should be == []
292
+ expect(@client.zinterstore("out", ["key1", "no_key"])).to eq(0)
293
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([])
251
294
  end
252
295
 
253
296
  it "should intersect two keys by minimum values" do
254
- @client.zinterstore("out", ["key1", "key2"], :aggregate => :min).should be == 2
255
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", 2], ["three", 3]]
297
+ expect(@client.zinterstore("out", ["key1", "key2"], :aggregate => :min)).to eq(2)
298
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 2], ["three", 3]])
256
299
  end
257
300
 
258
301
  it "should intersect two keys by maximum values" do
259
- @client.zinterstore("out", ["key1", "key2"], :aggregate => :max).should be == 2
260
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", 5], ["three", 7]]
302
+ expect(@client.zinterstore("out", ["key1", "key2"], :aggregate => :max)).to eq(2)
303
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 5], ["three", 7]])
261
304
  end
262
305
 
263
306
  it "should intersect two keys by explicitly summing values" do
264
- @client.zinterstore("out", %w(key1 key2), :aggregate => :sum).should be == 2
265
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", (2 + 5)], ["three", (3 + 7)]]
307
+ expect(@client.zinterstore("out", %w(key1 key2), :aggregate => :sum)).to eq(2)
308
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 + 5)], ["three", (3 + 7)]])
266
309
  end
267
310
 
268
311
  it "should intersect two keys with weighted values" do
269
- @client.zinterstore("out", %w(key1 key2), :weights => [10, 1]).should be == 2
270
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", (2 * 10 + 5)], ["three", (3 * 10 + 7)]]
312
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1])).to eq(2)
313
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 * 10 + 5)], ["three", (3 * 10 + 7)]])
271
314
  end
272
315
 
273
316
  it "should intersect two keys with weighted minimum values" do
274
- @client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min).should be == 2
275
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", 5], ["three", 7]]
317
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min)).to eq(2)
318
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", 5], ["three", 7]])
276
319
  end
277
320
 
278
321
  it "should intersect two keys with weighted maximum values" do
279
- @client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max).should be == 2
280
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["two", (2 * 10)], ["three", (3 * 10)]]
322
+ expect(@client.zinterstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max)).to eq(2)
323
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["two", (2 * 10)], ["three", (3 * 10)]])
281
324
  end
282
325
 
283
326
  it "should error without enough weights given" do
284
- lambda { @client.zinterstore("out", %w(key1 key2), :weights => []) }.should raise_error(Redis::CommandError, "ERR syntax error")
285
- lambda { @client.zinterstore("out", %w(key1 key2), :weights => [10]) }.should raise_error(Redis::CommandError, "ERR syntax error")
327
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => []) }.to raise_error(Redis::CommandError, "ERR syntax error")
328
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => [10]) }.to raise_error(Redis::CommandError, "ERR syntax error")
286
329
  end
287
330
 
288
331
  it "should error with too many weights given" do
289
- lambda { @client.zinterstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.should raise_error(Redis::CommandError, "ERR syntax error")
332
+ expect { @client.zinterstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.to raise_error(Redis::CommandError, "ERR syntax error")
290
333
  end
291
334
 
292
335
  it "should error with an invalid aggregate" do
293
- lambda { @client.zinterstore("out", %w(key1 key2), :aggregate => :invalid) }.should raise_error(Redis::CommandError, "ERR syntax error")
336
+ expect { @client.zinterstore("out", %w(key1 key2), :aggregate => :invalid) }.to raise_error(Redis::CommandError, "ERR syntax error")
337
+ end
338
+
339
+ it 'stores nothing when there are no members in common' do
340
+ @client.zadd("k1", 1, "1")
341
+ @client.zadd("k1", 1, "2")
342
+ @client.sadd("k2", "a")
343
+ @client.sadd("k3", "b")
344
+
345
+ expect(@client.zinterstore("out", %w(k1 k2 k3))).to eq(0)
346
+ expect(@client.zrange("out", 0, -1)).to eq([])
347
+ end
348
+
349
+ it 'handles range start being higher than number of members' do
350
+ @client.zadd("key", 1, "1")
351
+
352
+ expect(@client.zrange("key", 10, 10)).to eq([])
294
353
  end
295
354
  end
296
355
 
@@ -300,23 +359,23 @@ module FakeRedis
300
359
  @client.zadd("key", 2, "two")
301
360
  @client.zadd("key", 3, "three")
302
361
 
303
- @client.zremrangebyscore("key", 0, 2).should be == 2
304
- @client.zcard("key").should be == 1
362
+ expect(@client.zremrangebyscore("key", 0, 2)).to eq(2)
363
+ expect(@client.zcard("key")).to eq(1)
305
364
  end
306
365
 
307
366
  it "should remove items by score with infinity" do # Issue #50
308
367
  @client.zadd("key", 10.0, "one")
309
368
  @client.zadd("key", 20.0, "two")
310
369
  @client.zadd("key", 30.0, "three")
311
- @client.zremrangebyscore("key", "-inf", "+inf").should be == 3
312
- @client.zcard("key").should be == 0
313
- @client.zscore("key", "one").should be_nil
314
- @client.zscore("key", "two").should be_nil
315
- @client.zscore("key", "three").should be_nil
370
+ expect(@client.zremrangebyscore("key", "-inf", "+inf")).to eq(3)
371
+ expect(@client.zcard("key")).to eq(0)
372
+ expect(@client.zscore("key", "one")).to be_nil
373
+ expect(@client.zscore("key", "two")).to be_nil
374
+ expect(@client.zscore("key", "three")).to be_nil
316
375
  end
317
376
 
318
377
  it "should return 0 if the key didn't exist" do
319
- @client.zremrangebyscore("key", 0, 2).should be == 0
378
+ expect(@client.zremrangebyscore("key", 0, 2)).to eq(0)
320
379
  end
321
380
  end
322
381
 
@@ -326,8 +385,8 @@ module FakeRedis
326
385
  @client.zadd("key", 2, "two")
327
386
  @client.zadd("key", 3, "three")
328
387
 
329
- @client.zremrangebyrank("key", 0, 1).should be == 2
330
- @client.zcard('key').should be == 1
388
+ expect(@client.zremrangebyrank("key", 0, 1)).to eq(2)
389
+ expect(@client.zcard('key')).to eq(1)
331
390
  end
332
391
 
333
392
  it 'handles out of range requests' do
@@ -335,12 +394,12 @@ module FakeRedis
335
394
  @client.zadd("key", 2, "two")
336
395
  @client.zadd("key", 3, "three")
337
396
 
338
- @client.zremrangebyrank("key", 25, -1).should be == 0
339
- @client.zcard('key').should be == 3
397
+ expect(@client.zremrangebyrank("key", 25, -1)).to eq(0)
398
+ expect(@client.zcard('key')).to eq(3)
340
399
  end
341
400
 
342
401
  it "should return 0 if the key didn't exist" do
343
- @client.zremrangebyrank("key", 0, 1).should be == 0
402
+ expect(@client.zremrangebyrank("key", 0, 1)).to eq(0)
344
403
  end
345
404
  end
346
405
 
@@ -356,66 +415,66 @@ module FakeRedis
356
415
  end
357
416
 
358
417
  it "should union two keys with custom scores" do
359
- @client.zunionstore("out", %w(key1 key2)).should be == 3
360
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]]
418
+ expect(@client.zunionstore("out", %w(key1 key2))).to eq(3)
419
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]])
361
420
  end
362
421
 
363
422
  it "should union two keys with a default score" do
364
- @client.zunionstore("out", %w(key1 key3)).should be == 3
365
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", (1 + 1)], ["val2", (2 + 1)], ["val3", 3]]
423
+ expect(@client.zunionstore("out", %w(key1 key3))).to eq(3)
424
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 + 1)], ["val2", (2 + 1)], ["val3", 3]])
366
425
  end
367
426
 
368
427
  it "should union more than two keys" do
369
- @client.zunionstore("out", %w(key1 key2 key3)).should be == 3
370
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", (1 + 1)], ["val2", (2 + 5 + 1)], ["val3", (3 + 7)]]
428
+ expect(@client.zunionstore("out", %w(key1 key2 key3))).to eq(3)
429
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 + 1)], ["val2", (2 + 5 + 1)], ["val3", (3 + 7)]])
371
430
  end
372
431
 
373
432
  it "should union with an unknown key" do
374
- @client.zunionstore("out", %w(key1 no_key)).should be == 3
375
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", 1], ["val2", 2], ["val3", 3]]
433
+ expect(@client.zunionstore("out", %w(key1 no_key))).to eq(3)
434
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 2], ["val3", 3]])
376
435
  end
377
436
 
378
437
  it "should union two keys by minimum values" do
379
- @client.zunionstore("out", %w(key1 key2), :aggregate => :min).should be == 3
380
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", 1], ["val2", 2], ["val3", 3]]
438
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :min)).to eq(3)
439
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 2], ["val3", 3]])
381
440
  end
382
441
 
383
442
  it "should union two keys by maximum values" do
384
- @client.zunionstore("out", %w(key1 key2), :aggregate => :max).should be == 3
385
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", 1], ["val2", 5], ["val3", 7]]
443
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :max)).to eq(3)
444
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", 5], ["val3", 7]])
386
445
  end
387
446
 
388
447
  it "should union two keys by explicitly summing values" do
389
- @client.zunionstore("out", %w(key1 key2), :aggregate => :sum).should be == 3
390
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]]
448
+ expect(@client.zunionstore("out", %w(key1 key2), :aggregate => :sum)).to eq(3)
449
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", 1], ["val2", (2 + 5)], ["val3", (3 + 7)]])
391
450
  end
392
451
 
393
452
  it "should union two keys with weighted values" do
394
- @client.zunionstore("out", %w(key1 key2), :weights => [10, 1]).should be == 3
395
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", (1 * 10)], ["val2", (2 * 10 + 5)], ["val3", (3 * 10 + 7)]]
453
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1])).to eq(3)
454
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 * 10)], ["val2", (2 * 10 + 5)], ["val3", (3 * 10 + 7)]])
396
455
  end
397
456
 
398
457
  it "should union two keys with weighted minimum values" do
399
- @client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min).should be == 3
400
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val2", 5], ["val3", 7], ["val1", (1 * 10)]]
458
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :min)).to eq(3)
459
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val2", 5], ["val3", 7], ["val1", (1 * 10)]])
401
460
  end
402
461
 
403
462
  it "should union two keys with weighted maximum values" do
404
- @client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max).should be == 3
405
- @client.zrange("out", 0, -1, :with_scores => true).should be == [["val1", (1 * 10)], ["val2", (2 * 10)], ["val3", (3 * 10)]]
463
+ expect(@client.zunionstore("out", %w(key1 key2), :weights => [10, 1], :aggregate => :max)).to eq(3)
464
+ expect(@client.zrange("out", 0, -1, :with_scores => true)).to eq([["val1", (1 * 10)], ["val2", (2 * 10)], ["val3", (3 * 10)]])
406
465
  end
407
466
 
408
467
  it "should error without enough weights given" do
409
- lambda { @client.zunionstore("out", %w(key1 key2), :weights => []) }.should raise_error(Redis::CommandError, "ERR syntax error")
410
- lambda { @client.zunionstore("out", %w(key1 key2), :weights => [10]) }.should raise_error(Redis::CommandError, "ERR syntax error")
468
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => []) }.to raise_error(Redis::CommandError, "ERR syntax error")
469
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => [10]) }.to raise_error(Redis::CommandError, "ERR syntax error")
411
470
  end
412
471
 
413
472
  it "should error with too many weights given" do
414
- lambda { @client.zunionstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.should raise_error(Redis::CommandError, "ERR syntax error")
473
+ expect { @client.zunionstore("out", %w(key1 key2), :weights => [10, 1, 1]) }.to raise_error(Redis::CommandError, "ERR syntax error")
415
474
  end
416
475
 
417
476
  it "should error with an invalid aggregate" do
418
- lambda { @client.zunionstore("out", %w(key1 key2), :aggregate => :invalid) }.should raise_error(Redis::CommandError, "ERR syntax error")
477
+ expect { @client.zunionstore("out", %w(key1 key2), :aggregate => :invalid) }.to raise_error(Redis::CommandError, "ERR syntax error")
419
478
  end
420
479
  end
421
480
 
@@ -434,7 +493,280 @@ module FakeRedis
434
493
  it "zrem should remove members add by zadd" do
435
494
  @client.zadd("key1", 1, 3)
436
495
  @client.zrem("key1", 3)
437
- @client.zscore("key1", 3).should be_nil
496
+ expect(@client.zscore("key1", 3)).to be_nil
497
+ end
498
+
499
+ describe "#zscan" do
500
+ before { 50.times { |x| @client.zadd("key", x, "key #{x}") } }
501
+
502
+ it 'with no arguments should return 10 numbers in ascending order' do
503
+ result = @client.zscan("key", 0)[1]
504
+ expect(result).to eq(result.sort { |x, y| x[1] <=> y[1] })
505
+ expect(result.count).to eq(10)
506
+ end
507
+
508
+ it 'with a count should return that number of members' do
509
+ expect(@client.zscan("key", 0, count: 2)).to eq(["2", [["key 0", 0.0], ["key 1", 1.0]]])
510
+ end
511
+
512
+ it 'with a count greater than the number of members, returns all the members in asc order' do
513
+ result = @client.zscan("key", 0, count: 1000)[1]
514
+ expect(result).to eq(result.sort { |x, y| x[1] <=> y[1] })
515
+ expect(result.size).to eq(50)
516
+ end
517
+
518
+ it 'with match, should return key-values where the key matches' do
519
+ @client.zadd("key", 1.0, "blah")
520
+ @client.zadd("key", 2.0, "bluh")
521
+ result = @client.zscan("key", 0, count: 100, match: "key*")[1]
522
+ expect(result).to_not include(["blah", 1.0])
523
+ expect(result).to_not include(["bluh", 2.0])
524
+ end
525
+ end
526
+
527
+ describe "#zscan_each" do
528
+ before { 50.times { |x| @client.zadd("key", x, "key #{x}") } }
529
+
530
+ it 'enumerates over the items in the sorted set' do
531
+ expect(@client.zscan_each("key").to_a).to eq(@client.zscan("key", 0, count: 50)[1])
532
+ end
533
+ end
534
+
535
+ describe '#zrangebylex' do
536
+ before { @client.zadd "myzset", [0, 'a', 0, 'b', 0, 'd', 0, 'c'] }
537
+
538
+ it "should return empty list for '+'..'-' range" do
539
+ ranged = @client.zrangebylex "myzset", "+", "-"
540
+ expect(ranged).to be_empty
541
+ end
542
+
543
+ it "should return all elements for '-'..'+' range" do
544
+ ranged = @client.zrangebylex "myzset", "-", "+"
545
+ expect(ranged).to eq %w(a b c d)
546
+ end
547
+
548
+ it "should include values starting with [ symbol" do
549
+ ranged = @client.zrangebylex "myzset", "-", "[c"
550
+ expect(ranged).to eq %w(a b c)
551
+ end
552
+
553
+ it "should exclude values with ( symbol" do
554
+ ranged = @client.zrangebylex "myzset", "-", "(c"
555
+ expect(ranged).to eq %w(a b)
556
+ end
557
+
558
+ it "should work with both [ and ( properly" do
559
+ ranged = @client.zrangebylex "myzset", "[aaa", "(d"
560
+ expect(ranged).to eq %w(b c)
561
+ end
562
+
563
+ it "should return empty array if key is not exist" do
564
+ ranged = @client.zrangebylex "puppies", "-", "+"
565
+ expect(ranged).to be_empty
566
+ end
567
+
568
+ it 'should raise error for invalid range when range is invalid' do
569
+ expect{ @client.zrangebylex "myzset", "-", "d" }.to raise_error(Redis::CommandError, "ERR min or max not valid string range item")
570
+ end
571
+
572
+ it "should limit and offset values as 4th argument" do
573
+ ranged = @client.zrangebylex "myzset", "-", "+", limit: [1, 3]
574
+ expect(ranged).to eq %w(b c d)
575
+ end
576
+ end
577
+
578
+ describe "#zrevrangebylex" do
579
+ before { @client.zadd "myzset", [0, 'a', 0, 'b', 0, 'd', 0, 'c'] }
580
+
581
+ it "should return empty list for '-'..'+' range" do
582
+ ranged = @client.zrevrangebylex "myzset", "-", "+"
583
+ expect(ranged).to be_empty
584
+ end
585
+
586
+ it "should return all elements for '+'..'-' range in descending order" do
587
+ ranged = @client.zrevrangebylex "myzset", "+", "-"
588
+ expect(ranged).to eq %w(d c b a)
589
+ end
590
+
591
+ it "should include values starting with [ symbol" do
592
+ ranged = @client.zrevrangebylex "myzset", "[c", "-"
593
+ expect(ranged).to eq %w(c b a)
594
+ end
595
+
596
+ it "should exclude values with ( symbol" do
597
+ ranged = @client.zrevrangebylex "myzset", "+", "(c"
598
+ expect(ranged).to eq %w(d)
599
+ end
600
+
601
+ it "should work with both [ and ( properly" do
602
+ ranged = @client.zrevrangebylex "myzset", "(d", "[aaa"
603
+ expect(ranged).to eq %w(c b)
604
+ end
605
+
606
+ it "should return empty array if key does not exist" do
607
+ ranged = @client.zrevrangebylex "puppies", "+", "-"
608
+ expect(ranged).to be_empty
609
+ end
610
+
611
+ it 'should raise error for invalid range when range is invalid' do
612
+ expect { @client.zrevrangebylex "myzset", "-", "d" }.to raise_error(Redis::CommandError, "ERR min or max not valid string range item")
613
+ end
614
+
615
+ it "should limit and offset values as 4th argument" do
616
+ pending "current stable (3.2.0) redis-rb doesn't support limit option"
617
+
618
+ ranged = @client.zrevrangebylex "myzset", "+", "-", limit: [0, 3]
619
+ expect(ranged).to eq %w(d c b)
620
+ end
621
+ end
622
+
623
+ describe "#zadd" do
624
+ context "with {incr: true}" do
625
+ before { @client.zadd("key", 1, "existing") }
626
+ it "should increment the element's score with the provided value" do
627
+ @client.zadd("key", 99, "existing", incr: true)
628
+ expect(@client.zscore("key", "existing")).to eq(100.0)
629
+
630
+ @client.zadd("key", 2, "new", incr: true)
631
+ expect(@client.zscore("key", "new")).to eq(2.0)
632
+ end
633
+
634
+ it "should error when trying to add multiple increment-element pairs" do
635
+ expect {
636
+ @client.zadd("key", [1, "member1", 2, "member2"], incr: true)
637
+ }.to raise_error(Redis::CommandError, "ERR INCR option supports a single increment-element pair")
638
+ end
639
+ end
640
+
641
+ context "with {nx: true}" do
642
+ before { @client.zadd("key", [1, "existing1", 2, "existing2"]) }
643
+ it "should add new elements but not update the scores of existing elements" do
644
+ @client.zadd("key", [101, "existing1", 3, "new"], nx: true)
645
+
646
+ expect(@client.zscore("key", "existing1")).to eq(1.0)
647
+ expect(@client.zscore("key", "new")).to eq(3.0)
648
+
649
+ @client.zadd("key", 102, "existing2", nx: true)
650
+ expect(@client.zscore("key", "existing2")).to eq(2.0)
651
+ end
652
+ end
653
+
654
+ context "with {xx: true}" do
655
+ before { @client.zadd("key", 1, "existing") }
656
+ it "should not add new elements" do
657
+ expect(@client.zadd("key", 1, "new1", xx: true)).to eq(false)
658
+ expect(@client.zscore("key", "new1")).to be_nil
659
+
660
+ expect(@client.zadd("key", [11, "existing", 2, "new2"], xx: true)).to eq(0)
661
+ expect(@client.zscore("key", "existing")).to eq(11.0)
662
+ expect(@client.zscore("key", "new2")).to be_nil
663
+ end
664
+ end
665
+
666
+ context "with {ch: true}" do
667
+ it "should return the number of new elements added plus the number of existing elements for which the score was updated" do
668
+ expect(@client.zadd("key", 1, "first", ch: true)).to eq(true)
669
+
670
+ expect(@client.zadd("key", [1, "first", 2, "second"], ch: true)).to eq(1.0)
671
+ expect(@client.zadd("key", [11, "first", 2, "second"], ch: true)).to eq(1.0)
672
+ expect(@client.zadd("key", [99, "first", 99, "second"], ch: true)).to eq(2.0)
673
+ expect(@client.zadd("key", [111, "first", 22, "second", 3, "third"], ch: true)).to eq(3.0)
674
+ end
675
+ end
676
+
677
+ context "with {nx: true, xx: true}" do
678
+ it "should error" do
679
+ expect{
680
+ @client.zadd("key", 1, "value", nx: true, xx: true)
681
+ }.to raise_error(Redis::CommandError, "ERR XX and NX options at the same time are not compatible")
682
+ end
683
+ end
684
+
685
+ context "with {nx: true, incr: true}" do
686
+ let(:options) { {nx: true, incr: true} }
687
+ it "should increment to the provided score only if the element is new and return the element's score" do
688
+ expect(@client.zadd("key", 1, "first", options)).to eq(1.0)
689
+ expect(@client.zscore("key", "first")).to eq(1.0)
690
+
691
+ expect(@client.zadd("key", 2, "second", options)).to eq(2.0)
692
+ expect(@client.zscore("key", "second")).to eq(2.0)
693
+
694
+ expect(@client.zadd("key", 99, "first", options)).to be_nil
695
+ expect(@client.zscore("key", "first")).to eq(1.0)
696
+ end
697
+ end
698
+
699
+ context "with {nx: true, ch: true}" do
700
+ let(:options) { {nx: true, ch: true} }
701
+ it "should add only new elements, not update existing elements, and return the number of added elements" do
702
+ expect(@client.zadd("key", 1, "first", options)).to eq(true)
703
+ expect(@client.zadd("key", 1, "first", options)).to eq(false)
704
+
705
+ # add two new elements
706
+ expect(@client.zadd("key", [99, "first", 2, "second", 3, "third"], options)).to eq(2)
707
+ expect(@client.zscore("key", "first")).to eq(1.0)
708
+ end
709
+ end
710
+
711
+ context "with {nx: true, incr: true, ch: true}" do
712
+ let(:options) { {nx: true, incr: true, ch: true} }
713
+
714
+ it "should add only new elements" do
715
+ expect(@client.zadd("key", 1, "first", options)).to eq(1.0)
716
+ expect(@client.zadd("key", 99, "first", options)).to be_nil
717
+ expect(@client.zscore("key", "first")).to eq(1.0)
718
+ end
719
+
720
+ # when INCR is present, return value is always the new score of member
721
+ it "should return the score of the new member" do
722
+ expect(@client.zadd("key", 2, "second", options)).to eq(2.0)
723
+ end
724
+
725
+ it "should return nil when the member already exists" do
726
+ @client.zadd("key", 1, "first")
727
+ expect(@client.zadd("key", 99, "first", options)).to be_nil
728
+ end
729
+ end
730
+
731
+ context "with {xx: true, incr: true}" do
732
+ let(:options) { {xx: true, incr: true} }
733
+ before { @client.zadd("key", 1, "existing") }
734
+
735
+ it "should return nil if the member does not already exist" do
736
+ expect(@client.zadd("key", 1, "new1", options)).to be_nil
737
+ expect(@client.zscore("key", "new1")).to be_nil
738
+ end
739
+
740
+ it "should increment only existing elements" do
741
+ expect(@client.zadd("key", [11, "existing"], options)).to eq(12.0)
742
+ expect(@client.zscore("key", "existing")).to eq(12.0)
743
+ end
744
+ end
745
+
746
+ context "with {xx: true, ch: true}" do
747
+ let(:options) { {xx: true, ch: true} }
748
+ it "should return the number of updated elements and not add new members" do
749
+ @client.zadd("key", 1, "first")
750
+
751
+ expect(@client.zadd("key", 99, "first", options)).to eq(true)
752
+ expect(@client.zadd("key", [100, "first", 2, "second"], options)).to eq(1.0)
753
+ expect(@client.zscore("key", "second")).to be_nil
754
+ end
755
+ end
756
+
757
+ context "with {xx: true, incr: true, ch: true}" do
758
+ let(:options) { {xx: true, incr: true, ch: true} }
759
+ before { @client.zadd("key", 1, "existing") }
760
+
761
+ # when INCR is present, return value is always the new score of member
762
+ it "should return the new score of the inserted member" do
763
+ expect(@client.zadd("key", 2, "existing", options)).to eq(3.0)
764
+ end
765
+
766
+ it "should increment only existing elements" do
767
+ expect(@client.zadd("key", 1, "new", options)).to be_nil
768
+ end
769
+ end
438
770
  end
439
771
  end
440
772
  end