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.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.travis.yml +14 -5
- data/LICENSE +1 -1
- data/README.md +42 -24
- data/fakeredis.gemspec +1 -1
- data/lib/fakeredis.rb +28 -0
- data/lib/fakeredis/bitop_command.rb +56 -0
- data/lib/fakeredis/command_executor.rb +6 -9
- data/lib/fakeredis/expiring_hash.rb +3 -5
- data/lib/fakeredis/geo_commands.rb +142 -0
- data/lib/fakeredis/geo_set.rb +84 -0
- data/lib/fakeredis/minitest.rb +24 -0
- data/lib/fakeredis/rspec.rb +1 -0
- data/lib/fakeredis/sort_method.rb +3 -3
- data/lib/fakeredis/sorted_set_store.rb +1 -1
- data/lib/fakeredis/transaction_commands.rb +2 -2
- data/lib/fakeredis/version.rb +1 -1
- data/lib/fakeredis/zset.rb +8 -2
- data/lib/redis/connection/memory.rb +650 -82
- data/spec/bitop_command_spec.rb +209 -0
- data/spec/command_executor_spec.rb +15 -0
- data/spec/compatibility_spec.rb +1 -1
- data/spec/connection_spec.rb +21 -21
- data/spec/fakeredis_spec.rb +73 -0
- data/spec/geo_set_spec.rb +164 -0
- data/spec/hashes_spec.rb +138 -57
- data/spec/hyper_log_logs_spec.rb +50 -0
- data/spec/keys_spec.rb +232 -90
- data/spec/lists_spec.rb +91 -35
- data/spec/memory_spec.rb +80 -7
- data/spec/server_spec.rb +38 -24
- data/spec/sets_spec.rb +112 -46
- data/spec/sort_method_spec.rb +6 -0
- data/spec/sorted_sets_spec.rb +482 -150
- data/spec/spec_helper.rb +9 -18
- data/spec/spec_helper_live_redis.rb +4 -4
- data/spec/strings_spec.rb +113 -79
- data/spec/subscription_spec.rb +107 -0
- data/spec/support/shared_examples/bitwise_operation.rb +59 -0
- data/spec/support/shared_examples/sortable.rb +20 -16
- data/spec/transactions_spec.rb +34 -13
- data/spec/upcase_method_name_spec.rb +2 -2
- metadata +23 -6
data/spec/hashes_spec.rb
CHANGED
@@ -9,168 +9,194 @@ module FakeRedis
|
|
9
9
|
it "should delete a hash field" do
|
10
10
|
@client.hset("key1", "k1", "val1")
|
11
11
|
@client.hset("key1", "k2", "val2")
|
12
|
-
@client.hdel("key1", "k1").
|
12
|
+
expect(@client.hdel("key1", "k1")).to be(1)
|
13
13
|
|
14
|
-
@client.hget("key1", "k1").
|
15
|
-
@client.hget("key1", "k2").
|
14
|
+
expect(@client.hget("key1", "k1")).to be_nil
|
15
|
+
expect(@client.hget("key1", "k2")).to eq("val2")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should delete array of fields" do
|
19
|
+
@client.hset("key1", "k1", "val1")
|
20
|
+
@client.hset("key1", "k2", "val2")
|
21
|
+
@client.hset("key1", "k3", "val3")
|
22
|
+
expect(@client.hdel("key1", ["k1", "k2"])).to be(2)
|
23
|
+
|
24
|
+
expect(@client.hget("key1", "k1")).to be_nil
|
25
|
+
expect(@client.hget("key1", "k2")).to be_nil
|
26
|
+
expect(@client.hget("key1", "k3")).to eq("val3")
|
16
27
|
end
|
17
28
|
|
18
29
|
it "should remove a hash with no keys left" do
|
19
30
|
@client.hset("key1", "k1", "val1")
|
20
31
|
@client.hset("key1", "k2", "val2")
|
21
|
-
@client.hdel("key1", "k1").
|
22
|
-
@client.hdel("key1", "k2").
|
32
|
+
expect(@client.hdel("key1", "k1")).to be(1)
|
33
|
+
expect(@client.hdel("key1", "k2")).to be(1)
|
23
34
|
|
24
|
-
@client.exists("key1").
|
35
|
+
expect(@client.exists("key1")).to eq(false)
|
25
36
|
end
|
26
37
|
|
27
38
|
it "should convert key to a string for hset" do
|
28
39
|
m = double("key")
|
29
|
-
m.
|
40
|
+
allow(m).to receive(:to_s).and_return("foo")
|
30
41
|
|
31
42
|
@client.hset("key1", m, "bar")
|
32
|
-
@client.hget("key1", "foo").
|
43
|
+
expect(@client.hget("key1", "foo")).to eq("bar")
|
33
44
|
end
|
34
45
|
|
35
46
|
it "should convert key to a string for hget" do
|
36
47
|
m = double("key")
|
37
|
-
m.
|
48
|
+
allow(m).to receive(:to_s).and_return("foo")
|
38
49
|
|
39
50
|
@client.hset("key1", "foo", "bar")
|
40
|
-
@client.hget("key1", m).
|
51
|
+
expect(@client.hget("key1", m)).to eq("bar")
|
41
52
|
end
|
42
53
|
|
43
54
|
it "should determine if a hash field exists" do
|
44
55
|
@client.hset("key1", "index", "value")
|
45
56
|
|
46
|
-
@client.hexists("key1", "index").
|
47
|
-
@client.hexists("key2", "i2").
|
57
|
+
expect(@client.hexists("key1", "index")).to be true
|
58
|
+
expect(@client.hexists("key2", "i2")).to be false
|
48
59
|
end
|
49
60
|
|
50
61
|
it "should get the value of a hash field" do
|
51
62
|
@client.hset("key1", "index", "value")
|
52
63
|
|
53
|
-
@client.hget("key1", "index").
|
64
|
+
expect(@client.hget("key1", "index")).to eq("value")
|
54
65
|
end
|
55
66
|
|
56
67
|
it "should get all the fields and values in a hash" do
|
57
68
|
@client.hset("key1", "i1", "val1")
|
58
69
|
@client.hset("key1", "i2", "val2")
|
59
70
|
|
60
|
-
@client.hgetall("key1").
|
71
|
+
expect(@client.hgetall("key1")).to eq({"i1" => "val1", "i2" => "val2"})
|
61
72
|
end
|
62
73
|
|
63
74
|
it "should increment the integer value of a hash field by the given number" do
|
64
75
|
@client.hset("key1", "cont1", "5")
|
65
|
-
@client.hincrby("key1", "cont1", "5").
|
66
|
-
@client.hget("key1", "cont1").
|
76
|
+
expect(@client.hincrby("key1", "cont1", "5")).to eq(10)
|
77
|
+
expect(@client.hget("key1", "cont1")).to eq("10")
|
67
78
|
end
|
68
79
|
|
69
80
|
it "should increment non existing hash keys" do
|
70
|
-
@client.hget("key1", "cont2").
|
71
|
-
@client.hincrby("key1", "cont2", "5").
|
81
|
+
expect(@client.hget("key1", "cont2")).to be_nil
|
82
|
+
expect(@client.hincrby("key1", "cont2", "5")).to eq(5)
|
72
83
|
end
|
73
84
|
|
74
85
|
it "should increment the float value of a hash field by the given float" do
|
75
86
|
@client.hset("key1", "cont1", 5.0)
|
76
|
-
@client.hincrbyfloat("key1", "cont1", 4.1).
|
77
|
-
@client.hget("key1", "cont1").
|
87
|
+
expect(@client.hincrbyfloat("key1", "cont1", 4.1)).to eq(9.1)
|
88
|
+
expect(@client.hget("key1", "cont1")).to eq("9.1")
|
78
89
|
end
|
79
90
|
|
80
91
|
it "should increment non existing hash keys" do
|
81
|
-
@client.hget("key1", "cont2").
|
82
|
-
@client.hincrbyfloat("key1", "cont2", 5.5).
|
92
|
+
expect(@client.hget("key1", "cont2")).to be_nil
|
93
|
+
expect(@client.hincrbyfloat("key1", "cont2", 5.5)).to eq(5.5)
|
83
94
|
end
|
84
95
|
|
85
96
|
it "should get all the fields in a hash" do
|
86
97
|
@client.hset("key1", "i1", "val1")
|
87
98
|
@client.hset("key1", "i2", "val2")
|
88
99
|
|
89
|
-
@client.hkeys("key1").
|
90
|
-
@client.hkeys("key2").
|
100
|
+
expect(@client.hkeys("key1")).to match_array(["i1", "i2"])
|
101
|
+
expect(@client.hkeys("key2")).to eq([])
|
91
102
|
end
|
92
103
|
|
93
104
|
it "should get the number of fields in a hash" do
|
94
105
|
@client.hset("key1", "i1", "val1")
|
95
106
|
@client.hset("key1", "i2", "val2")
|
96
107
|
|
97
|
-
@client.hlen("key1").
|
108
|
+
expect(@client.hlen("key1")).to eq(2)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should get the string length of the value associated with field in a hash" do
|
112
|
+
@client.hset("key1", "i1", "val1")
|
113
|
+
expect(@client.hstrlen("key1", "i1")).to eq(4)
|
114
|
+
expect(@client.hstrlen("key1", "nonexistent")).to eq(0)
|
115
|
+
expect(@client.hstrlen("nonexistent", "field")).to eq(0)
|
98
116
|
end
|
99
117
|
|
100
118
|
it "should get the values of all the given hash fields" do
|
101
119
|
@client.hset("key1", "i1", "val1")
|
102
120
|
@client.hset("key1", "i2", "val2")
|
103
121
|
|
104
|
-
@client.hmget("key1", "i1", "i2", "i3").
|
105
|
-
@client.hmget("key1", ["i1", "i2", "i3"]).
|
122
|
+
expect(@client.hmget("key1", "i1", "i2", "i3")).to match_array(["val1", "val2", nil])
|
123
|
+
expect(@client.hmget("key1", ["i1", "i2", "i3"])).to match_array(["val1", "val2", nil])
|
106
124
|
|
107
|
-
@client.hmget("key2", "i1", "i2").
|
125
|
+
expect(@client.hmget("key2", "i1", "i2")).to eq([nil, nil])
|
108
126
|
end
|
109
127
|
|
110
128
|
it "should throw an argument error when you don't ask for any keys" do
|
111
|
-
|
129
|
+
expect { @client.hmget("key1") }.to raise_error(Redis::CommandError)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should throw an argument error when the list of keys you ask for is empty" do
|
133
|
+
expect { @client.hmget("key1", []) }.to raise_error(Redis::CommandError)
|
112
134
|
end
|
113
135
|
|
114
136
|
it "should reject an empty list of values" do
|
115
|
-
|
116
|
-
@client.exists("key").
|
137
|
+
expect { @client.hmset("key") }.to raise_error(Redis::CommandError)
|
138
|
+
expect(@client.exists("key")).to be false
|
117
139
|
end
|
118
140
|
|
119
141
|
it "rejects an insert with a key but no value" do
|
120
|
-
|
121
|
-
|
122
|
-
@client.exists("key").
|
142
|
+
expect { @client.hmset("key", 'foo') }.to raise_error(Redis::CommandError)
|
143
|
+
expect { @client.hmset("key", 'foo', 3, 'bar') }.to raise_error(Redis::CommandError)
|
144
|
+
expect(@client.exists("key")).to be false
|
123
145
|
end
|
124
146
|
|
125
147
|
it "should reject the wrong number of arguments" do
|
126
|
-
|
148
|
+
expect { @client.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3") }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for HMSET")
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should return OK on success" do
|
152
|
+
expect(@client.hmset("key", "k1", "value1")).to eq("OK")
|
127
153
|
end
|
128
154
|
|
129
155
|
it "should set multiple hash fields to multiple values" do
|
130
156
|
@client.hmset("key", "k1", "value1", "k2", "value2")
|
131
157
|
|
132
|
-
@client.hget("key", "k1").
|
133
|
-
@client.hget("key", "k2").
|
158
|
+
expect(@client.hget("key", "k1")).to eq("value1")
|
159
|
+
expect(@client.hget("key", "k2")).to eq("value2")
|
134
160
|
end
|
135
161
|
|
136
162
|
it "should set multiple hash fields from a ruby hash to multiple values" do
|
137
163
|
@client.mapped_hmset("foo", :k1 => "value1", :k2 => "value2")
|
138
164
|
|
139
|
-
@client.hget("foo", "k1").
|
140
|
-
@client.hget("foo", "k2").
|
165
|
+
expect(@client.hget("foo", "k1")).to eq("value1")
|
166
|
+
expect(@client.hget("foo", "k2")).to eq("value2")
|
141
167
|
end
|
142
168
|
|
143
169
|
it "should set the string value of a hash field" do
|
144
|
-
@client.hset("key1", "k1", "val1").
|
145
|
-
@client.hset("key1", "k1", "val1").
|
170
|
+
expect(@client.hset("key1", "k1", "val1")).to eq(true)
|
171
|
+
expect(@client.hset("key1", "k1", "val1")).to eq(false)
|
146
172
|
|
147
|
-
@client.hget("key1", "k1").
|
173
|
+
expect(@client.hget("key1", "k1")).to eq("val1")
|
148
174
|
end
|
149
175
|
|
150
176
|
it "should set the value of a hash field, only if the field does not exist" do
|
151
177
|
@client.hset("key1", "k1", "val1")
|
152
|
-
@client.hsetnx("key1", "k1", "value").
|
153
|
-
@client.hsetnx("key1", "k2", "val2").
|
154
|
-
@client.hsetnx("key1", :k1, "value").
|
155
|
-
@client.hsetnx("key1", :k3, "val3").
|
156
|
-
|
157
|
-
@client.hget("key1", "k1").
|
158
|
-
@client.hget("key1", "k2").
|
159
|
-
@client.hget("key1", "k3").
|
178
|
+
expect(@client.hsetnx("key1", "k1", "value")).to eq(false)
|
179
|
+
expect(@client.hsetnx("key1", "k2", "val2")).to eq(true)
|
180
|
+
expect(@client.hsetnx("key1", :k1, "value")).to eq(false)
|
181
|
+
expect(@client.hsetnx("key1", :k3, "val3")).to eq(true)
|
182
|
+
|
183
|
+
expect(@client.hget("key1", "k1")).to eq("val1")
|
184
|
+
expect(@client.hget("key1", "k2")).to eq("val2")
|
185
|
+
expect(@client.hget("key1", "k3")).to eq("val3")
|
160
186
|
end
|
161
187
|
|
162
188
|
it "should get all the values in a hash" do
|
163
189
|
@client.hset("key1", "k1", "val1")
|
164
190
|
@client.hset("key1", "k2", "val2")
|
165
191
|
|
166
|
-
@client.hvals("key1").
|
192
|
+
expect(@client.hvals("key1")).to match_array(["val1", "val2"])
|
167
193
|
end
|
168
194
|
|
169
195
|
it "should accept a list of array pairs as arguments and not throw an invalid argument number error" do
|
170
196
|
@client.hmset("key1", [:k1, "val1"], [:k2, "val2"], [:k3, "val3"])
|
171
|
-
@client.hget("key1", :k1).
|
172
|
-
@client.hget("key1", :k2).
|
173
|
-
@client.hget("key1", :k3).
|
197
|
+
expect(@client.hget("key1", :k1)).to eq("val1")
|
198
|
+
expect(@client.hget("key1", :k2)).to eq("val2")
|
199
|
+
expect(@client.hget("key1", :k3)).to eq("val3")
|
174
200
|
end
|
175
201
|
|
176
202
|
it "should reject a list of arrays that contain an invalid number of arguments" do
|
@@ -179,17 +205,72 @@ module FakeRedis
|
|
179
205
|
|
180
206
|
it "should convert a integer field name to string for hdel" do
|
181
207
|
@client.hset("key1", "1", 1)
|
182
|
-
@client.hdel("key1", 1).
|
208
|
+
expect(@client.hdel("key1", 1)).to be(1)
|
183
209
|
end
|
184
210
|
|
185
211
|
it "should convert a integer field name to string for hexists" do
|
186
212
|
@client.hset("key1", "1", 1)
|
187
|
-
@client.hexists("key1", 1).
|
213
|
+
expect(@client.hexists("key1", 1)).to be true
|
188
214
|
end
|
189
215
|
|
190
216
|
it "should convert a integer field name to string for hincrby" do
|
191
217
|
@client.hset("key1", 1, 0)
|
192
|
-
@client.hincrby("key1", 1, 1).
|
218
|
+
expect(@client.hincrby("key1", 1, 1)).to be(1)
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "#hscan" do
|
222
|
+
it 'with no arguments and few items, returns all items' do
|
223
|
+
@client.hmset('hash', 'name', 'Jack', 'age', '33')
|
224
|
+
result = @client.hscan('hash', 0)
|
225
|
+
|
226
|
+
expect(result[0]).to eq('0')
|
227
|
+
expect(result[1]).to eq([['name', 'Jack'], ['age', '33']])
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'with a count should return that number of members or more' do
|
231
|
+
@client.hmset('hash',
|
232
|
+
'a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5', 'f', '6', 'g', '7'
|
233
|
+
)
|
234
|
+
result = @client.hscan('hash', 0, count: 3)
|
235
|
+
expect(result[0]).to eq('3')
|
236
|
+
expect(result[1]).to eq([
|
237
|
+
['a', '1'],
|
238
|
+
['b', '2'],
|
239
|
+
['c', '3'],
|
240
|
+
])
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'returns items starting at the provided cursor' do
|
244
|
+
@client.hmset('hash',
|
245
|
+
'a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5', 'f', '6', 'g', '7'
|
246
|
+
)
|
247
|
+
result = @client.hscan('hash', 2, count: 3)
|
248
|
+
expect(result[0]).to eq('5')
|
249
|
+
expect(result[1]).to eq([
|
250
|
+
['c', '3'],
|
251
|
+
['d', '4'],
|
252
|
+
['e', '5']
|
253
|
+
])
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'with match, returns items matching the given pattern' do
|
257
|
+
@client.hmset('hash',
|
258
|
+
'aa', '1', 'b', '2', 'cc', '3', 'd', '4', 'ee', '5', 'f', '6', 'gg', '7'
|
259
|
+
)
|
260
|
+
result = @client.hscan('hash', 2, count: 3, match: '??')
|
261
|
+
expect(result[0]).to eq('5')
|
262
|
+
expect(result[1]).to eq([
|
263
|
+
['cc', '3'],
|
264
|
+
['ee', '5']
|
265
|
+
])
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'returns an empty result if the key is not found' do
|
269
|
+
result = @client.hscan('hash', 0)
|
270
|
+
|
271
|
+
expect(result[0]).to eq('0')
|
272
|
+
expect(result[1]).to eq([])
|
273
|
+
end
|
193
274
|
end
|
194
275
|
end
|
195
276
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "HyperLogLogsMethods" do
|
5
|
+
let(:redis) { Redis.new }
|
6
|
+
|
7
|
+
it "should add item to hyperloglog" do
|
8
|
+
expect(redis.pfadd("hll", "val")).to eq(true)
|
9
|
+
expect(redis.pfcount("hll")).to eq(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not add duplicated item to hyperloglog" do
|
13
|
+
redis.pfadd("hll", "val")
|
14
|
+
expect(redis.pfadd("hll", "val")).to eq(false)
|
15
|
+
expect(redis.pfcount("hll")).to eq(1)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not add multiple items to hyperloglog" do
|
19
|
+
expect(redis.pfadd("hll", ["val1", "val2"])).to eq(true)
|
20
|
+
expect(redis.pfcount("hll")).to eq(2)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return zero as cardinality for nonexistent key" do
|
24
|
+
expect(redis.pfcount("nonexistent")).to eq(0)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return cardinality of union of hyperloglogs" do
|
28
|
+
redis.pfadd("hll1", ["val1", "val2"])
|
29
|
+
redis.pfadd("hll2", ["val2", "val3"])
|
30
|
+
expect(redis.pfcount("hll1", "hll2")).to eq(3)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should error if an empty list of keys is given" do
|
34
|
+
expect { redis.pfcount([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'pfcount' command")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should merge hyperloglogs" do
|
38
|
+
redis.pfadd("hll1", ["val1", "val2"])
|
39
|
+
redis.pfadd("hll2", ["val2", "val3"])
|
40
|
+
expect(redis.pfmerge("hll3", "hll1", "hll2")).to eq(true)
|
41
|
+
expect(redis.pfcount("hll3")).to eq(3)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should merge nonexistent hyperloglogs with others" do
|
45
|
+
redis.pfadd("hll1", "val")
|
46
|
+
expect(redis.pfmerge("hll3", "hll1", "nonexistent")).to eq(true)
|
47
|
+
expect(redis.pfcount("hll3")).to eq(1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/keys_spec.rb
CHANGED
@@ -7,56 +7,89 @@ module FakeRedis
|
|
7
7
|
@client = Redis.new
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
[:del, :unlink].each do |command|
|
11
|
+
it "should #{command} a key" do
|
12
|
+
@client.set("key1", "1")
|
13
|
+
@client.set("key2", "2")
|
14
|
+
@client.public_send(command, "key1", "key2")
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
expect(@client.get("key1")).to eq(nil)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
it "should #{command} multiple keys" do
|
20
|
+
@client.set("key1", "1")
|
21
|
+
@client.set("key2", "2")
|
22
|
+
@client.public_send(command, ["key1", "key2"])
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
expect(@client.get("key1")).to eq(nil)
|
25
|
+
expect(@client.get("key2")).to eq(nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the number of '#{command}'ed keys" do
|
29
|
+
@client.set("key1", "1")
|
30
|
+
expect(@client.public_send(command, ["key1", "key2"])).to eq(1)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should error '#{command}'ing no keys" do
|
34
|
+
expect { @client.public_send(command) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for '#{command}' command")
|
35
|
+
expect { @client.public_send(command, []) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for '#{command}' command")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return true when setnx keys that don't exist" do
|
40
|
+
expect(@client.setnx("key1", "1")).to eq(true)
|
25
41
|
end
|
26
42
|
|
27
|
-
it "should
|
28
|
-
|
29
|
-
|
43
|
+
it "should return false when setnx keys exist" do
|
44
|
+
@client.set("key1", "1")
|
45
|
+
expect(@client.setnx("key1", "1")).to eq(false)
|
30
46
|
end
|
31
47
|
|
32
48
|
it "should return true when setting expires on keys that exist" do
|
33
49
|
@client.set("key1", "1")
|
34
|
-
@client.expire("key1", 1).
|
50
|
+
expect(@client.expire("key1", 1)).to eq(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return true when setting pexpires on keys that exist" do
|
54
|
+
@client.set("key1", "1")
|
55
|
+
expect(@client.pexpire("key1", 1)).to eq(true)
|
35
56
|
end
|
36
57
|
|
37
58
|
it "should return false when attempting to set expires on a key that does not exist" do
|
38
|
-
@client.expire("key1", 1).
|
59
|
+
expect(@client.expire("key1", 1)).to eq(false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return false when attempting to set pexpires on a key that does not exist" do
|
63
|
+
expect(@client.pexpire("key1", 1)).to eq(false)
|
39
64
|
end
|
40
65
|
|
41
66
|
it "should determine if a key exists" do
|
42
67
|
@client.set("key1", "1")
|
43
68
|
|
44
|
-
@client.exists("key1").
|
45
|
-
@client.exists("key2").
|
69
|
+
expect(@client.exists("key1")).to eq(true)
|
70
|
+
expect(@client.exists("key2")).to eq(false)
|
46
71
|
end
|
47
72
|
|
48
73
|
it "should set a key's time to live in seconds" do
|
49
74
|
@client.set("key1", "1")
|
50
75
|
@client.expire("key1", 1)
|
51
76
|
|
52
|
-
@client.ttl("key1").
|
77
|
+
expect(@client.ttl("key1")).to eq(1)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should set a key's time to live in miliseconds" do
|
81
|
+
allow(Time).to receive(:now).and_return(1000)
|
82
|
+
@client.set("key1", "1")
|
83
|
+
@client.pexpire("key1", 2200)
|
84
|
+
expect(@client.pttl("key1")).to be_within(0.1).of(2200)
|
85
|
+
allow(Time).to receive(:now).and_call_original
|
53
86
|
end
|
54
87
|
|
55
88
|
it "should set the expiration for a key as a UNIX timestamp" do
|
56
89
|
@client.set("key1", "1")
|
57
90
|
@client.expireat("key1", Time.now.to_i + 2)
|
58
91
|
|
59
|
-
@client.ttl("key1").
|
92
|
+
expect(@client.ttl("key1")).to eq(2)
|
60
93
|
end
|
61
94
|
|
62
95
|
it "should not have an expiration after re-set" do
|
@@ -64,21 +97,21 @@ module FakeRedis
|
|
64
97
|
@client.expireat("key1", Time.now.to_i + 2)
|
65
98
|
@client.set("key1", "1")
|
66
99
|
|
67
|
-
@client.ttl("key1").
|
100
|
+
expect(@client.ttl("key1")).to eq(-1)
|
68
101
|
end
|
69
102
|
|
70
103
|
it "should not have a ttl if expired (and thus key does not exist)" do
|
71
104
|
@client.set("key1", "1")
|
72
105
|
@client.expireat("key1", Time.now.to_i)
|
73
106
|
|
74
|
-
@client.ttl("key1").
|
107
|
+
expect(@client.ttl("key1")).to eq(-2)
|
75
108
|
end
|
76
109
|
|
77
110
|
it "should not find a key if expired" do
|
78
111
|
@client.set("key1", "1")
|
79
112
|
@client.expireat("key1", Time.now.to_i)
|
80
113
|
|
81
|
-
@client.get("key1").
|
114
|
+
expect(@client.get("key1")).to be_nil
|
82
115
|
end
|
83
116
|
|
84
117
|
it "should not find multiple keys if expired" do
|
@@ -86,7 +119,7 @@ module FakeRedis
|
|
86
119
|
@client.set("key2", "2")
|
87
120
|
@client.expireat("key1", Time.now.to_i)
|
88
121
|
|
89
|
-
@client.mget("key1", "key2").
|
122
|
+
expect(@client.mget("key1", "key2")).to eq([nil, "2"])
|
90
123
|
end
|
91
124
|
|
92
125
|
it "should only find keys that aren't expired" do
|
@@ -94,14 +127,21 @@ module FakeRedis
|
|
94
127
|
@client.set("key2", "2")
|
95
128
|
@client.expireat("key1", Time.now.to_i)
|
96
129
|
|
97
|
-
@client.keys.
|
130
|
+
expect(@client.keys).to eq(["key2"])
|
98
131
|
end
|
99
132
|
|
100
133
|
it "should not exist if expired" do
|
101
134
|
@client.set("key1", "1")
|
102
135
|
@client.expireat("key1", Time.now.to_i)
|
103
136
|
|
104
|
-
@client.exists("key1").
|
137
|
+
expect(@client.exists("key1")).to be false
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should get integer and string keys" do
|
141
|
+
@client.set("key1", "1")
|
142
|
+
@client.set(2, "2")
|
143
|
+
|
144
|
+
expect(@client.mget("key1", 2)).to eq(["1", "2"])
|
105
145
|
end
|
106
146
|
|
107
147
|
it "should find all keys matching the given pattern" do
|
@@ -113,32 +153,32 @@ module FakeRedis
|
|
113
153
|
|
114
154
|
@client.mset("database", 1, "above", 2, "suitability", 3, "able", 4)
|
115
155
|
|
116
|
-
@client.keys("key:*").
|
117
|
-
@client.keys("ab*").
|
156
|
+
expect(@client.keys("key:*")).to match_array(["key:a", "key:b", "key:c"])
|
157
|
+
expect(@client.keys("ab*")).to match_array(["above", "able"])
|
118
158
|
end
|
119
159
|
|
120
160
|
it "should remove the expiration from a key" do
|
121
161
|
@client.set("key1", "1")
|
122
162
|
@client.expireat("key1", Time.now.to_i + 1)
|
123
|
-
@client.persist("key1").
|
124
|
-
@client.persist("key1").
|
163
|
+
expect(@client.persist("key1")).to eq(true)
|
164
|
+
expect(@client.persist("key1")).to eq(false)
|
125
165
|
|
126
|
-
@client.ttl("key1").
|
166
|
+
expect(@client.ttl("key1")).to eq(-1)
|
127
167
|
end
|
128
168
|
|
129
169
|
it "should return a random key from the keyspace" do
|
130
170
|
@client.set("key1", "1")
|
131
171
|
@client.set("key2", "2")
|
132
172
|
|
133
|
-
["key1", "key2"].include?(@client.randomkey).
|
173
|
+
expect(["key1", "key2"].include?(@client.randomkey)).to eq(true)
|
134
174
|
end
|
135
175
|
|
136
176
|
it "should rename a key" do
|
137
177
|
@client.set("key1", "2")
|
138
178
|
@client.rename("key1", "key2")
|
139
179
|
|
140
|
-
@client.get("key1").
|
141
|
-
@client.get("key2").
|
180
|
+
expect(@client.get("key1")).to eq(nil)
|
181
|
+
expect(@client.get("key2")).to eq("2")
|
142
182
|
end
|
143
183
|
|
144
184
|
it "should rename a key, only if new key does not exist" do
|
@@ -148,100 +188,100 @@ module FakeRedis
|
|
148
188
|
@client.renamenx("key1", "key2")
|
149
189
|
@client.renamenx("key3", "key4")
|
150
190
|
|
151
|
-
@client.get("key1").
|
152
|
-
@client.get("key2").
|
153
|
-
@client.get("key3").
|
154
|
-
@client.get("key4").
|
191
|
+
expect(@client.get("key1")).to eq("1")
|
192
|
+
expect(@client.get("key2")).to eq("2")
|
193
|
+
expect(@client.get("key3")).to eq(nil)
|
194
|
+
expect(@client.get("key4")).to eq("3")
|
155
195
|
end
|
156
196
|
|
157
197
|
it "should determine the type stored at key" do
|
158
198
|
# Non-existing key
|
159
|
-
@client.type("key0").
|
199
|
+
expect(@client.type("key0")).to eq("none")
|
160
200
|
|
161
201
|
# String
|
162
202
|
@client.set("key1", "1")
|
163
|
-
@client.type("key1").
|
203
|
+
expect(@client.type("key1")).to eq("string")
|
164
204
|
|
165
205
|
# List
|
166
206
|
@client.lpush("key2", "1")
|
167
|
-
@client.type("key2").
|
207
|
+
expect(@client.type("key2")).to eq("list")
|
168
208
|
|
169
209
|
# Set
|
170
210
|
@client.sadd("key3", "1")
|
171
|
-
@client.type("key3").
|
211
|
+
expect(@client.type("key3")).to eq("set")
|
172
212
|
|
173
213
|
# Sorted Set
|
174
214
|
@client.zadd("key4", 1.0, "1")
|
175
|
-
@client.type("key4").
|
215
|
+
expect(@client.type("key4")).to eq("zset")
|
176
216
|
|
177
217
|
# Hash
|
178
218
|
@client.hset("key5", "a", "1")
|
179
|
-
@client.type("key5").
|
219
|
+
expect(@client.type("key5")).to eq("hash")
|
180
220
|
end
|
181
221
|
|
182
222
|
it "should convert the value into a string before storing" do
|
183
223
|
@client.set("key1", 1)
|
184
|
-
@client.get("key1").
|
224
|
+
expect(@client.get("key1")).to eq("1")
|
185
225
|
|
186
226
|
@client.setex("key2", 30, 1)
|
187
|
-
@client.get("key2").
|
227
|
+
expect(@client.get("key2")).to eq("1")
|
188
228
|
|
189
229
|
@client.getset("key3", 1)
|
190
|
-
@client.get("key3").
|
230
|
+
expect(@client.get("key3")).to eq("1")
|
191
231
|
end
|
192
232
|
|
193
233
|
it "should return 'OK' for the setex command" do
|
194
|
-
@client.setex("key4", 30, 1).
|
234
|
+
expect(@client.setex("key4", 30, 1)).to eq("OK")
|
195
235
|
end
|
196
236
|
|
197
237
|
it "should convert the key into a string before storing" do
|
198
238
|
@client.set(123, "foo")
|
199
|
-
@client.keys.
|
200
|
-
@client.get("123").
|
239
|
+
expect(@client.keys).to include("123")
|
240
|
+
expect(@client.get("123")).to eq("foo")
|
201
241
|
|
202
242
|
@client.setex(456, 30, "foo")
|
203
|
-
@client.keys.
|
204
|
-
@client.get("456").
|
243
|
+
expect(@client.keys).to include("456")
|
244
|
+
expect(@client.get("456")).to eq("foo")
|
205
245
|
|
206
246
|
@client.getset(789, "foo")
|
207
|
-
@client.keys.
|
208
|
-
@client.get("789").
|
247
|
+
expect(@client.keys).to include("789")
|
248
|
+
expect(@client.get("789")).to eq("foo")
|
209
249
|
end
|
210
250
|
|
211
251
|
it "should only operate against keys containing string values" do
|
212
252
|
@client.sadd("key1", "one")
|
213
|
-
|
214
|
-
|
253
|
+
expect { @client.get("key1") }.to raise_error(Redis::CommandError, "WRONGTYPE Operation against a key holding the wrong kind of value")
|
254
|
+
expect { @client.getset("key1", 1) }.to raise_error(Redis::CommandError, "WRONGTYPE Operation against a key holding the wrong kind of value")
|
215
255
|
|
216
256
|
@client.hset("key2", "one", "two")
|
217
|
-
|
218
|
-
|
257
|
+
expect { @client.get("key2") }.to raise_error(Redis::CommandError, "WRONGTYPE Operation against a key holding the wrong kind of value")
|
258
|
+
expect { @client.getset("key2", 1) }.to raise_error(Redis::CommandError, "WRONGTYPE Operation against a key holding the wrong kind of value")
|
219
259
|
end
|
220
260
|
|
221
261
|
it "should move a key from one database to another successfully" do
|
222
262
|
@client.select(0)
|
223
263
|
@client.set("key1", "1")
|
224
264
|
|
225
|
-
@client.move("key1", 1).
|
265
|
+
expect(@client.move("key1", 1)).to eq(true)
|
226
266
|
|
227
267
|
@client.select(0)
|
228
|
-
@client.get("key1").
|
268
|
+
expect(@client.get("key1")).to be_nil
|
229
269
|
|
230
270
|
@client.select(1)
|
231
|
-
@client.get("key1").
|
271
|
+
expect(@client.get("key1")).to eq("1")
|
232
272
|
end
|
233
273
|
|
234
274
|
it "should fail to move a key that does not exist in the source database" do
|
235
275
|
@client.select(0)
|
236
|
-
@client.get("key1").
|
276
|
+
expect(@client.get("key1")).to be_nil
|
237
277
|
|
238
|
-
@client.move("key1", 1).
|
278
|
+
expect(@client.move("key1", 1)).to eq(false)
|
239
279
|
|
240
280
|
@client.select(0)
|
241
|
-
@client.get("key1").
|
281
|
+
expect(@client.get("key1")).to be_nil
|
242
282
|
|
243
283
|
@client.select(1)
|
244
|
-
@client.get("key1").
|
284
|
+
expect(@client.get("key1")).to be_nil
|
245
285
|
end
|
246
286
|
|
247
287
|
it "should fail to move a key that exists in the destination database" do
|
@@ -252,23 +292,23 @@ module FakeRedis
|
|
252
292
|
@client.set("key1", "2")
|
253
293
|
|
254
294
|
@client.select(0)
|
255
|
-
@client.move("key1", 1).
|
295
|
+
expect(@client.move("key1", 1)).to eq(false)
|
256
296
|
|
257
297
|
@client.select(0)
|
258
|
-
@client.get("key1").
|
298
|
+
expect(@client.get("key1")).to eq("1")
|
259
299
|
|
260
300
|
@client.select(1)
|
261
|
-
@client.get("key1").
|
301
|
+
expect(@client.get("key1")).to eq("2")
|
262
302
|
end
|
263
303
|
|
264
304
|
it "should fail to move a key to the same database" do
|
265
305
|
@client.select(0)
|
266
306
|
@client.set("key1", "1")
|
267
307
|
|
268
|
-
|
308
|
+
expect { @client.move("key1", 0) }.to raise_error(Redis::CommandError, "ERR source and destination objects are the same")
|
269
309
|
|
270
310
|
@client.select(0)
|
271
|
-
@client.get("key1").
|
311
|
+
expect(@client.get("key1")).to eq("1")
|
272
312
|
end
|
273
313
|
|
274
314
|
it "should scan all keys in the database" do
|
@@ -284,8 +324,8 @@ module FakeRedis
|
|
284
324
|
break if cursor == "0"
|
285
325
|
}
|
286
326
|
|
287
|
-
all_keys.uniq.size.
|
288
|
-
all_keys[0].
|
327
|
+
expect(all_keys.uniq.size).to eq(100)
|
328
|
+
expect(all_keys[0]).to match(/key\d+/)
|
289
329
|
end
|
290
330
|
|
291
331
|
it "should match keys to a pattern when scanning" do
|
@@ -304,7 +344,7 @@ module FakeRedis
|
|
304
344
|
break if cursor == "0"
|
305
345
|
}
|
306
346
|
|
307
|
-
all_keys.uniq.size.
|
347
|
+
expect(all_keys.uniq.size).to eq(50)
|
308
348
|
end
|
309
349
|
|
310
350
|
it "should specify doing more work when scanning" do
|
@@ -314,23 +354,23 @@ module FakeRedis
|
|
314
354
|
|
315
355
|
cursor, all_keys = @client.scan(cursor, :count => 100)
|
316
356
|
|
317
|
-
cursor.
|
318
|
-
all_keys.uniq.size.
|
357
|
+
expect(cursor).to eq("0")
|
358
|
+
expect(all_keys.uniq.size).to eq(100)
|
319
359
|
end
|
320
360
|
|
321
361
|
context "with extended options" do
|
322
362
|
it "uses ex option to set the expire time, in seconds" do
|
323
363
|
ttl = 7
|
324
364
|
|
325
|
-
@client.set("key1", "1", { :ex => ttl }).
|
326
|
-
@client.ttl("key1").
|
365
|
+
expect(@client.set("key1", "1", { :ex => ttl })).to eq("OK")
|
366
|
+
expect(@client.ttl("key1")).to eq(ttl)
|
327
367
|
end
|
328
368
|
|
329
369
|
it "uses px option to set the expire time, in miliseconds" do
|
330
370
|
ttl = 7000
|
331
371
|
|
332
|
-
@client.set("key1", "1", { :px => ttl }).
|
333
|
-
@client.ttl("key1").
|
372
|
+
expect(@client.set("key1", "1", { :px => ttl })).to eq("OK")
|
373
|
+
expect(@client.ttl("key1")).to eq(ttl / 1000)
|
334
374
|
end
|
335
375
|
|
336
376
|
# Note that the redis-rb implementation will always give PX last.
|
@@ -340,30 +380,132 @@ module FakeRedis
|
|
340
380
|
ttl_ex = 10
|
341
381
|
|
342
382
|
@client.set("key1", "1", { :px => ttl_px, :ex => ttl_ex })
|
343
|
-
@client.ttl("key1").
|
383
|
+
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
344
384
|
|
345
385
|
@client.set("key1", "1", { :ex => ttl_ex, :px => ttl_px })
|
346
|
-
@client.ttl("key1").
|
386
|
+
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
347
387
|
end
|
348
388
|
|
349
389
|
it "uses nx option to only set the key if it does not already exist" do
|
350
|
-
@client.set("key1", "1", { :nx => true }).
|
351
|
-
@client.set("key1", "2", { :nx => true }).
|
390
|
+
expect(@client.set("key1", "1", { :nx => true })).to eq(true)
|
391
|
+
expect(@client.set("key1", "2", { :nx => true })).to eq(false)
|
352
392
|
|
353
|
-
@client.get("key1").
|
393
|
+
expect(@client.get("key1")).to eq("1")
|
354
394
|
end
|
355
395
|
|
356
396
|
it "uses xx option to only set the key if it already exists" do
|
357
|
-
@client.set("key2", "1", { :xx => true }).
|
397
|
+
expect(@client.set("key2", "1", { :xx => true })).to eq(false)
|
358
398
|
@client.set("key2", "2")
|
359
|
-
@client.set("key2", "1", { :xx => true }).
|
399
|
+
expect(@client.set("key2", "1", { :xx => true })).to eq(true)
|
360
400
|
|
361
|
-
@client.get("key2").
|
401
|
+
expect(@client.get("key2")).to eq("1")
|
362
402
|
end
|
363
403
|
|
364
404
|
it "does not set the key if both xx and nx option are specified" do
|
365
|
-
@client.set("key2", "1", { :nx => true, :xx => true }).
|
366
|
-
@client.get("key2").
|
405
|
+
expect(@client.set("key2", "1", { :nx => true, :xx => true })).to eq(false)
|
406
|
+
expect(@client.get("key2")).to be_nil
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
describe "#dump" do
|
411
|
+
it "returns nil for unknown key" do
|
412
|
+
expect(@client.exists("key1")).to be false
|
413
|
+
expect(@client.dump("key1")).to be nil
|
414
|
+
end
|
415
|
+
|
416
|
+
it "dumps a single known key successfully" do
|
417
|
+
@client.set("key1", "zomgwtf")
|
418
|
+
|
419
|
+
value = @client.dump("key1")
|
420
|
+
expect(value).not_to eq nil
|
421
|
+
expect(value).to be_a_kind_of(String)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "errors with more than one argument" do
|
425
|
+
expect { @client.dump("key1", "key2") }.to raise_error(ArgumentError)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
describe "#restore" do
|
430
|
+
it "errors with a missing payload" do
|
431
|
+
expect do
|
432
|
+
@client.restore("key1", 0, nil)
|
433
|
+
end.to raise_error(Redis::CommandError, "ERR DUMP payload version or checksum are wrong")
|
434
|
+
end
|
435
|
+
|
436
|
+
it "errors with an invalid payload" do
|
437
|
+
expect do
|
438
|
+
@client.restore("key1", 0, "zomgwtf not valid")
|
439
|
+
end.to raise_error(Redis::CommandError, "ERR DUMP payload version or checksum are wrong")
|
440
|
+
end
|
441
|
+
|
442
|
+
describe "with a dumped value" do
|
443
|
+
before do
|
444
|
+
@client.set("key1", "original value")
|
445
|
+
@dumped_value = @client.dump("key1")
|
446
|
+
|
447
|
+
@client.del("key1")
|
448
|
+
expect(@client.exists("key1")).to be false
|
449
|
+
end
|
450
|
+
|
451
|
+
it "restores to a new key successfully" do
|
452
|
+
response = @client.restore("key1", 0, @dumped_value)
|
453
|
+
expect(response).to eq "OK"
|
454
|
+
end
|
455
|
+
|
456
|
+
it "errors trying to restore to an existing key" do
|
457
|
+
@client.set("key1", "something else")
|
458
|
+
|
459
|
+
expect do
|
460
|
+
@client.restore("key1", 0, @dumped_value)
|
461
|
+
end.to raise_error(Redis::CommandError, "ERR Target key name is busy.")
|
462
|
+
end
|
463
|
+
|
464
|
+
it "restores successfully with a given expire time" do
|
465
|
+
@client.restore("key2", 2000, @dumped_value)
|
466
|
+
|
467
|
+
expect(@client.ttl("key2")).to eq 2
|
468
|
+
end
|
469
|
+
|
470
|
+
it "restores a list successfully" do
|
471
|
+
@client.lpush("key1", "val1")
|
472
|
+
@client.lpush("key1", "val2")
|
473
|
+
|
474
|
+
expect(@client.type("key1")).to eq "list"
|
475
|
+
|
476
|
+
dumped_value = @client.dump("key1")
|
477
|
+
|
478
|
+
response = @client.restore("key2", 0, dumped_value)
|
479
|
+
expect(response).to eq "OK"
|
480
|
+
|
481
|
+
expect(@client.type("key2")).to eq "list"
|
482
|
+
end
|
483
|
+
|
484
|
+
it "restores a set successfully" do
|
485
|
+
@client.sadd("key1", "val1")
|
486
|
+
@client.sadd("key1", "val2")
|
487
|
+
|
488
|
+
expect(@client.type("key1")).to eq "set"
|
489
|
+
|
490
|
+
dumped_value = @client.dump("key1")
|
491
|
+
|
492
|
+
response = @client.restore("key2", 0, dumped_value)
|
493
|
+
expect(response).to eq "OK"
|
494
|
+
|
495
|
+
expect(@client.type("key2")).to eq "set"
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
describe "#psetex" do
|
501
|
+
it "should set a key's time to live in milliseconds" do
|
502
|
+
allow(Time).to receive(:now).and_return(1000)
|
503
|
+
@client.psetex("key", 2200, "value")
|
504
|
+
expect(@client.pttl("key")).to be_within(0.1).of(2200)
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should return 'OK'" do
|
508
|
+
expect(@client.psetex("key", 1000, "value")).to eq("OK")
|
367
509
|
end
|
368
510
|
end
|
369
511
|
end
|