fakeredis 0.4.3 → 0.5.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 +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
|