fakeredis 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/Gemfile +6 -2
- data/LICENSE +1 -1
- data/README.md +2 -2
- data/fakeredis.gemspec +2 -2
- data/lib/fakeredis/command_executor.rb +25 -0
- data/lib/fakeredis/sort_method.rb +116 -0
- data/lib/fakeredis/transaction_commands.rb +83 -0
- data/lib/fakeredis/version.rb +1 -1
- data/lib/fakeredis/zset.rb +7 -3
- data/lib/redis/connection/memory.rb +132 -69
- data/spec/hashes_spec.rb +21 -8
- data/spec/keys_spec.rb +107 -5
- data/spec/lists_spec.rb +9 -1
- data/spec/memory_spec.rb +28 -0
- data/spec/server_spec.rb +4 -4
- data/spec/sets_spec.rb +87 -3
- data/spec/sort_method_spec.rb +68 -0
- data/spec/sorted_sets_spec.rb +9 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/strings_spec.rb +52 -4
- data/spec/support/shared_examples/sortable.rb +69 -0
- data/spec/transactions_spec.rb +72 -7
- metadata +24 -16
- data/.rspec +0 -1
data/spec/hashes_spec.rb
CHANGED
@@ -9,7 +9,7 @@ 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
|
+
@client.hdel("key1", "k1").should be(1)
|
13
13
|
|
14
14
|
@client.hget("key1", "k1").should be_nil
|
15
15
|
@client.hget("key1", "k2").should be == "val2"
|
@@ -18,8 +18,8 @@ module FakeRedis
|
|
18
18
|
it "should remove a hash with no keys left" do
|
19
19
|
@client.hset("key1", "k1", "val1")
|
20
20
|
@client.hset("key1", "k2", "val2")
|
21
|
-
@client.hdel("key1", "k1")
|
22
|
-
@client.hdel("key1", "k2")
|
21
|
+
@client.hdel("key1", "k1").should be(1)
|
22
|
+
@client.hdel("key1", "k2").should be(1)
|
23
23
|
|
24
24
|
@client.exists("key1").should be == false
|
25
25
|
end
|
@@ -43,8 +43,8 @@ module FakeRedis
|
|
43
43
|
it "should determine if a hash field exists" do
|
44
44
|
@client.hset("key1", "index", "value")
|
45
45
|
|
46
|
-
@client.hexists("key1", "index").should
|
47
|
-
@client.hexists("key2", "i2").should
|
46
|
+
@client.hexists("key1", "index").should be true
|
47
|
+
@client.hexists("key2", "i2").should be false
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should get the value of a hash field" do
|
@@ -71,6 +71,17 @@ module FakeRedis
|
|
71
71
|
@client.hincrby("key1", "cont2", "5").should be == 5
|
72
72
|
end
|
73
73
|
|
74
|
+
it "should increment the float value of a hash field by the given float" do
|
75
|
+
@client.hset("key1", "cont1", 5.0)
|
76
|
+
@client.hincrbyfloat("key1", "cont1", 4.1).should be == 9.1
|
77
|
+
@client.hget("key1", "cont1").should be == "9.1"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should increment non existing hash keys" do
|
81
|
+
@client.hget("key1", "cont2").should be_nil
|
82
|
+
@client.hincrbyfloat("key1", "cont2", 5.5).should be == 5.5
|
83
|
+
end
|
84
|
+
|
74
85
|
it "should get all the fields in a hash" do
|
75
86
|
@client.hset("key1", "i1", "val1")
|
76
87
|
@client.hset("key1", "i2", "val2")
|
@@ -91,6 +102,8 @@ module FakeRedis
|
|
91
102
|
@client.hset("key1", "i2", "val2")
|
92
103
|
|
93
104
|
@client.hmget("key1", "i1", "i2", "i3").should =~ ["val1", "val2", nil]
|
105
|
+
@client.hmget("key1", ["i1", "i2", "i3"]).should =~ ["val1", "val2", nil]
|
106
|
+
|
94
107
|
@client.hmget("key2", "i1", "i2").should be == [nil, nil]
|
95
108
|
end
|
96
109
|
|
@@ -100,13 +113,13 @@ module FakeRedis
|
|
100
113
|
|
101
114
|
it "should reject an empty list of values" do
|
102
115
|
lambda { @client.hmset("key") }.should raise_error(Redis::CommandError)
|
103
|
-
@client.exists("key").should
|
116
|
+
@client.exists("key").should be false
|
104
117
|
end
|
105
118
|
|
106
119
|
it "rejects an insert with a key but no value" do
|
107
120
|
lambda { @client.hmset("key", 'foo') }.should raise_error(Redis::CommandError)
|
108
121
|
lambda { @client.hmset("key", 'foo', 3, 'bar') }.should raise_error(Redis::CommandError)
|
109
|
-
@client.exists("key").should
|
122
|
+
@client.exists("key").should be false
|
110
123
|
end
|
111
124
|
|
112
125
|
it "should reject the wrong number of arguments" do
|
@@ -171,7 +184,7 @@ module FakeRedis
|
|
171
184
|
|
172
185
|
it "should convert a integer field name to string for hexists" do
|
173
186
|
@client.hset("key1", "1", 1)
|
174
|
-
@client.hexists("key1", 1).should
|
187
|
+
@client.hexists("key1", 1).should be true
|
175
188
|
end
|
176
189
|
|
177
190
|
it "should convert a integer field name to string for hincrby" do
|
data/spec/keys_spec.rb
CHANGED
@@ -29,6 +29,15 @@ module FakeRedis
|
|
29
29
|
lambda { @client.del [] }.should raise_error(Redis::CommandError, "ERR wrong number of arguments for 'del' command")
|
30
30
|
end
|
31
31
|
|
32
|
+
it "should return true when setting expires on keys that exist" do
|
33
|
+
@client.set("key1", "1")
|
34
|
+
@client.expire("key1", 1).should == true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return false when attempting to set expires on a key that does not exist" do
|
38
|
+
@client.expire("key1", 1).should == false
|
39
|
+
end
|
40
|
+
|
32
41
|
it "should determine if a key exists" do
|
33
42
|
@client.set("key1", "1")
|
34
43
|
|
@@ -92,7 +101,7 @@ module FakeRedis
|
|
92
101
|
@client.set("key1", "1")
|
93
102
|
@client.expireat("key1", Time.now.to_i)
|
94
103
|
|
95
|
-
@client.exists("key1").should
|
104
|
+
@client.exists("key1").should be false
|
96
105
|
end
|
97
106
|
|
98
107
|
it "should find all keys matching the given pattern" do
|
@@ -145,10 +154,6 @@ module FakeRedis
|
|
145
154
|
@client.get("key4").should be == "3"
|
146
155
|
end
|
147
156
|
|
148
|
-
it "should sort the elements in a list, set or sorted set" do
|
149
|
-
pending "SORT Command not implemented yet"
|
150
|
-
end
|
151
|
-
|
152
157
|
it "should determine the type stored at key" do
|
153
158
|
# Non-existing key
|
154
159
|
@client.type("key0").should be == "none"
|
@@ -265,5 +270,102 @@ module FakeRedis
|
|
265
270
|
@client.select(0)
|
266
271
|
@client.get("key1").should be == "1"
|
267
272
|
end
|
273
|
+
|
274
|
+
it "should scan all keys in the database" do
|
275
|
+
100.times do |x|
|
276
|
+
@client.set("key#{x}", "#{x}")
|
277
|
+
end
|
278
|
+
|
279
|
+
cursor = 0
|
280
|
+
all_keys = []
|
281
|
+
loop {
|
282
|
+
cursor, keys = @client.scan(cursor)
|
283
|
+
all_keys += keys
|
284
|
+
break if cursor == "0"
|
285
|
+
}
|
286
|
+
|
287
|
+
all_keys.uniq.size.should == 100
|
288
|
+
all_keys[0].should =~ /key\d+/
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should match keys to a pattern when scanning" do
|
292
|
+
50.times do |x|
|
293
|
+
@client.set("key#{x}", "#{x}")
|
294
|
+
end
|
295
|
+
|
296
|
+
@client.set("miss_me", 1)
|
297
|
+
@client.set("pass_me", 2)
|
298
|
+
|
299
|
+
cursor = 0
|
300
|
+
all_keys = []
|
301
|
+
loop {
|
302
|
+
cursor, keys = @client.scan(cursor, :match => "key*")
|
303
|
+
all_keys += keys
|
304
|
+
break if cursor == "0"
|
305
|
+
}
|
306
|
+
|
307
|
+
all_keys.uniq.size.should == 50
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should specify doing more work when scanning" do
|
311
|
+
100.times do |x|
|
312
|
+
@client.set("key#{x}", "#{x}")
|
313
|
+
end
|
314
|
+
|
315
|
+
cursor, all_keys = @client.scan(cursor, :count => 100)
|
316
|
+
|
317
|
+
cursor.should == "0"
|
318
|
+
all_keys.uniq.size.should == 100
|
319
|
+
end
|
320
|
+
|
321
|
+
context "with extended options" do
|
322
|
+
it "uses ex option to set the expire time, in seconds" do
|
323
|
+
ttl = 7
|
324
|
+
|
325
|
+
@client.set("key1", "1", { :ex => ttl }).should == "OK"
|
326
|
+
@client.ttl("key1").should == ttl
|
327
|
+
end
|
328
|
+
|
329
|
+
it "uses px option to set the expire time, in miliseconds" do
|
330
|
+
ttl = 7000
|
331
|
+
|
332
|
+
@client.set("key1", "1", { :px => ttl }).should == "OK"
|
333
|
+
@client.ttl("key1").should == (ttl / 1000)
|
334
|
+
end
|
335
|
+
|
336
|
+
# Note that the redis-rb implementation will always give PX last.
|
337
|
+
# Redis seems to process each expiration option and the last one wins.
|
338
|
+
it "prefers the finer-grained PX expiration option over EX" do
|
339
|
+
ttl_px = 6000
|
340
|
+
ttl_ex = 10
|
341
|
+
|
342
|
+
@client.set("key1", "1", { :px => ttl_px, :ex => ttl_ex })
|
343
|
+
@client.ttl("key1").should == (ttl_px / 1000)
|
344
|
+
|
345
|
+
@client.set("key1", "1", { :ex => ttl_ex, :px => ttl_px })
|
346
|
+
@client.ttl("key1").should == (ttl_px / 1000)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "uses nx option to only set the key if it does not already exist" do
|
350
|
+
@client.set("key1", "1", { :nx => true }).should == true
|
351
|
+
@client.set("key1", "2", { :nx => true }).should == false
|
352
|
+
|
353
|
+
@client.get("key1").should == "1"
|
354
|
+
end
|
355
|
+
|
356
|
+
it "uses xx option to only set the key if it already exists" do
|
357
|
+
@client.set("key2", "1", { :xx => true }).should == false
|
358
|
+
@client.set("key2", "2")
|
359
|
+
@client.set("key2", "1", { :xx => true }).should == true
|
360
|
+
|
361
|
+
@client.get("key2").should == "1"
|
362
|
+
end
|
363
|
+
|
364
|
+
it "does not set the key if both xx and nx option are specified" do
|
365
|
+
@client.set("key2", "1", { :nx => true, :xx => true }).should == false
|
366
|
+
@client.get("key2").should be_nil
|
367
|
+
end
|
368
|
+
end
|
268
369
|
end
|
269
370
|
end
|
371
|
+
|
data/spec/lists_spec.rb
CHANGED
@@ -119,7 +119,7 @@ module FakeRedis
|
|
119
119
|
@client.rpush("key1", "two")
|
120
120
|
@client.rpush("key1", "three")
|
121
121
|
|
122
|
-
@client.ltrim("key1", 1, -1)
|
122
|
+
@client.ltrim("key1", 1, -1).should be == "OK"
|
123
123
|
@client.lrange("key1", 0, -1).should be == ["two", "three"]
|
124
124
|
end
|
125
125
|
|
@@ -176,6 +176,14 @@ module FakeRedis
|
|
176
176
|
@client.lrange("key2", 0, -1).should be == ["three"]
|
177
177
|
end
|
178
178
|
|
179
|
+
context 'when the source list is empty' do
|
180
|
+
it 'rpoplpush does not add anything to the destination list' do
|
181
|
+
@client.rpoplpush("source", "destination")
|
182
|
+
|
183
|
+
@client.lrange("destination", 0, -1).should be == []
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
179
187
|
it "should append a value to a list" do
|
180
188
|
@client.rpush("key1", "one")
|
181
189
|
@client.rpush("key1", "two")
|
data/spec/memory_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe 'time' do
|
5
|
+
before(:each) do
|
6
|
+
@client = Redis.new
|
7
|
+
Time.stub_chain(:now, :to_f).and_return(1397845595.5139461)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'is an array' do
|
11
|
+
expect(@client.time).to be_an_instance_of(Array)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has two elements' do
|
15
|
+
expect(@client.time.count).to eql 2
|
16
|
+
end
|
17
|
+
|
18
|
+
if fakeredis?
|
19
|
+
it 'has the current time in seconds' do
|
20
|
+
expect(@client.time.first).to eql 1397845595
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'has the current leftover microseconds' do
|
24
|
+
expect(@client.time.last).to eql 513946
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/server_spec.rb
CHANGED
@@ -45,13 +45,13 @@ module FakeRedis
|
|
45
45
|
|
46
46
|
@client.select(0)
|
47
47
|
@client.dbsize.should be == 2
|
48
|
-
@client.exists("key1").should
|
49
|
-
@client.exists("key3").should
|
48
|
+
@client.exists("key1").should be true
|
49
|
+
@client.exists("key3").should be false
|
50
50
|
|
51
51
|
@client.select(1)
|
52
52
|
@client.dbsize.should be == 3
|
53
|
-
@client.exists("key4").should
|
54
|
-
@client.exists("key2").should
|
53
|
+
@client.exists("key4").should be true
|
54
|
+
@client.exists("key2").should be false
|
55
55
|
|
56
56
|
@client.flushall
|
57
57
|
@client.dbsize.should be == 0
|
data/spec/sets_spec.rb
CHANGED
@@ -125,8 +125,8 @@ module FakeRedis
|
|
125
125
|
@client.sadd("key1", "a")
|
126
126
|
@client.sadd("key1", "b")
|
127
127
|
|
128
|
-
["a", "b"].include?(@client.spop("key1")).should
|
129
|
-
["a", "b"].include?(@client.spop("key1")).should
|
128
|
+
["a", "b"].include?(@client.spop("key1")).should be true
|
129
|
+
["a", "b"].include?(@client.spop("key1")).should be true
|
130
130
|
@client.spop("key1").should be_nil
|
131
131
|
end
|
132
132
|
|
@@ -134,7 +134,7 @@ module FakeRedis
|
|
134
134
|
@client.sadd("key1", "a")
|
135
135
|
@client.sadd("key1", "b")
|
136
136
|
|
137
|
-
["a", "b"].include?(@client.spop("key1")).should
|
137
|
+
["a", "b"].include?(@client.spop("key1")).should be true
|
138
138
|
end
|
139
139
|
|
140
140
|
it "should remove a member from a set" do
|
@@ -146,6 +146,14 @@ module FakeRedis
|
|
146
146
|
@client.smembers("key1").should be == ["b"]
|
147
147
|
end
|
148
148
|
|
149
|
+
it "should remove multiple members from a set" do
|
150
|
+
@client.sadd("key1", "a")
|
151
|
+
@client.sadd("key1", "b")
|
152
|
+
|
153
|
+
@client.srem("key1", [ "a", "b"]).should == 2
|
154
|
+
@client.smembers("key1").should be_empty
|
155
|
+
end
|
156
|
+
|
149
157
|
it "should remove the set's key once it's empty" do
|
150
158
|
@client.sadd("key1", "a")
|
151
159
|
@client.sadd("key1", "b")
|
@@ -182,4 +190,80 @@ module FakeRedis
|
|
182
190
|
@client.smembers("key").should =~ ["a", "b", "c", "d", "e"]
|
183
191
|
end
|
184
192
|
end
|
193
|
+
|
194
|
+
describe 'srandmember' do
|
195
|
+
before(:each) do
|
196
|
+
@client = Redis.new
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'with a set that has three elements' do
|
200
|
+
before do
|
201
|
+
@client.sadd("key1", "a")
|
202
|
+
@client.sadd("key1", "b")
|
203
|
+
@client.sadd("key1", "c")
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'when called without the optional number parameter' do
|
207
|
+
it 'is a random element from the set' do
|
208
|
+
random_element = @client.srandmember("key1")
|
209
|
+
|
210
|
+
['a', 'b', 'c'].include?(random_element).should be true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'when called with the optional number parameter of 1' do
|
215
|
+
it 'is an array of one random element from the set' do
|
216
|
+
random_elements = @client.srandmember("key1", 1)
|
217
|
+
|
218
|
+
[['a'], ['b'], ['c']].include?(@client.srandmember("key1", 1)).should be true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'when called with the optional number parameter of 2' do
|
223
|
+
it 'is an array of two unique, random elements from the set' do
|
224
|
+
random_elements = @client.srandmember("key1", 2)
|
225
|
+
|
226
|
+
random_elements.count.should == 2
|
227
|
+
random_elements.uniq.count.should == 2
|
228
|
+
random_elements.all? do |element|
|
229
|
+
['a', 'b', 'c'].include?(element).should be true
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'when called with an optional parameter of -100' do
|
235
|
+
it 'is an array of 100 random elements from the set, some of which are repeated' do
|
236
|
+
random_elements = @client.srandmember("key1", -100)
|
237
|
+
|
238
|
+
random_elements.count.should == 100
|
239
|
+
random_elements.uniq.count.should <= 3
|
240
|
+
random_elements.all? do |element|
|
241
|
+
['a', 'b', 'c'].include?(element).should be true
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'when called with an optional parameter of 100' do
|
247
|
+
it 'is an array of all of the elements from the set, none of which are repeated' do
|
248
|
+
random_elements = @client.srandmember("key1", 100)
|
249
|
+
|
250
|
+
random_elements.count.should == 3
|
251
|
+
random_elements.uniq.count.should == 3
|
252
|
+
random_elements.should =~ ['a', 'b', 'c']
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'with an empty set' do
|
258
|
+
before { @client.del("key1") }
|
259
|
+
|
260
|
+
it 'is nil without the extra parameter' do
|
261
|
+
@client.srandmember("key1").should be_nil
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'is an empty array with an extra parameter' do
|
265
|
+
@client.srandmember("key1", 1).should == []
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
185
269
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "#sort" do
|
5
|
+
before(:each) do
|
6
|
+
@client = Redis.new
|
7
|
+
|
8
|
+
@client.set('fake-redis-test:values_1', 'a')
|
9
|
+
@client.set('fake-redis-test:values_2', 'b')
|
10
|
+
|
11
|
+
@client.set('fake-redis-test:weight_1', '2')
|
12
|
+
@client.set('fake-redis-test:weight_2', '1')
|
13
|
+
|
14
|
+
@client.hset('fake-redis-test:hash_1', 'key', 'x')
|
15
|
+
@client.hset('fake-redis-test:hash_2', 'key', 'y')
|
16
|
+
end
|
17
|
+
|
18
|
+
context "WRONGTYPE Operation" do
|
19
|
+
it "should not allow #sort on Strings" do
|
20
|
+
@client.set("key1", "Hello")
|
21
|
+
expect {
|
22
|
+
@client.sort("key1")
|
23
|
+
}.to raise_error(Redis::CommandError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not allow #sort on Hashes" do
|
27
|
+
@client.hset("key1", "k1", "val1")
|
28
|
+
@client.hset("key1", "k2", "val2")
|
29
|
+
expect {
|
30
|
+
@client.sort("key1")
|
31
|
+
}.to raise_error(Redis::CommandError)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "list" do
|
36
|
+
before do
|
37
|
+
@key = "fake-redis-test:list_sort"
|
38
|
+
|
39
|
+
@client.rpush(@key, '1')
|
40
|
+
@client.rpush(@key, '2')
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_behave_like "a sortable"
|
44
|
+
end
|
45
|
+
|
46
|
+
context "set" do
|
47
|
+
before do
|
48
|
+
@key = "fake-redis-test:set_sort"
|
49
|
+
|
50
|
+
@client.sadd(@key, '1')
|
51
|
+
@client.sadd(@key, '2')
|
52
|
+
end
|
53
|
+
|
54
|
+
it_should_behave_like "a sortable"
|
55
|
+
end
|
56
|
+
|
57
|
+
context "zset" do
|
58
|
+
before do
|
59
|
+
@key = "fake-redis-test:zset_sort"
|
60
|
+
|
61
|
+
@client.zadd(@key, 100, '1')
|
62
|
+
@client.zadd(@key, 99, '2')
|
63
|
+
end
|
64
|
+
|
65
|
+
it_should_behave_like "a sortable"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|