fakeredis 0.7.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.
@@ -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
@@ -7,26 +7,33 @@ module FakeRedis
7
7
  @client = Redis.new
8
8
  end
9
9
 
10
- it "should delete a key" do
11
- @client.set("key1", "1")
12
- @client.set("key2", "2")
13
- @client.del("key1", "key2")
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
- expect(@client.get("key1")).to eq(nil)
16
- end
16
+ expect(@client.get("key1")).to eq(nil)
17
+ end
17
18
 
18
- it "should delete multiple keys" do
19
- @client.set("key1", "1")
20
- @client.set("key2", "2")
21
- @client.del(["key1", "key2"])
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
- expect(@client.get("key1")).to eq(nil)
24
- expect(@client.get("key2")).to eq(nil)
25
- end
24
+ expect(@client.get("key1")).to eq(nil)
25
+ expect(@client.get("key2")).to eq(nil)
26
+ end
26
27
 
27
- it "should error deleting no keys" do
28
- expect { @client.del }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'del' command")
29
- expect { @client.del [] }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'del' command")
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
30
37
  end
31
38
 
32
39
  it "should return true when setnx keys that don't exist" do
@@ -130,6 +137,13 @@ module FakeRedis
130
137
  expect(@client.exists("key1")).to be false
131
138
  end
132
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"])
145
+ end
146
+
133
147
  it "should find all keys matching the given pattern" do
134
148
  @client.set("key:a", "1")
135
149
  @client.set("key:b", "2")
@@ -483,6 +497,17 @@ module FakeRedis
483
497
  end
484
498
  end
485
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")
509
+ end
510
+ end
486
511
  end
487
512
  end
488
513
 
@@ -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
@@ -86,16 +86,12 @@ RSpec.describe FakeRedis do
86
86
  end
87
87
 
88
88
  describe '#client' do
89
- it 'returns 1 when command is :setname' do
90
- expect(redis.write([:client, :setname])).to eq 1
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.write([:client, :getname])).to eq nil
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
@@ -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
@@ -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
@@ -242,7 +243,7 @@ module FakeRedis
242
243
  it 'is an array of one random element from the set' do
243
244
  random_elements = @client.srandmember("key1", 1)
244
245
 
245
- expect([['a'], ['b'], ['c']].include?(@client.srandmember("key1", 1))).to be true
246
+ expect([['a'], ['b'], ['c']].include?(random_elements)).to be true
246
247
  end
247
248
  end
248
249
 
@@ -103,6 +103,34 @@ module FakeRedis
103
103
  expect(@client.exists("key")).to eq(false)
104
104
  end
105
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)
132
+ end
133
+
106
134
  it "should get the number of members in a sorted set" do
107
135
  @client.zadd("key", 1, "val2")
108
136
  @client.zadd("key", 2, "val1")
@@ -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 is not exist" do
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
@@ -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
- require "support/shared_examples/sortable"
8
- require "support/shared_examples/bitwise_operation"
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?