fakeredis 0.7.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/codeql.yml +74 -0
- data/.github/workflows/ruby.yml +33 -0
- data/.gitignore +0 -1
- data/Gemfile +0 -6
- data/LICENSE +1 -1
- data/README.md +4 -3
- data/fakeredis.gemspec +2 -2
- data/lib/fakeredis/command_executor.rb +0 -6
- data/lib/fakeredis/expiring_hash.rb +2 -4
- data/lib/fakeredis/geo_commands.rb +142 -0
- data/lib/fakeredis/geo_set.rb +84 -0
- data/lib/fakeredis/minitest.rb +1 -1
- data/lib/fakeredis/sort_method.rb +0 -1
- data/lib/fakeredis/version.rb +1 -1
- data/lib/fakeredis/zset.rb +2 -2
- data/lib/fakeredis.rb +16 -0
- data/lib/redis/connection/memory.rb +261 -62
- data/spec/bitop_command_spec.rb +71 -71
- data/spec/fakeredis_spec.rb +52 -0
- data/spec/geo_set_spec.rb +164 -0
- data/spec/hashes_spec.rb +46 -5
- data/spec/hyper_log_logs_spec.rb +50 -0
- data/spec/keys_spec.rb +92 -34
- data/spec/lists_spec.rb +20 -3
- data/spec/memory_spec.rb +4 -8
- data/spec/server_spec.rb +18 -4
- data/spec/sets_spec.rb +23 -2
- data/spec/sorted_sets_spec.rb +180 -2
- data/spec/spec_helper.rb +5 -19
- data/spec/strings_spec.rb +42 -2
- data/spec/subscription_spec.rb +31 -31
- data/spec/support/shared_examples/bitwise_operation.rb +12 -12
- data/spec/transactions_spec.rb +14 -1
- metadata +20 -21
- data/.travis.yml +0 -22
- data/gemfiles/redisrb-master.gemfile +0 -14
data/spec/keys_spec.rb
CHANGED
@@ -7,26 +7,38 @@ 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
|
25
32
|
end
|
26
33
|
|
27
|
-
it "should
|
28
|
-
expect
|
29
|
-
expect
|
34
|
+
it "should return 0 when deleting no keys" do
|
35
|
+
expect(@client.del).to eq(0)
|
36
|
+
expect(@client.del([])).to eq(0)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should error when unlinking no keys" do
|
40
|
+
expect { @client.unlink }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'unlink' command")
|
41
|
+
expect { @client.unlink([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'unlink' command")
|
30
42
|
end
|
31
43
|
|
32
44
|
it "should return true when setnx keys that don't exist" do
|
@@ -56,13 +68,6 @@ module FakeRedis
|
|
56
68
|
expect(@client.pexpire("key1", 1)).to eq(false)
|
57
69
|
end
|
58
70
|
|
59
|
-
it "should determine if a key exists" do
|
60
|
-
@client.set("key1", "1")
|
61
|
-
|
62
|
-
expect(@client.exists("key1")).to eq(true)
|
63
|
-
expect(@client.exists("key2")).to eq(false)
|
64
|
-
end
|
65
|
-
|
66
71
|
it "should set a key's time to live in seconds" do
|
67
72
|
@client.set("key1", "1")
|
68
73
|
@client.expire("key1", 1)
|
@@ -127,7 +132,14 @@ module FakeRedis
|
|
127
132
|
@client.set("key1", "1")
|
128
133
|
@client.expireat("key1", Time.now.to_i)
|
129
134
|
|
130
|
-
expect(@client.exists("key1")).to be false
|
135
|
+
expect(@client.exists?("key1")).to be false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should get integer and string keys" do
|
139
|
+
@client.set("key1", "1")
|
140
|
+
@client.set(2, "2")
|
141
|
+
|
142
|
+
expect(@client.mget("key1", 2)).to eq(["1", "2"])
|
131
143
|
end
|
132
144
|
|
133
145
|
it "should find all keys matching the given pattern" do
|
@@ -348,14 +360,14 @@ module FakeRedis
|
|
348
360
|
it "uses ex option to set the expire time, in seconds" do
|
349
361
|
ttl = 7
|
350
362
|
|
351
|
-
expect(@client.set("key1", "1",
|
363
|
+
expect(@client.set("key1", "1", ex: ttl)).to eq("OK")
|
352
364
|
expect(@client.ttl("key1")).to eq(ttl)
|
353
365
|
end
|
354
366
|
|
355
367
|
it "uses px option to set the expire time, in miliseconds" do
|
356
368
|
ttl = 7000
|
357
369
|
|
358
|
-
expect(@client.set("key1", "1",
|
370
|
+
expect(@client.set("key1", "1", px: ttl)).to eq("OK")
|
359
371
|
expect(@client.ttl("key1")).to eq(ttl / 1000)
|
360
372
|
end
|
361
373
|
|
@@ -365,37 +377,37 @@ module FakeRedis
|
|
365
377
|
ttl_px = 6000
|
366
378
|
ttl_ex = 10
|
367
379
|
|
368
|
-
@client.set("key1", "1",
|
380
|
+
@client.set("key1", "1", px: ttl_px, ex: ttl_ex)
|
369
381
|
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
370
382
|
|
371
|
-
@client.set("key1", "1",
|
383
|
+
@client.set("key1", "1", ex: ttl_ex, px: ttl_px)
|
372
384
|
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
373
385
|
end
|
374
386
|
|
375
387
|
it "uses nx option to only set the key if it does not already exist" do
|
376
|
-
expect(@client.set("key1", "1",
|
377
|
-
expect(@client.set("key1", "2",
|
388
|
+
expect(@client.set("key1", "1", nx: true)).to eq(true)
|
389
|
+
expect(@client.set("key1", "2", nx: true)).to eq(false)
|
378
390
|
|
379
391
|
expect(@client.get("key1")).to eq("1")
|
380
392
|
end
|
381
393
|
|
382
394
|
it "uses xx option to only set the key if it already exists" do
|
383
|
-
expect(@client.set("key2", "1",
|
395
|
+
expect(@client.set("key2", "1", xx: true)).to eq(false)
|
384
396
|
@client.set("key2", "2")
|
385
|
-
expect(@client.set("key2", "1",
|
397
|
+
expect(@client.set("key2", "1", xx: true)).to eq(true)
|
386
398
|
|
387
399
|
expect(@client.get("key2")).to eq("1")
|
388
400
|
end
|
389
401
|
|
390
402
|
it "does not set the key if both xx and nx option are specified" do
|
391
|
-
expect(@client.set("key2", "1",
|
403
|
+
expect(@client.set("key2", "1", nx: true, xx: true)).to eq(false)
|
392
404
|
expect(@client.get("key2")).to be_nil
|
393
405
|
end
|
394
406
|
end
|
395
407
|
|
396
408
|
describe "#dump" do
|
397
409
|
it "returns nil for unknown key" do
|
398
|
-
expect(@client.exists("key1")).to be false
|
410
|
+
expect(@client.exists?("key1")).to be false
|
399
411
|
expect(@client.dump("key1")).to be nil
|
400
412
|
end
|
401
413
|
|
@@ -431,7 +443,7 @@ module FakeRedis
|
|
431
443
|
@dumped_value = @client.dump("key1")
|
432
444
|
|
433
445
|
@client.del("key1")
|
434
|
-
expect(@client.exists("key1")).to be false
|
446
|
+
expect(@client.exists?("key1")).to be false
|
435
447
|
end
|
436
448
|
|
437
449
|
it "restores to a new key successfully" do
|
@@ -483,6 +495,52 @@ module FakeRedis
|
|
483
495
|
end
|
484
496
|
end
|
485
497
|
|
498
|
+
describe "#psetex" do
|
499
|
+
it "should set a key's time to live in milliseconds" do
|
500
|
+
allow(Time).to receive(:now).and_return(1000)
|
501
|
+
@client.psetex("key", 2200, "value")
|
502
|
+
expect(@client.pttl("key")).to be_within(0.1).of(2200)
|
503
|
+
end
|
504
|
+
|
505
|
+
it "should raise an error if a non-integer is provided as the expiration" do
|
506
|
+
expect { @client.psetex("key", 100.5, "value") }.to raise_error(Redis::CommandError)
|
507
|
+
end
|
508
|
+
|
509
|
+
it "should return 'OK'" do
|
510
|
+
expect(@client.psetex("key", 1000, "value")).to eq("OK")
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
describe "#exists" do
|
515
|
+
it "returns 0 if none of the keys exist" do
|
516
|
+
expect(@client.exists("key1", "key2")).to eq 0
|
517
|
+
end
|
518
|
+
|
519
|
+
it "returns number of the keys that exist" do
|
520
|
+
@client.set("key2", "val2")
|
521
|
+
@client.set("key3", "val3")
|
522
|
+
expect(@client.exists("key1", "key2", "key3")).to eq 2
|
523
|
+
end
|
524
|
+
|
525
|
+
it "keys mentioned and existing multiple times counted multiple times" do
|
526
|
+
@client.set("key2", "val")
|
527
|
+
expect(@client.exists("key2", "key2")).to eq 2
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
describe "#exists?" do
|
532
|
+
it "should return true if any of the key exists" do
|
533
|
+
@client.set("key1", "1")
|
534
|
+
|
535
|
+
expect(@client.exists?("key1")).to eq(true)
|
536
|
+
expect(@client.exists?("key1", "key2")).to eq(true)
|
537
|
+
end
|
538
|
+
|
539
|
+
it "should return false if none of the key exists" do
|
540
|
+
expect(@client.exists?("key2")).to eq(false)
|
541
|
+
expect(@client.exists?("key2", "key3")).to eq(false)
|
542
|
+
end
|
543
|
+
end
|
486
544
|
end
|
487
545
|
end
|
488
546
|
|
data/spec/lists_spec.rb
CHANGED
@@ -119,7 +119,7 @@ module FakeRedis
|
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should return 0 if key does not map to a list" do
|
122
|
-
expect(@client.exists("nonexistant")).to eq(false)
|
122
|
+
expect(@client.exists?("nonexistant")).to eq(false)
|
123
123
|
expect(@client.lrem("nonexistant", 0, "value")).to eq(0)
|
124
124
|
end
|
125
125
|
|
@@ -129,7 +129,7 @@ module FakeRedis
|
|
129
129
|
@client.lrem("key1", 1, "v1")
|
130
130
|
@client.lrem("key1", 1, "v2")
|
131
131
|
|
132
|
-
expect(@client.exists("key1")).to eq(false)
|
132
|
+
expect(@client.exists?("key1")).to eq(false)
|
133
133
|
end
|
134
134
|
|
135
135
|
it "should set the value of an element in a list by its index" do
|
@@ -196,7 +196,7 @@ module FakeRedis
|
|
196
196
|
expect(@client.lrange("key1", 0, -1)).to eq(["one", "two"])
|
197
197
|
end
|
198
198
|
|
199
|
-
it "should remove the last element in a list, append it to another list and return it" do
|
199
|
+
it "rpoplpush should remove the last element in a list, append it to another list and return it" do
|
200
200
|
@client.rpush("key1", "one")
|
201
201
|
@client.rpush("key1", "two")
|
202
202
|
@client.rpush("key1", "three")
|
@@ -207,12 +207,29 @@ module FakeRedis
|
|
207
207
|
expect(@client.lrange("key2", 0, -1)).to eq(["three"])
|
208
208
|
end
|
209
209
|
|
210
|
+
it "brpoplpush should remove the last element in a list, append it to another list and return it" do
|
211
|
+
@client.rpush("key1", "one")
|
212
|
+
@client.rpush("key1", "two")
|
213
|
+
@client.rpush("key1", "three")
|
214
|
+
|
215
|
+
expect(@client.brpoplpush("key1", "key2")).to eq("three")
|
216
|
+
|
217
|
+
expect(@client.lrange("key1", 0, -1)).to eq(["one", "two"])
|
218
|
+
expect(@client.lrange("key2", 0, -1)).to eq(["three"])
|
219
|
+
end
|
220
|
+
|
210
221
|
context 'when the source list is empty' do
|
211
222
|
it 'rpoplpush does not add anything to the destination list' do
|
212
223
|
@client.rpoplpush("source", "destination")
|
213
224
|
|
214
225
|
expect(@client.lrange("destination", 0, -1)).to eq([])
|
215
226
|
end
|
227
|
+
|
228
|
+
it 'brpoplpush does not add anything to the destination list' do
|
229
|
+
expect(@client.brpoplpush("source", "destination")).to be_nil
|
230
|
+
|
231
|
+
expect(@client.lrange("destination", 0, -1)).to eq([])
|
232
|
+
end
|
216
233
|
end
|
217
234
|
|
218
235
|
it "should append a value to a list" do
|
data/spec/memory_spec.rb
CHANGED
@@ -21,7 +21,7 @@ RSpec.describe FakeRedis do
|
|
21
21
|
cursor = 0
|
22
22
|
|
23
23
|
loop do
|
24
|
-
cursor, keys = redis.scan(cursor, match_arguments)
|
24
|
+
cursor, keys = redis.scan(cursor, **match_arguments)
|
25
25
|
returned_keys += keys
|
26
26
|
break if cursor == '0'
|
27
27
|
end
|
@@ -86,16 +86,12 @@ RSpec.describe FakeRedis do
|
|
86
86
|
end
|
87
87
|
|
88
88
|
describe '#client' do
|
89
|
-
it 'returns
|
90
|
-
expect(redis.
|
89
|
+
it 'returns OK when command is :setname' do
|
90
|
+
expect(redis.client(:setname, 'my-client-01')).to eq 'OK'
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'returns nil when command is :getname' do
|
94
|
-
expect(redis.
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'returns true when the comment is :client with an argument' do
|
98
|
-
expect(redis.write([:client, :client, :list])).to eq 1
|
94
|
+
expect(redis.client(:getname)).to eq nil
|
99
95
|
end
|
100
96
|
|
101
97
|
it 'raises error for other commands' do
|
data/spec/server_spec.rb
CHANGED
@@ -45,13 +45,13 @@ module FakeRedis
|
|
45
45
|
|
46
46
|
@client.select(0)
|
47
47
|
expect(@client.dbsize).to eq(2)
|
48
|
-
expect(@client.exists("key1")).to be true
|
49
|
-
expect(@client.exists("key3")).to be false
|
48
|
+
expect(@client.exists?("key1")).to be true
|
49
|
+
expect(@client.exists?("key3")).to be false
|
50
50
|
|
51
51
|
@client.select(1)
|
52
52
|
expect(@client.dbsize).to eq(3)
|
53
|
-
expect(@client.exists("key4")).to be true
|
54
|
-
expect(@client.exists("key2")).to be false
|
53
|
+
expect(@client.exists?("key4")).to be true
|
54
|
+
expect(@client.exists?("key2")).to be false
|
55
55
|
|
56
56
|
@client.flushall
|
57
57
|
expect(@client.dbsize).to eq(0)
|
@@ -97,4 +97,18 @@ module FakeRedis
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
describe 'custom options' do
|
102
|
+
describe 'version' do
|
103
|
+
it 'reports default Redis version when not provided' do
|
104
|
+
client = Redis.new
|
105
|
+
expect(client.info['redis_version']).to eq Redis::Connection::DEFAULT_REDIS_VERSION
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'creates with and reports properly' do
|
109
|
+
client = Redis.new(version: '3.3.0')
|
110
|
+
expect(client.info['redis_version']).to eq '3.3.0'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
100
114
|
end
|
data/spec/sets_spec.rb
CHANGED
@@ -19,6 +19,7 @@ module FakeRedis
|
|
19
19
|
expect { @client.sinter([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sinter' command")
|
20
20
|
expect { @client.sunion(*[]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'sunion' command")
|
21
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")
|
22
23
|
|
23
24
|
expect(@client.smembers("key")).to be_empty
|
24
25
|
end
|
@@ -29,6 +30,13 @@ module FakeRedis
|
|
29
30
|
expect(@client.smembers("key")).to match_array(["value", "other", "something", "more", "and", "additional", "values"])
|
30
31
|
end
|
31
32
|
|
33
|
+
it "should return the number added to a set when an array is passed in" do
|
34
|
+
expect(@client.sadd("key", %w(value other something more))).to eq(4)
|
35
|
+
expect(@client.sadd("key", %w(more value additional))).to eq(1)
|
36
|
+
expect(@client.sadd("key", %w(additional))).to eq(0)
|
37
|
+
expect(@client.smembers("key")).to match_array(["value", "other", "something", "more", "additional"])
|
38
|
+
end
|
39
|
+
|
32
40
|
it "should get the number of members in a set" do
|
33
41
|
@client.sadd("key", "val1")
|
34
42
|
@client.sadd("key", "val2")
|
@@ -74,6 +82,19 @@ module FakeRedis
|
|
74
82
|
expect(@client.smembers("new_key")).to match_array(["b", "d"])
|
75
83
|
end
|
76
84
|
|
85
|
+
it "should return integer on sdiffstore" do
|
86
|
+
@client.sadd("key1", "a")
|
87
|
+
@client.sadd("key1", "b")
|
88
|
+
@client.sadd("key1", "c")
|
89
|
+
@client.sadd("key1", "d")
|
90
|
+
@client.sadd("key2", "c")
|
91
|
+
@client.sadd("key3", "a")
|
92
|
+
@client.sadd("key3", "c")
|
93
|
+
@client.sadd("key3", "e")
|
94
|
+
|
95
|
+
expect(@client.sdiffstore("key", "key1", "key2", "key3")).to eq(2)
|
96
|
+
end
|
97
|
+
|
77
98
|
it "should intersect multiple sets" do
|
78
99
|
@client.sadd("key1", "a")
|
79
100
|
@client.sadd("key1", "b")
|
@@ -187,7 +208,7 @@ module FakeRedis
|
|
187
208
|
@client.srem("key1", "b")
|
188
209
|
@client.srem("key1", "a")
|
189
210
|
|
190
|
-
expect(@client.exists("key1")).to eq(false)
|
211
|
+
expect(@client.exists?("key1")).to eq(false)
|
191
212
|
end
|
192
213
|
|
193
214
|
it "should add multiple sets" do
|
@@ -242,7 +263,7 @@ module FakeRedis
|
|
242
263
|
it 'is an array of one random element from the set' do
|
243
264
|
random_elements = @client.srandmember("key1", 1)
|
244
265
|
|
245
|
-
expect([['a'], ['b'], ['c']].include?(
|
266
|
+
expect([['a'], ['b'], ['c']].include?(random_elements)).to be true
|
246
267
|
end
|
247
268
|
end
|
248
269
|
|
data/spec/sorted_sets_spec.rb
CHANGED
@@ -100,7 +100,35 @@ module FakeRedis
|
|
100
100
|
it "should remove sorted set's key when it is empty" do
|
101
101
|
@client.zadd("key", 1, "val")
|
102
102
|
@client.zrem("key", "val")
|
103
|
-
expect(@client.exists("key")).to eq(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)
|
104
132
|
end
|
105
133
|
|
106
134
|
it "should get the number of members in a sorted set" do
|
@@ -147,6 +175,7 @@ module FakeRedis
|
|
147
175
|
|
148
176
|
expect(@client.zrange("key", 0, -1)).to eq(["one", "two", "three"])
|
149
177
|
expect(@client.zrange("key", 1, 2)).to eq(["two", "three"])
|
178
|
+
expect(@client.zrange("key", -50, -2)).to eq(["one", "two"])
|
150
179
|
expect(@client.zrange("key", 0, -1, :withscores => true)).to eq([["one", 1], ["two", 2], ["three", 3]])
|
151
180
|
expect(@client.zrange("key", 1, 2, :with_scores => true)).to eq([["two", 2], ["three", 3]])
|
152
181
|
end
|
@@ -574,7 +603,7 @@ module FakeRedis
|
|
574
603
|
expect(ranged).to eq %w(c b)
|
575
604
|
end
|
576
605
|
|
577
|
-
it "should return empty array if key
|
606
|
+
it "should return empty array if key does not exist" do
|
578
607
|
ranged = @client.zrevrangebylex "puppies", "+", "-"
|
579
608
|
expect(ranged).to be_empty
|
580
609
|
end
|
@@ -590,5 +619,154 @@ module FakeRedis
|
|
590
619
|
expect(ranged).to eq %w(d c b)
|
591
620
|
end
|
592
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
|
770
|
+
end
|
593
771
|
end
|
594
772
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,31 +1,17 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
1
|
require 'rspec'
|
4
|
-
require 'fakeredis'
|
5
|
-
require "fakeredis/rspec"
|
6
2
|
|
7
|
-
|
8
|
-
|
3
|
+
$LOAD_PATH.unshift(File.join(__dir__, '..', 'lib'))
|
4
|
+
$LOAD_PATH.unshift(File.join(__dir__, '..'))
|
5
|
+
Dir['spec/support/**/*.rb'].each { |f| require f }
|
9
6
|
|
7
|
+
require 'fakeredis'
|
8
|
+
require "fakeredis/rspec"
|
10
9
|
|
11
10
|
RSpec.configure do |config|
|
12
11
|
# Enable memory adapter
|
13
12
|
config.before(:each) { FakeRedis.enable }
|
14
13
|
|
15
|
-
# replaces -b -fdoc --color in .rspec
|
16
|
-
config.color = true
|
17
|
-
config.default_formatter = "doc"
|
18
14
|
config.backtrace_exclusion_patterns = []
|
19
|
-
|
20
|
-
config.mock_with :rspec do |c|
|
21
|
-
# TODO: upgrade should syntax to expect syntax
|
22
|
-
c.syntax = [:should, :expect]
|
23
|
-
end
|
24
|
-
|
25
|
-
config.expect_with :rspec do |c|
|
26
|
-
# TODO: upgrade should syntax to expect syntax
|
27
|
-
c.syntax = [:should, :expect]
|
28
|
-
end
|
29
15
|
end
|
30
16
|
|
31
17
|
def fakeredis?
|