Skip to content

Commit

Permalink
Merge 18c79fa into 6a679fe
Browse files Browse the repository at this point in the history
  • Loading branch information
jrmhaig committed Jan 25, 2019
2 parents 6a679fe + 18c79fa commit 5d4f876
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 230 deletions.
11 changes: 7 additions & 4 deletions lib/mock_redis/stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ def last_id

def add(id, values)
@last_id = MockRedis::Stream::Id.new(id, min: @last_id)
members.add [@last_id, values.map(&:to_s)]
members.add [@last_id, Hash[values.map { |k, v| [k.to_s, v.to_s] }]]
@last_id.to_s
end

def trim(count)
deleted = @members.size - count
@members = @members.to_a[-count..-1].to_set
deleted
end

def range(start, finish, reversed, *opts_in)
opts = options opts_in, ['count']
unless opts['count'].nil? || /^\d*$/.match(opts['count'])
raise Redis::CommandError, 'ERR value is not an integer or out of range'
end
start_id = MockRedis::Stream::Id.new(start)
finish_id = MockRedis::Stream::Id.new(finish, sequence: Float::INFINITY)
items = members
Expand Down
67 changes: 41 additions & 26 deletions lib/mock_redis/stream_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,68 @@
require 'mock_redis/utility_methods'
require 'mock_redis/stream'

# TODO: Implement the following commands
#
# * xread
# * xgroup
# * xreadgroup
# * xack
# * xpending
# * xclaim
# * xinfo
# * xtrim
# * xdel
#
# TODO: Complete support for
#
# * xtrim
# - `approximate: true` argument is currently ignored
# * xadd
# - `approximate: true` argument (for capped streams) is currently ignored
#
# For details of these commands see
# * https://redis.io/topics/streams-intro
# * https://redis.io/commands#stream

class MockRedis
module StreamMethods
include Assertions
include UtilityMethods

def xadd(key = nil, id = nil, *args)
if args.count == 0
raise Redis::CommandError,
"ERR wrong number of arguments for 'xadd' command"
end
if args.count.odd?
raise Redis::CommandError,
'ERR wrong number of arguments for XADD'
end
def xadd(key, entry, opts = {})
id = opts[:id] || '*'
with_stream_at(key) do |stream|
stream.add id, args
stream.add id, entry
stream.trim opts[:maxlen] if opts[:maxlen]
return stream.last_id
end
end

def xlen(key = nil, *args)
if key.nil? || args.count > 0
raise Redis::CommandError,
"ERR wrong number of arguments for 'xlen' command"
def xtrim(key, count)
with_stream_at(key) do |stream|
stream.trim count
end
end

def xlen(key)
with_stream_at(key) do |stream|
return stream.count
end
end

def xrange(key = nil, start = nil, finish = nil, *options)
if finish.nil?
raise Redis::CommandError,
"ERR wrong number of arguments for 'xrange' command"
end
def xrange(key, first = '-', last = '+', count: nil)
args = [first, last, false]
args += ['COUNT', count] if count
with_stream_at(key) do |stream|
return stream.range(start, finish, false, *options)
return stream.range(*args)
end
end

def xrevrange(key = nil, finish = nil, start = nil, *options)
if start.nil?
raise Redis::CommandError,
"ERR wrong number of arguments for 'xrevrange' command"
end
def xrevrange(key, last = '+', first = '-', count: nil)
args = [first, last, true]
args += ['COUNT', count] if count
with_stream_at(key) do |stream|
return stream.range(start, finish, true, *options)
return stream.range(*args)
end
end

Expand Down
2 changes: 1 addition & 1 deletion mock_redis.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 2.2'

s.add_development_dependency 'rake', '>= 10', '< 12'
s.add_development_dependency 'redis', '~>4.0.1'
s.add_development_dependency 'redis', '~>4.1.0'
s.add_development_dependency 'rspec', '~> 3.0'
s.add_development_dependency 'rspec-its', '~> 1.0'
s.add_development_dependency 'timecop', '~> 0.9.1'
Expand Down
65 changes: 35 additions & 30 deletions spec/commands/xadd_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'spec_helper'

describe '#xadd(key, id, [field, value, ...])' do
describe '#xadd("mystream", { f1: "v1", f2: "v2" }, id: "0-0", maxlen: 1000, approximate: true)' do
before :all do
sleep 1 - (Time.now.to_f % 1)
@key = 'mock-redis-test:xadd'
Expand All @@ -12,35 +12,35 @@

it 'returns an id based on the timestamp' do
t = Time.now.to_i
expect(@redises.xadd(@key, '*', 'key', 'value')).to match(/#{t}\d{3}-0/)
expect(@redises.xadd(@key, key: 'value')).to match(/#{t}\d{3}-0/)
end

it 'adds data with symbols' do
@redises.xadd(@key, '*', :symbol_key, :symbol_value)
@redises.xadd(@key, symbol_key: :symbol_value)
expect(@redises.xrange(@key, '-', '+').last[1])
.to eq(%w[symbol_key symbol_value])
.to eq('symbol_key' => 'symbol_value')
end

it 'increments the sequence number with the same timestamp' do
Timecop.freeze do
@redises.xadd(@key, '*', 'key', 'value')
expect(@redises.xadd(@key, '*', 'key', 'value')).to match(/\d+-1/)
@redises.xadd(@key, key: 'value')
expect(@redises.xadd(@key, key: 'value')).to match(/\d+-1/)
end
end

it 'sets the id if it is given' do
expect(@redises.xadd(@key, '1234567891234-2', 'key', 'value'))
expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234-2'))
.to eq '1234567891234-2'
end

it 'accepts is as an integer' do
expect(@redises.xadd(@key, 1_234_567_891_234, 'key', 'value'))
expect(@redises.xadd(@key, { key: 'value' }, id: 1_234_567_891_234))
.to eq '1234567891234-0'
end

it 'sets an id based on the timestamp if the given id is before the last' do
@redises.xadd(@key, '1234567891234-0', 'key', 'value')
expect { @redises.xadd(@key, '1234567891233-0', 'key', 'value') }
@redises.xadd(@key, { key: 'value' }, id: '1234567891234-0')
expect { @redises.xadd(@key, { key: 'value' }, id: '1234567891233-0') }
.to raise_error(
Redis::CommandError,
'ERR The ID specified in XADD is equal or smaller than the target ' \
Expand All @@ -50,36 +50,41 @@

it 'caters for the current time being before the last time' do
t = (Time.now.to_f * 1000).to_i + 2000
@redises.xadd(@key, "#{t}-0", 'key', 'value')
expect(@redises.xadd(@key, '*', 'key', 'value')).to match(/#{t}-1/)
@redises.xadd(@key, { key: 'value' }, id: "#{t}-0")
expect(@redises.xadd(@key, key: 'value')).to match(/#{t}-1/)
end

it 'appends a sequence number if it is missing' do
expect(@redises.xadd(@key, '1234567891234', 'key', 'value'))
expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234'))
.to eq '1234567891234-0'
end

it 'raises wrong number of arguments error with missing values' do
expect { @redises.xadd(@key, '*') }
.to raise_error(
Redis::CommandError,
"ERR wrong number of arguments for 'xadd' command"
)
end

it 'raises wrong number of arguments error with odd number of values' do
expect { @redises.xadd(@key, '*', 'key', 'value', 'key') }
.to raise_error(
Redis::CommandError,
'ERR wrong number of arguments for XADD'
)
end

it 'raises an invalid stream id error' do
expect { @redises.xadd(@key, 'X', 'key', 'value') }
expect { @redises.xadd(@key, { key: 'value' }, id: 'X') }
.to raise_error(
Redis::CommandError,
'ERR Invalid stream ID specified as stream command argument'
)
end

it 'caps the stream to 5 elements' do
@redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
@redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0')
@redises.xadd(@key, { key3: 'value3' }, id: '1234567891245-1')
@redises.xadd(@key, { key4: 'value4' }, id: '1234567891278-0')
@redises.xadd(@key, { key5: 'value5' }, id: '1234567891278-1')
@redises.xadd(@key, { key6: 'value6' }, id: '1234567891299-0')
@redises.xadd(@key, { key7: 'value7' }, id: '1234567891300-0', maxlen: 5)
expect(@redises.xrange(@key, '-', '+')).to eq(
[
['1234567891245-1', { 'key3' => 'value3' }],
['1234567891278-0', { 'key4' => 'value4' }],
['1234567891278-1', { 'key5' => 'value5' }],
['1234567891299-0', { 'key6' => 'value6' }],
['1234567891300-0', { 'key7' => 'value7' }]
]
)
end
end

# Redis::CommandError: ERR The ID specified in XADD is equal or smaller than the target stream top item
20 changes: 2 additions & 18 deletions spec/commands/xlen_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,9 @@

it 'returns the number of items in the stream' do
expect(@redises.xlen(@key)).to eq 0
@redises.xadd(@key, '*', 'key', 'value')
@redises.xadd(@key, key: 'value')
expect(@redises.xlen(@key)).to eq 1
3.times { @redises.xadd(@key, '*', 'key', 'value') }
3.times { @redises.xadd(@key, key: 'value') }
expect(@redises.xlen(@key)).to eq 4
end

it 'raises wrong number of arguments error with missing key' do
expect { @redises.xlen }
.to raise_error(
Redis::CommandError,
"ERR wrong number of arguments for 'xlen' command"
)
end

it 'raises wrong number of arguments error with extra arguments' do
expect { @redises.xlen(@key, 'xyz') }
.to raise_error(
Redis::CommandError,
"ERR wrong number of arguments for 'xlen' command"
)
end
end

0 comments on commit 5d4f876

Please sign in to comment.