lib/redis/connection/memory.rb in fakeredis-0.4.0 vs lib/redis/connection/memory.rb in fakeredis-0.4.1
- old
+ new
@@ -74,12 +74,16 @@
def connected?
@connected
end
+ def self.instances
+ @instances ||= {}
+ end
+
def self.connect(options = {})
- self.new(true)
+ self.instances[options] ||= self.new(true)
end
def connect_unix(path, timeout)
@connected = true
end
@@ -179,11 +183,11 @@
@data[key] = value
return old_value
end
def mget(*keys)
- raise ArgumentError, "wrong number of arguments for 'mget' command" if keys.empty?
+ raise Redis::CommandError, "wrong number of arguments for 'mget' command" if keys.empty?
@data.values_at(*keys)
end
def append(key, value)
@data[key] = (@data[key] || "")
@@ -252,11 +256,11 @@
@data[key].size
end
def lrange(key, startidx, endidx)
data_type_check(key, Array)
- @data[key] && @data[key][startidx..endidx]
+ (@data[key] && @data[key][startidx..endidx]) || []
end
def ltrim(key, start, stop)
data_type_check(key, Array)
return unless @data[key]
@@ -273,11 +277,11 @@
return unless @data[key]
index = @data[key].index(pivot)
case where
when :before then @data[key].insert(index, value)
when :after then @data[key].insert(index + 1, value)
- else raise ArgumentError
+ else raise Redis::CommandError, "ERR syntax error"
end
end
def lset(key, index, value)
data_type_check(key, Array)
@@ -305,11 +309,13 @@
end
def rpush(key, value)
data_type_check(key, Array)
@data[key] ||= []
- @data[key].push(value)
+ [value].flatten.each do |val|
+ @data[key].push(val.to_s)
+ end
@data[key].size
end
def rpushx(key, value)
data_type_check(key, Array)
@@ -318,11 +324,13 @@
end
def lpush(key, value)
data_type_check(key, Array)
@data[key] ||= []
- @data[key].unshift(value)
+ [value].flatten.each do |val|
+ @data[key].unshift(val.to_s)
+ end
@data[key].size
end
def lpushx(key, value)
data_type_check(key, Array)
@@ -360,16 +368,24 @@
@data[key].include?(value.to_s)
end
def sadd(key, value)
data_type_check(key, ::Set)
- if @data[key]
- !!@data[key].add?(value.to_s)
+ value = Array(value)
+
+ result = if @data[key]
+ old_set = @data[key].dup
+ @data[key].merge(value.map(&:to_s))
+ (@data[key] - old_set).size
else
- @data[key] = ::Set.new([value.to_s])
- true
+ @data[key] = ::Set.new(value.map(&:to_s))
+ @data[key].size
end
+
+ # 0 = false, 1 = true, 2+ untouched
+ return result == 1 if result < 2
+ result
end
def srem(key, value)
data_type_check(key, ::Set)
deleted = !!(@data[key] && @data[key].delete?(value.to_s))
@@ -445,12 +461,14 @@
return nil unless @data[key]
@data[key].to_a[rand(@data[key].size)]
end
def del(*keys)
+ keys = keys.flatten(1)
+ raise Redis::CommandError, "ERR wrong number of arguments for 'del' command" if keys.empty?
old_count = @data.keys.size
- keys.flatten.each do |key|
+ keys.each do |key|
@data.delete(key)
end
deleted_count = old_count - @data.keys.size
end
@@ -521,20 +539,20 @@
return false if @data[key] && @data[key][field]
hset(key, field, value)
end
def hmset(key, *fields)
- raise ArgumentError, "wrong number of arguments for 'hmset' command" if fields.empty? || fields.size.odd?
+ raise Redis::CommandError, "wrong number of arguments for 'hmset' command" if fields.empty? || fields.size.odd?
data_type_check(key, Hash)
@data[key] ||= {}
fields.each_slice(2) do |field|
@data[key][field[0].to_s] = field[1].to_s
end
end
def hmget(key, *fields)
- raise ArgumentError, "wrong number of arguments for 'hmget' command" if fields.empty?
+ raise Redis::CommandError, "wrong number of arguments for 'hmget' command" if fields.empty?
data_type_check(key, Hash)
values = []
fields.map do |field|
field = field.to_s
if @data[key]
@@ -629,30 +647,26 @@
def sort(key)
# TODO: Implement
end
def incr(key)
- @data[key] = (@data[key] || "0")
- @data[key] = (@data[key].to_i + 1).to_s
+ @data.merge!({ key => (@data[key].to_i + 1).to_s || "1"})
@data[key].to_i
end
def incrby(key, by)
- @data[key] = (@data[key] || "0")
- @data[key] = (@data[key].to_i + by.to_i).to_s
+ @data.merge!({ key => (@data[key].to_i + by.to_i).to_s || by })
@data[key].to_i
end
def decr(key)
- @data[key] = (@data[key] || "0")
- @data[key] = (@data[key].to_i - 1).to_s
+ @data.merge!({ key => (@data[key].to_i - 1).to_s || "-1"})
@data[key].to_i
end
def decrby(key, by)
- @data[key] = (@data[key] || "0")
- @data[key] = (@data[key].to_i - by.to_i).to_s
+ @data.merge!({ key => ((@data[key].to_i - by.to_i) || (by.to_i * -1)).to_s })
@data[key].to_i
end
def type(key)
case value = @data[key]
@@ -688,16 +702,38 @@
def unwatch
"OK"
end
- def zadd(key, score, value)
+ def zadd(key, *args)
+ if !args.first.is_a?(Array)
+ if args.size < 2
+ raise Redis::CommandError, "ERR wrong number of arguments for 'zadd' command"
+ elsif args.size.odd?
+ raise Redis::CommandError, "ERR syntax error"
+ end
+ else
+ unless args.all? {|pair| pair.size == 2 }
+ raise(Redis::CommandError, "ERR syntax error")
+ end
+ end
+
data_type_check(key, ZSet)
@data[key] ||= ZSet.new
- exists = @data[key].key?(value.to_s)
- @data[key][value.to_s] = score
- !exists
+
+ if args.size == 2
+ score, value = args
+ exists = !@data[key].key?(value.to_s)
+ @data[key][value.to_s] = score
+ else
+ # Turn [1, 2, 3, 4] into [[1, 2], [3, 4]] unless it is already
+ args = args.each_slice(2).to_a unless args.first.is_a?(Array)
+ exists = args.map(&:last).map { |el| @data[key].key?(el.to_s) }.count(false)
+ args.each { |score, value| @data[key][value.to_s] = score }
+ end
+
+ exists
end
def zrem(key, value)
data_type_check(key, ZSet)
exists = false
@@ -809,11 +845,12 @@
data_type_check(out, ZSet)
hashes = keys.map do |src|
case @data[src]
when ::Set
- Hash[@data[src].zip([0] * @data[src].size)]
+ # Every value has a score of 1
+ Hash[@data[src].map {|k,v| [k, 1]}]
when Hash
@data[src]
else
{}
end
@@ -828,18 +865,27 @@
@data[out].size
end
def zremrangebyrank(key, start, stop)
sorted_elements = @data[key].sort { |(v_a, r_a), (v_b, r_b)| r_a <=> r_b }
+ start = sorted_elements.length if start > sorted_elements.length
elements_to_delete = sorted_elements[start..stop]
elements_to_delete.each { |elem, rank| @data[key].delete(elem) }
elements_to_delete.size
end
private
def zrange_select_by_score(key, min, max)
- @data[key].reject {|_,v| v < min || v > max }
+ if min == '-inf' && max == '+inf'
+ @data[key]
+ elsif max == '+inf'
+ @data[key].reject { |_,v| v < min }
+ elsif min == '-inf'
+ @data[key].reject { |_,v| v > max }
+ else
+ @data[key].reject {|_,v| v < min || v > max }
+ end
end
def remove_key_for_empty_collection(key)
del(key) if @data[key] && @data[key].empty?
end