mock_redis 0.19.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/.travis.yml +9 -10
  4. data/CHANGELOG.md +15 -0
  5. data/Gemfile +2 -2
  6. data/README.md +2 -2
  7. data/lib/mock_redis/database.rb +6 -5
  8. data/lib/mock_redis/geospatial_methods.rb +10 -18
  9. data/lib/mock_redis/hash_methods.rb +4 -4
  10. data/lib/mock_redis/indifferent_hash.rb +0 -8
  11. data/lib/mock_redis/list_methods.rb +2 -2
  12. data/lib/mock_redis/pipelined_wrapper.rb +25 -6
  13. data/lib/mock_redis/set_methods.rb +15 -4
  14. data/lib/mock_redis/stream.rb +62 -0
  15. data/lib/mock_redis/stream/id.rb +53 -0
  16. data/lib/mock_redis/stream_methods.rb +87 -0
  17. data/lib/mock_redis/string_methods.rb +5 -8
  18. data/lib/mock_redis/transaction_wrapper.rb +25 -12
  19. data/lib/mock_redis/utility_methods.rb +1 -1
  20. data/lib/mock_redis/version.rb +1 -1
  21. data/lib/mock_redis/zset_methods.rb +2 -2
  22. data/mock_redis.gemspec +6 -5
  23. data/spec/commands/geodist_spec.rb +8 -4
  24. data/spec/commands/geohash_spec.rb +4 -4
  25. data/spec/commands/geopos_spec.rb +4 -4
  26. data/spec/commands/get_spec.rb +1 -0
  27. data/spec/commands/hdel_spec.rb +2 -2
  28. data/spec/commands/mget_spec.rb +34 -15
  29. data/spec/commands/mset_spec.rb +14 -0
  30. data/spec/commands/pipelined_spec.rb +52 -0
  31. data/spec/commands/spop_spec.rb +15 -0
  32. data/spec/commands/watch_spec.rb +8 -3
  33. data/spec/commands/xadd_spec.rb +102 -0
  34. data/spec/commands/xlen_spec.rb +20 -0
  35. data/spec/commands/xrange_spec.rb +141 -0
  36. data/spec/commands/xrevrange_spec.rb +130 -0
  37. data/spec/commands/xtrim_spec.rb +30 -0
  38. data/spec/spec_helper.rb +2 -0
  39. data/spec/support/redis_multiplexer.rb +17 -1
  40. data/spec/support/shared_examples/does_not_cleanup_empty_strings.rb +14 -0
  41. data/spec/support/shared_examples/only_operates_on_hashes.rb +2 -0
  42. data/spec/support/shared_examples/only_operates_on_lists.rb +2 -0
  43. data/spec/support/shared_examples/only_operates_on_sets.rb +2 -0
  44. data/spec/support/shared_examples/only_operates_on_zsets.rb +2 -0
  45. data/spec/transactions_spec.rb +17 -29
  46. metadata +38 -12
  47. data/spec/commands/hash_operator_spec.rb +0 -21
@@ -10,6 +10,14 @@ describe '#mset(key, value [, key, value, ...])' do
10
10
  @redises.mset(@key1, 1).should == 'OK'
11
11
  end
12
12
 
13
+ it "responds with 'OK' for passed Array with 1 item" do
14
+ @redises.mset([@key1, 1]).should == 'OK'
15
+ end
16
+
17
+ it "responds with 'OK' for passed Array with 2 items" do
18
+ @redises.mset([@key1, 1, @key2, 2]).should == 'OK'
19
+ end
20
+
13
21
  it 'sets the values' do
14
22
  @redises.mset(@key1, 'value1', @key2, 'value2')
15
23
  @redises.mget(@key1, @key2).should == %w[value1 value2]
@@ -26,4 +34,10 @@ describe '#mset(key, value [, key, value, ...])' do
26
34
  @redises.mset
27
35
  end.should raise_error(Redis::CommandError)
28
36
  end
37
+
38
+ it 'raises an error if given odd-sized array' do
39
+ lambda do
40
+ @redises.mset([@key1, 1, @key2])
41
+ end.should raise_error(Redis::CommandError)
42
+ end
29
43
  end
@@ -39,4 +39,56 @@ describe '#pipelined' do
39
39
  future.class.should be MockRedis::Future
40
40
  end
41
41
  end
42
+
43
+ context 'with pipelined operations returning array replies' do
44
+ let(:key1) { 'colors' }
45
+ let(:key2) { 'seasons' }
46
+ let(:value1) { %w[blue yellow] }
47
+ let(:value2) { %w[summer winter] }
48
+
49
+ before do
50
+ @redises.rpush(key1, value1)
51
+ @redises.rpush(key2, value2)
52
+ end
53
+
54
+ after do
55
+ @redises.del key1
56
+ @redises.del key2
57
+ end
58
+
59
+ it 'returns an array of the array replies' do
60
+ results = @redises.pipelined do |_redis|
61
+ @redises.lrange(key1, 0, -1)
62
+ @redises.lrange(key2, 0, -1)
63
+ end
64
+
65
+ results.should == [value1, value2]
66
+ end
67
+ end
68
+
69
+ context 'with nested pipelines' do
70
+ let(:key1) { 'hello' }
71
+ let(:key2) { 'world' }
72
+ let(:value1) { 'foo' }
73
+ let(:value2) { 'bar' }
74
+
75
+ before do
76
+ @redises.set key1, value1
77
+ @redises.set key2, value2
78
+ end
79
+
80
+ it 'returns results of the nested pipelines' do
81
+ results = @redises.pipelined do |pr1|
82
+ pr1.pipelined do |pr2|
83
+ pr2.get key1
84
+ end
85
+
86
+ pr1.pipelined do |pr2|
87
+ pr2.get key2
88
+ end
89
+ end
90
+
91
+ results.should == [value1, value2]
92
+ end
93
+ end
42
94
  end
@@ -21,5 +21,20 @@ describe '#spop(key)' do
21
21
  @redises.spop(@key).should be_nil
22
22
  end
23
23
 
24
+ it 'returns an array if count is not nil' do
25
+ @redises.sadd(@key, 'value2')
26
+ @redises.spop(@key, 2).should == %w[value value2]
27
+ end
28
+
29
+ it 'returns only whats in the set' do
30
+ @redises.spop(@key, 2).should == ['value']
31
+ @redises.smembers(@key).should == []
32
+ end
33
+
34
+ it 'returns an empty array if count is not nil and the set it empty' do
35
+ @redises.spop(@key)
36
+ @redises.spop(@key, 100).should == []
37
+ end
38
+
24
39
  it_should_behave_like 'a set-only command'
25
40
  end
@@ -1,12 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe '#watch(key)' do
3
+ describe '#watch(key [, key, ...)' do
4
+ before do
5
+ @key1 = 'mock-redis-test-watch1'
6
+ @key2 = 'mock-redis-test-watch2'
7
+ end
8
+
4
9
  it "returns 'OK'" do
5
- @redises.watch('mock-redis-test').should == 'OK'
10
+ @redises.watch(@key1, @key2).should == 'OK'
6
11
  end
7
12
 
8
13
  it 'EXECs its MULTI on successes' do
9
- @redises.watch 'foo' do
14
+ @redises.watch @key1, @key2 do
10
15
  @redises.multi do |multi|
11
16
  multi.set 'bar', 'baz'
12
17
  end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#xadd("mystream", { f1: "v1", f2: "v2" }, id: "0-0", maxlen: 1000, approximate: true)' do
4
+ before :all do
5
+ sleep 1 - (Time.now.to_f % 1)
6
+ @key = 'mock-redis-test:xadd'
7
+ end
8
+
9
+ before :each do
10
+ @redises._gsub(/\d{3}-\d/, '...-.')
11
+ end
12
+
13
+ it 'returns an id based on the timestamp' do
14
+ t = Time.now.to_i
15
+ expect(@redises.xadd(@key, key: 'value')).to match(/#{t}\d{3}-0/)
16
+ end
17
+
18
+ it 'adds data with symbols' do
19
+ @redises.xadd(@key, symbol_key: :symbol_value)
20
+ expect(@redises.xrange(@key, '-', '+').last[1])
21
+ .to eq('symbol_key' => 'symbol_value')
22
+ end
23
+
24
+ it 'increments the sequence number with the same timestamp' do
25
+ Timecop.freeze do
26
+ @redises.xadd(@key, key: 'value')
27
+ expect(@redises.xadd(@key, key: 'value')).to match(/\d+-1/)
28
+ end
29
+ end
30
+
31
+ it 'sets the id if it is given' do
32
+ expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234-2'))
33
+ .to eq '1234567891234-2'
34
+ end
35
+
36
+ it 'accepts is as an integer' do
37
+ expect(@redises.xadd(@key, { key: 'value' }, id: 1_234_567_891_234))
38
+ .to eq '1234567891234-0'
39
+ end
40
+
41
+ it 'raises exception if id is less that stream top item' do
42
+ @redises.xadd(@key, { key: 'value' }, id: '1234567891234-0')
43
+ expect { @redises.xadd(@key, { key: 'value' }, id: '1234567891233-0') }
44
+ .to raise_error(
45
+ Redis::CommandError,
46
+ 'ERR The ID specified in XADD is equal or smaller than the target ' \
47
+ 'stream top item'
48
+ )
49
+ end
50
+
51
+ it 'raises exception if id of 0 is added to an empty stream' do
52
+ expect { @redises.xadd('mock-redis-test:unknown-stream', { key: 'value' }, id: '0') }
53
+ .to raise_error(
54
+ Redis::CommandError,
55
+ 'ERR The ID specified in XADD is equal or smaller than the target ' \
56
+ 'stream top item'
57
+ )
58
+ end
59
+
60
+ it 'does not raise exception on empty stream with id of 0 and positive sequence number' do
61
+ expect { @redises.xadd('mock-redis-test:unknown-stream', { key: 'value' }, id: '0-1') }
62
+ .to_not raise_error
63
+ end
64
+
65
+ it 'caters for the current time being before the last time' do
66
+ t = (Time.now.to_f * 1000).to_i + 2000
67
+ @redises.xadd(@key, { key: 'value' }, id: "#{t}-0")
68
+ expect(@redises.xadd(@key, key: 'value')).to match(/#{t}-1/)
69
+ end
70
+
71
+ it 'appends a sequence number if it is missing' do
72
+ expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234'))
73
+ .to eq '1234567891234-0'
74
+ end
75
+
76
+ it 'raises an invalid stream id error' do
77
+ expect { @redises.xadd(@key, { key: 'value' }, id: 'X') }
78
+ .to raise_error(
79
+ Redis::CommandError,
80
+ 'ERR Invalid stream ID specified as stream command argument'
81
+ )
82
+ end
83
+
84
+ it 'caps the stream to 5 elements' do
85
+ @redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
86
+ @redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0')
87
+ @redises.xadd(@key, { key3: 'value3' }, id: '1234567891245-1')
88
+ @redises.xadd(@key, { key4: 'value4' }, id: '1234567891278-0')
89
+ @redises.xadd(@key, { key5: 'value5' }, id: '1234567891278-1')
90
+ @redises.xadd(@key, { key6: 'value6' }, id: '1234567891299-0')
91
+ @redises.xadd(@key, { key7: 'value7' }, id: '1234567891300-0', maxlen: 5)
92
+ expect(@redises.xrange(@key, '-', '+')).to eq(
93
+ [
94
+ ['1234567891245-1', { 'key3' => 'value3' }],
95
+ ['1234567891278-0', { 'key4' => 'value4' }],
96
+ ['1234567891278-1', { 'key5' => 'value5' }],
97
+ ['1234567891299-0', { 'key6' => 'value6' }],
98
+ ['1234567891300-0', { 'key7' => 'value7' }]
99
+ ]
100
+ )
101
+ end
102
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#xlen(key)' do
4
+ before :all do
5
+ sleep 1 - (Time.now.to_f % 1)
6
+ @key = 'mock-redis-test:xlen'
7
+ end
8
+
9
+ before :each do
10
+ @redises._gsub(/\d{3}-\d/, '...-.')
11
+ end
12
+
13
+ it 'returns the number of items in the stream' do
14
+ expect(@redises.xlen(@key)).to eq 0
15
+ @redises.xadd(@key, key: 'value')
16
+ expect(@redises.xlen(@key)).to eq 1
17
+ 3.times { @redises.xadd(@key, key: 'value') }
18
+ expect(@redises.xlen(@key)).to eq 4
19
+ end
20
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#xrange("mystream", first: "0-1", last: "0-3", count: 10)' do
4
+ before { @key = 'mock-redis-test:xrange' }
5
+
6
+ it 'finds an empty range' do
7
+ expect(@redises.xrange(@key, '-', '+')).to eq []
8
+ end
9
+
10
+ it 'finds a single entry with a full range' do
11
+ @redises.xadd(@key, { key: 'value' }, id: '1234567891234-0')
12
+ expect(@redises.xrange(@key, '-', '+'))
13
+ .to eq [['1234567891234-0', { 'key' => 'value' }]]
14
+ end
15
+
16
+ it 'finds multiple key/value pairs with a full range' do
17
+ @redises.xadd(@key, { key1: 'value1', key2: 'value2', key3: 'value3' }, id: '1234567891234-0')
18
+ expect(@redises.xrange(@key, '-', '+'))
19
+ .to eq [['1234567891234-0', { 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }]]
20
+ end
21
+
22
+ context 'six items on the list' do
23
+ before :each do
24
+ @redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
25
+ @redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0')
26
+ @redises.xadd(@key, { key3: 'value3' }, id: '1234567891245-1')
27
+ @redises.xadd(@key, { key4: 'value4' }, id: '1234567891278-0')
28
+ @redises.xadd(@key, { key5: 'value5' }, id: '1234567891278-1')
29
+ @redises.xadd(@key, { key6: 'value6' }, id: '1234567891299-0')
30
+ end
31
+
32
+ it 'returns entries in sequential order' do
33
+ expect(@redises.xrange(@key, '-', '+')).to eq(
34
+ [
35
+ ['1234567891234-0', { 'key1' => 'value1' }],
36
+ ['1234567891245-0', { 'key2' => 'value2' }],
37
+ ['1234567891245-1', { 'key3' => 'value3' }],
38
+ ['1234567891278-0', { 'key4' => 'value4' }],
39
+ ['1234567891278-1', { 'key5' => 'value5' }],
40
+ ['1234567891299-0', { 'key6' => 'value6' }]
41
+ ]
42
+ )
43
+ end
44
+
45
+ it 'returns entries with a lower limit' do
46
+ expect(@redises.xrange(@key, '1234567891239-0', '+')).to eq(
47
+ [
48
+ ['1234567891245-0', { 'key2' => 'value2' }],
49
+ ['1234567891245-1', { 'key3' => 'value3' }],
50
+ ['1234567891278-0', { 'key4' => 'value4' }],
51
+ ['1234567891278-1', { 'key5' => 'value5' }],
52
+ ['1234567891299-0', { 'key6' => 'value6' }]
53
+ ]
54
+ )
55
+ end
56
+
57
+ it 'returns entries with an upper limit' do
58
+ expect(@redises.xrange(@key, '-', '1234567891285-0')).to eq(
59
+ [
60
+ ['1234567891234-0', { 'key1' => 'value1' }],
61
+ ['1234567891245-0', { 'key2' => 'value2' }],
62
+ ['1234567891245-1', { 'key3' => 'value3' }],
63
+ ['1234567891278-0', { 'key4' => 'value4' }],
64
+ ['1234567891278-1', { 'key5' => 'value5' }]
65
+ ]
66
+ )
67
+ end
68
+
69
+ it 'returns entries with both a lower and an upper limit' do
70
+ expect(@redises.xrange(@key, '1234567891239-0', '1234567891285-0')).to eq(
71
+ [
72
+ ['1234567891245-0', { 'key2' => 'value2' }],
73
+ ['1234567891245-1', { 'key3' => 'value3' }],
74
+ ['1234567891278-0', { 'key4' => 'value4' }],
75
+ ['1234567891278-1', { 'key5' => 'value5' }]
76
+ ]
77
+ )
78
+ end
79
+
80
+ it 'finds the list with sequence numbers' do
81
+ expect(@redises.xrange(@key, '1234567891245-1', '1234567891278-0')).to eq(
82
+ [
83
+ ['1234567891245-1', { 'key3' => 'value3' }],
84
+ ['1234567891278-0', { 'key4' => 'value4' }]
85
+ ]
86
+ )
87
+ end
88
+
89
+ it 'finds the list with lower bound without sequence numbers' do
90
+ expect(@redises.xrange(@key, '1234567891245', '+')).to eq(
91
+ [
92
+ ['1234567891245-0', { 'key2' => 'value2' }],
93
+ ['1234567891245-1', { 'key3' => 'value3' }],
94
+ ['1234567891278-0', { 'key4' => 'value4' }],
95
+ ['1234567891278-1', { 'key5' => 'value5' }],
96
+ ['1234567891299-0', { 'key6' => 'value6' }]
97
+ ]
98
+ )
99
+ end
100
+
101
+ it 'finds the list with upper bound without sequence numbers' do
102
+ expect(@redises.xrange(@key, '-', '1234567891278')).to eq(
103
+ [
104
+ ['1234567891234-0', { 'key1' => 'value1' }],
105
+ ['1234567891245-0', { 'key2' => 'value2' }],
106
+ ['1234567891245-1', { 'key3' => 'value3' }],
107
+ ['1234567891278-0', { 'key4' => 'value4' }],
108
+ ['1234567891278-1', { 'key5' => 'value5' }]
109
+ ]
110
+ )
111
+ end
112
+
113
+ it 'accepts limits as integers' do
114
+ expect(@redises.xrange(@key, 1_234_567_891_245, 1_234_567_891_278)).to eq(
115
+ [
116
+ ['1234567891245-0', { 'key2' => 'value2' }],
117
+ ['1234567891245-1', { 'key3' => 'value3' }],
118
+ ['1234567891278-0', { 'key4' => 'value4' }],
119
+ ['1234567891278-1', { 'key5' => 'value5' }]
120
+ ]
121
+ )
122
+ end
123
+
124
+ it 'returns a limited number of items' do
125
+ expect(@redises.xrange(@key, '-', '+', count: 2)).to eq(
126
+ [
127
+ ['1234567891234-0', { 'key1' => 'value1' }],
128
+ ['1234567891245-0', { 'key2' => 'value2' }]
129
+ ]
130
+ )
131
+ end
132
+ end
133
+
134
+ it 'raises an invalid stream id error' do
135
+ expect { @redises.xrange(@key, 'X', '+') }
136
+ .to raise_error(
137
+ Redis::CommandError,
138
+ 'ERR Invalid stream ID specified as stream command argument'
139
+ )
140
+ end
141
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#xrevrange(key, start, end)' do
4
+ before { @key = 'mock-redis-test:xrevrange' }
5
+
6
+ it 'finds an empty range' do
7
+ expect(@redises.xrevrange(@key, '-', '+')).to eq []
8
+ end
9
+
10
+ it 'finds a single entry with a full range' do
11
+ @redises.xadd(@key, { key: 'value' }, id: '1234567891234-0')
12
+ expect(@redises.xrevrange(@key, '+', '-'))
13
+ .to eq [['1234567891234-0', { 'key' => 'value' }]]
14
+ end
15
+
16
+ it 'finds multiple key/value pairs with a full range' do
17
+ @redises.xadd(@key, { key1: 'value1', key2: 'value2', key3: 'value3' }, id: '1234567891234-0')
18
+ expect(@redises.xrevrange(@key, '+', '-'))
19
+ .to eq [['1234567891234-0', { 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }]]
20
+ end
21
+
22
+ context 'six items on the list' do
23
+ before :each do
24
+ @redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
25
+ @redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0')
26
+ @redises.xadd(@key, { key3: 'value3' }, id: '1234567891245-1')
27
+ @redises.xadd(@key, { key4: 'value4' }, id: '1234567891278-0')
28
+ @redises.xadd(@key, { key5: 'value5' }, id: '1234567891278-1')
29
+ @redises.xadd(@key, { key6: 'value6' }, id: '1234567891299-0')
30
+ end
31
+
32
+ it 'returns entries in sequential order' do
33
+ expect(@redises.xrevrange(@key, '+', '-')).to eq(
34
+ [
35
+ ['1234567891299-0', { 'key6' => 'value6' }],
36
+ ['1234567891278-1', { 'key5' => 'value5' }],
37
+ ['1234567891278-0', { 'key4' => 'value4' }],
38
+ ['1234567891245-1', { 'key3' => 'value3' }],
39
+ ['1234567891245-0', { 'key2' => 'value2' }],
40
+ ['1234567891234-0', { 'key1' => 'value1' }],
41
+ ]
42
+ )
43
+ end
44
+
45
+ it 'returns entries with a lower limit' do
46
+ expect(@redises.xrevrange(@key, '+', '1234567891239-0')).to eq(
47
+ [
48
+ ['1234567891299-0', { 'key6' => 'value6' }],
49
+ ['1234567891278-1', { 'key5' => 'value5' }],
50
+ ['1234567891278-0', { 'key4' => 'value4' }],
51
+ ['1234567891245-1', { 'key3' => 'value3' }],
52
+ ['1234567891245-0', { 'key2' => 'value2' }],
53
+ ]
54
+ )
55
+ end
56
+
57
+ it 'returns entries with an upper limit' do
58
+ expect(@redises.xrevrange(@key, '1234567891285-0', '-')).to eq(
59
+ [
60
+ ['1234567891278-1', { 'key5' => 'value5' }],
61
+ ['1234567891278-0', { 'key4' => 'value4' }],
62
+ ['1234567891245-1', { 'key3' => 'value3' }],
63
+ ['1234567891245-0', { 'key2' => 'value2' }],
64
+ ['1234567891234-0', { 'key1' => 'value1' }],
65
+ ]
66
+ )
67
+ end
68
+
69
+ it 'returns entries with both a lower and an upper limit' do
70
+ expect(@redises.xrevrange(@key, '1234567891285-0', '1234567891239-0')).to eq(
71
+ [
72
+ ['1234567891278-1', { 'key5' => 'value5' }],
73
+ ['1234567891278-0', { 'key4' => 'value4' }],
74
+ ['1234567891245-1', { 'key3' => 'value3' }],
75
+ ['1234567891245-0', { 'key2' => 'value2' }],
76
+ ]
77
+ )
78
+ end
79
+
80
+ it 'finds the list with sequence numbers' do
81
+ expect(@redises.xrevrange(@key, '1234567891278-0', '1234567891245-1')).to eq(
82
+ [
83
+ ['1234567891278-0', { 'key4' => 'value4' }],
84
+ ['1234567891245-1', { 'key3' => 'value3' }],
85
+ ]
86
+ )
87
+ end
88
+
89
+ it 'finds the list with lower bound without sequence numbers' do
90
+ expect(@redises.xrevrange(@key, '+', '1234567891245')).to eq(
91
+ [
92
+ ['1234567891299-0', { 'key6' => 'value6' }],
93
+ ['1234567891278-1', { 'key5' => 'value5' }],
94
+ ['1234567891278-0', { 'key4' => 'value4' }],
95
+ ['1234567891245-1', { 'key3' => 'value3' }],
96
+ ['1234567891245-0', { 'key2' => 'value2' }],
97
+ ]
98
+ )
99
+ end
100
+
101
+ it 'finds the list with upper bound without sequence numbers' do
102
+ expect(@redises.xrevrange(@key, '1234567891278', '-')).to eq(
103
+ [
104
+ ['1234567891278-1', { 'key5' => 'value5' }],
105
+ ['1234567891278-0', { 'key4' => 'value4' }],
106
+ ['1234567891245-1', { 'key3' => 'value3' }],
107
+ ['1234567891245-0', { 'key2' => 'value2' }],
108
+ ['1234567891234-0', { 'key1' => 'value1' }],
109
+ ]
110
+ )
111
+ end
112
+
113
+ it 'returns a limited number of items' do
114
+ expect(@redises.xrevrange(@key, count: 2)).to eq(
115
+ [
116
+ ['1234567891299-0', { 'key6' => 'value6' }],
117
+ ['1234567891278-1', { 'key5' => 'value5' }],
118
+ ]
119
+ )
120
+ end
121
+ end
122
+
123
+ it 'raises an invalid stream id error' do
124
+ expect { @redises.xrevrange(@key, 'X', '-') }
125
+ .to raise_error(
126
+ Redis::CommandError,
127
+ 'ERR Invalid stream ID specified as stream command argument'
128
+ )
129
+ end
130
+ end