fakeredis 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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?