Skip to content

Commit

Permalink
Change exists return and add exists? (#188)
Browse files Browse the repository at this point in the history
* Change exists return and add exists?

* Bump redis version

* Fix usage of exists and specs

* Change xadd error message

* Address rubocop

* Rubocop
  • Loading branch information
jmthomas committed Jun 18, 2020
1 parent d7d9352 commit 166c8bb
Show file tree
Hide file tree
Showing 20 changed files with 105 additions and 53 deletions.
23 changes: 14 additions & 9 deletions lib/mock_redis/database.rb
Expand Up @@ -106,7 +106,7 @@ def pexpireat(key, timestamp_ms)
raise Redis::CommandError, 'ERR value is not an integer or out of range'
end

if exists(key)
if exists?(key)
timestamp = Rational(timestamp_ms.to_i, 1000)
set_expiration(key, @base.time_at(timestamp))
true
Expand All @@ -115,8 +115,13 @@ def pexpireat(key, timestamp_ms)
end
end

def exists(key)
data.key?(key)
def exists(*keys)
keys.count { |key| data.key?(key) }
end

def exists?(*keys)
keys.each { |key| return true if data.key?(key) }
false
end

def flushdb
Expand All @@ -130,7 +135,7 @@ def dump(key)
end

def restore(key, ttl, value, replace: false)
if !replace && exists(key)
if !replace && exists?(key)
raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
end
data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
Expand Down Expand Up @@ -163,7 +168,7 @@ def lastsave
end

def persist(key)
if exists(key) && has_expiration?(key)
if exists?(key) && has_expiration?(key)
remove_expiration(key)
true
else
Expand Down Expand Up @@ -204,7 +209,7 @@ def renamenx(key, newkey)
raise Redis::CommandError, 'ERR no such key'
end

if exists(newkey)
if exists?(newkey)
false
else
rename(key, newkey)
Expand All @@ -217,7 +222,7 @@ def save
end

def ttl(key)
if !exists(key)
if !exists?(key)
-2
elsif has_expiration?(key)
now, = @base.now
Expand All @@ -231,7 +236,7 @@ def pttl(key)
now, miliseconds = @base.now
now_ms = now * 1000 + miliseconds

if !exists(key)
if !exists?(key)
-2
elsif has_expiration?(key)
(expiration(key).to_r * 1000).to_i - now_ms
Expand All @@ -248,7 +253,7 @@ def now
alias time now

def type(key)
if !exists(key)
if !exists?(key)
'none'
elsif hashy?(key)
'hash'
Expand Down
13 changes: 9 additions & 4 deletions lib/mock_redis/hash_methods.rb
Expand Up @@ -128,10 +128,15 @@ def hscan_each(key, opts = {}, &block)
end
end

def hset(key, field, value)
field_exists = hexists(key, field)
with_hash_at(key) { |h| h[field.to_s] = value.to_s }
!field_exists
def hset(key, *args)
added = 0
with_hash_at(key) do |hash|
args.each_slice(2) do |field, value|
added += 1 unless hash.key?(field.to_s)
hash[field.to_s] = value.to_s
end
end
added
end

def hsetnx(key, field, value)
Expand Down
2 changes: 1 addition & 1 deletion lib/mock_redis/multi_db_wrapper.rb
Expand Up @@ -39,7 +39,7 @@ def move(key, db_index)
src = current_db
dest = db(db_index)

if !src.exists(key) || dest.exists(key)
if !src.exists?(key) || dest.exists?(key)
false
else
case current_db.type(key)
Expand Down
9 changes: 8 additions & 1 deletion lib/mock_redis/stream/id.rb
Expand Up @@ -31,7 +31,14 @@ def initialize(id, min: nil, sequence: 0)
@timestamp = id
end
@sequence = @sequence.nil? ? sequence : @sequence.to_i
if (@timestamp == 0 && @sequence == 0) || self <= min
if @timestamp == 0 && @sequence == 0
raise Redis::CommandError,
'ERR The ID specified in XADD is equal or smaller than ' \
'the target stream top item'
# TOOD: Redis version 6.0.4, w redis 4.2.1 generates the following error message:
# 'ERR The ID specified in XADD must be greater than 0-0'
end
if self <= min
raise Redis::CommandError,
'ERR The ID specified in XADD is equal or smaller than ' \
'the target stream top item'
Expand Down
11 changes: 7 additions & 4 deletions lib/mock_redis/string_methods.rb
Expand Up @@ -188,7 +188,7 @@ def mapped_mset(hash)
def msetnx(*kvpairs)
assert_has_args(kvpairs, 'msetnx')

if kvpairs.each_slice(2).any? { |(k, _)| exists(k) }
if kvpairs.each_slice(2).any? { |(k, _)| exists?(k) }
false
else
mset(*kvpairs)
Expand All @@ -205,14 +205,14 @@ def set(key, value, options = {})
return_true = false
options = options.dup
if options.delete(:nx)
if exists(key)
if exists?(key)
return false
else
return_true = true
end
end
if options.delete(:xx)
if exists(key)
if exists?(key)
return_true = true
else
return false
Expand All @@ -235,6 +235,9 @@ def set(key, value, options = {})
end
pexpire(key, duration)
end
unless options.empty?
raise ArgumentError, "unknown keyword: #{options.keys[0]}"
end

return_true ? true : 'OK'
end
Expand Down Expand Up @@ -323,7 +326,7 @@ def setex(key, seconds, value)
end

def setnx(key, value)
if exists(key)
if exists?(key)
false
else
set(key, value)
Expand Down
2 changes: 1 addition & 1 deletion mock_redis.gemspec
Expand Up @@ -23,7 +23,7 @@ Gem::Specification.new do |s|

s.required_ruby_version = '>= 2.4'

s.add_development_dependency 'redis', '~> 4.1.0'
s.add_development_dependency 'redis', '~> 4.2.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
6 changes: 0 additions & 6 deletions spec/commands/blpop_spec.rb
Expand Up @@ -27,12 +27,6 @@
[@list1, 'one']
end

it 'raises an error on subsecond timeouts' do
lambda do
@redises.blpop(@list1, @list2, :timeout => 0.5)
end.should raise_error(Redis::CommandError)
end

it 'raises an error on negative timeout' do
lambda do
@redises.blpop(@list1, @list2, :timeout => -1)
Expand Down
11 changes: 6 additions & 5 deletions spec/commands/brpop_spec.rb
Expand Up @@ -26,11 +26,12 @@
[@list1, 'two']
end

it 'raises an error on subsecond timeouts' do
lambda do
@redises.brpop(@list1, @list2, :timeout => 0.5)
end.should raise_error(Redis::CommandError)
end
# TODO: Not sure how redis-rb is handling this but they're not raising an error
# it 'raises an error on subsecond timeouts' do
# lambda do
# @redises.brpop(@list1, @list2, :timeout => 0.5)
# end.should raise_error(Redis::CommandError)
# end

it 'raises an error on negative timeout' do
lambda do
Expand Down
39 changes: 34 additions & 5 deletions spec/commands/exists_spec.rb
@@ -1,14 +1,43 @@
require 'spec_helper'

describe '#exists(key)' do
before { @key = 'mock-redis-test:45794' }
describe '#exists(*keys)' do
before { @key1 = 'mock-redis-test:exists1' }
before { @key2 = 'mock-redis-test:exists2' }

it 'returns 0 for keys that do not exist' do
@redises.exists(@key1).should == 0
@redises.exists(@key1, @key2).should == 0
end

it 'returns 1 for keys that do exist' do
@redises.set(@key1, 1)
@redises.exists(@key1).should == 1
end

it 'returns the count of all keys that exist' do
@redises.set(@key1, 1)
@redises.set(@key2, 1)
@redises.exists(@key1, @key2).should == 2
@redises.exists(@key1, @key2, 'does-not-exist').should == 2
end
end

describe '#exists?(*keys)' do
before { @key1 = 'mock-redis-test:exists1' }
before { @key2 = 'mock-redis-test:exists2' }

it 'returns false for keys that do not exist' do
@redises.exists(@key).should == false
@redises.exists?(@key1).should == false
@redises.exists?(@key1, @key2).should == false
end

it 'returns true for keys that do exist' do
@redises.set(@key, 1)
@redises.exists(@key).should == true
@redises.set(@key1, 1)
@redises.exists?(@key1).should == true
end

it 'returns true if any keys exist' do
@redises.set(@key2, 1)
@redises.exists?(@key1, @key2).should == true
end
end
12 changes: 6 additions & 6 deletions spec/commands/hset_spec.rb
Expand Up @@ -5,18 +5,18 @@
@key = 'mock-redis-test:hset'
end

it 'returns true if the key does not exist' do
@redises.hset(@key, 'k1', 'v1').should == true
it 'returns 1 if the key does not exist' do
@redises.hset(@key, 'k1', 'v1').should == 1
end

it 'returns true if the key exists but the field does not' do
it 'returns 1 if the key exists but the field does not' do
@redises.hset(@key, 'k1', 'v1')
@redises.hset(@key, 'k2', 'v2').should == true
@redises.hset(@key, 'k2', 'v2').should == 1
end

it 'returns false if the field already exists' do
it 'returns 0 if the field already exists' do
@redises.hset(@key, 'k1', 'v1')
@redises.hset(@key, 'k1', 'v1').should == false
@redises.hset(@key, 'k1', 'v1').should == 0
end

it 'creates a hash there is no such field' do
Expand Down
10 changes: 5 additions & 5 deletions spec/commands/move_spec.rb
Expand Up @@ -64,7 +64,7 @@
end

it 'removes key from srcdb' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
end

it 'copies key to destdb' do
Expand All @@ -81,7 +81,7 @@
end

it 'removes key from srcdb' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
end

it 'copies key to destdb' do
Expand All @@ -99,7 +99,7 @@
end

it 'removes key from srcdb' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
end

it 'copies key to destdb' do
Expand All @@ -117,7 +117,7 @@
end

it 'removes key from srcdb' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
end

it 'copies key to destdb' do
Expand All @@ -135,7 +135,7 @@
end

it 'removes key from srcdb' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
end

it 'copies key to destdb' do
Expand Down
6 changes: 4 additions & 2 deletions spec/commands/set_spec.rb
Expand Up @@ -33,10 +33,12 @@
@redises.set(key, 1, xx: true).should == true
end

it 'ignores other options' do
it 'raises on unknown options' do
key = 'mock-redis-test'
@redises.del(key)
@redises.set(key, 1, logger: :something).should == 'OK'
expect do
@redises.set(key, 1, logger: :something)
end.to raise_error(ArgumentError, 'unknown keyword: logger')
end

context '[mock only]' do
Expand Down
1 change: 1 addition & 0 deletions spec/commands/setbit_spec.rb
Expand Up @@ -2,6 +2,7 @@

describe '#setbit(key, offset)' do
before do
Encoding.default_external = 'UTF-8'
@key = 'mock-redis-test:setbit'
@redises.set(@key, 'h') # ASCII 0x68
end
Expand Down
2 changes: 2 additions & 0 deletions spec/commands/xadd_spec.rb
Expand Up @@ -54,6 +54,8 @@
Redis::CommandError,
'ERR The ID specified in XADD is equal or smaller than the target ' \
'stream top item'
# TOOD: Redis version 6.0.4, w redis 4.2.1 generates the following error message:
# 'ERR The ID specified in XADD must be greater than 0-0'
)
end

Expand Down
2 changes: 1 addition & 1 deletion spec/commands/zrange_spec.rb
Expand Up @@ -15,7 +15,7 @@
end

it 'should return an empty array' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
@redises.zrange(@key, 0, 4).should == []
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/commands/zrangebyscore_spec.rb
Expand Up @@ -15,7 +15,7 @@
end

it 'should return an empty array' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
@redises.zrangebyscore(@key, 0, 4).should == []
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/commands/zrevrange_spec.rb
Expand Up @@ -15,7 +15,7 @@
end

it 'should return an empty array' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
@redises.zrevrange(@key, 0, 4).should == []
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/commands/zrevrangebyscore_spec.rb
Expand Up @@ -15,7 +15,7 @@
end

it 'should return an empty array' do
@redises.exists(@key).should == false
@redises.exists?(@key).should == false
@redises.zrevrangebyscore(@key, 0, 4).should == []
end
end
Expand Down

0 comments on commit 166c8bb

Please sign in to comment.