fakeredis 0.7.0 → 0.9.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/.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?
|