Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change exists return and add exists? #188

Merged
merged 6 commits into from Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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