lib/redis/connection/memory.rb in kuende-fakeredis-0.6.0 vs lib/redis/connection/memory.rb in kuende-fakeredis-0.10.0
- old
+ new
@@ -7,11 +7,10 @@
require "fakeredis/sorted_set_argument_handler"
require "fakeredis/sorted_set_store"
require "fakeredis/transaction_commands"
require "fakeredis/zset"
require "fakeredis/bitop_command"
-require "fakeredis/version"
class Redis
module Connection
class Memory
include Redis::Connection::CommandHelper
@@ -88,10 +87,19 @@
end
def disconnect
end
+ def client(command, options = {})
+ case command
+ when :setname then true
+ when :getname then nil
+ else
+ raise Redis::CommandError, "ERR unknown command '#{command}'"
+ end
+ end
+
def timeout=(usecs)
end
def read
replies.shift
@@ -345,11 +353,18 @@
data[key].size
end
def lrange(key, startidx, endidx)
data_type_check(key, Array)
- (data[key] && data[key][startidx..endidx]) || []
+ if data[key]
+ # In Ruby when negative start index is out of range Array#slice returns
+ # nil which is not the case for lrange in Redis.
+ startidx = 0 if startidx < 0 && startidx.abs > data[key].size
+ data[key][startidx..endidx] || []
+ else
+ []
+ end
end
def ltrim(key, start, stop)
data_type_check(key, Array)
return unless data[key]
@@ -378,13 +393,13 @@
value = value.to_s
index = data[key].index(pivot.to_s)
return -1 if index.nil?
- case where
- when :before then data[key].insert(index, value)
- when :after then data[key].insert(index + 1, value)
+ case where.to_s
+ when /\Abefore\z/i then data[key].insert(index, value)
+ when /\Aafter\z/i then data[key].insert(index + 1, value)
else raise_syntax_error
end
end
def lset(key, index, value)
@@ -551,15 +566,18 @@
result = self.srem(source, value)
self.sadd(destination, value) if result
result
end
- def spop(key)
+ def spop(key, count = nil)
data_type_check(key, ::Set)
- elem = srandmember(key)
- srem(key, elem)
- elem
+ results = (count || 1).times.map do
+ elem = srandmember(key)
+ srem(key, elem)
+ elem
+ end.compact
+ count.nil? ? results.first : results
end
def scard(key)
data_type_check(key, ::Set)
return 0 unless data[key]
@@ -618,10 +636,48 @@
def srandmember(key, number=nil)
number.nil? ? srandmember_single(key) : srandmember_multiple(key, number)
end
+ def sscan(key, start_cursor, *args)
+ data_type_check(key, ::Set)
+ return ["0", []] unless data[key]
+
+ match = "*"
+ count = 10
+
+ if args.size.odd?
+ raise_argument_error('sscan')
+ end
+
+ if idx = args.index("MATCH")
+ match = args[idx + 1]
+ end
+
+ if idx = args.index("COUNT")
+ count = args[idx + 1]
+ end
+
+ start_cursor = start_cursor.to_i
+
+ cursor = start_cursor
+ next_keys = []
+
+ if start_cursor + count >= data[key].length
+ next_keys = (data[key].to_a)[start_cursor..-1]
+ cursor = 0
+ else
+ cursor = start_cursor + count
+ next_keys = (data[key].to_a)[start_cursor..cursor-1]
+ end
+
+ filtered_next_keys = next_keys.select{ |k,v| File.fnmatch(match, k)}
+ result = filtered_next_keys.flatten.map(&:to_s)
+
+ return ["#{cursor}", result]
+ end
+
def del(*keys)
keys = keys.flatten(1)
raise_argument_error('del') if keys.empty?
old_count = data.keys.size
@@ -733,10 +789,11 @@
else
fields.each_slice(2) do |field|
data[key][field[0].to_s] = field[1].to_s
end
end
+ "OK"
end
def hmget(key, *fields)
raise_argument_error('hmget') if fields.empty?
@@ -912,37 +969,38 @@
def scan(start_cursor, *args)
match = "*"
count = 10
- if args.size.odd?
- raise_argument_error('scan')
- end
-
if idx = args.index("MATCH")
match = args[idx + 1]
end
if idx = args.index("COUNT")
count = args[idx + 1]
end
start_cursor = start_cursor.to_i
- data_type_check(start_cursor, Fixnum)
+ data_type_check(start_cursor, Integer)
cursor = start_cursor
- next_keys = []
+ returned_keys = []
+ final_page = start_cursor + count >= keys(match).length
- if start_cursor + count >= data.length
- next_keys = keys(match)[start_cursor..-1]
+ if final_page
+ previous_keys_been_deleted = (count >= keys(match).length)
+ start_index = previous_keys_been_deleted ? 0 : cursor
+
+ returned_keys = keys(match)[start_index..-1]
cursor = 0
else
- cursor = start_cursor + 10
- next_keys = keys(match)[start_cursor..cursor]
+ end_index = start_cursor + (count - 1)
+ returned_keys = keys(match)[start_cursor..end_index]
+ cursor = start_cursor + count
end
- return "#{cursor}", next_keys
+ return "#{cursor}", returned_keys
end
def zadd(key, *args)
if !args.first.is_a?(Array)
if args.size < 2
@@ -1030,11 +1088,11 @@
return [] unless data[key]
results = sort_keys(data[key])
# Select just the keys unless we want scores
results = results.map(&:first) unless with_scores
- results[start..stop].flatten.map(&:to_s)
+ (results[start..stop] || []).flatten.map(&:to_s)
end
def zrangebylex(key, start, stop, *opts)
data_type_check(key, ZSet)
return [] unless data[key]
@@ -1239,11 +1297,11 @@
if idx = args.index("COUNT")
count = args[idx + 1]
end
start_cursor = start_cursor.to_i
- data_type_check(start_cursor, Fixnum)
+ data_type_check(start_cursor, Integer)
cursor = start_cursor
next_keys = []
sorted_keys = sort_keys(data[key])
@@ -1370,6 +1428,7 @@
end
end
end
end
+# FIXME this line should be deleted as explicit enabling is better
Redis::Connection.drivers << Redis::Connection::Memory