mock_redis 0.19.0 → 0.20.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.
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